init.c 4.4 KB

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