⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sys_term.c

📁 经典的unix下telnetd代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    char *user;    int save_errno;    char *buf;    extern char *gettytab[2], *gettyent;#ifdef HAVE_UTMPX_H    int pid = getpid();    struct utmpx utmpx;    char *clean_tty;    /*     * Create utmp entry for child     */    clean_tty = clean_ttyname(line);    memset(&utmpx, 0, sizeof(utmpx));    strncpy(utmpx.ut_user,  ".telnet", sizeof(utmpx.ut_user));    strncpy(utmpx.ut_line,  clean_tty, sizeof(utmpx.ut_line));#ifdef HAVE_STRUCT_UTMP_UT_ID    strncpy(utmpx.ut_id, make_id(clean_tty), sizeof(utmpx.ut_id));#endif    utmpx.ut_pid = pid;	    utmpx.ut_type = LOGIN_PROCESS;    gettimeofday (&utmpx.ut_tv, NULL);    if (pututxline(&utmpx) == NULL)	fatal(net, "pututxline failed");#endif#if 0    scrub_env();#endif    /*     * -h : pass on name of host.     *		WARNING:  -h is accepted by login if and only if     *			getuid() == 0.     * -p : don't clobber the environment (so terminal type stays set).     *     * -f : force this login, he has already been authenticated     */    /* init argv structure */     argv.size=0;    argv.argc=0;    argv.argv=malloc(0); /*so we can call realloc later */    addarg(&argv, "login");    addarg(&argv, "-h");    addarg(&argv, host);    addarg(&argv, "-p");    if(name[0])	user = name;    else	user = getenv("USER");#ifdef AUTHENTICATION    if (auth_level < 0 || autologin != AUTH_VALID) {	if(!no_warn) {	    printf("User not authenticated. "		"Using plaintext username and password\r\n");	}	if(log_unauth) 	    syslog(LOG_INFO, "unauthenticated access from %s (%s)", 		   host, user ? user : "unknown user");    }    if (auth_level >= 0 && autologin == AUTH_VALID)	addarg(&argv, "-f");#endif    if(user){	addarg(&argv, "--");	addarg(&argv, strdup(user));    }    if (new_login == NULL && cgetent(&buf, gettytab, gettyent) >= 0) {	cgetstr(buf, "lo", &new_login);	cgetclose();    }    if (new_login == NULL)	new_login = _PATH_LOGIN;    if (getenv("USER")) {	/*	 * Assume that login will set the USER variable	 * correctly.  For SysV systems, this means that	 * USER will no longer be set, just LOGNAME by	 * login.  (The problem is that if the auto-login	 * fails, and the user then specifies a different	 * account name, he can get logged in with both	 * LOGNAME and USER in his environment, but the	 * USER value will be wrong.	 */	unsetenv("USER");    }    closelog();    /*     * This sleep(1) is in here so that telnetd can     * finish up with the tty.  There's a race condition     * the login banner message gets lost...     */    sleep(1);    execv(new_login, (char *const*)argv.argv);    save_errno = errno;    syslog(LOG_ERR, "%s: %m", new_login);    fatalperror_errno(net, new_login, save_errno);    /*NOTREACHED*/}static voidaddarg(struct arg_val *argv, const char *val){    const char **tmp;    if (argv->size <= argv->argc+1) {	tmp = realloc(argv->argv, sizeof(char*) * (argv->size + 10));	if (tmp == NULL) {	    if (argv->argv)		    free(argv->argv);	    argv->argv = NULL;	    argv->size = 0;	    fatal (net, "realloc: out of memory");	}	argv->argv = tmp;	argv->size+=10;    }    argv->argv[argv->argc++] = val;    argv->argv[argv->argc]   = NULL;}/* * rmut() * * This is the function called by cleanup() to * remove the utmp entry for this person. */#ifdef HAVE_UTMPX_Hstatic voidrmut(void){    struct utmpx utmpx, *non_save_utxp;    char *clean_tty = clean_ttyname(line);    /*     * This updates the utmpx and utmp entries and make a wtmp/x entry     */    setutxent();    memset(&utmpx, 0, sizeof(utmpx));    strncpy(utmpx.ut_line, clean_tty, sizeof(utmpx.ut_line));    utmpx.ut_type = LOGIN_PROCESS;    non_save_utxp = getutxline(&utmpx);    if (non_save_utxp) {	struct utmpx *utxp;	char user0;	utxp = malloc(sizeof(struct utmpx));	*utxp = *non_save_utxp;	user0 = utxp->ut_user[0];	utxp->ut_user[0] = '\0';	utxp->ut_type = DEAD_PROCESS;#ifdef HAVE_STRUCT_UTMPX_UT_EXIT#ifdef _STRUCT___EXIT_STATUS	utxp->ut_exit.__e_termination = 0;	utxp->ut_exit.__e_exit = 0;#elif defined(__osf__) /* XXX */	utxp->ut_exit.ut_termination = 0;	utxp->ut_exit.ut_exit = 0;#else		utxp->ut_exit.e_termination = 0;	utxp->ut_exit.e_exit = 0;#endif#endif	gettimeofday(&utxp->ut_tv, NULL);	pututxline(utxp);#ifdef WTMPX_FILE	utxp->ut_user[0] = user0;	updwtmpx(WTMPX_FILE, utxp);#elif defined(WTMP_FILE)	/* This is a strange system with a utmpx and a wtmp! */	{	  int f = open(wtmpf, O_WRONLY|O_APPEND);	  struct utmp wtmp;	  if (f >= 0) {	    strncpy(wtmp.ut_line,  clean_tty, sizeof(wtmp.ut_line));	    strncpy(wtmp.ut_name,  "", sizeof(wtmp.ut_name));#ifdef HAVE_STRUCT_UTMP_UT_HOST	    strncpy(wtmp.ut_host,  "", sizeof(wtmp.ut_host));#endif	    wtmp.ut_time = time(NULL);	    write(f, &wtmp, sizeof(wtmp));	    close(f);	  }	}#endif	free (utxp);    }    endutxent();}  /* end of rmut */#endif#if !defined(HAVE_UTMPX_H) && !(defined(_CRAY) || defined(__hpux))static voidrmut(void){    int f;    int found = 0;    struct utmp *u, *utmp;    int nutmp;    struct stat statbf;    char *clean_tty = clean_ttyname(line);    f = open(utmpf, O_RDWR);    if (f >= 0) {	fstat(f, &statbf);	utmp = (struct utmp *)malloc((unsigned)statbf.st_size);	if (!utmp)	    syslog(LOG_ERR, "utmp malloc failed");	if (statbf.st_size && utmp) {	    nutmp = read(f, utmp, (int)statbf.st_size);	    nutmp /= sizeof(struct utmp);	    for (u = utmp ; u < &utmp[nutmp] ; u++) {		if (strncmp(u->ut_line,			    clean_tty,			    sizeof(u->ut_line)) ||		    u->ut_name[0]==0)		    continue;		lseek(f, ((long)u)-((long)utmp), L_SET);		strncpy(u->ut_name,  "", sizeof(u->ut_name));#ifdef HAVE_STRUCT_UTMP_UT_HOST		strncpy(u->ut_host,  "", sizeof(u->ut_host));#endif		u->ut_time = time(NULL);		write(f, u, sizeof(wtmp));		found++;	    }	}	close(f);    }    if (found) {	f = open(wtmpf, O_WRONLY|O_APPEND);	if (f >= 0) {	    strncpy(wtmp.ut_line,  clean_tty, sizeof(wtmp.ut_line));	    strncpy(wtmp.ut_name,  "", sizeof(wtmp.ut_name));#ifdef HAVE_STRUCT_UTMP_UT_HOST	    strncpy(wtmp.ut_host,  "", sizeof(wtmp.ut_host));#endif	    wtmp.ut_time = time(NULL);	    write(f, &wtmp, sizeof(wtmp));	    close(f);	}    }    chmod(line, 0666);    chown(line, 0, 0);    line[strlen("/dev/")] = 'p';    chmod(line, 0666);    chown(line, 0, 0);}  /* end of rmut */#endif	/* CRAY */#if defined(__hpux) && !defined(HAVE_UTMPX_H)static voidrmut (char *line){    struct utmp utmp;    struct utmp *utptr;    int fd;			/* for /etc/wtmp */    utmp.ut_type = USER_PROCESS;    strncpy(utmp.ut_line, clean_ttyname(line), sizeof(utmp.ut_line));    setutent();    utptr = getutline(&utmp);    /* write it out only if it exists */    if (utptr) {	utptr->ut_type = DEAD_PROCESS;	utptr->ut_time = time(NULL);	pututline(utptr);	/* set wtmp entry if wtmp file exists */	if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) {	    write(fd, utptr, sizeof(utmp));	    close(fd);	}    }    endutent();    chmod(line, 0666);    chown(line, 0, 0);    line[14] = line[13];    line[13] = line[12];    line[8] = 'm';    line[9] = '/';    line[10] = 'p';    line[11] = 't';    line[12] = 'y';    chmod(line, 0666);    chown(line, 0, 0);}#endif/* * cleanup() * * This is the routine to call when we are all through, to * clean up anything that needs to be cleaned up. */#ifdef PARENT_DOES_UTMPvoidcleanup(int sig){#ifdef _CRAY    static int incleanup = 0;    int t;    int child_status; /* status of child process as returned by waitpid */    int flags = WNOHANG|WUNTRACED;        /*     * 1: Pick up the zombie, if we are being called     *    as the signal handler.     * 2: If we are a nested cleanup(), return.     * 3: Try to clean up TMPDIR.     * 4: Fill in utmp with shutdown of process.     * 5: Close down the network and pty connections.     * 6: Finish up the TMPDIR cleanup, if needed.     */    if (sig == SIGCHLD) {	while (waitpid(-1, &child_status, flags) > 0)	    ;	/* VOID */	/* Check if the child process was stopped	 * rather than exited.  We want cleanup only if	 * the child has died.	 */	if (WIFSTOPPED(child_status)) {	    return;	}    }    t = sigblock(sigmask(SIGCHLD));    if (incleanup) {	sigsetmask(t);	return;    }    incleanup = 1;    sigsetmask(t);        t = cleantmp(&wtmp);    setutent();	/* just to make sure */#endif /* CRAY */    rmut(line);    close(ourpty);    shutdown(net, 2);#ifdef _CRAY    if (t == 0)	cleantmp(&wtmp);#endif /* CRAY */    exit(1);}#else /* PARENT_DOES_UTMP */voidcleanup(int sig){#if defined(HAVE_UTMPX_H) || !defined(HAVE_LOGWTMP)    rmut();#ifdef HAVE_VHANGUP#ifndef __sgi    vhangup(); /* XXX */#endif#endif#else    char *p;        p = line + sizeof("/dev/") - 1;    if (logout(p))	logwtmp(p, "", "");    chmod(line, 0666);    chown(line, 0, 0);    *p = 'p';    chmod(line, 0666);    chown(line, 0, 0);#endif    shutdown(net, 2);    _exit(1);}#endif /* PARENT_DOES_UTMP */#ifdef PARENT_DOES_UTMP/* * _utmp_sig_rcv * utmp_sig_init * utmp_sig_wait *	These three functions are used to coordinate the handling of *	the utmp file between the server and the soon-to-be-login shell. *	The server actually creates the utmp structure, the child calls *	utmp_sig_wait(), until the server calls utmp_sig_notify() and *	signals the future-login shell to proceed. */static int caught=0;		/* NZ when signal intercepted */static void (*func)();		/* address of previous handler */void_utmp_sig_rcv(sig)     int sig;{    caught = 1;    signal(SIGUSR1, func);}voidutmp_sig_init(){    /*     * register signal handler for UTMP creation     */    if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1)	fatalperror(net, "telnetd/signal");}voidutmp_sig_reset(){    signal(SIGUSR1, func);	/* reset handler to default */}# ifdef __hpux# define sigoff() /* do nothing */# define sigon() /* do nothing */# endifvoidutmp_sig_wait(){    /*     * Wait for parent to write our utmp entry.	 */    sigoff();    while (caught == 0) {	pause();	/* wait until we get a signal (sigon) */	sigoff();	/* turn off signals while we check caught */    }    sigon();		/* turn on signals again */}voidutmp_sig_notify(pid){    kill(pid, SIGUSR1);}#ifdef _CRAYstatic int gotsigjob = 0;	/*ARGSUSED*/voidsigjob(sig)     int sig;{    int jid;    struct jobtemp *jp;    while ((jid = waitjob(NULL)) != -1) {	if (jid == 0) {	    return;	}	gotsigjob++;	jobend(jid, NULL, NULL);    }}/* *	jid_getutid: *		called by jobend() before calling cleantmp() *		to find the correct $TMPDIR to cleanup. */struct utmp *jid_getutid(jid)     int jid;{    struct utmp *cur = NULL;    setutent();	/* just to make sure */    while (cur = getutent()) {	if ( (cur->ut_type != NULL) && (jid == cur->ut_jid) ) {	    return(cur);	}    }    return(0);}/* * Clean up the TMPDIR that login created. * The first time this is called we pick up the info * from the utmp.  If the job has already gone away, * then we'll clean up and be done.  If not, then * when this is called the second time it will wait * for the signal that the job is done. */intcleantmp(wtp)     struct utmp *wtp;{    struct utmp *utp;    static int first = 1;    int mask, omask, ret;    extern struct utmp *getutid (const struct utmp *_Id);    mask = sigmask(WJSIGNAL);    if (first == 0) {	omask = sigblock(mask);	while (gotsigjob == 0)	    sigpause(omask);	return(1);    }    first = 0;    setutent();	/* just to make sure */    utp = getutid(wtp);    if (utp == 0) {	syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR");	return(-1);    }    /*     * Nothing to clean up if the user shell was never started.     */    if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0)	return(1);    /*     * Block the WJSIGNAL while we are in jobend().     */    omask = sigblock(mask);    ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user);    sigsetmask(omask);    return(ret);}/* *	jobend *		Assumes that if path is not NULL, then user is also * 		not NULL. */intjobend(jid, path, user)     int jid;     char *path;     char *user;{    static int saved_jid = 0;    static int pty_saved_jid = 0;    static char saved_path[sizeof(wtmp.ut_tpath)+1];    static char saved_user[sizeof(wtmp.ut_user)+1];    /*     * this little piece of code comes into play     * only when ptyreconnect is used to reconnect     * to an previous session.     *     * this is the only time when the     * "saved_jid != jid" code is executed.     */    if ( saved_jid && saved_jid != jid ) {	if (!path) {	/* called from signal handler */	    pty_saved_jid = jid;	} else {	    pty_saved_jid = saved_jid;	}    }    if (path) {	strncpy(saved_path, path, sizeof(saved_path) - 1);	strncpy(saved_user, path, sizeof(saved_user) - 1);	saved_path[sizeof(saved_path) - 1] = '\0';	saved_user[sizeof(saved_user) - 1] = '\0';    }    if (saved_jid == 0) {	saved_jid = jid;	return(0);    }    /* if the jid has changed, get the correct entry from the utmp file */    if ( saved_jid != jid ) {	struct utmp *utp = NULL;	struct utmp *jid_getutid();	utp = jid_getutid(pty_saved_jid);	if (utp == 0) {	    syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR");	    return(-1);	}	cleantmpdir(jid, utp->ut_tpath, utp->ut_user);	return(1);    }    cleantmpdir(jid, saved_path, saved_user);    return(1);}/* * Fork a child process to clean up the TMPDIR */cleantmpdir(jid, tpath, user)     int jid;     char *tpath;     char *user;{    switch(fork()) {    case -1:	syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m",	       tpath);	break;    case 0:	execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, (char *)NULL);	syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m",	       tpath, CLEANTMPCMD);	exit(1);    default:	/*	 * Forget about child.  We will exit, and	 * /etc/init will pick it up.	 */	break;    }}#endif /* CRAY */#endif	/* defined(PARENT_DOES_UTMP) */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -