convert to 4.1c directory layout
[unix-history] / usr / src / usr.sbin / rwhod / rwhod.c
CommitLineData
52b4fb0c 1#ifndef lint
a0f59ac1 2static char sccsid[] = "@(#)rwhod.c 4.4 82/10/10";
52b4fb0c
BJ
3#endif
4
5#include <stdio.h>
6#include <signal.h>
7#include <sys/types.h>
8#include <net/in.h>
9#include <sys/socket.h>
10#include <errno.h>
11#include <utmp.h>
12#include "rwhod.h"
13#include <sys/stat.h>
14#include <nlist.h>
15#include <sys/ioctl.h>
a0f59ac1
SL
16#include <ctype.h>
17#include <netdb.h>
52b4fb0c 18
a0f59ac1 19struct sockaddr_in sin = { AF_INET };
52b4fb0c
BJ
20
21extern errno;
22
23char *localnet = "localnet";
24char *myname = "myname";
25
26struct nlist nl[] = {
27#define NL_AVENRUN 0
28 { "_avenrun" },
29#define NL_BOOTIME 1
30 { "_bootime" },
31 0
32};
33
34struct whod mywd;
35int s, utmpf, kmemf = -1;
36
37int onalrm();
38char *strcpy(), *sprintf();
39long lseek();
40int getkmem();
41
42main()
43{
44 struct sockaddr_in from;
45 char path[64];
46 int addr;
a0f59ac1 47 struct servent *sp;
52b4fb0c 48
a0f59ac1
SL
49 sp = getservbyname("who", "udp");
50 if (sp == 0) {
51 fprintf(stderr, "rwhod: udp/who: unknown service\n");
52 exit(1);
53 }
54#if vax || pdp11
55 sp->s_port = htons(sp->s_port);
56#endif
57 sin.sin_port = sp->s_port;
52b4fb0c
BJ
58#ifndef DEBUG
59 if (fork())
60 exit(0);
61 { int s;
62 for (s = 0; s < 10; s++)
63 (void) close(s);
64 (void) open("/", 0);
65 (void) dup2(0, 1);
66 (void) dup2(0, 2);
67 s = open("/dev/tty", 2);
68 if (s >= 0) {
69 ioctl(s, TIOCNOTTY, 0);
70 (void) close(s);
71 }
72 }
73#endif
74 (void) chdir("/dev");
75 (void) signal(SIGHUP, getkmem);
76 if (getuid()) {
a0f59ac1 77 fprintf(stderr, "rwhod: not super user\n");
52b4fb0c
BJ
78 exit(1);
79 }
80 addr = rhost(&localnet);
81 if (addr == -1) {
a0f59ac1 82 fprintf(stderr, "rwhod: no localnet\n");
52b4fb0c
BJ
83 exit(1);
84 }
85 sin.sin_addr.s_addr = addr;
86 if (rhost(&myname) == -1) {
a0f59ac1 87 fprintf(stderr, "rwhod: don't know \"myname\"\n");
52b4fb0c
BJ
88 exit(1);
89 }
90 strncpy(mywd.wd_hostname, myname, sizeof (mywd.wd_hostname) - 1);
91 utmpf = open("/etc/utmp", 0);
92 if (utmpf < 0) {
93 (void) close(creat("/etc/utmp", 0644));
94 utmpf = open("/etc/utmp", 0);
95 }
96 if (utmpf < 0) {
a0f59ac1 97 perror("rwhod: /etc/utmp");
52b4fb0c
BJ
98 exit(1);
99 }
100 getkmem();
52b4fb0c
BJ
101again:
102 if ((s = socket(SOCK_DGRAM, 0, &sin, 0)) < 0) {
a0f59ac1 103 perror("rwhod: socket");
52b4fb0c
BJ
104 sleep(5);
105 goto again;
106 }
107 sigset(SIGALRM, onalrm);
108 onalrm();
109 for (;;) {
110 struct whod wd;
111 int cc, whod;
112
113 cc = receive(s, &from, (char *)&wd, sizeof (struct whod));
114 if (cc <= 0) {
115 if (cc < 0 && errno != EINTR)
a0f59ac1 116 perror("rwhod: receive");
52b4fb0c
BJ
117 continue;
118 }
a0f59ac1
SL
119 if (from.sin_port != sp->s_port) {
120 fprintf(stderr, "rwhod: %d: bad from port\n",
121 ntohs(from.sin_port));
52b4fb0c
BJ
122 continue;
123 }
a0f59ac1
SL
124#ifdef notdef
125 if (gethostbyname(wd.wd_hostname) == 0) {
126 fprintf(stderr, "rwhod: %s: unknown host\n",
127 wd.wd_hostname);
128 continue;
129 }
130#endif
131 if (!verify(wd.wd_hostname)) {
132 fprintf(stderr, "rwhod: malformed host name from %x\n",
133 from.sin_addr);
52b4fb0c
BJ
134 continue;
135 }
52b4fb0c
BJ
136 (void) sprintf(path, "/etc/whod.%s", wd.wd_hostname);
137 whod = creat(path, 0666);
138 if (whod < 0) {
a0f59ac1
SL
139 fprintf(stderr, "rwhod: ");
140 perror(path);
52b4fb0c
BJ
141 continue;
142 }
143 (void) time(&wd.wd_recvtime);
144 (void) write(whod, (char *)&wd, cc);
145 (void) close(whod);
146 }
147}
148
a0f59ac1
SL
149/*
150 * Check out host name for unprintables
151 * and other funnies before allowing a file
152 * to be created. Sorry, but blanks aren't allowed.
153 */
154verify(name)
155 register char *name;
156{
157 register int size = 0;
158
159 while (*name) {
160 if (!isascii(*name) || !isalnum(*name))
161 return (0);
162 name++, size++;
163 }
164 return (size > 0);
165}
166
52b4fb0c
BJ
167int utmptime;
168int utmpent;
76886f32 169struct utmp utmp[100];
52b4fb0c
BJ
170int alarmcount;
171
172onalrm()
173{
174 register int i;
175 struct stat stb;
76886f32 176 register struct whoent *we = mywd.wd_we, *wlast;
52b4fb0c
BJ
177 int cc;
178 double avenrun[3];
179 time_t now = time(0);
180
181 if (alarmcount % 10 == 0)
182 getkmem();
183 alarmcount++;
184 (void) fstat(utmpf, &stb);
185 if (stb.st_mtime != utmptime) {
186 (void) lseek(utmpf, (long)0, 0);
187 cc = read(utmpf, (char *)utmp, sizeof (utmp));
188 if (cc < 0) {
189 perror("/etc/utmp");
190 return;
191 }
76886f32 192 wlast = &mywd.wd_we[(1024 / sizeof (struct whoent)) - 1];
52b4fb0c
BJ
193 utmpent = cc / sizeof (struct utmp);
194 for (i = 0; i < utmpent; i++)
195 if (utmp[i].ut_name[0]) {
196 we->we_utmp = utmp[i];
76886f32
SL
197 if (we >= wlast)
198 break;
52b4fb0c
BJ
199 we++;
200 }
201 utmpent = we - mywd.wd_we;
202 }
203 we = mywd.wd_we;
204 for (i = 0; i < utmpent; i++) {
205 if (stat(we->we_utmp.ut_line, &stb) >= 0)
206 we->we_idle = now - stb.st_atime;
207 we++;
208 }
209 (void) lseek(kmemf, (long)nl[NL_AVENRUN].n_value, 0);
210 (void) read(kmemf, (char *)avenrun, sizeof (avenrun));
211 for (i = 0; i < 3; i++)
212 mywd.wd_loadav[i] = avenrun[i] * 100;
213 cc = (char *)we - (char *)&mywd;
214 (void) time(&mywd.wd_sendtime);
215 send(s, &sin, (char *)&mywd, cc);
216 (void) alarm(60);
217}
218
219getkmem()
220{
221 struct nlist *nlp;
222
223 signal(SIGHUP, getkmem);
224 if (kmemf >= 0)
225 (void) close(kmemf);
226loop:
227 for (nlp = &nl[sizeof (nl) / sizeof (nl[0])]; --nlp >= nl; ) {
228 nlp->n_value = 0;
229 nlp->n_type = 0;
230 }
231 nlist("/vmunix", nl);
232 if (nl[0].n_value == 0) {
233 fprintf(stderr, "/vmunix namelist botch\n");
234 sleep(300);
235 goto loop;
236 }
237 kmemf = open("/dev/kmem", 0);
238 if (kmemf < 0) {
239 perror("/dev/kmem");
240 sleep(300);
241 goto loop;
242 }
243 (void) lseek(kmemf, (long)nl[NL_BOOTIME].n_value, 0);
244 (void) read(kmemf, (char *)&mywd.wd_bootime, sizeof (mywd.wd_bootime));
245}