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