xref: /csrg-svn/sbin/init/init.c (revision 1429)
1 static	char *sccsid = "@(#)init.c	4.3 (Berkeley) 10/13/80";
2 #include <signal.h>
3 #include <sys/types.h>
4 #include <utmp.h>
5 #include <setjmp.h>
6 #include <sys/reboot.h>
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 
15 char	shell[]	= "/bin/sh";
16 char	getty[]	 = "/etc/getty";
17 char	minus[]	= "-";
18 char	runc[]	= "/etc/rc";
19 char	ifile[]	= "/etc/ttys";
20 char	utmp[]	= "/etc/utmp";
21 char	wtmpf[]	= "/usr/adm/wtmp";
22 char	ctty[]	= "/dev/console";
23 char	dev[]	= "/dev/";
24 
25 struct utmp wtmp;
26 struct
27 {
28 	char	line[LINSIZ];
29 	char	comn;
30 	char	flag;
31 } line;
32 struct	tab
33 {
34 	char	line[LINSIZ];
35 	char	comn;
36 	char	xflag;
37 	int	pid;
38 } itab[TABSIZ];
39 
40 int	fi;
41 int	mergflag;
42 char	tty[20];
43 jmp_buf	sjbuf, shutpass;
44 
45 int	reset();
46 char	*strcpy(), *strcat();
47 long	lseek();
48 
49 main()
50 {
51 	register int r11;		/* passed thru from boot */
52 	int howto, oldhowto;
53 
54 	howto = r11;
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) {
62 		oldhowto = howto;
63 		howto = RB_SINGLE;
64 		if (setjmp(shutpass) == 0)
65 			shutdown();
66 		if (oldhowto & RB_SINGLE)
67 			single();
68 		if (runcom(oldhowto) == 0)
69 			continue;
70 		merge();
71 		multiple();
72 	}
73 }
74 
75 int	shutreset();
76 
77 shutdown()
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 	}
88 	signal(SIGALRM, shutreset);
89 	alarm(30);
90 	for(i=0; i<5; i++)
91 		kill(-1, SIGKILL);
92 	while(wait((int *)0) != -1)
93 		;
94 	alarm(0);
95 	shutend();
96 }
97 
98 char shutfailm[] = "WARNING: Something is hung (wont die); ps axl advised\n";
99 
100 shutreset()
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 
115 shutend()
116 {
117 	register i;
118 
119 	signal(SIGALRM, SIG_DFL);
120 	for(i=0; i<10; i++)
121 		close(i);
122 }
123 
124 single()
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 
146 runcom(oldhowto)
147 	int oldhowto;
148 {
149 	register pid, f;
150 	int status;
151 
152 	pid = fork();
153 	if(pid == 0) {
154 		open("/", 0);
155 		dup(0);
156 		dup(0);
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);
162 	}
163 	while(wait(&status) != pid)
164 		;
165 	if(status)
166 		return(0);
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 	}
176 	return(1);
177 }
178 
179 setmerge()
180 {
181 
182 	signal(SIGHUP, setmerge);
183 	mergflag = 1;
184 }
185 
186 multiple()
187 {
188 	register struct tab *p;
189 	register pid;
190 
191 loop:
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 
210 term(p)
211 register 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 
221 rline()
222 {
223 	register c, i;
224 
225 loop:
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 
256 get()
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 
270 merge()
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 
314 dfork(p)
315 struct 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 
342 rmut(p)
343 register 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 
370 reset()
371 {
372 	longjmp(sjbuf, 1);
373 }
374