master xplshn/aruu / cmd / posix / who.c
 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}