xref: /plan9/sys/src/cmd/init.c (revision ff8c3af2f44d95267f67219afa20ba82ff6cf7e4)
1 #include <u.h>
2 #include <libc.h>
3 #include <auth.h>
4 #include <authsrv.h>
5 
6 char*	readenv(char*);
7 void	setenv(char*, char*);
8 void	cpenv(char*, char*);
9 void	closefds(void);
10 void	fexec(void(*)(void));
11 void	rcexec(void);
12 void	cpustart(void);
13 void	pass(int);
14 
15 char	*service;
16 char	*cmd;
17 char	*cpu;
18 char	*systemname;
19 int	manual;
20 int	iscpu;
21 
22 void
23 main(int argc, char *argv[])
24 {
25 	char *user;
26 	int fd;
27 	char ctl[128];
28 
29 	closefds();
30 
31 	service = "cpu";
32 	manual = 0;
33 	ARGBEGIN{
34 	case 'c':
35 		service = "cpu";
36 		break;
37 	case 'm':
38 		manual = 1;
39 		break;
40 	case 't':
41 		service = "terminal";
42 		break;
43 	}ARGEND
44 	cmd = *argv;
45 
46 	snprint(ctl, sizeof(ctl), "#p/%d/ctl", getpid());
47 	fd = open(ctl, OWRITE);
48 	if(fd < 0)
49 		print("init: warning: can't open %s: %r\n", ctl);
50 	else
51 		if(write(fd, "pri 10", 6) != 6)
52 			print("init: warning: can't set priority: %r\n");
53 	close(fd);
54 
55 	cpu = readenv("#e/cputype");
56 	setenv("#e/objtype", cpu);
57 	setenv("#e/service", service);
58 	cpenv("/adm/timezone/local", "#e/timezone");
59 	user = readenv("#c/user");
60 	systemname = readenv("#c/sysname");
61 
62 	newns(user, 0);
63 	iscpu = strcmp(service, "cpu")==0;
64 
65 	if(iscpu && manual == 0)
66 		fexec(cpustart);
67 
68 	for(;;){
69 		print("\ninit: starting /bin/rc\n");
70 		fexec(rcexec);
71 		manual = 1;
72 		cmd = 0;
73 		sleep(1000);
74 	}
75 }
76 
77 void
78 pass(int fd)
79 {
80 	char key[DESKEYLEN];
81 	char typed[32];
82 	char crypted[DESKEYLEN];
83 	int i;
84 
85 	for(;;){
86 		print("\n%s password:", systemname);
87 		for(i=0; i<sizeof typed; i++){
88 			if(read(0, typed+i, 1) != 1){
89 				print("init: can't read password; insecure\n");
90 				return;
91 			}
92 			if(typed[i] == '\n'){
93 				typed[i] = 0;
94 				break;
95 			}
96 		}
97 		if(i == sizeof typed)
98 			continue;
99 		if(passtokey(crypted, typed) == 0)
100 			continue;
101 		seek(fd, 0, 0);
102 		if(read(fd, key, DESKEYLEN) != DESKEYLEN){
103 			print("init: can't read key; insecure\n");
104 			return;
105 		}
106 		if(memcmp(crypted, key, sizeof key))
107 			continue;
108 		/* clean up memory */
109 		memset(crypted, 0, sizeof crypted);
110 		memset(key, 0, sizeof key);
111 		return;
112 	}
113 }
114 
115 void
116 fexec(void (*execfn)(void))
117 {
118 	Waitmsg *w;
119 	int pid;
120 
121 	switch(pid=fork()){
122 	case 0:
123 		rfork(RFNOTEG);
124 		(*execfn)();
125 		print("init: exec error: %r\n");
126 		exits("exec");
127 	case -1:
128 		print("init: fork error: %r\n");
129 		exits("fork");
130 	default:
131 	casedefault:
132 		w = wait();
133 		if(w == nil){
134 			print("init: wait error: %r\n");
135 			break;
136 		}
137 		if(w->pid != pid){
138 			free(w);
139 			goto casedefault;
140 		}
141 		if(strstr(w->msg, "exec error") != 0){
142 			print("init: exit string %s\n", w->msg);
143 			print("init: sleeping because exec failed\n");
144 			free(w);
145 			for(;;)
146 				sleep(1000);
147 		}
148 		if(w->msg[0])
149 			print("init: rc exit status: %s\n", w->msg);
150 		free(w);
151 		break;
152 	}
153 }
154 
155 void
156 rcexec(void)
157 {
158 	if(cmd)
159 		execl("/bin/rc", "rc", "-c", cmd, 0);
160 	else if(manual || iscpu)
161 		execl("/bin/rc", "rc", 0);
162 	else if(strcmp(service, "terminal") == 0)
163 		execl("/bin/rc", "rc", "-c", ". /rc/bin/termrc; home=/usr/$user; cd; . lib/profile", 0);
164 	else
165 		execl("/bin/rc", "rc", 0);
166 }
167 
168 void
169 cpustart(void)
170 {
171 	execl("/bin/rc", "rc", "-c", "/rc/bin/cpurc", 0);
172 }
173 
174 char*
175 readenv(char *name)
176 {
177 	int f, len;
178 	Dir *d;
179 	char *val;
180 
181 	f = open(name, OREAD);
182 	if(f < 0){
183 		print("init: can't open %s: %r\n", name);
184 		return "*unknown*";
185 	}
186 	d = dirfstat(f);
187 	if(d == nil){
188 		print("init: can't stat %s: %r\n", name);
189 		return "*unknown*";
190 	}
191 	len = d->length;
192 	free(d);
193 	if(len == 0)	/* device files can be zero length but have contents */
194 		len = 64;
195 	val = malloc(len+1);
196 	if(val == nil){
197 		print("init: can't malloc %s: %r\n", name);
198 		return "*unknown*";
199 	}
200 	len = read(f, val, len);
201 	close(f);
202 	if(len < 0){
203 		print("init: can't read %s: %r\n", name);
204 		return "*unknown*";
205 	}else
206 		val[len] = '\0';
207 	return val;
208 }
209 
210 void
211 setenv(char *var, char *val)
212 {
213 	int fd;
214 
215 	fd = create(var, OWRITE, 0644);
216 	if(fd < 0)
217 		print("init: can't open %s\n", var);
218 	else{
219 		fprint(fd, val);
220 		close(fd);
221 	}
222 }
223 
224 void
225 cpenv(char *file, char *var)
226 {
227 	int i, fd;
228 	char buf[8192];
229 
230 	fd = open(file, OREAD);
231 	if(fd < 0)
232 		print("init: can't open %s\n", file);
233 	else{
234 		i = read(fd, buf, sizeof(buf)-1);
235 		if(i <= 0)
236 			print("init: can't read %s: %r\n", file);
237 		else{
238 			close(fd);
239 			buf[i] = 0;
240 			setenv(var, buf);
241 		}
242 	}
243 }
244 
245 /*
246  *  clean up after /boot
247  */
248 void
249 closefds(void)
250 {
251 	int i;
252 
253 	for(i = 3; i < 30; i++)
254 		close(i);
255 }
256