]>
git.saurik.com Git - apple/shell_cmds.git/blob - who/who.c
2 * Copyright (c) 2002 Tim J. Robbins.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include <sys/cdefs.h>
28 /* commented as FBSDID not needed for Tiger ......
29 __FBSDID("$FreeBSD: src/usr.bin/who/who.c,v 1.20 2003/10/26 05:05:48 peter Exp $");
32 #include <sys/types.h>
33 #include <sys/ioctl.h>
51 static void heading(void);
52 static void process_utmp(FILE *);
53 static void process_wtmp(FILE *);
54 static void quick(FILE *);
55 static void row(struct utmp
*);
56 static int ttywidth(void);
57 static void usage(void);
58 static void whoami(FILE *);
60 static int bflag
; /* date & time of last reboot */
61 static int dflag
; /* dead processes */
62 static int Hflag
; /* Write column headings */
63 static int lflag
; /* waiting to login */
64 static int mflag
; /* Show info about current terminal */
65 static int pflag
; /* Processes active & spawned by init */
66 static int qflag
; /* "Quick" mode */
67 static int rflag
; /* run-level of the init process */
68 static int sflag
; /* Show name, line, time */
69 static int tflag
; /* time of change to system clock */
70 static int Tflag
; /* Show terminal state */
71 static int uflag
; /* Show idle time */
74 main(int argc
, char *argv
[])
81 setlocale(LC_TIME
, "");
83 while ((ch
= getopt(argc
, argv
, "abdHlmpqrstTu")) != -1) {
86 case 'a': /* -b, -d, -l, -p, -r, -t, -T and -u */
87 bflag
= dflag
= lflag
= pflag
= 1;
88 rflag
= tflag
= Tflag
= uflag
= 1;
90 case 'b': /* date & time of last reboot */
93 case 'd': /* dead processes */
96 case 'H': /* Write column headings */
99 case 'l': /* waiting to login */
102 case 'm': /* Show info about current terminal */
105 case 'p': /* Processes active & spawned by init */
108 case 'q': /* "Quick" mode */
111 case 'r': /* run-level of the init process */
114 case 's': /* Show name, line, time */
117 case 't': /* time of change to system clock */
120 case 'T': /* Show terminal state */
123 case 'u': /* Show idle time */
134 if (argc
>= 2 && strcmp(argv
[0], "am") == 0 &&
135 (strcmp(argv
[1], "i") == 0 || strcmp(argv
[1], "I") == 0)) {
136 /* "who am i" or "who am I", equivalent to -m */
148 if ((fp
= fopen(file
, "r")) == NULL
)
161 /* read and process utmp file for relevant options */
162 if( Tflag
|| uflag
|| !(bflag
|| dflag
|| lflag
|| pflag
|| rflag
) )
168 /* read and process wtmp file for relevant options */
169 if (bflag
|| dflag
|| lflag
|| pflag
|| rflag
) {
171 /* Open the wtmp file */
172 if ((wtmp_fp
= fopen(_PATH_WTMP
, "r")) == NULL
)
173 err(1, "%s", _PATH_WTMP
);
175 process_wtmp(wtmp_fp
);
187 fprintf(stderr
, "usage: who [-abdHlmpqrstTu] [am I] [file]\n");
195 printf("%-*s ", UT_NAMESIZE
, "NAME");
198 printf("%-*s ", UT_LINESIZE
, "LINE");
199 printf("%-*s ", 12, "TIME");
202 printf("%-*s", UT_HOSTSIZE
, "FROM");
209 char buf
[80], tty
[sizeof(_PATH_DEV
) + UT_LINESIZE
];
212 static int d_first
= -1;
217 d_first
= (*nl_langinfo(D_MD_ORDER
) == 'd');
219 if (Tflag
|| uflag
) {
220 snprintf(tty
, sizeof(tty
), "%s%.*s", _PATH_DEV
,
221 UT_LINESIZE
, ut
->ut_line
);
224 if (stat(tty
, &sb
) == 0) {
225 state
= sb
.st_mode
& (S_IWOTH
|S_IWGRP
) ?
227 idle
= time(NULL
) - sb
.st_mtime
;
231 printf("%-*.*s ", UT_NAMESIZE
, UT_NAMESIZE
, ut
->ut_name
);
233 printf("%c ", state
);
234 printf("%-*.*s ", UT_LINESIZE
, UT_LINESIZE
, ut
->ut_line
);
235 t
= _time32_to_time(ut
->ut_time
);
237 strftime(buf
, sizeof(buf
), d_first
? "%e %b %R" : "%b %e %R", tm
);
238 printf("%-*s ", 12, buf
);
242 else if (idle
< 24 * 60 * 60)
243 printf("%02d:%02d ", (int)(idle
/ 60 / 60),
244 (int)(idle
/ 60 % 60));
248 if (*ut
->ut_host
!= '\0')
249 printf("(%.*s)", UT_HOSTSIZE
, ut
->ut_host
);
255 process_utmp(FILE *fp
)
259 while (fread(&ut
, sizeof(ut
), 1, fp
) == 1)
260 if (*ut
.ut_name
!= '\0') {
265 /* For some options, process the wtmp file to generate output */
267 process_wtmp(FILE *fp
)
270 struct utmp lboot_ut
= { "", "", "", 0 };
271 int num
= 0; /* count of user entries */
273 while (fread(&ut
, sizeof(ut
), 1, fp
) == 1)
274 if (*ut
.ut_name
!= '\0') {
275 if (bflag
&& (!strcmp(ut
.ut_name
, "reboot"))) {
276 memcpy(&lboot_ut
, &ut
, sizeof(ut
));
282 if (bflag
&& (!strcmp(lboot_ut
.ut_name
, "reboot")))
285 /* run level of the init process is unknown in BSD system. If multi
286 user, then display the highest run level. Else, no-op.
288 if (rflag
&& (num
> 1))
289 printf(" . run-level 3\n");
300 while (fread(&ut
, sizeof(ut
), 1, fp
) == 1) {
301 if (*ut
.ut_name
== '\0')
303 printf("%-*.*s", UT_NAMESIZE
, UT_NAMESIZE
, ut
.ut_name
);
304 if (++col
< ncols
/ (UT_NAMESIZE
+ 1))
315 printf("# users = %d\n", num
);
323 const char *name
, *p
, *tty
;
325 if ((tty
= ttyname(STDIN_FILENO
)) == NULL
)
327 else if ((p
= strrchr(tty
, '/')) != NULL
)
330 /* Search utmp for our tty, dump first matching record. */
331 while (fread(&ut
, sizeof(ut
), 1, fp
) == 1)
332 if (*ut
.ut_name
!= '\0' && strncmp(ut
.ut_line
, tty
,
338 /* Not found; fill the utmp structure with the information we have. */
339 memset(&ut
, 0, sizeof(ut
));
340 if ((pwd
= getpwuid(getuid())) != NULL
)
344 strncpy(ut
.ut_name
, name
, UT_NAMESIZE
);
345 strncpy(ut
.ut_line
, tty
, UT_LINESIZE
);
346 ut
.ut_time
= _time_to_time32(time(NULL
));
357 if ((cols
= getenv("COLUMNS")) != NULL
&& *cols
!= '\0') {
359 width
= strtol(cols
, &ep
, 10);
360 if (errno
|| width
<= 0 || width
> INT_MAX
|| ep
== cols
||
362 warnx("invalid COLUMNS environment variable ignored");
366 if (ioctl(STDOUT_FILENO
, TIOCGWINSZ
, &ws
) != -1)