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