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 } 270