Annotation of src/usr.bin/rwho/rwho.c, Revision 1.19
1.19 ! martynas 1: /* $OpenBSD: rwho.c,v 1.18 2013/11/27 13:32:02 okan Exp $ */
1.2 deraadt 2:
1.1 deraadt 3: /*
4: * Copyright (c) 1983 The Regents of the University of California.
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
1.15 millert 15: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 16: * may be used to endorse or promote products derived from this software
17: * without specific prior written permission.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29: * SUCH DAMAGE.
30: */
31:
1.12 pjanzen 32: #include <sys/types.h>
1.1 deraadt 33: #include <sys/param.h>
34: #include <sys/file.h>
35: #include <dirent.h>
36: #include <protocols/rwhod.h>
37: #include <stdio.h>
38: #include <string.h>
1.3 deraadt 39: #include <unistd.h>
40: #include <stdlib.h>
1.12 pjanzen 41: #include <time.h>
1.11 deraadt 42: #include <utmp.h>
1.8 deraadt 43: #include <vis.h>
1.9 deraadt 44: #include <err.h>
1.1 deraadt 45:
46: DIR *dirp;
47:
48: struct whod wd;
49: #define NUSERS 1000
50: struct myutmp {
51: char myhost[MAXHOSTNAMELEN];
52: int myidle;
1.13 millert 53: struct {
54: char out_line[9]; /* tty name + NUL */
55: char out_name[9]; /* user id + NUL */
56: int32_t out_time; /* time on */
57: } myutmp;
1.1 deraadt 58: } myutmp[NUSERS];
59: int nusers;
60:
1.13 millert 61: int utmpcmp(const void *, const void *);
62: __dead void usage(void);
1.3 deraadt 63:
1.13 millert 64: #define WHDRSIZE (sizeof(wd) - sizeof(wd.wd_we))
1.1 deraadt 65: /*
66: * this macro should be shared with ruptime.
67: */
68: #define down(w,now) ((now) - (w)->wd_recvtime > 11 * 60)
69:
70: time_t now;
71: int aflg;
72:
1.3 deraadt 73: int
1.13 millert 74: main(int argc, char **argv)
1.1 deraadt 75: {
76: int ch;
77: struct dirent *dp;
78: int cc, width;
1.13 millert 79: struct whod *w = &wd;
80: struct whoent *we;
81: struct myutmp *mp;
1.1 deraadt 82: int f, n, i;
1.6 deraadt 83: int nhosts = 0;
1.1 deraadt 84:
1.5 millert 85: while ((ch = getopt(argc, argv, "a")) != -1)
1.18 okan 86: switch(ch) {
1.1 deraadt 87: case 'a':
88: aflg = 1;
89: break;
90: default:
1.10 deraadt 91: usage();
1.1 deraadt 92: }
1.10 deraadt 93: argc -= optind;
94: argv += optind;
95: if (argc != 0)
96: usage();
97:
1.13 millert 98: if (chdir(_PATH_RWHODIR) || (dirp = opendir(".")) == NULL)
99: err(1, _PATH_RWHODIR);
1.1 deraadt 100: mp = myutmp;
101: (void)time(&now);
1.3 deraadt 102: while ((dp = readdir(dirp))) {
1.1 deraadt 103: if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5))
104: continue;
105: f = open(dp->d_name, O_RDONLY);
106: if (f < 0)
107: continue;
1.13 millert 108: cc = read(f, &wd, sizeof(struct whod));
1.1 deraadt 109: if (cc < WHDRSIZE) {
1.13 millert 110: (void)close(f);
1.1 deraadt 111: continue;
112: }
1.6 deraadt 113: nhosts++;
1.1 deraadt 114: if (down(w,now)) {
1.13 millert 115: (void)close(f);
1.1 deraadt 116: continue;
117: }
118: cc -= WHDRSIZE;
119: we = w->wd_we;
1.13 millert 120: for (n = cc / sizeof(struct whoent); n > 0; n--) {
1.1 deraadt 121: if (aflg == 0 && we->we_idle >= 60*60) {
122: we++;
123: continue;
124: }
1.12 pjanzen 125: if (nusers >= NUSERS)
126: errx(1, "too many users");
1.19 ! martynas 127: strncpy(mp->myhost, w->wd_hostname,
1.3 deraadt 128: sizeof(mp->myhost)-1);
129: mp->myhost[sizeof(mp->myhost)-1] = '\0';
1.13 millert 130: mp->myidle = we->we_idle;
131: /*
132: * Copy we->we_utmp by hand since the name and line
133: * variables in myutmp have room for NUL (unlike outmp).
134: */
135: memcpy(mp->myutmp.out_line, we->we_utmp.out_line,
136: sizeof(mp->myutmp.out_line)-1);
137: mp->myutmp.out_line[sizeof(mp->myutmp.out_line)-1] = 0;
138: memcpy(mp->myutmp.out_name, we->we_utmp.out_name,
139: sizeof(mp->myutmp.out_name)-1);
140: mp->myutmp.out_name[sizeof(mp->myutmp.out_name)-1] = 0;
141: mp->myutmp.out_time = we->we_utmp.out_time;
1.1 deraadt 142: nusers++; we++; mp++;
143: }
1.13 millert 144: (void)close(f);
1.1 deraadt 145: }
1.6 deraadt 146: if (nhosts == 0)
147: errx(0, "no hosts in %s.", _PATH_RWHODIR);
1.13 millert 148: qsort(myutmp, nusers, sizeof(struct myutmp), utmpcmp);
1.1 deraadt 149: mp = myutmp;
150: width = 0;
151: for (i = 0; i < nusers; i++) {
152: int j = strlen(mp->myhost) + 1 + strlen(mp->myutmp.out_line);
153: if (j > width)
154: width = j;
155: mp++;
156: }
157: mp = myutmp;
158: for (i = 0; i < nusers; i++) {
1.14 vincent 159: char buf[BUFSIZ], vis_user[4 * sizeof(mp->myutmp.out_name) + 1];
1.17 deraadt 160: time_t t;
1.13 millert 161:
162: (void)snprintf(buf, sizeof(buf), "%s:%s", mp->myhost,
1.7 deraadt 163: mp->myutmp.out_line);
1.14 vincent 164: strnvis(vis_user, mp->myutmp.out_name, sizeof vis_user,
165: VIS_CSTYLE);
1.17 deraadt 166: t = mp->myutmp.out_time; /* XXX 2038 */
1.11 deraadt 167: printf("%-*.*s %-*s %.12s",
1.13 millert 168: UT_NAMESIZE, UT_NAMESIZE, vis_user, width, buf,
1.17 deraadt 169: ctime(&t)+4);
1.1 deraadt 170: mp->myidle /= 60;
171: if (mp->myidle) {
172: if (aflg) {
173: if (mp->myidle >= 100*60)
174: mp->myidle = 100*60 - 1;
175: if (mp->myidle >= 60)
176: printf(" %2d", mp->myidle / 60);
177: else
178: printf(" ");
179: } else
180: printf(" ");
181: printf(":%02d", mp->myidle % 60);
182: }
183: printf("\n");
184: mp++;
185: }
186: exit(0);
187: }
188:
1.3 deraadt 189: int
1.13 millert 190: utmpcmp(const void *v1, const void *v2)
1.1 deraadt 191: {
192: int rc;
1.13 millert 193: const struct myutmp *u1 = (struct myutmp *)v1;
194: const struct myutmp *u2 = (struct myutmp *)v2;
1.1 deraadt 195:
196: rc = strncmp(u1->myutmp.out_name, u2->myutmp.out_name, 8);
197: if (rc)
198: return (rc);
199: rc = strncmp(u1->myhost, u2->myhost, 8);
200: if (rc)
201: return (rc);
202: return (strncmp(u1->myutmp.out_line, u2->myutmp.out_line, 8));
1.13 millert 203: }
204:
205: void
206: usage(void)
207: {
208: extern char *__progname;
209:
210: fprintf(stderr, "usage: %s [-a]\n", __progname);
211: exit(1);
1.1 deraadt 212: }