BSD 4 release
[unix-history] / usr / src / cmd / init.c
CommitLineData
31cef89c 1static char *sccsid = "@(#)init.c 4.3 (Berkeley) 10/13/80";
7c8ab0e6
BJ
2#include <signal.h>
3#include <sys/types.h>
4#include <utmp.h>
5#include <setjmp.h>
215943cc 6#include <sys/reboot.h>
7c8ab0e6
BJ
7
8#define LINSIZ sizeof(wtmp.ut_line)
9#define TABSIZ 100
10#define ALL p = &itab[0]; p < &itab[TABSIZ]; p++
11#define EVER ;;
12#define SCPYN(a, b) strncpy(a, b, sizeof(a))
13#define SCMPN(a, b) strncmp(a, b, sizeof(a))
14
15char shell[] = "/bin/sh";
215943cc 16char getty[] = "/etc/getty";
7c8ab0e6
BJ
17char minus[] = "-";
18char runc[] = "/etc/rc";
19char ifile[] = "/etc/ttys";
20char utmp[] = "/etc/utmp";
21char wtmpf[] = "/usr/adm/wtmp";
22char ctty[] = "/dev/console";
23char dev[] = "/dev/";
24
25struct utmp wtmp;
26struct
27{
28 char line[LINSIZ];
29 char comn;
30 char flag;
31} line;
32struct tab
33{
34 char line[LINSIZ];
35 char comn;
36 char xflag;
37 int pid;
38} itab[TABSIZ];
39
40int fi;
41int mergflag;
42char tty[20];
abf0db3c 43jmp_buf sjbuf, shutpass;
7c8ab0e6
BJ
44
45int reset();
46char *strcpy(), *strcat();
47long lseek();
48
49main()
50{
215943cc
BJ
51 register int r11; /* passed thru from boot */
52 int howto, oldhowto;
53
54 howto = r11;
7c8ab0e6
BJ
55 setjmp(sjbuf);
56 signal(SIGTERM, reset);
57 signal(SIGSTOP, SIG_IGN);
58 signal(SIGTSTP, SIG_IGN);
59 signal(SIGTTIN, SIG_IGN);
60 signal(SIGTTOU, SIG_IGN);
61 for(EVER) {
215943cc
BJ
62 oldhowto = howto;
63 howto = RB_SINGLE;
abf0db3c
BJ
64 if (setjmp(shutpass) == 0)
65 shutdown();
215943cc
BJ
66 if (oldhowto & RB_SINGLE)
67 single();
68 if (runcom(oldhowto) == 0)
69 continue;
7c8ab0e6
BJ
70 merge();
71 multiple();
72 }
73}
74
abf0db3c
BJ
75int shutreset();
76
7c8ab0e6
BJ
77shutdown()
78{
79 register i;
80 register struct tab *p;
81
82 close(creat(utmp, 0644));
83 signal(SIGHUP, SIG_IGN);
84 for(ALL) {
85 term(p);
86 p->line[0] = 0;
87 }
abf0db3c
BJ
88 signal(SIGALRM, shutreset);
89 alarm(30);
7c8ab0e6
BJ
90 for(i=0; i<5; i++)
91 kill(-1, SIGKILL);
92 while(wait((int *)0) != -1)
93 ;
94 alarm(0);
abf0db3c
BJ
95 shutend();
96}
97
98char shutfailm[] = "WARNING: Something is hung (wont die); ps axl advised\n";
99
100shutreset()
101{
102 int status;
103
104 if (fork() == 0) {
105 int ct = open(ctty, 1);
106 write(ct, shutfailm, sizeof (shutfailm));
107 sleep(5);
108 exit(1);
109 }
110 sleep(5);
111 shutend();
112 longjmp(shutpass, 1);
113}
114
115shutend()
116{
117 register i;
118
7c8ab0e6
BJ
119 signal(SIGALRM, SIG_DFL);
120 for(i=0; i<10; i++)
121 close(i);
122}
123
124single()
125{
126 register pid;
127
128 pid = fork();
129 if(pid == 0) {
130/*
131 alarm(300);
132*/
133 signal(SIGTERM, SIG_DFL);
134 signal(SIGHUP, SIG_DFL);
135 signal(SIGALRM, SIG_DFL);
136 open(ctty, 2);
137 dup(0);
138 dup(0);
139 execl(shell, minus, (char *)0);
140 exit(0);
141 }
142 while(wait((int *)0) != pid)
143 ;
144}
145
215943cc
BJ
146runcom(oldhowto)
147 int oldhowto;
7c8ab0e6
BJ
148{
149 register pid, f;
215943cc 150 int status;
7c8ab0e6
BJ
151
152 pid = fork();
153 if(pid == 0) {
154 open("/", 0);
155 dup(0);
156 dup(0);
215943cc
BJ
157 if (oldhowto & RB_SINGLE)
158 execl(shell, shell, runc, (char *)0);
159 else
160 execl(shell, shell, runc, "autoboot", (char *)0);
161 exit(1);
7c8ab0e6 162 }
215943cc 163 while(wait(&status) != pid)
7c8ab0e6 164 ;
215943cc
BJ
165 if(status)
166 return(0);
7c8ab0e6
BJ
167 f = open(wtmpf, 1);
168 if (f >= 0) {
169 lseek(f, 0L, 2);
170 SCPYN(wtmp.ut_line, "~");
171 SCPYN(wtmp.ut_name, "reboot");
172 time(&wtmp.ut_time);
173 write(f, (char *)&wtmp, sizeof(wtmp));
174 close(f);
175 }
215943cc 176 return(1);
7c8ab0e6
BJ
177}
178
179setmerge()
180{
181
182 signal(SIGHUP, setmerge);
183 mergflag = 1;
184}
185
186multiple()
187{
188 register struct tab *p;
189 register pid;
190
191loop:
192 mergflag = 0;
193 signal(SIGHUP, setmerge);
194 for(EVER) {
195 pid = wait((int *)0);
196 if(mergflag) {
197 merge();
198 goto loop;
199 }
200 if(pid == -1)
201 return;
202 for(ALL)
203 if(p->pid == pid || p->pid == -1) {
204 rmut(p);
205 dfork(p);
206 }
207 }
208}
209
210term(p)
211register struct tab *p;
212{
213
214 if(p->pid != 0) {
215 rmut(p);
216 kill(p->pid, SIGKILL);
217 }
218 p->pid = 0;
219}
220
221rline()
222{
223 register c, i;
224
225loop:
226 c = get();
227 if(c < 0)
228 return(0);
229 if(c == 0)
230 goto loop;
231 line.flag = c;
232 c = get();
233 if(c <= 0)
234 goto loop;
235 line.comn = c;
236 SCPYN(line.line, "");
237 for (i=0; i<LINSIZ; i++) {
238 c = get();
239 if(c <= 0)
240 break;
241 line.line[i] = c;
242 }
243 while(c > 0)
244 c = get();
245 if(line.line[0] == 0)
246 goto loop;
247 if(line.flag == '0')
248 goto loop;
249 strcpy(tty, dev);
250 strncat(tty, line.line, LINSIZ);
251 if(access(tty, 06) < 0)
252 goto loop;
253 return(1);
254}
255
256get()
257{
258 char b;
259
260 if(read(fi, &b, 1) != 1)
261 return(-1);
262 if(b == '\n')
263 return(0);
264 return(b);
265}
266
267#define FOUND 1
268#define CHANGE 2
269
270merge()
271{
272 register struct tab *p;
273
274 fi = open(ifile, 0);
275 if(fi < 0)
276 return;
277 for(ALL)
278 p->xflag = 0;
279 while(rline()) {
280 for(ALL) {
281 if (SCMPN(p->line, line.line))
282 continue;
283 p->xflag |= FOUND;
284 if(line.comn != p->comn) {
285 p->xflag |= CHANGE;
286 p->comn = line.comn;
287 }
288 goto contin1;
289 }
290 for(ALL) {
291 if(p->line[0] != 0)
292 continue;
293 SCPYN(p->line, line.line);
294 p->xflag |= FOUND|CHANGE;
295 p->comn = line.comn;
296 goto contin1;
297 }
298 contin1:
299 ;
300 }
301 close(fi);
302 for(ALL) {
303 if((p->xflag&FOUND) == 0) {
304 term(p);
305 p->line[0] = 0;
306 }
307 if((p->xflag&CHANGE) != 0) {
308 term(p);
309 dfork(p);
310 }
311 }
312}
313
314dfork(p)
315struct tab *p;
316{
317 register pid;
318
319 pid = fork();
320 if(pid == 0) {
321 signal(SIGTERM, SIG_DFL);
322 signal(SIGHUP, SIG_IGN);
323 strcpy(tty, dev);
324 strncat(tty, p->line, LINSIZ);
325 chown(tty, 0, 0);
326 chmod(tty, 0622);
327 open(tty, 2);
328 vhangup();
329 signal(SIGHUP, SIG_DFL);
330 open(tty, 2);
331 close(0);
332 dup(1);
333 dup(0);
334 tty[0] = p->comn;
335 tty[1] = 0;
336 execl(getty, minus, tty, (char *)0);
337 exit(0);
338 }
339 p->pid = pid;
340}
341
342rmut(p)
343register struct tab *p;
344{
345 register f;
346
347 f = open(utmp, 2);
348 if(f >= 0) {
349 while(read(f, (char *)&wtmp, sizeof(wtmp)) == sizeof(wtmp)) {
350 if (SCMPN(wtmp.ut_line, p->line))
351 continue;
352 lseek(f, -(long)sizeof(wtmp), 1);
353 SCPYN(wtmp.ut_name, "");
354 time(&wtmp.ut_time);
355 write(f, (char *)&wtmp, sizeof(wtmp));
356 }
357 close(f);
358 }
359 f = open(wtmpf, 1);
360 if (f >= 0) {
361 SCPYN(wtmp.ut_line, p->line);
362 SCPYN(wtmp.ut_name, "");
363 time(&wtmp.ut_time);
364 lseek(f, (long)0, 2);
365 write(f, (char *)&wtmp, sizeof(wtmp));
366 close(f);
367 }
368}
369
370reset()
371{
372 longjmp(sjbuf, 1);
373}