1/* See LICENSE file for copyright and license details. */
2
3#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
6#include <time.h>
7#include <unistd.h>
8#include <utmp.h>
9
10#include "config.h"
11#include "util.h"
12
13static void
14usage(void)
15{
16 eprintf("usage: %s [-ml]\n", argv0);
17}
18
19// ?man who: show logged in users
20// ?man display a list of users currently logged into the system
21int
22main(int argc, char *argv[])
23{
24 struct utmp usr;
25 FILE *ufp;
26 char timebuf[sizeof "yyyy-mm-dd hh:mm"];
27 char line_buf[sizeof(usr.ut_line) + 1];
28 char name_buf[sizeof(usr.ut_name) + 1];
29 char *tty, *ttmp;
30 int mflag = 0, lflag = 0;
31 time_t t;
32
33 ARGBEGIN
34 {
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 }
51 ARGEND;
52
53 if (argc > 0)
54 usage();
55
56 if (!(ufp = fopen(UTMP_PATH, "r")))
57 eprintf("fopen: %s:", UTMP_PATH);
58
59 while (fread(&usr, sizeof(usr), 1, ufp) == 1) {
60 memcpy(line_buf, usr.ut_line, sizeof(usr.ut_line));
61 line_buf[sizeof(usr.ut_line)] = '\0';
62 memcpy(name_buf, usr.ut_name, sizeof(usr.ut_name));
63 name_buf[sizeof(usr.ut_name)] = '\0';
64
65 if (!*name_buf || !*line_buf || 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}