From: Tom Yu Date: Tue, 8 May 2001 04:28:33 +0000 (+0000) Subject: * cleanup.c: Call update_utmp() with the correct pid to assist in X-Git-Tag: krb5-1.3-alpha1~1517 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=5c4ec4398a5a80f245391670d7e5b79fa1c0effe;p=krb5.git * cleanup.c: Call update_utmp() with the correct pid to assist in finding the old utmp entry. * open_ctty.c: Reformat somewhat and revise comment. * open_slave.c: Rework significantly. Primarily, keep a fd open to the slave if we need to reopen the slave device following vhangup() or revoke(), to accommodate various OS quirks. * update_utmp.c: Revise history section somewhat to document more HP-UX brokenness. Search via ut_pid before searching via ut_line. Copy stuff around because entuxent() will clobber some things. * void_assoc.c: Revise comment and reformat somewhat. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@13234 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/util/pty/ChangeLog b/src/util/pty/ChangeLog index ef8e0b849..8bea2de82 100644 --- a/src/util/pty/ChangeLog +++ b/src/util/pty/ChangeLog @@ -1,3 +1,21 @@ +2001-05-08 Tom Yu + + * cleanup.c: Call update_utmp() with the correct pid to assist in + finding the old utmp entry. + + * open_ctty.c: Reformat somewhat and revise comment. + + * open_slave.c: Rework significantly. Primarily, keep a fd open + to the slave if we need to reopen the slave device following + vhangup() or revoke(), to accommodate various OS quirks. + + * update_utmp.c: Revise history section somewhat to document more + HP-UX brokenness. Search via ut_pid before searching via + ut_line. Copy stuff around because entuxent() will clobber some + things. + + * void_assoc.c: Revise comment and reformat somewhat. + 2001-05-04 Ezra Peisach * open_slave.c (pty_open_slave): If revoke() present on system but diff --git a/src/util/pty/cleanup.c b/src/util/pty/cleanup.c index 23db2a2f3..87a77c173 100644 --- a/src/util/pty/cleanup.c +++ b/src/util/pty/cleanup.c @@ -37,7 +37,7 @@ long pty_cleanup (slave, pid, update_utmp) #endif if (update_utmp) - pty_update_utmp(PTY_DEAD_PROCESS,0, "", slave, (char *)0, PTY_UTMP_USERNAME_VALID); + pty_update_utmp(PTY_DEAD_PROCESS, pid, "", slave, (char *)0, PTY_UTMP_USERNAME_VALID); (void)chmod(slave, 0666); (void)chown(slave, 0, 0); diff --git a/src/util/pty/open_ctty.c b/src/util/pty/open_ctty.c index d02a8c135..5e41d9531 100644 --- a/src/util/pty/open_ctty.c +++ b/src/util/pty/open_ctty.c @@ -24,35 +24,37 @@ #include "pty-int.h" /* - * This routine will be called twice. It's not particularly important - * that the setsid() or TIOCSTTY ioctls succeed (they may not the - * second time), but rather that we have a controlling terminal at the - * end. It is assumed that vhangup doesn't exist and confuse the - * process's notion of controlling terminal on any system without - * TIOCNOTTY. That is, either vhangup() leaves the controlling - * terminal in tact, breaks the association completely, or the system - * provides TIOCNOTTY to get things back into a reasonable state. In - * practice, vhangup() either breaks the association completely or - * doesn't effect controlling terminals, so this condition is met. + * This function will be called twice. The first time it will acquire + * a controlling terminal from which to vhangup() or revoke() (see + * comments in open_slave.c); the second time, it will be to open the + * actual slave device for use by the application. We no longer call + * ptyint_void_association(), as that will be called in + * pty_open_slave() to avoid spurious calls to setsid(), etc. + * + * It is assumed that systems where vhangup() exists and does break + * the ctty association will allow the slave to be re-acquired as the + * ctty. Also, if revoke() or vhangup() doesn't break the ctty + * association, we assume that we can successfully reopen the slave. + * + * This function doesn't check whether we actually acquired the ctty; + * we assume that the caller will check that, or that it doesn't + * matter in the particular case. */ long -pty_open_ctty (slave, fd) - const char * slave; - int *fd; +pty_open_ctty(const char *slave, int *fd) { - int retval; -/* First, dissociate from previous terminal */ - if ( (retval = ptyint_void_association()) != 0 ) - return retval; #ifdef ultrix - /* The Ultrix (and other BSD tty drivers) require the process group - * to be zero, in order to acquire the new tty as a controlling tty. */ + /* + * The Ultrix (and other BSD tty drivers) require the process + * group to be zero, in order to acquire the new tty as a + * controlling tty. This may actually belong in + * ptyint_void_association(). + */ (void) setpgrp(0, 0); #endif - *fd = open(slave, O_RDWR); - if (*fd < 0 ) + if (*fd < 0) return PTY_OPEN_SLAVE_OPENFAIL; #ifdef ultrix setpgrp(0, getpid()); diff --git a/src/util/pty/open_slave.c b/src/util/pty/open_slave.c index 235b8e8da..6e80befb2 100644 --- a/src/util/pty/open_slave.c +++ b/src/util/pty/open_slave.c @@ -1,7 +1,8 @@ /* * pty_open_slave: open slave side of terminal, clearing for use. * - * Copyright 1995, 1996 by the Massachusetts Institute of Technology. + * Copyright 1995, 1996, 2001 by the Massachusetts Institute of + * Technology. * * * Permission to use, copy, modify, and distribute this software and @@ -24,93 +25,73 @@ #include "libpty.h" #include "pty-int.h" - -long pty_open_slave ( slave, fd) - const char *slave; - int *fd; +long +pty_open_slave(const char *slave, int *fd) { -#if defined(VHANG_FIRST) || defined(HAVE_REVOKE) - int vfd; -#endif - - int testfd; + int tmpfd; long retval; -#ifdef POSIX_SIGNALS - struct sigaction sa; - /* Initialize "sa" structure. */ - (void) sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - -#endif + /* Sanity check. */ + if (slave == NULL || *slave == '\0') + return PTY_OPEN_SLAVE_TOOSHORT; + + /* First, set up a new session and void old associations. */ + ptyint_void_association(); - /* First, chmod and chown the slave*/ /* - * If we have vhangup then we really need pty_open_ctty to make sure - * Our controlling terminal is the pty we're opening. However, if we - * are using revoke or nothing then we just need a file descriiptor - * for the pty. Considering some OSes in this category break on - * the second call to open_ctty (currently OSF but others may), - * we simply use a descriptor if we can. - */ -#ifdef VHANG_FIRST - if (( retval = pty_open_ctty ( slave, &vfd )) != 0 ) - return retval; - if (vfd < 0) + * Make a first attempt at acquiring the ctty. This is necessary + * for several reasons: + * + * Under Irix, if you open a pty slave and then close it, a + * subsequent open of the slave will cause the master to read EOF. + * To prevent this, don't close the first fd until we do the real + * open following vhangup(). + * + * Under Tru64 v5.0, if there isn't a fd open on the slave, + * revoke() fails with ENOTTY, curiously enough. + * + * Anyway, sshd seems to make a practice of doing this. + */ + retval = pty_open_ctty(slave, fd); + if (retval) + return retval; + if (*fd < 0) return PTY_OPEN_SLAVE_OPENFAIL; -#endif - + /* chmod and chown the slave. */ + if (chmod(slave, 0)) + return PTY_OPEN_SLAVE_CHMODFAIL; + if (chown(slave, 0, 0) == -1) + return PTY_OPEN_SLAVE_CHOWNFAIL; - if (slave == NULL || *slave == '\0') - return PTY_OPEN_SLAVE_TOOSHORT; - if (chmod(slave, 0)) - return PTY_OPEN_SLAVE_CHMODFAIL; - if ( chown(slave, 0, 0 ) == -1 ) - return PTY_OPEN_SLAVE_CHOWNFAIL; - -#ifdef VHANG_FIRST - ptyint_vhangup(); - (void) close(vfd); -#endif - - if ( (retval = ptyint_void_association()) != 0) - return retval; - #ifdef HAVE_REVOKE -#if defined(O_NOCTTY) && !defined(OPEN_CTTY_ONLY_ONCE) - /* - * Some OSes, notably Tru64 v5.0, fail on revoke() if the slave - * isn't open. Since we don't want to acquire it as controlling - * tty yet, use O_NOCTTY if available. - */ - vfd = open(slave, O_RDWR | O_NOCTTY); - if (vfd < 0) - return PTY_OPEN_SLAVE_OPENFAIL; -#endif - if (revoke (slave) < 0 ) { + if (revoke(slave) < 0) { return PTY_OPEN_SLAVE_REVOKEFAIL; } -#if defined(O_NOCTTY) && !defined(OPEN_CTTY_ONLY_ONCE) - close(vfd); +#else /* !HAVE_REVOKE */ +#ifdef VHANG_FIRST + ptyint_vhangup(); #endif -#endif /*HAVE_REVOKE*/ +#endif /* !HAVE_REVOKE */ -/* Open the pty for real. */ - if (( retval = pty_open_ctty ( slave, fd)) != 0 ) { + /* Open the pty for real. */ + retval = pty_open_ctty(slave, &tmpfd); + close(*fd); + if (retval) { + *fd = -1; return PTY_OPEN_SLAVE_OPENFAIL; } - retval = pty_initialize_slave (*fd); - + *fd = tmpfd; + retval = pty_initialize_slave(*fd); if (retval) - return retval; - testfd = open("/dev/tty", O_RDWR|O_NDELAY); - if ( testfd < 0 ) - { + return retval; + /* Make sure it's really our ctty. */ + tmpfd = open("/dev/tty", O_RDWR|O_NDELAY); + if (tmpfd < 0) { close(*fd); *fd = -1; return PTY_OPEN_SLAVE_NOCTTY; - } - close(testfd); + } + close(tmpfd); return 0; } diff --git a/src/util/pty/update_utmp.c b/src/util/pty/update_utmp.c index 976febe1a..6eefe89b6 100644 --- a/src/util/pty/update_utmp.c +++ b/src/util/pty/update_utmp.c @@ -30,16 +30,17 @@ * BSD: * ---- * - * The simplest (and earliest?) case is 4.x BSD utmp/wtmp. There are - * no auxiliary files. There is only a struct utmp, declared in - * utmp.h. Its contents usually include: + * The simplest (and earliest? possibly dating back to Version 7...) + * case is 4.x BSD utmp/wtmp. There are no auxiliary files. There is + * only a struct utmp, declared in utmp.h. Its contents usually + * include: * * char ut_line[] * char ut_name[] * char ut_host[] * long ut_time * - * The meanings of these fields follows their names reasonbly well. + * The meanings of these fields follow their names reasonbly well. * The ut_line field usually is the pathname of the tty device * associated with the login, with the leading "/dev/" stripped off. * @@ -53,10 +54,10 @@ * determine this if a utmp entry is made by the window system on at * least SunOS 4.x. * - * It is not know whether the login program or init is responsible for - * clearing the utmp entry, or for entering a logout record in wtmp. - * It is likely the case that init cleans up for processes that it is - * itself responsible for starting. + * The native login never clears its own utmp entry or writes its own + * logout record; its parent (one of init, rlogind, telnetd, etc.) + * should handle that. In theory, getty could do that, but getty + * usually doesn't fork to exec login. * * Old (c. 1984) System V: * ----------------------- @@ -217,11 +218,30 @@ * * HP-UX 10.x: * - * When init cleans up after processes it doesn't start, if the - * process being cleaned up after allocated a pty, ut_line gets a - * prefix of "pty/" for no readily apparent reason. This causes - * ut_line of logout entries in wtmp to not match that of their login - * entries, confusing various utilities. + * There is a curious interaction between how we allocate pty masters + * and how ttyname() works. It seems that if /dev/ptmx/clone is + * opened, a call to ptsname() on the master fd gets a filename of the + * form /dev/pty/tty[pqrs][0-9a-f], while ttyname() called on a fd + * opened with that filename returns a filename of the form + * /dev/tty[pqrs][0-9a-f] instead. These two filenames are actually + * hardlinks to the same special device node, so it shouldn't be a + * security problem. + * + * We can't call ttyname() in the parent because it would involve + * possibly acquiring a controlling terminal (which would be + * potentially problematic), so we have to resort to some trickery in + * order to ensure that the ut_line in the wtmp logout and login + * records match. If they don't match, various utilities such as last + * will get confused. Of course it's likely an OS bug that ttyname() + * and ptsname() are inconsistent in this way, but it's one that isn't + * too painful to work around. + * + * It seems that the HP-UX native telnetd has problems similar to ours + * in this area, though it manages to write the correct logout record + * to wtmp somehow. It probably does basically what we do here: + * search for a record with a matching ut_pid and grab its ut_line for + * writing into the logout record. Interestingly enough, its + * LOGIN_PROCESS record is of the form pty/tty[pqrs][0-9][a-f]. * * Uses four-character unique IDs for /etc/inittab, which means that * programs not running out of init should use two-character ut_id @@ -305,12 +325,14 @@ #ifdef HAVE_SETUTXENT #define PTY_STRUCT_UTMPX struct utmpx #define PTY_SETUTXENT setutxent +#define PTY_GETUTXENT getutxent #define PTY_GETUTXLINE getutxline #define PTY_PUTUTXLINE pututxline #define PTY_ENDUTXENT endutxent #else #define PTY_STRUCT_UTMPX struct utmp #define PTY_SETUTXENT setutent +#define PTY_GETUTXENT gettutent #define PTY_GETUTXLINE getutline #define PTY_PUTUTXLINE pututline #define PTY_ENDUTXENT endutent @@ -318,35 +340,42 @@ static int better(const PTY_STRUCT_UTMPX *, const PTY_STRUCT_UTMPX *, const PTY_STRUCT_UTMPX *); -static PTY_STRUCT_UTMPX *best_utxline(const PTY_STRUCT_UTMPX *); +static int match_pid(const PTY_STRUCT_UTMPX *, + const PTY_STRUCT_UTMPX *); +static PTY_STRUCT_UTMPX *best_utxent(const PTY_STRUCT_UTMPX *); /* * Utility function to determine whether A is a better match for - * SEARCH than B. Should only be called by best_utxline(). + * SEARCH than B. Should only be called by best_utxent(). */ static int better(const PTY_STRUCT_UTMPX *search, const PTY_STRUCT_UTMPX *a, const PTY_STRUCT_UTMPX *b) { + if (strncmp(search->ut_id, b->ut_id, sizeof(b->ut_id))) { + if (!strncmp(search->ut_id, a->ut_id, sizeof(a->ut_id))) { + return 1; + } + } + if (strncmp(a->ut_id, b->ut_id, sizeof(b->ut_id))) { - /* different UT_IDs; find the right one */ - if (a->ut_type == LOGIN_PROCESS) { - if (b->ut_type != LOGIN_PROCESS) { - /* prefer LOGIN_PROCESS */ - return 1; - } else if (search->ut_pid == a->ut_pid - && a->ut_pid != b->ut_pid) { - /* - * Prefer entry whose ut_pid matches that of SEARCH, - * if all else is the same. Note that this will fail - * in the case of login.krb5 called from krlogind, - * etc., since the login.krb5 will have a different - * pid from its parent. Consequently, we save this - * test for last, in order to catch the case of - * login.krb5 being called from getty. - */ - return 1; - } + /* Got different UT_IDs; find the right one. */ + if (!strncmp(search->ut_id, b->ut_id, sizeof(b->ut_id))) { + /* Old entry already matches; use it. */ + return 0; + } + if (a->ut_type == LOGIN_PROCESS + && b->ut_type != LOGIN_PROCESS) { + /* Prefer LOGIN_PROCESS */ + return 1; + } + if (search->ut_type == DEAD_PROCESS + && a->ut_type == USER_PROCESS + && b->ut_type != USER_PROCESS) { + /* + * Try USER_PROCESS if we're entering a DEAD_PROCESS. + */ + return 1; } return 0; } else { @@ -362,54 +391,96 @@ better(const PTY_STRUCT_UTMPX *search, } } +static int +match_pid(const PTY_STRUCT_UTMPX *search, const PTY_STRUCT_UTMPX *u) +{ + if (u->ut_type != LOGIN_PROCESS && u->ut_type != USER_PROCESS) + return 0; + if (u->ut_pid == search->ut_pid) { + /* + * One of ut_line or ut_id should match, else some nastiness + * may result. We can fall back to searching by ut_line if + * need be. This should only really break if we're login.krb5 + * running out of getty, or we're cleaning up after the vendor + * login, and either the vendor login or the getty has + * different ideas than we do of what both ut_id and ut_line + * should be. It should be rare, though. We may want to + * remove this restriction later. + */ + if (!strncmp(u->ut_line, search->ut_line, sizeof(u->ut_line))) + return 1; + if (!strncmp(u->ut_id, search->ut_id, sizeof(u->ut_id))) + return 1; + } + return 0; +} + /* * This expects to be called with SEARCH pointing to a struct utmpx * with its ut_type equal to USER_PROCESS or DEAD_PROCESS, since if * we're making a LOGIN_PROCESS entry, we presumably don't care about * preserving existing state. At the very least, the ut_pid, ut_line, - * and ut_type fields must be filled in by the caller. + * ut_id, and ut_type fields must be filled in by the caller. */ static PTY_STRUCT_UTMPX * -best_utxline(const PTY_STRUCT_UTMPX *search) +best_utxent(const PTY_STRUCT_UTMPX *search) { PTY_STRUCT_UTMPX utxtmp, *utxp; int i, best; - i = best = 0; memset(&utxtmp, 0, sizeof(utxtmp)); + /* + * First, search based on pid, but only if non-zero. + */ + if (search->ut_pid) { + i = 0; + PTY_SETUTXENT(); + while ((utxp = PTY_GETUTXENT()) != NULL) { + if (match_pid(search, utxp)) { + return utxp; + } + i++; + } + } + /* + * Uh-oh, someone didn't enter our pid. Try valiantly to search + * by terminal line. + */ + i = 0; + best = -1; PTY_SETUTXENT(); - utxp = PTY_GETUTXLINE(search); - if (utxp == NULL) - return NULL; - utxtmp = *utxp; - - for (;;) { - memset(utxp, 0, sizeof(*utxp)); - utxp = PTY_GETUTXLINE(search); - if (utxp == NULL) - break; - i++; + while ((utxp = PTY_GETUTXLINE(search)) != NULL) { if (better(search, utxp, &utxtmp)) { utxtmp = *utxp; best = i; } + memset(utxp, 0, sizeof(*utxp)); + i++; } + if (best == -1) + return NULL; PTY_SETUTXENT(); for (i = 0; i <= best; i++) { if (utxp != NULL) memset(utxp, 0, sizeof(*utxp)); utxp = PTY_GETUTXLINE(search); } - PTY_ENDUTXENT(); return utxp; } +/* + * All calls to this function for a given login session must have the + * pids be equal; various things will break if this is not the case, + * since we do some searching based on the pid. Note that if a parent + * process calls this via pty_cleanup(), it should still pass the + * child's pid rather than its own. + */ long pty_update_utmp(int process_type, int pid, const char *username, const char *line, const char *host, int flags) { - PTY_STRUCT_UTMPX utx, *utxtmp; + PTY_STRUCT_UTMPX utx, *utxtmp, utx2; const char *cp; size_t len; char utmp_id[5]; @@ -421,13 +492,6 @@ pty_update_utmp(int process_type, int pid, const char *username, memset(&utx, 0, sizeof(utx)); utxtmp = NULL; cp = line; - /* - * XXX For some reason HP-UX init uses a prefix of "pty/" when - * writing the process termination record to utmp and wtmp if the - * line is a pty. Not sure why. Native HP-UX telnetd appears to - * write its own process termination record without the "pty/" - * prefix, and init or whatever doesn't clean up after it. - */ if (strncmp(cp, "/dev/", sizeof("/dev/") - 1) == 0) cp += sizeof("/dev/") - 1; strncpy(utx.ut_line, cp, sizeof(utx.ut_line)); @@ -445,25 +509,45 @@ pty_update_utmp(int process_type, int pid, const char *username, default: return PTY_UPDATE_UTMP_PROCTYPE_INVALID; } + len = strlen(line); + if (len >= 2) { + cp = line + len - 1; + if (*(cp - 1) != '/') + cp--; /* last two characters, unless it's a / */ + } else + cp = line; /* - * Get existing utmpx entry for LINE, if any, so we can copy some - * stuff from it. This is particularly important if we're running - * out of getty, since getty will have written the entry for the - * line with ut_type == LOGIN_PROCESS, and what it has recorded in - * ut_id may not be what we come up with, since that's up to the - * whim of the sysadmin who writes the inittab entry. - * - * We make the assumption that getty constructs ut_line the same - * way that we do, which may be unwarranted. + * HP-UX has mostly 4-character inittab ids, while most other sysV + * variants use only 2-charcter inittab ids, so to avoid + * conflicts, we pick 2-character ut_ids for our own use. We may + * want to feature-test for this, but it would be somewhat of a + * pain, and would eit cross-compiling. + */ +#ifdef __hpux + strcpy(utmp_id, cp); +#else + sprintf(utmp_id, "kl%s", cp); +#endif + strncpy(utx.ut_id, utmp_id, sizeof(utx.ut_id)); + /* + * Get existing utmpx entry for PID or LINE, if any, so we can + * copy some stuff from it. This is particularly important if we + * are login.krb5 and are running out of getty, since getty will + * have written the entry for the line with ut_type == + * LOGIN_PROCESS, and what it has recorded in ut_id may not be + * what we come up with, since that's up to the whim of the + * sysadmin who writes the inittab entry. * - * It seems that getty will find its ut_id by means of searching - * for a utmpx entry of type INIT_PROCESS containing getty's pid - * in ut_pid, though that is largely conjecture at the moment. - * This should be irrelevant for this library, since none of its - * callers should attempt to be a replacement for getty. + * Note that we may be screwed if we try to write a logout record + * for a vendor's login program, since it may construct ut_line + * and ut_id differently from us; even though we search on ut_pid, + * we validate against ut_id or ut_line to sanity-check. We may + * want to rethink whether to actually include this check, since + * it should be highly unlikely that there will be a bogus entry + * in utmpx matching our pid. */ if (process_type != PTY_LOGIN_PROCESS) - utxtmp = best_utxline(&utx); + utxtmp = best_utxent(&utx); #ifdef HAVE_SETUTXENT if (gettimeofday(&utx.ut_tv, NULL)) @@ -480,7 +564,7 @@ pty_update_utmp(int process_type, int pid, const char *username, */ #if (defined(HAVE_SETUTXENT) && defined(HAVE_STRUCT_UTMPX_UT_HOST)) \ || (!defined(HAVE_SETUTXENT) && defined(HAVE_STRUCT_UTMP_UT_HOST)) - if (host) { + if (host != NULL) { strncpy(utx.ut_host, host, sizeof(utx.ut_host)); /* Unlike other things in utmpx, ut_host is nul-terminated? */ utx.ut_host[sizeof(utx.ut_host) - 1] = '\0'; @@ -497,8 +581,6 @@ pty_update_utmp(int process_type, int pid, const char *username, /* XXX deal with ut_addr? */ - utx.ut_id[0] = '\0'; - if (utxtmp != NULL) { /* * For entries not of type LOGIN_PROCESS, override some stuff @@ -508,29 +590,30 @@ pty_update_utmp(int process_type, int pid, const char *username, utx.ut_pid = utxtmp->ut_pid; } - if (utx.ut_id[0] == '\0') { - len = strlen(line); - if (len >= 2) { - cp = line + len - 1; - if (*(cp - 1) != '/') - cp--; /* last two characters, unless it's a / */ - } else - cp = line; + strncpy(utx.ut_user, username, sizeof(utx.ut_user)); + + /* + * Make a copy now and deal with copying relevant things out of + * utxtmp in case setutxline() or pututxline() clobbers utxtmp. + * (After all, the returned pointer from the getutx*() functions + * is allowed to point to static storage that may get overwritten + * by subsequent calls to related functions.) + */ + utx2 = utx; + if (process_type == PTY_DEAD_PROCESS && utxtmp != NULL) { /* - * HP-UX has mostly 4-character inittab ids, while most other - * sysV variants use only 2-charcter inittab ids, so to avoid - * conflicts, we pick 2-character ut_ids for our own use. We - * may want to feature-test for this, but it would be somewhat - * of a pain, and would eit cross-compiling. + * Use ut_line from old entry to avoid confusing last on + * HP-UX. */ -#ifdef __hpux - strcpy(utmp_id, cp); -#else - sprintf(utmp_id, "kl%s", cp); -#endif - strncpy(utx.ut_id, utmp_id, sizeof(utx.ut_id)); + strncpy(utx2.ut_line, utxtmp->ut_line, sizeof(utx2.ut_line)); + } + + if (username[0] == '\0' + && (flags & PTY_UTMP_USERNAME_VALID) && utxtmp != NULL) { + /* Use the ut_user from the entry we looked up, if any. */ + /* XXX Is this really necessary? */ + strncpy(utx2.ut_user, utxtmp->ut_user, sizeof(utx2.ut_user)); } - strncpy(utx.ut_user, username, sizeof(utx.ut_user)); PTY_SETUTXENT(); PTY_PUTUTXLINE(&utx); @@ -540,16 +623,10 @@ pty_update_utmp(int process_type, int pid, const char *username, if (process_type == PTY_LOGIN_PROCESS) return 0; - if (username[0] == '\0' - && (flags & PTY_UTMP_USERNAME_VALID) && utxtmp != NULL) - /* Use the ut_user from the entry we looked up, if any. */ - /* XXX Is this really necessary? */ - strncpy(utx.ut_user, utxtmp->ut_user, sizeof(utx.ut_user)); - #ifdef HAVE_SETUTXENT - return ptyint_update_wtmpx(&utx); + return ptyint_update_wtmpx(&utx2); #else - return ptyint_update_wtmp(&utx); + return ptyint_update_wtmp(&utx2); #endif } diff --git a/src/util/pty/void_assoc.c b/src/util/pty/void_assoc.c index a6ec33d75..4b7e26c5c 100644 --- a/src/util/pty/void_assoc.c +++ b/src/util/pty/void_assoc.c @@ -23,32 +23,27 @@ #include #include "libpty.h" #include "pty-int.h" -/* - * This routine will be called twice. It's not particularly important - * that the setsid() or TIOCSTTY ioctls succeed (they may not the - * second time), but rather that we have a controlling terminal at the - * end. It is assumed that vhangup doesn't exist and confuse the - * process's notion of controlling terminal on any system without - * TIOCNOTTY. That is, either vhangup() leaves the controlling - * terminal in tact, breaks the association completely, or the system - * provides TIOCNOTTY to get things back into a reasonable state. In - * practice, vhangup() either breaks the association completely or - * doesn't effect controlling terminals, so this condition is met. - */ -long ptyint_void_association() +/* + * This function gets called to set up the current process as a + * session leader (hence, can't be called except from a process that + * isn't already a session leader) and dissociates the controlling + * terminal (if any) from the session. + */ +long +ptyint_void_association(void) { - int con_fd; + int fd; #ifdef HAVE_SETSID (void) setsid(); #endif - - /* Void tty association first */ + /* Void tty association first */ #ifdef TIOCNOTTY - if ((con_fd = open("/dev/tty", O_RDWR)) >= 0) { - ioctl(con_fd, TIOCNOTTY, 0); - close(con_fd); - } + fd = open("/dev/tty", O_RDWR); + if (fd >= 0) { + ioctl(fd, TIOCNOTTY, 0); + close(fd); + } #endif - return 0; + return 0; }