1/* See LICENSE file for copyright and license details. */
2
3
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include <time.h>
8#include <unistd.h>
9#include <utmp.h>
10
11#include "config.h"
12#include "util.h"
13
14static void
15usage(void)
16{
17 eprintf("usage: %s [-ml]\n", argv0);
18}
19
20// ?man who: show logged in users
21// ?man display a list of users currently logged into the system
22int
23main(int argc, char *argv[])
24{
25 struct utmp usr;
26 FILE *ufp;
27 char timebuf[sizeof "yyyy-mm-dd hh:mm"];
28 char line_buf[sizeof(usr.ut_line) + 1];
29 char name_buf[sizeof(usr.ut_name) + 1];
30 char *tty, *ttmp;
31 int mflag = 0, lflag = 0;
32 time_t t;
33
34 ARGBEGIN {
35 // ?man -m: specify mode or limit
36 case 'm':
37 mflag = 1;
38 tty = ttyname(0);
39 if (!tty)
40 eprintf("ttyname: stdin:");
41 if ((ttmp = strrchr(tty, '/')))
42 tty = ttmp+1;
43 break;
44 // ?man -l: list in long format
45 case 'l':
46 lflag = 1;
47 break;
48 default:
49 usage();
50 } ARGEND;
51
52 if (argc > 0)
53 usage();
54
55 if (!(ufp = fopen(UTMP_PATH, "r")))
56 eprintf("fopen: %s:", UTMP_PATH);
57
58 while (fread(&usr, sizeof(usr), 1, ufp) == 1) {
59 memcpy(line_buf, usr.ut_line, sizeof(usr.ut_line));
60 line_buf[sizeof(usr.ut_line)] = '\0';
61 memcpy(name_buf, usr.ut_name, sizeof(usr.ut_name));
62 name_buf[sizeof(usr.ut_name)] = '\0';
63
64 if (!*name_buf || !*line_buf ||
65 line_buf[0] == '~')
66 continue;
67 if (mflag != 0 && strcmp(line_buf, tty) != 0)
68 continue;
69 if (!!strcmp(name_buf, "LOGIN") == lflag)
70 continue;
71 t = usr.ut_time;
72 strftime(timebuf, sizeof timebuf, "%Y-%m-%d %H:%M", localtime(&t));
73 printf("%-8s %-12s %-16s\n", name_buf, line_buf, timebuf);
74 }
75 fclose(ufp);
76 return 0;
77}