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