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