]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/init.c
merge
[plan9front.git] / sys / src / cmd / init.c
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 static int gotnote;
116
117 void
118 pinhead(void*, char *msg)
119 {
120         gotnote = 1;
121         fprint(2, "init got note '%s'\n", msg);
122         noted(NCONT);
123 }
124
125 void
126 fexec(void (*execfn)(void))
127 {
128         Waitmsg *w;
129         int pid;
130
131         switch(pid=fork()){
132         case 0:
133                 rfork(RFNOTEG);
134                 (*execfn)();
135                 print("init: exec error: %r\n");
136                 exits("exec");
137         case -1:
138                 print("init: fork error: %r\n");
139                 exits("fork");
140         default:
141         casedefault:
142                 notify(pinhead);
143                 gotnote = 0;
144                 w = wait();
145                 if(w == nil){
146                         if(gotnote)
147                                 goto casedefault;
148                         print("init: wait error: %r\n");
149                         break;
150                 }
151                 if(w->pid != pid){
152                         free(w);
153                         goto casedefault;
154                 }
155                 if(strstr(w->msg, "exec error") != 0){
156                         print("init: exit string %s\n", w->msg);
157                         print("init: sleeping because exec failed\n");
158                         free(w);
159                         for(;;)
160                                 sleep(1000);
161                 }
162                 if(w->msg[0])
163                         print("init: rc exit status: %s\n", w->msg);
164                 free(w);
165                 break;
166         }
167 }
168
169 void
170 rcexec(void)
171 {
172         if(cmd)
173                 execl("/bin/rc", "rc", "-c", cmd, nil);
174         else if(manual || iscpu)
175                 execl("/bin/rc", "rc", nil);
176         else if(strcmp(service, "terminal") == 0)
177                 execl("/bin/rc", "rc", "-c", ". /rc/bin/termrc; home=/usr/$user; cd; . lib/profile", nil);
178         else
179                 execl("/bin/rc", "rc", nil);
180 }
181
182 void
183 cpustart(void)
184 {
185         execl("/bin/rc", "rc", "-c", "/rc/bin/cpurc", nil);
186 }
187
188 char*
189 readenv(char *name)
190 {
191         int f, len;
192         Dir *d;
193         char *val;
194
195         f = open(name, OREAD);
196         if(f < 0){
197                 print("init: can't open %s: %r\n", name);
198                 return "*unknown*";     
199         }
200         d = dirfstat(f);
201         if(d == nil){
202                 print("init: can't stat %s: %r\n", name);
203                 return "*unknown*";
204         }
205         len = d->length;
206         free(d);
207         if(len == 0)    /* device files can be zero length but have contents */
208                 len = 64;
209         val = malloc(len+1);
210         if(val == nil){
211                 print("init: can't malloc %s: %r\n", name);
212                 return "*unknown*";
213         }
214         len = read(f, val, len);
215         close(f);
216         if(len < 0){
217                 print("init: can't read %s: %r\n", name);
218                 return "*unknown*";
219         }else
220                 val[len] = '\0';
221         return val;
222 }
223
224 void
225 setenv(char *var, char *val)
226 {
227         int fd;
228
229         fd = create(var, OWRITE, 0644);
230         if(fd < 0)
231                 print("init: can't open %s\n", var);
232         else{
233                 fprint(fd, val);
234                 close(fd);
235         }
236 }
237
238 void
239 cpenv(char *file, char *var)
240 {
241         int i, fd;
242         char buf[8192];
243
244         fd = open(file, OREAD);
245         if(fd < 0)
246                 print("init: can't open %s\n", file);
247         else{
248                 i = read(fd, buf, sizeof(buf)-1);
249                 if(i <= 0)
250                         print("init: can't read %s: %r\n", file);
251                 else{
252                         close(fd);
253                         buf[i] = 0;
254                         setenv(var, buf);
255                 }
256         }
257 }
258
259 /*
260  *  clean up after /boot
261  */
262 void
263 closefds(void)
264 {
265         int i;
266
267         for(i = 3; i < 30; i++)
268                 close(i);
269 }