boot.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  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. swapproc();
  130. cmd = getenv("init");
  131. if(cmd == nil){
  132. sprint(cmdbuf, "/%s/init -%s%s", cputype,
  133. cpuflag ? "c" : "t", mflag ? "m" : "");
  134. cmd = cmdbuf;
  135. }
  136. iargc = tokenize(cmd, iargv, nelem(iargv)-1);
  137. cmd = iargv[0];
  138. /* make iargv[0] basename(iargv[0]) */
  139. if(iargv[0] = strrchr(iargv[0], '/'))
  140. iargv[0]++;
  141. else
  142. iargv[0] = cmd;
  143. iargv[iargc] = nil;
  144. exec(cmd, iargv);
  145. fatal(cmd);
  146. }
  147. Method*
  148. findmethod(char *a)
  149. {
  150. Method *mp;
  151. int i, j;
  152. char *cp;
  153. i = strlen(a);
  154. cp = strchr(a, '!');
  155. if(cp)
  156. i = cp - a;
  157. for(mp = method; mp->name; mp++){
  158. j = strlen(mp->name);
  159. if(j > i)
  160. j = i;
  161. if(strncmp(a, mp->name, j) == 0)
  162. break;
  163. }
  164. if(mp->name)
  165. return mp;
  166. return 0;
  167. }
  168. /*
  169. * ask user from whence cometh the root file system
  170. */
  171. static Method*
  172. rootserver(char *arg)
  173. {
  174. char prompt[256];
  175. Method *mp;
  176. char *cp;
  177. int n;
  178. /* look for required reply */
  179. readfile("#e/nobootprompt", reply, sizeof(reply));
  180. if(reply[0]){
  181. mp = findmethod(reply);
  182. if(mp)
  183. goto HaveMethod;
  184. print("boot method %s not found\n", reply);
  185. reply[0] = 0;
  186. }
  187. /* make list of methods */
  188. mp = method;
  189. n = sprint(prompt, "root is from (%s", mp->name);
  190. for(mp++; mp->name; mp++)
  191. n += sprint(prompt+n, ", %s", mp->name);
  192. sprint(prompt+n, ")");
  193. /* create default reply */
  194. readfile("#e/bootargs", reply, sizeof(reply));
  195. if(reply[0] == 0 && arg != 0)
  196. strcpy(reply, arg);
  197. if(reply[0]){
  198. mp = findmethod(reply);
  199. if(mp == 0)
  200. reply[0] = 0;
  201. }
  202. if(reply[0] == 0)
  203. strcpy(reply, method->name);
  204. /* parse replies */
  205. for(;;){
  206. outin(prompt, reply, sizeof(reply));
  207. if(strlen(reply) == 0)
  208. continue;
  209. mp = findmethod(reply);
  210. if(mp){
  211. HaveMethod:
  212. bargc = tokenize(reply, bargv, Nbarg-2);
  213. bargv[bargc] = nil;
  214. cp = strchr(reply, '!');
  215. if(cp)
  216. strcpy(sys, cp+1);
  217. return mp;
  218. }
  219. }
  220. return 0; /* not reached */
  221. }
  222. static void
  223. swapproc(void)
  224. {
  225. int fd;
  226. fd = open("#c/swap", OWRITE);
  227. if(fd < 0){
  228. warning("opening #c/swap");
  229. return;
  230. }
  231. if(write(fd, "start", 5) <= 0)
  232. warning("starting swap kproc");
  233. close(fd);
  234. }
  235. int
  236. old9p(int fd)
  237. {
  238. int p[2];
  239. if(pipe(p) < 0)
  240. fatal("pipe");
  241. print("srvold9p...");
  242. switch(fork()) {
  243. case -1:
  244. fatal("rfork srvold9p");
  245. case 0:
  246. dup(fd, 1);
  247. close(fd);
  248. dup(p[0], 0);
  249. close(p[0]);
  250. close(p[1]);
  251. execl("/srvold9p", "srvold9p", "-s", 0);
  252. fatal("exec srvold9p");
  253. default:
  254. close(fd);
  255. close(p[0]);
  256. }
  257. return p[1];
  258. }