/* utmp.c Shareware Copyright by Sam Lantinga 10/6/93 */ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <utmp.h> #include <stdio.h> #ifdef DEBUG #undef UTMP_FILE #define UTMP_FILE "/tmp/utmp" #else #ifndef UTMP_FILE #define UTMP_FILE "/etc/utmp" #endif /* UTMP_FILE */ #endif /* DEBUG */ char utmp_name[14]; /* Temporary storage for the utmp user */ char utmp_host[64]; /* Temporary storage for the ut_host field */ time_t utmp_time; /* Temporary storage for the login time */ /* Remove us from the utmp file, saving our entry to replace later */ static char tmphost[64]; /* Temporary storage for our ut_host field */ static char tmpuser[14]; /* Temporary storage for our utmp user */ static time_t tmptime; /* Temporary storage for our login time */ static char tmptty[64]; /* Temporary storage for our tty name */ int remove_me() { struct stat sb; char *tmpptr; utmp_host[0]='\0'; utmp_time=0; tmphost[0]='\0'; tmptime=0L; tmpuser[0]='\0'; tmptty[0]='\0'; if ( (! isatty(0)) || ((tmpptr=(char *)ttyname(0)) == NULL) ) return(-1); if ( utmp(tmpptr, "", NULL, 0L, 1) < 0 ) return(-1); strcpy(tmpuser, utmp_name); strcpy(tmptty, tmpptr); strcpy(tmphost, utmp_host); tmptime=utmp_time; return(0); } /* You MUST call this AFTER you call remove_me() */ int replace_me() { return(utmp(tmptty, tmpuser, tmphost, tmptime, 0)); } /* Set up a utmp entry and tty for a user and a tty */ int addutmp(user, uid, tty) char *user; /* The user to add to the utmp file */ int uid; /* The uid corresponding to user */ char *tty; /* /dev/ttyxx */ { struct stat sb; time_t now; int retval; /* Add the utmp entry */ (void) time(&now); retval=utmp(tty, user, NULL, now, 0); /* Change the ownership and mode of the tty */ if ( stat(tty, &sb) == 0 ) { (void) chmod(tty, 0640); /* crw--w---- */ (void) chown(tty, uid, sb.st_gid); } return(retval); } /* End a utmp entry and tty for a user and a tty */ int delutmp(user, tty) char *user; char *tty; /* /dev/ttyxx */ { struct stat sb; time_t now; int retval; /* Add the utmp entry */ (void) time(&now); retval=utmp(tty, user, NULL, now, 1); if ( stat(tty, &sb) == 0 ) { (void) chmod(tty, 0666); /* crw-rw-rw- */ (void) chown(tty, 0, sb.st_gid); } return(retval); } /* This utmp function was adapted from pty's logs.c */ int utmp(line, name, host, date, cleanup) char *line; char name[]; char *host; time_t date; int cleanup; { struct utmp ut; struct utmp xt; char *lineptr; int fd, found=0; if ( (fd=open(UTMP_FILE, O_RDWR)) < 0 ) return(-1); /* Initialize the utmp structure */ d_zero((char *)&ut, sizeof(struct utmp)); /* Get the ttyxy form of the tty pathname if possible. */ if ( *line == '/' ) { for ( lineptr=(line+1); *lineptr; ++lineptr ) { if ( *lineptr == '/' ) break; } if ( *lineptr == '/' ) ++lineptr; } else lineptr=line; (void) strncpy(ut.ut_line, lineptr, sizeof(ut.ut_line)); if ( cleanup ) { ut.ut_name[0]='\0'; #ifdef USER_PROCESS ut.ut_type = DEAD_PROCESS; #endif } else { #ifdef USER_PROCESS ut.ut_type = USER_PROCESS; ut.ut_pid = getpid(); #endif strncpy(ut.ut_name, name, sizeof(ut.ut_name)); } ut.ut_time=date; #ifdef HAVE_UTHOST if ( ! cleanup && host ) strncpy(ut.ut_host, host, sizeof(ut.ut_host)); else ut.ut_host[0]='\0'; #endif while (read(fd,(char *) &xt, sizeof(xt)) == sizeof(xt)) { if (strncmp(xt.ut_line, ut.ut_line, sizeof(xt.ut_line)) == 0) { #ifdef HAVE_UTHOST /* Save the host entry */ strcpy(utmp_host, xt.ut_host); #else utmp_host[0]='\0'; #endif /* Save the login time and user name */ utmp_time=xt.ut_time; strcpy(utmp_name, xt.ut_name); /* Break out; we've found our entry! */ found=1; lseek(fd, -(long)sizeof(struct utmp), 1); break; } } /* Add a new entry to the utmp file if we can't find our entry */ if ( (!found) && (!cleanup) ) { /* Reopen to avoid a race with other end-of-utmp entries. */ (void) close(fd); if ( (fd=open(UTMP_FILE, (O_RDWR|O_APPEND))) < 0 ) return -1; } if (write(fd, (char *) &ut, sizeof(ut)) < sizeof(ut)) { (void) close(fd); return -1; } return(close(fd)); }