xref: /original-bsd/usr.bin/last/last.c (revision d25e1985)
1 static char *sccsid = "@(#)last.c	4.1 (Berkeley) 10/01/80";
2 /*
3  * last
4  */
5 #include <sys/types.h>
6 #include <stdio.h>
7 #include <signal.h>
8 #include <stat.h>
9 #include <utmp.h>
10 
11 #define NMAX	sizeof(buf[0].ut_name)
12 #define LMAX	sizeof(buf[0].ut_line)
13 #define	SECDAY	(24*60*60)
14 
15 #define	lineq(a,b)	(!strncmp(a,b,LMAX))
16 #define	nameq(a,b)	(!strncmp(a,b,NMAX))
17 
18 #define MAXTTYS 256
19 
20 char	**argv;
21 int	argc;
22 
23 struct	utmp buf[128];
24 char	ttnames[MAXTTYS][LMAX+1];
25 long	logouts[MAXTTYS];
26 
27 char	*ctime(), *strspl();
28 int	onintr();
29 
30 main(ac, av)
31 	char **av;
32 {
33 	register int i, k;
34 	int bl, wtmp;
35 	char *ct;
36 	register struct utmp *bp;
37 	long otime;
38 	struct stat stb;
39 	int print;
40 
41 	time(&buf[0].ut_time);
42 	ac--, av++;
43 	argc = ac;
44 	argv = av;
45 	for (i = 0; i < argc; i++) {
46 		if (strlen(argv[i])>2)
47 			continue;
48 		if (!strcmp(argv[i], "~"))
49 			continue;
50 		if (getpwnam(argv[i]))
51 			continue;
52 		argv[i] = strspl("tty", argv[i]);
53 	}
54 	wtmp = open("/usr/adm/wtmp", 0);
55 	if (wtmp < 0) {
56 		perror("/usr/adm/wtmp");
57 		exit(1);
58 	}
59 	fstat(wtmp, &stb);
60 	bl = (stb.st_size + sizeof (buf)-1) / sizeof (buf);
61 	if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
62 		signal(SIGINT, onintr);
63 		signal(SIGQUIT, onintr);
64 	}
65 	for (bl--; bl >= 0; bl--) {
66 		lseek(wtmp, bl * sizeof (buf), 0);
67 		bp = &buf[read(wtmp, buf, sizeof (buf)) / sizeof(buf[0]) - 1];
68 		for ( ; bp >= buf; bp--) {
69 			print = want(bp);
70 			if (print) {
71 				ct = ctime(&bp->ut_time);
72 				printf("%-*.*s  %-*.*s  %10.10s %5.5s ",
73 				    NMAX, NMAX, bp->ut_name,
74 				    LMAX, LMAX, bp->ut_line, ct, 11+ct);
75 			}
76 			for (i = 0; i < MAXTTYS; i++) {
77 				if (ttnames[i][0] == 0) {
78 					strncpy(ttnames[i], bp->ut_line,
79 					    sizeof(bp->ut_line));
80 					otime = 0;
81 					logouts[i] = bp->ut_time;
82 					break;
83 				}
84 				if (lineq(ttnames[i], bp->ut_line)) {
85 					otime = logouts[i];
86 					logouts[i] = bp->ut_time;
87 					break;
88 				}
89 			}
90 			if (print) {
91 				if (otime == 0)
92 					printf("  still logged in\n");
93 				else {
94 					long delta;
95 					if (otime < 0) {
96 						otime = -otime;
97 						printf("- crash");
98 					} else
99 						printf("- %5.5s",
100 						    ctime(&otime)+11);
101 					delta = otime - bp->ut_time;
102 					if (delta < SECDAY)
103 					    printf("  (%5.5s)\n",
104 						asctime(gmtime(&delta))+11);
105 					else
106 					    printf(" (%ld+%5.5s)\n",
107 						delta / SECDAY,
108 						asctime(gmtime(&delta))+11);
109 				}
110 				fflush(stdout);
111 			}
112 			if (lineq(bp->ut_line, "~") ||
113 			    lineq(bp->ut_line, "tty~"))
114 				for (i = 0; *ttnames[i] && i < MAXTTYS; i++)
115 					logouts[i] = -bp->ut_time;
116 		}
117 	}
118 	ct = ctime(&buf[0].ut_time);
119 	printf("\nwtmp begins %10.10s %5.5s \n", ct, ct + 11);
120 	exit(0);
121 }
122 
123 onintr(signo)
124 	int signo;
125 {
126 	char *ct;
127 
128 	if (signo == SIGQUIT)
129 		signal(SIGQUIT, onintr);
130 	ct = ctime(&buf[0].ut_time);
131 	printf("\ninterrupted %10.10s %5.5s \n", ct, ct + 11);
132 	if (signo == SIGINT)
133 		exit(1);
134 }
135 
136 want(bp)
137 	struct utmp *bp;
138 {
139 	register char **av;
140 	register int ac;
141 
142 	if (bp->ut_line[0] == '~')
143 		strcpy(bp->ut_name, "reboot");		/* bandaid */
144 	if (bp->ut_name[0] == 0)
145 		return (0);
146 	if (argc == 0)
147 		return (1);
148 	av = argv;
149 	for (ac = 0; ac < argc; ac++) {
150 		if (nameq(*av, bp->ut_name) || lineq(*av, bp->ut_line))
151 			return (1);
152 		av++;
153 	}
154 	return (0);
155 }
156 
157 char *
158 strspl(left, right)
159 	char *left, *right;
160 {
161 	char *res = (char *)malloc(strlen(left)+strlen(right)+1);
162 
163 	strcpy(res, left);
164 	strcat(res, right);
165 	return (res);
166 }
167