summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Kaivo <jkk@ung.org>2019-07-18 13:21:47 -0400
committerJakob Kaivo <jkk@ung.org>2019-07-18 13:21:47 -0400
commit66b91392b453bfc602ac01de0de309031fd36833 (patch)
tree34c6de51412ca7ae8aed77002680b9dada4dc815
parent766d492d1ee9381ee0c266e0ce230f9b85d64891 (diff)
implement some basic functionality
-rw-r--r--who.c91
1 files changed, 84 insertions, 7 deletions
diff --git a/who.c b/who.c
index fc913f2..729e4a2 100644
--- a/who.c
+++ b/who.c
@@ -1,8 +1,11 @@
-#define _XOPEN_SOURCE
+#define _XOPEN_SOURCE 700
#include <locale.h>
#include <stdio.h>
#include <string.h>
+#include <sys/stat.h>
+#include <time.h>
#include <unistd.h>
+#include <utmpx.h>
enum {
BOOT = 1<<0,
@@ -18,6 +21,36 @@ enum {
IDLE = 1<<10,
};
+char * utmpx_time(const struct utmpx *u)
+{
+ static char dt[32];
+ time_t t = u->ut_tv.tv_sec;
+ struct tm *tm = localtime(&t);
+ strftime(dt, sizeof(dt), "%b %e %H:%M", tm);
+ return dt;
+}
+
+char utmpx_state(const struct utmpx *u)
+{
+ char term[FILENAME_MAX];
+ snprintf(term, sizeof(term), "/dev/%s", u->ut_line);
+ struct stat st;
+
+ if (stat(term, &st) == -1) {
+ return '?';
+ }
+
+ if ((st.st_mode & S_IFCHR) != S_IFCHR) {
+ return ' ';
+ }
+
+ if (S_IWGRP & st.st_mode) {
+ return '+';
+ }
+
+ return '-';
+}
+
int main(int argc, char *argv[])
{
int flags = 0;
@@ -64,7 +97,7 @@ int main(int argc, char *argv[])
break;
case 'q':
- flags |= QUICK;
+ flags = QUICK;
break;
case 'r':
@@ -92,10 +125,6 @@ int main(int argc, char *argv[])
}
}
- if (flags & QUICK) {
- flags = QUICK;
- }
-
if (flags == 0 && argc == optind + 2) {
if (strcmp("am", argv[optind]))
return 1;
@@ -104,9 +133,57 @@ int main(int argc, char *argv[])
return 1;
}
- printf("ok\n");
flags = SELF;
}
+ setutxent();
+ struct utmpx *u = NULL;
+ while ((u = getutxent()) != NULL) {
+ if (flags == QUICK) {
+ printf("%s\n", u->ut_user);
+ continue;
+ }
+
+ if (u->ut_type == BOOT_TIME) {
+ if (!(flags & BOOT)) {
+ continue;
+ }
+ u->ut_user[0] = '\0';
+ strcpy(u->ut_line, "system boot");
+ }
+
+ if (!strcmp(u->ut_user, "runlevel")) {
+ if (!(flags & RUNLEVEL)) {
+ continue;
+ }
+ u->ut_user[0] = '\0';
+ strcpy(u->ut_line, "run-level");
+ }
+
+ printf("%-12s\t", u->ut_user);
+
+ if (flags & TERMINAL) {
+ if (u->ut_user[0] == '\0') {
+ printf(" ");
+ } else {
+ printf("%c ", utmpx_state(u));
+ }
+ }
+
+ printf("%-8s\t", u->ut_line);
+
+ printf("%s", utmpx_time(u));
+
+ if ((flags & TERMINAL) && u->ut_user[0] != '\0') {
+ printf("\t");
+ /* activity */
+ printf("%d\t", u->ut_pid);
+ /* comment */
+ /* exit */
+ }
+
+ printf("\n");
+ }
+
return 0;
}