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