Changeset View
Changeset View
Standalone View
Standalone View
usr.bin/who/who.c
Show First 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | |||||
#include <pwd.h> | #include <pwd.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <time.h> | #include <time.h> | ||||
#include <timeconv.h> | #include <timeconv.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
#include <utmpx.h> | #include <utmpx.h> | ||||
#include <libxo/xo.h> | |||||
static void heading(void); | static void heading(void); | ||||
static void process_utmp(void); | static void process_utmp(void); | ||||
static void quick(void); | static void quick(void); | ||||
static void row(const struct utmpx *); | static void row(const struct utmpx *); | ||||
static int ttywidth(void); | static int ttywidth(void); | ||||
static void usage(void); | static void usage(void); | ||||
static void whoami(void); | static void whoami(void); | ||||
Show All 9 Lines | |||||
int | int | ||||
main(int argc, char *argv[]) | main(int argc, char *argv[]) | ||||
{ | { | ||||
int ch; | int ch; | ||||
setlocale(LC_TIME, ""); | setlocale(LC_TIME, ""); | ||||
argc = xo_parse_args(argc, argv); | |||||
while ((ch = getopt(argc, argv, "HTabmqsu")) != -1) { | while ((ch = getopt(argc, argv, "HTabmqsu")) != -1) { | ||||
switch (ch) { | switch (ch) { | ||||
case 'H': /* Write column headings */ | case 'H': /* Write column headings */ | ||||
Hflag = 1; | Hflag = 1; | ||||
break; | break; | ||||
case 'T': /* Show terminal state */ | case 'T': /* Show terminal state */ | ||||
Tflag = 1; | Tflag = 1; | ||||
break; | break; | ||||
Show All 33 Lines | main(int argc, char *argv[]) | ||||
if (argc > 1) | if (argc > 1) | ||||
usage(); | usage(); | ||||
if (*argv != NULL) { | if (*argv != NULL) { | ||||
if (setutxdb(UTXDB_ACTIVE, *argv) != 0) | if (setutxdb(UTXDB_ACTIVE, *argv) != 0) | ||||
err(1, "%s", *argv); | err(1, "%s", *argv); | ||||
} | } | ||||
if (qflag) | xo_open_container("who"); | ||||
if (qflag) { | |||||
quick(); | quick(); | ||||
else { | } else { | ||||
if (sflag) | if (sflag) | ||||
Tflag = uflag = 0; | Tflag = uflag = 0; | ||||
if (Hflag) | if (Hflag) | ||||
heading(); | heading(); | ||||
xo_open_list("entry"); | |||||
if (mflag) | if (mflag) | ||||
whoami(); | whoami(); | ||||
else | else | ||||
process_utmp(); | process_utmp(); | ||||
xo_close_list("entry"); | |||||
} | } | ||||
endutxent(); | endutxent(); | ||||
xo_close_container("who"); | |||||
xo_finish(); | |||||
exit(0); | exit(0); | ||||
} | } | ||||
static void | static void | ||||
usage(void) | usage(void) | ||||
{ | { | ||||
fprintf(stderr, "usage: who [-abHmqsTu] [am I] [file]\n"); | xo_error("usage: who [-abHmqsTu] [am I] [file]\n"); | ||||
xo_finish(); | |||||
exit(1); | exit(1); | ||||
} | } | ||||
static void | static void | ||||
heading(void) | heading(void) | ||||
{ | { | ||||
printf("%-16s ", "NAME"); | if (xo_get_style(NULL) == XO_STYLE_TEXT) { | ||||
xo_emit("{:headingname/%-16s} ", "NAME"); | |||||
if (Tflag) | if (Tflag) | ||||
printf("S "); | xo_emit("%s", "S "); | ||||
jlduran_gmail.com: This should be changed to `xo_emit("{:headingstate/%s}", "S ");` | |||||
printf("%-12s %-12s ", "LINE", "TIME"); | xo_emit("{:headingline/%-12s} {:headingtime/%-12s} ", "LINE", "TIME"); | ||||
if (uflag) | if (uflag) | ||||
printf("IDLE "); | xo_emit("{:idle/%s}", "IDLE "); | ||||
jlduran_gmail.comUnsubmitted Not Done Inline ActionsI believe this should be :headingidle jlduran_gmail.com: I believe this should be `:headingidle` | |||||
printf("%-16s\n", "FROM"); | xo_emit("{:headingfrom/%-16s}\n", "FROM"); | ||||
} | } | ||||
} | |||||
static void | static void | ||||
row(const struct utmpx *ut) | row(const struct utmpx *ut) | ||||
{ | { | ||||
char buf[80], tty[PATH_MAX]; | char buf[80], tty[PATH_MAX]; | ||||
struct stat sb; | struct stat sb; | ||||
time_t idle, t; | time_t idle, t; | ||||
static int d_first = -1; | static int d_first = -1; | ||||
struct tm *tm; | struct tm *tm; | ||||
char state; | char state; | ||||
xo_open_instance("entry"); | |||||
if (d_first < 0) | if (d_first < 0) | ||||
d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); | d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); | ||||
state = '?'; | state = '?'; | ||||
idle = 0; | idle = 0; | ||||
if (Tflag || uflag) { | if (Tflag || uflag) { | ||||
snprintf(tty, sizeof(tty), "%s%s", _PATH_DEV, ut->ut_line); | snprintf(tty, sizeof(tty), "%s%s", _PATH_DEV, ut->ut_line); | ||||
if (stat(tty, &sb) == 0) { | if (stat(tty, &sb) == 0) { | ||||
state = sb.st_mode & (S_IWOTH|S_IWGRP) ? | state = sb.st_mode & (S_IWOTH|S_IWGRP) ? | ||||
'+' : '-'; | '+' : '-'; | ||||
idle = time(NULL) - sb.st_mtime; | idle = time(NULL) - sb.st_mtime; | ||||
} | } | ||||
} | } | ||||
printf("%-16s ", ut->ut_user); | if (xo_get_style(NULL) != XO_STYLE_TEXT) | ||||
if (Tflag) | xo_emit("{:name/%s}", ut->ut_user); | ||||
printf("%c ", state); | else | ||||
xo_emit("{:name/%-16s} ", ut->ut_user); | |||||
if (Tflag) { | |||||
if (xo_get_style(NULL) != XO_STYLE_TEXT) { | |||||
xo_emit("{:state/%c}", state); | |||||
} else { | |||||
xo_emit("{:state/%c} ", state); | |||||
} | |||||
} | |||||
if (ut->ut_type == BOOT_TIME) | if (ut->ut_type == BOOT_TIME) | ||||
printf("%-12s ", "system boot"); | if (xo_get_style(NULL) != XO_STYLE_TEXT) | ||||
xo_emit("{:line/%s}", "system boot"); | |||||
else | else | ||||
printf("%-12s ", ut->ut_line); | xo_emit("{:line/%-12s} ", "system boot"); | ||||
else | |||||
if (xo_get_style(NULL) != XO_STYLE_TEXT) | |||||
xo_emit("{:line/%s}", ut->ut_line); | |||||
else | |||||
xo_emit("{:line/%-12s} ", ut->ut_line); | |||||
t = ut->ut_tv.tv_sec; | t = ut->ut_tv.tv_sec; | ||||
tm = localtime(&t); | tm = localtime(&t); | ||||
strftime(buf, sizeof(buf), d_first ? "%e %b %R" : "%b %e %R", tm); | strftime(buf, sizeof(buf), d_first ? "%e %b %R" : "%b %e %R", tm); | ||||
printf("%-*s ", 12, buf); | if (xo_get_style(NULL) != XO_STYLE_TEXT) | ||||
if (uflag) { | xo_emit("{:time/%s}", buf); | ||||
if (idle < 60) | |||||
printf(" . "); | |||||
else if (idle < 24 * 60 * 60) | |||||
printf("%02d:%02d ", (int)(idle / 60 / 60), | |||||
(int)(idle / 60 % 60)); | |||||
else | else | ||||
printf(" old "); | xo_emit("{:time/%-12s} ", buf); | ||||
if (uflag) { | |||||
if (idle < 60) { | |||||
if (xo_get_style(NULL) != XO_STYLE_TEXT) { | |||||
xo_emit("{:idle/%s}", "."); | |||||
} else { | |||||
xo_emit("{:idle/%s}", " . "); | |||||
} | } | ||||
if (*ut->ut_host != '\0') | } else if (idle < 24 * 60 * 60) { | ||||
printf("(%s)", ut->ut_host); | if (xo_get_style(NULL) != XO_STYLE_TEXT) { | ||||
putchar('\n'); | xo_emit("{:idle/%02d:%02d}", (int)(idle / 60 / 60), (int)(idle / 60 % 60)); | ||||
} else { | |||||
xo_emit("{:idle/%02d:%02d} ", (int)(idle / 60 / 60), (int)(idle / 60 % 60)); | |||||
} | } | ||||
} else { | |||||
if (xo_get_style(NULL) != XO_STYLE_TEXT) { | |||||
xo_emit("{:idle/%s}", "old"); | |||||
} else { | |||||
xo_emit("{:idle/%s}", " old "); | |||||
} | |||||
} | |||||
} | |||||
if (*ut->ut_host != '\0') { | |||||
xo_emit("{:host/(%s)}", ut->ut_host); | |||||
} else { | |||||
xo_emit("{:host/%s}", ""); | |||||
} | |||||
if (xo_get_style(NULL) == XO_STYLE_TEXT) | |||||
xo_emit("\n"); | |||||
xo_close_instance("entry"); | |||||
} | |||||
static int | static int | ||||
ttystat(char *line) | ttystat(char *line) | ||||
{ | { | ||||
struct stat sb; | struct stat sb; | ||||
char ttybuf[MAXPATHLEN]; | char ttybuf[MAXPATHLEN]; | ||||
if (line == NULL) | if (line == NULL) | ||||
Show All 22 Lines | |||||
static void | static void | ||||
quick(void) | quick(void) | ||||
{ | { | ||||
struct utmpx *utx; | struct utmpx *utx; | ||||
int col, ncols, num; | int col, ncols, num; | ||||
ncols = ttywidth(); | ncols = ttywidth(); | ||||
col = num = 0; | col = num = 0; | ||||
xo_open_list("entry"); | |||||
while ((utx = getutxent()) != NULL) { | while ((utx = getutxent()) != NULL) { | ||||
if (utx->ut_type != USER_PROCESS) | if (utx->ut_type != USER_PROCESS) | ||||
continue; | continue; | ||||
printf("%-16s", utx->ut_user); | xo_open_instance("entry"); | ||||
if (xo_get_style(NULL) == XO_STYLE_TEXT) | |||||
xo_emit("{:name/%-16s}", utx->ut_user); | |||||
else | |||||
xo_emit("{:name/%s}", utx->ut_user); | |||||
if (xo_get_style(NULL) == XO_STYLE_TEXT) { | |||||
if (++col < ncols / (16 + 1)) | if (++col < ncols / (16 + 1)) | ||||
putchar(' '); | xo_emit(" "); | ||||
else { | else { | ||||
col = 0; | col = 0; | ||||
putchar('\n'); | xo_emit("\n"); | ||||
} | } | ||||
} | |||||
num++; | num++; | ||||
xo_close_instance("entry"); | |||||
} | } | ||||
if (col != 0) | if (col != 0) | ||||
putchar('\n'); | xo_emit("\n"); | ||||
printf("# users = %d\n", num); | xo_close_list("entry"); | ||||
xo_emit("# users = {:users/%d}\n", num); | |||||
} | } | ||||
static void | static void | ||||
whoami(void) | whoami(void) | ||||
{ | { | ||||
struct utmpx ut, *utx; | struct utmpx ut, *utx; | ||||
struct passwd *pwd; | struct passwd *pwd; | ||||
const char *name, *tty; | const char *name, *tty; | ||||
Show All 28 Lines | ttywidth(void) | ||||
long width; | long width; | ||||
char *cols, *ep; | char *cols, *ep; | ||||
if ((cols = getenv("COLUMNS")) != NULL && *cols != '\0') { | if ((cols = getenv("COLUMNS")) != NULL && *cols != '\0') { | ||||
errno = 0; | errno = 0; | ||||
width = strtol(cols, &ep, 10); | width = strtol(cols, &ep, 10); | ||||
if (errno || width <= 0 || width > INT_MAX || ep == cols || | if (errno || width <= 0 || width > INT_MAX || ep == cols || | ||||
*ep != '\0') | *ep != '\0') | ||||
warnx("invalid COLUMNS environment variable ignored"); | xo_warnx("invalid COLUMNS environment variable ignored"); | ||||
else | else | ||||
return (width); | return (width); | ||||
} | } | ||||
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1) | if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1) | ||||
return (ws.ws_col); | return (ws.ws_col); | ||||
return (80); | return (80); | ||||
} | } |
This should be changed to xo_emit("{:headingstate/%s}", "S ");