init.c 4.4 KB

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