boot.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <auth.h>
  4. #include <fcall.h>
  5. #include "../boot/boot.h"
  6. char cputype[64];
  7. char sys[2*64];
  8. char reply[256];
  9. int printcol;
  10. int mflag;
  11. int fflag;
  12. int kflag;
  13. char *bargv[Nbarg];
  14. int bargc;
  15. static void swapproc(void);
  16. static Method *rootserver(char*);
  17. void
  18. boot(int argc, char *argv[])
  19. {
  20. int fd, afd;
  21. Method *mp;
  22. char *cmd, cmdbuf[64], *iargv[16];
  23. char rootbuf[64];
  24. int islocal, ishybrid;
  25. char *rp, *rsp;
  26. int iargc, n;
  27. char buf[32];
  28. AuthInfo *ai;
  29. fmtinstall('r', errfmt);
  30. open("#c/cons", OREAD);
  31. open("#c/cons", OWRITE);
  32. open("#c/cons", OWRITE);
  33. bind("#c", "/dev", MAFTER);
  34. /*
  35. * init will reinitialize its namespace.
  36. * #ec gets us plan9.ini settings (*var variables).
  37. */
  38. bind("#ec", "/env", MREPL);
  39. bind("#e", "/env", MBEFORE|MCREATE);
  40. bind("#s", "/srv", MREPL|MCREATE);
  41. #ifdef DEBUG
  42. print("argc=%d\n", argc);
  43. for(fd = 0; fd < argc; fd++)
  44. print("%lux %s ", argv[fd], argv[fd]);
  45. print("\n");
  46. #endif DEBUG
  47. ARGBEGIN{
  48. case 'k':
  49. kflag = 1;
  50. break;
  51. case 'm':
  52. mflag = 1;
  53. break;
  54. case 'f':
  55. fflag = 1;
  56. break;
  57. }ARGEND
  58. readfile("#e/cputype", cputype, sizeof(cputype));
  59. /*
  60. * pick a method and initialize it
  61. */
  62. mp = rootserver(argc ? *argv : 0);
  63. (*mp->config)(mp);
  64. islocal = strcmp(mp->name, "local") == 0;
  65. ishybrid = strcmp(mp->name, "hybrid") == 0;
  66. /*
  67. * authentication agent
  68. */
  69. authentication(cpuflag);
  70. /*
  71. * connect to the root file system
  72. */
  73. fd = (*mp->connect)();
  74. if(fd < 0)
  75. fatal("can't connect to file server");
  76. if(getenv("srvold9p"))
  77. fd = old9p(fd);
  78. if(!islocal && !ishybrid){
  79. if(cfs)
  80. fd = (*cfs)(fd);
  81. }
  82. print("version...");
  83. buf[0] = '\0';
  84. n = fversion(fd, 0, buf, sizeof buf);
  85. if(n < 0)
  86. fatal("can't init 9P");
  87. srvcreate("boot", fd);
  88. /*
  89. * create the name space, mount the root fs
  90. */
  91. if(bind("/", "/", MREPL) < 0)
  92. fatal("bind /");
  93. rp = getenv("rootspec");
  94. if(rp == nil)
  95. rp = "";
  96. afd = fauth(fd, rp);
  97. if(afd >= 0){
  98. ai = auth_proxy(afd, auth_getkey, "proto=p9any role=client");
  99. if(ai == nil)
  100. print("authentication failed (%r), trying mount anyways\n");
  101. }
  102. if(mount(fd, afd, "/root", MREPL|MCREATE, rp) < 0)
  103. fatal("mount /");
  104. rsp = rp;
  105. rp = getenv("rootdir");
  106. if(rp == nil)
  107. rp = rootdir;
  108. if(bind(rp, "/", MAFTER|MCREATE) < 0){
  109. if(strncmp(rp, "/root", 5) == 0){
  110. fprint(2, "boot: couldn't bind $rootdir=%s to root: %r\n", rp);
  111. fatal("second bind /");
  112. }
  113. snprint(rootbuf, sizeof rootbuf, "/root/%s", rp);
  114. rp = rootbuf;
  115. if(bind(rp, "/", MAFTER|MCREATE) < 0){
  116. fprint(2, "boot: couldn't bind $rootdir=%s to root: %r\n", rp);
  117. if(strcmp(rootbuf, "/root//plan9") == 0){
  118. fprint(2, "**** warning: remove rootdir=/plan9 entry from plan9.ini\n");
  119. rp = "/root";
  120. if(bind(rp, "/", MAFTER|MCREATE) < 0)
  121. fatal("second bind /");
  122. }else
  123. fatal("second bind /");
  124. }
  125. }
  126. close(fd);
  127. setenv("rootdir", rp);
  128. settime(islocal, afd, rsp);
  129. if(afd > 0)
  130. close(afd);
  131. swapproc();
  132. cmd = getenv("init");
  133. if(cmd == nil){
  134. sprint(cmdbuf, "/%s/init -%s%s", cputype,
  135. cpuflag ? "c" : "t", mflag ? "m" : "");
  136. cmd = cmdbuf;
  137. }
  138. iargc = tokenize(cmd, iargv, nelem(iargv)-1);
  139. cmd = iargv[0];
  140. /* make iargv[0] basename(iargv[0]) */
  141. if(iargv[0] = strrchr(iargv[0], '/'))
  142. iargv[0]++;
  143. else
  144. iargv[0] = cmd;
  145. iargv[iargc] = nil;
  146. exec(cmd, iargv);
  147. fatal(cmd);
  148. }
  149. Method*
  150. findmethod(char *a)
  151. {
  152. Method *mp;
  153. int i, j;
  154. char *cp;
  155. i = strlen(a);
  156. cp = strchr(a, '!');
  157. if(cp)
  158. i = cp - a;
  159. for(mp = method; mp->name; mp++){
  160. j = strlen(mp->name);
  161. if(j > i)
  162. j = i;
  163. if(strncmp(a, mp->name, j) == 0)
  164. break;
  165. }
  166. if(mp->name)
  167. return mp;
  168. return 0;
  169. }
  170. /*
  171. * ask user from whence cometh the root file system
  172. */
  173. static Method*
  174. rootserver(char *arg)
  175. {
  176. char prompt[256];
  177. Method *mp;
  178. char *cp;
  179. int n;
  180. /* look for required reply */
  181. readfile("#e/nobootprompt", reply, sizeof(reply));
  182. if(reply[0]){
  183. mp = findmethod(reply);
  184. if(mp)
  185. goto HaveMethod;
  186. print("boot method %s not found\n", reply);
  187. reply[0] = 0;
  188. }
  189. /* make list of methods */
  190. mp = method;
  191. n = sprint(prompt, "root is from (%s", mp->name);
  192. for(mp++; mp->name; mp++)
  193. n += sprint(prompt+n, ", %s", mp->name);
  194. sprint(prompt+n, ")");
  195. /* create default reply */
  196. readfile("#e/bootargs", reply, sizeof(reply));
  197. if(reply[0] == 0 && arg != 0)
  198. strcpy(reply, arg);
  199. if(reply[0]){
  200. mp = findmethod(reply);
  201. if(mp == 0)
  202. reply[0] = 0;
  203. }
  204. if(reply[0] == 0)
  205. strcpy(reply, method->name);
  206. /* parse replies */
  207. for(;;){
  208. outin(prompt, reply, sizeof(reply));
  209. if(strlen(reply) == 0)
  210. continue;
  211. mp = findmethod(reply);
  212. if(mp){
  213. HaveMethod:
  214. bargc = tokenize(reply, bargv, Nbarg-2);
  215. bargv[bargc] = nil;
  216. cp = strchr(reply, '!');
  217. if(cp)
  218. strcpy(sys, cp+1);
  219. return mp;
  220. }
  221. }
  222. return 0; /* not reached */
  223. }
  224. static void
  225. swapproc(void)
  226. {
  227. int fd;
  228. fd = open("#c/swap", OWRITE);
  229. if(fd < 0){
  230. warning("opening #c/swap");
  231. return;
  232. }
  233. if(write(fd, "start", 5) <= 0)
  234. warning("starting swap kproc");
  235. close(fd);
  236. }
  237. int
  238. old9p(int fd)
  239. {
  240. int p[2];
  241. if(pipe(p) < 0)
  242. fatal("pipe");
  243. print("srvold9p...");
  244. switch(fork()) {
  245. case -1:
  246. fatal("rfork srvold9p");
  247. case 0:
  248. dup(fd, 1);
  249. close(fd);
  250. dup(p[0], 0);
  251. close(p[0]);
  252. close(p[1]);
  253. execl("/srvold9p", "srvold9p", "-s", 0);
  254. fatal("exec srvold9p");
  255. default:
  256. close(fd);
  257. close(p[0]);
  258. }
  259. return p[1];
  260. }