utmpset.c (2867B)
1 #include <fcntl.h> 2 #include <time.h> 3 #include <sys/types.h> 4 #include <sys/stat.h> 5 #include <unistd.h> 6 #include <string.h> 7 #include <utmp.h> 8 #include "strerr.h" 9 #include "sgetopt.h" 10 #include "seek.h" 11 #include "str.h" 12 #include "open.h" 13 #include "byte.h" 14 #include "lock.h" 15 16 #define USAGE " [-w] line" 17 #define FATAL "utmpset: fatal: " 18 #define WARNING "utmpset: warning: " 19 20 static const char *progname; 21 22 static void usage(void) { strerr_die4x(1, "usage: ", progname, USAGE, "\n"); } 23 24 static int utmp_logout(const char *line) 25 { 26 int fd; 27 struct utmp ut; 28 time_t t; 29 int ok =-1; 30 31 if ((fd =open(UTMP_FILE, O_RDWR, 0)) < 0) 32 strerr_die4sys(111, FATAL, "unable to open ", UTMP_FILE, ": "); 33 if (lock_ex(fd) == -1) 34 strerr_die4sys(111, FATAL, "unable to lock: ", UTMP_FILE, ": "); 35 36 while (read(fd, &ut, sizeof(struct utmp)) == sizeof(struct utmp)) { 37 if (!ut.ut_name[0] || (str_diff(ut.ut_line, line) != 0)) continue; 38 memset(ut.ut_name, 0, sizeof ut.ut_name); 39 memset(ut.ut_host, 0, sizeof ut.ut_host); 40 if (time(&t) == -1) break; 41 ut.ut_time = t; 42 #ifdef DEAD_PROCESS 43 ut.ut_type =DEAD_PROCESS; 44 #endif 45 if (lseek(fd, -(off_t)sizeof(struct utmp), SEEK_CUR) == -1) break; 46 if (write(fd, &ut, sizeof(struct utmp)) != sizeof(struct utmp)) break; 47 ok =1; 48 break; 49 } 50 close(fd); 51 return(ok); 52 } 53 static int wtmp_logout(const char *line) 54 { 55 int fd; 56 int len; 57 struct stat st; 58 struct utmp ut; 59 time_t t; 60 61 if ((fd = open_append(WTMP_FILE)) == -1) 62 strerr_die4sys(111, FATAL, "unable to open ", WTMP_FILE, ": "); 63 if (lock_ex(fd) == -1) 64 strerr_die4sys(111, FATAL, "unable to lock ", WTMP_FILE, ": "); 65 66 if (fstat(fd, &st) == -1) { 67 close(fd); 68 return(-1); 69 } 70 memset(&ut, 0, sizeof(struct utmp)); 71 if ((len =str_len(line)) > sizeof ut.ut_line) len =sizeof ut.ut_line -2; 72 byte_copy(ut.ut_line, len, line); 73 if (time(&t) == -1) { 74 close(fd); 75 return(-1); 76 } 77 ut.ut_time = t; 78 #ifdef DEAD_PROCESS 79 ut.ut_type =DEAD_PROCESS; 80 #endif 81 if (write(fd, &ut, sizeof(struct utmp)) != sizeof(struct utmp)) { 82 ftruncate(fd, st.st_size); 83 close(fd); 84 return(-1); 85 } 86 close(fd); 87 return(1); 88 } 89 90 int main (int argc, const char * const *argv, const char * const *envp) 91 { 92 int opt; 93 int wtmp =0; 94 95 progname =*argv; 96 97 while ((opt =getopt(argc, argv, "wV")) != opteof) { 98 switch(opt) { 99 case 'w': 100 wtmp =1; 101 break; 102 case 'V': 103 strerr_warn1(VERSION, 0); 104 __attribute__((fallthrough)); 105 case '?': 106 usage(); 107 } 108 } 109 argv +=optind; 110 111 if (! argv || ! *argv) usage(); 112 if (utmp_logout(*argv) == -1) 113 strerr_die4x(111, WARNING, "unable to logout line ", *argv, 114 " in utmp: no such entry"); 115 if (wtmp) 116 if (wtmp_logout(*argv) == -1) 117 strerr_die4sys(111, WARNING, 118 "unable to logout line ", *argv, " in wtmp: "); 119 _exit(0); 120 }