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