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