Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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