Commit | Line | Data |
---|---|---|
52b4fb0c | 1 | #ifndef lint |
76886f32 | 2 | static char sccsid[] = "@(#)rwhod.c 4.3 82/04/20"; |
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> | |
16 | ||
17 | struct sockaddr_in sin = { AF_INET, IPPORT_WHOSERVER }; | |
18 | ||
19 | extern errno; | |
20 | ||
21 | char *localnet = "localnet"; | |
22 | char *myname = "myname"; | |
23 | ||
24 | struct nlist nl[] = { | |
25 | #define NL_AVENRUN 0 | |
26 | { "_avenrun" }, | |
27 | #define NL_BOOTIME 1 | |
28 | { "_bootime" }, | |
29 | 0 | |
30 | }; | |
31 | ||
32 | struct whod mywd; | |
33 | int s, utmpf, kmemf = -1; | |
34 | ||
35 | int onalrm(); | |
36 | char *strcpy(), *sprintf(); | |
37 | long lseek(); | |
38 | int getkmem(); | |
39 | ||
40 | main() | |
41 | { | |
42 | struct sockaddr_in from; | |
43 | char path[64]; | |
44 | int addr; | |
45 | ||
46 | #ifndef DEBUG | |
47 | if (fork()) | |
48 | exit(0); | |
49 | { int s; | |
50 | for (s = 0; s < 10; s++) | |
51 | (void) close(s); | |
52 | (void) open("/", 0); | |
53 | (void) dup2(0, 1); | |
54 | (void) dup2(0, 2); | |
55 | s = open("/dev/tty", 2); | |
56 | if (s >= 0) { | |
57 | ioctl(s, TIOCNOTTY, 0); | |
58 | (void) close(s); | |
59 | } | |
60 | } | |
61 | #endif | |
62 | (void) chdir("/dev"); | |
63 | (void) signal(SIGHUP, getkmem); | |
64 | if (getuid()) { | |
65 | fprintf(stderr, "not super user\n"); | |
66 | exit(1); | |
67 | } | |
68 | addr = rhost(&localnet); | |
69 | if (addr == -1) { | |
70 | fprintf(stderr, "no localnet for whod\n"); | |
71 | exit(1); | |
72 | } | |
73 | sin.sin_addr.s_addr = addr; | |
74 | if (rhost(&myname) == -1) { | |
75 | fprintf(stderr, "don't know my name\n"); | |
76 | exit(1); | |
77 | } | |
78 | strncpy(mywd.wd_hostname, myname, sizeof (mywd.wd_hostname) - 1); | |
79 | utmpf = open("/etc/utmp", 0); | |
80 | if (utmpf < 0) { | |
81 | (void) close(creat("/etc/utmp", 0644)); | |
82 | utmpf = open("/etc/utmp", 0); | |
83 | } | |
84 | if (utmpf < 0) { | |
85 | perror("/etc/utmp"); | |
86 | exit(1); | |
87 | } | |
88 | getkmem(); | |
89 | #ifdef vax | |
90 | sin.sin_port = htons(sin.sin_port); | |
91 | #endif | |
92 | again: | |
93 | if ((s = socket(SOCK_DGRAM, 0, &sin, 0)) < 0) { | |
94 | perror("socket"); | |
95 | sleep(5); | |
96 | goto again; | |
97 | } | |
98 | sigset(SIGALRM, onalrm); | |
99 | onalrm(); | |
100 | for (;;) { | |
101 | struct whod wd; | |
102 | int cc, whod; | |
103 | ||
104 | cc = receive(s, &from, (char *)&wd, sizeof (struct whod)); | |
105 | if (cc <= 0) { | |
106 | if (cc < 0 && errno != EINTR) | |
107 | perror("receive"); | |
108 | continue; | |
109 | } | |
110 | #ifdef vax | |
111 | from.sin_port = ntohs(from.sin_port); | |
112 | #endif | |
113 | if (from.sin_port != IPPORT_WHOSERVER) { | |
114 | printf("bad from port %d\n", from.sin_port); | |
115 | continue; | |
116 | } | |
117 | /* | |
118 | if (rhost(&wd.wd_hostname) == -1) { | |
119 | printf("unknown host %s\n", wd.wd_hostname); | |
120 | continue; | |
121 | } | |
122 | */ | |
123 | (void) sprintf(path, "/etc/whod.%s", wd.wd_hostname); | |
124 | whod = creat(path, 0666); | |
125 | if (whod < 0) { | |
126 | printf("can't create %s\n", path); | |
127 | continue; | |
128 | } | |
129 | (void) time(&wd.wd_recvtime); | |
130 | (void) write(whod, (char *)&wd, cc); | |
131 | (void) close(whod); | |
132 | } | |
133 | } | |
134 | ||
135 | int utmptime; | |
136 | int utmpent; | |
76886f32 | 137 | struct utmp utmp[100]; |
52b4fb0c BJ |
138 | int alarmcount; |
139 | ||
140 | onalrm() | |
141 | { | |
142 | register int i; | |
143 | struct stat stb; | |
76886f32 | 144 | register struct whoent *we = mywd.wd_we, *wlast; |
52b4fb0c BJ |
145 | int cc; |
146 | double avenrun[3]; | |
147 | time_t now = time(0); | |
148 | ||
149 | if (alarmcount % 10 == 0) | |
150 | getkmem(); | |
151 | alarmcount++; | |
152 | (void) fstat(utmpf, &stb); | |
153 | if (stb.st_mtime != utmptime) { | |
154 | (void) lseek(utmpf, (long)0, 0); | |
155 | cc = read(utmpf, (char *)utmp, sizeof (utmp)); | |
156 | if (cc < 0) { | |
157 | perror("/etc/utmp"); | |
158 | return; | |
159 | } | |
76886f32 | 160 | wlast = &mywd.wd_we[(1024 / sizeof (struct whoent)) - 1]; |
52b4fb0c BJ |
161 | utmpent = cc / sizeof (struct utmp); |
162 | for (i = 0; i < utmpent; i++) | |
163 | if (utmp[i].ut_name[0]) { | |
164 | we->we_utmp = utmp[i]; | |
76886f32 SL |
165 | if (we >= wlast) |
166 | break; | |
52b4fb0c BJ |
167 | we++; |
168 | } | |
169 | utmpent = we - mywd.wd_we; | |
170 | } | |
171 | we = mywd.wd_we; | |
172 | for (i = 0; i < utmpent; i++) { | |
173 | if (stat(we->we_utmp.ut_line, &stb) >= 0) | |
174 | we->we_idle = now - stb.st_atime; | |
175 | we++; | |
176 | } | |
177 | (void) lseek(kmemf, (long)nl[NL_AVENRUN].n_value, 0); | |
178 | (void) read(kmemf, (char *)avenrun, sizeof (avenrun)); | |
179 | for (i = 0; i < 3; i++) | |
180 | mywd.wd_loadav[i] = avenrun[i] * 100; | |
181 | cc = (char *)we - (char *)&mywd; | |
182 | (void) time(&mywd.wd_sendtime); | |
183 | send(s, &sin, (char *)&mywd, cc); | |
184 | (void) alarm(60); | |
185 | } | |
186 | ||
187 | getkmem() | |
188 | { | |
189 | struct nlist *nlp; | |
190 | ||
191 | signal(SIGHUP, getkmem); | |
192 | if (kmemf >= 0) | |
193 | (void) close(kmemf); | |
194 | loop: | |
195 | for (nlp = &nl[sizeof (nl) / sizeof (nl[0])]; --nlp >= nl; ) { | |
196 | nlp->n_value = 0; | |
197 | nlp->n_type = 0; | |
198 | } | |
199 | nlist("/vmunix", nl); | |
200 | if (nl[0].n_value == 0) { | |
201 | fprintf(stderr, "/vmunix namelist botch\n"); | |
202 | sleep(300); | |
203 | goto loop; | |
204 | } | |
205 | kmemf = open("/dev/kmem", 0); | |
206 | if (kmemf < 0) { | |
207 | perror("/dev/kmem"); | |
208 | sleep(300); | |
209 | goto loop; | |
210 | } | |
211 | (void) lseek(kmemf, (long)nl[NL_BOOTIME].n_value, 0); | |
212 | (void) read(kmemf, (char *)&mywd.wd_bootime, sizeof (mywd.wd_bootime)); | |
213 | } |