xref: /plan9-contrib/sys/src/cmd/init.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
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	systemname[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", systemname, sizeof systemname);
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/systemname", systemname, sizeof systemname);
89 		print("\n%s password:", systemname);
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 		rfork(RFNOTEG);
127 		(*execfn)();
128 		print("init: exec error: %r\n");
129 		exits("exec");
130 	case -1:
131 		print("init: fork error: %r\n");
132 		exits("fork");
133 	default:
134 	casedefault:
135 		i = wait(&w);
136 		if(i == -1)
137 			print("init: wait error: %r\n");
138 		else if(i != pid)
139 			goto casedefault;
140 		if(strcmp(w.msg, "exec") == 0){
141 			print("init: sleeping because exec failed\n");
142 			for(;;)
143 				sleep(1000);
144 		}
145 		if(w.msg[0])
146 			print("init: rc exit status: %s\n", w.msg);
147 		break;
148 	}
149 }
150 
151 void
152 rcexec(void)
153 {
154 	if(cmd)
155 		execl("/bin/rc", "rc", "-c", cmd, 0);
156 	else if(manual || iscpu)
157 		execl("/bin/rc", "rc", 0);
158 	else if(strcmp(service, "terminal") == 0)
159 		execl("/bin/rc", "rc", "-c", ". /rc/bin/termrc; home=/usr/$user; cd; . lib/profile", 0);
160 	else
161 		execl("/bin/rc", "rc", 0);
162 }
163 
164 void
165 cpustart(void)
166 {
167 	execl("/bin/rc", "rc", "-c", "/rc/bin/cpurc", 0);
168 }
169 
170 void
171 readenv(char *name, char *val, int len)
172 {
173 	int f;
174 
175 	f = open(name, OREAD);
176 	if(f < 0){
177 		print("init: can't open %s\n", name);
178 		return;
179 	}
180 	len = read(f, val, len-1);
181 	close(f);
182 	if(len < 0)
183 		print("init: can't read %s\n", name);
184 	else
185 		val[len] = '\0';
186 }
187 
188 void
189 setenv(char *var, char *val)
190 {
191 	int fd;
192 
193 	fd = create(var, OWRITE, 0644);
194 	if(fd < 0)
195 		print("init: can't open %s\n", var);
196 	else{
197 		fprint(fd, val);
198 		close(fd);
199 	}
200 }
201 
202 void
203 cpenv(char *file, char *var)
204 {
205 	int i, fd;
206 	char buf[8192];
207 
208 	fd = open(file, OREAD);
209 	if(fd < 0)
210 		print("init: can't open %s\n", file);
211 	else{
212 		i = read(fd, buf, sizeof(buf)-1);
213 		if(i <= 0)
214 			print("init: can't read %s: %r\n", file);
215 		else{
216 			close(fd);
217 			buf[i] = 0;
218 			setenv(var, buf);
219 		}
220 	}
221 }
222 
223 /*
224  *  clean up after /boot
225  */
226 void
227 closefds(void)
228 {
229 	int i;
230 
231 	for(i = 3; i < 30; i++)
232 		close(i);
233 }
234