local.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <../boot/boot.h>
  4. static char diskname[64];
  5. static char *disk;
  6. static char **args;
  7. void
  8. configlocal(Method *mp)
  9. {
  10. char *p, *inibootdisk;
  11. int n;
  12. inibootdisk = getenv("bootdisk");
  13. if(*sys == '/' || *sys == '#'){
  14. /*
  15. * if the user specifies the disk in the boot cmd or
  16. * 'root is from' prompt, use it
  17. */
  18. disk = sys;
  19. } else if(strncmp(argv0, "dksc(0,", 7) == 0){
  20. /*
  21. * on many mips arg0 of the boot command specifies the
  22. * scsi logical unit number
  23. */
  24. p = strchr(argv0, ',');
  25. n = strtoul(p+1, 0, 10);
  26. sprint(diskname, "#w%d/sd%dfs", n, n);
  27. disk = diskname;
  28. } else if(mp->arg){
  29. /*
  30. * a default is optionally supplied when the kernel is made
  31. */
  32. disk = mp->arg;
  33. } else if(inibootdisk != nil && *inibootdisk)
  34. /* plan9.ini overrides default from config file */
  35. disk = inibootdisk;
  36. else if(bootdisk != nil && *bootdisk){
  37. /*
  38. * an environment variable from a pc's plan9.ini or
  39. * from the mips nvram or generated by the kernel
  40. * is the last resort.
  41. */
  42. disk = bootdisk;
  43. }
  44. /* if we've decided on one, pass it on to all programs */
  45. if(disk) {
  46. bootdisk = disk;
  47. setenv("bootdisk", bootdisk);
  48. }
  49. }
  50. int
  51. connectlocalkfs(void)
  52. {
  53. int i, pid, fd, p[2];
  54. char partition[64];
  55. char *dev;
  56. char **arg, **argp;
  57. Dir *d;
  58. if(stat("/boot/kfs", statbuf, sizeof statbuf) < 0)
  59. return -1;
  60. dev = disk ? disk : bootdisk;
  61. snprint(partition, sizeof partition, "%sfs", dev);
  62. fd = open(partition, OREAD);
  63. if(fd < 0){
  64. strcpy(partition, dev);
  65. fd = open(partition, OREAD);
  66. if(fd < 0)
  67. return -1;
  68. }
  69. /*
  70. * can't do this check -- might be some other server posing as kfs.
  71. *
  72. memset(buf, 0, sizeof buf);
  73. pread(fd, buf, 512, 0);
  74. close(fd);
  75. if(memcmp(buf+256, "kfs wren device\n", 16) != 0){
  76. if(strstr(partition, "/fs"))
  77. print("no kfs file system found on %s\n", partition);
  78. return -1;
  79. }
  80. *
  81. */
  82. d = dirfstat(fd);
  83. close(fd);
  84. if(d == nil)
  85. return -1;
  86. if(d->mode&DMDIR){
  87. free(d);
  88. return -1;
  89. }
  90. free(d);
  91. print("kfs...");
  92. if(pipe(p)<0)
  93. fatal("pipe");
  94. switch(pid = fork()){
  95. case -1:
  96. fatal("fork");
  97. case 0:
  98. arg = malloc((bargc+5)*sizeof(char*));
  99. argp = arg;
  100. *argp++ = "kfs";
  101. *argp++ = "-f";
  102. *argp++ = partition;
  103. *argp++ = "-s";
  104. for(i=1; i<bargc; i++)
  105. *argp++ = bargv[i];
  106. *argp = 0;
  107. dup(p[0], 0);
  108. dup(p[1], 1);
  109. close(p[0]);
  110. close(p[1]);
  111. exec("/boot/kfs", arg);
  112. fatal("can't exec kfs");
  113. default:
  114. break;
  115. }
  116. for(;;){
  117. if((i = waitpid()) == -1)
  118. fatal("waitpid for kfs failed");
  119. if(i == pid)
  120. break;
  121. }
  122. close(p[1]);
  123. return p[0];
  124. }
  125. void
  126. runv(char **argv)
  127. {
  128. int i, pid;
  129. switch(pid = fork()){
  130. case -1:
  131. fatal("fork");
  132. case 0:
  133. exec(argv[0], argv);
  134. fatal(smprint("can't exec %s: %r", argv[0]));
  135. default:
  136. while ((i = waitpid()) != pid && i != -1)
  137. ;
  138. if(i == -1)
  139. fatal(smprint("wait failed running %s", argv[0]));
  140. }
  141. }
  142. void
  143. run(char *file, ...)
  144. {
  145. runv(&file);
  146. }
  147. static int
  148. print1(int fd, char *s)
  149. {
  150. return write(fd, s, strlen(s));
  151. }
  152. void
  153. configloopback(void)
  154. {
  155. int fd;
  156. if((fd = open("/net/ipifc/clone", ORDWR)) < 0){
  157. bind("#I", "/net", MAFTER);
  158. if((fd = open("/net/ipifc/clone", ORDWR)) < 0)
  159. fatal("open /net/ipifc/clone for loopback");
  160. }
  161. if(print1(fd, "bind loopback /dev/null") < 0
  162. || print1(fd, "add 127.0.0.1 255.255.255.255") < 0)
  163. fatal("write /net/ipifc/clone for loopback");
  164. }
  165. int
  166. connectlocalfossil(void)
  167. {
  168. int fd;
  169. char *venti, *f[32], *p;
  170. int nf;
  171. char partition[128], buf[512];
  172. char *dev;
  173. if(stat("/boot/fossil", statbuf, sizeof statbuf) < 0)
  174. return -1;
  175. /* look for fossil partition */
  176. dev = disk ? disk : bootdisk;
  177. snprint(partition, sizeof partition, "%sfossil", dev);
  178. fd = open(partition, OREAD);
  179. if(fd < 0){
  180. strcpy(partition, dev);
  181. fd = open(partition, OREAD);
  182. if(fd < 0)
  183. return -1;
  184. }
  185. memset(buf, 0, sizeof buf);
  186. pread(fd, buf, 512, 127*1024);
  187. close(fd);
  188. if(memcmp(buf, "fossil config\n", 14) != 0){
  189. if(strstr(partition, "/fossil"))
  190. print("no fossil config found on %s\n", partition);
  191. return -1;
  192. }
  193. settime(1, -1, nil);
  194. /* make venti available. give it 20% of free memory. */
  195. if((venti = getenv("venti")) && (nf = tokenize(venti, f, nelem(f)))){
  196. if((fd = open(f[0], OREAD)) >= 0){
  197. print("venti...");
  198. memset(buf, 0, sizeof buf);
  199. pread(fd, buf, 512, 248*1024);
  200. close(fd);
  201. if(memcmp(buf, "venti config\n", 13) != 0){
  202. print("no venti config found on %s\n", f[0]);
  203. return -1;
  204. }
  205. if(stat("/boot/venti", statbuf, sizeof statbuf) < 0){
  206. print("/boot/venti does not exist\n");
  207. return -1;
  208. }
  209. switch(nf){
  210. case 1:
  211. f[1] = "tcp!127.1!17034";
  212. case 2:
  213. f[2] = "tcp!127.1!8000";
  214. }
  215. configloopback();
  216. run("/boot/venti", "-m", "20", "-c", f[0],
  217. "-a", f[1], "-h", f[2], nil);
  218. /*
  219. * If the announce address is tcp!*!foo, then set
  220. * $venti to tcp!127.1!foo instead, which is actually dialable.
  221. */
  222. if((p = strstr(f[1], "!*!")) != 0){
  223. *p = 0;
  224. snprint(buf, sizeof buf, "%s!127.1!%s", f[1], p+3);
  225. f[1] = buf;
  226. }
  227. setenv("venti", f[1]);
  228. }else{
  229. /* set up the network so we can talk to the venti server */
  230. /* this is such a crock. */
  231. configip(nf, f, 0);
  232. setenv("venti", f[0]);
  233. }
  234. }
  235. /* start fossil. give it 20% of free memory. */
  236. print("fossil(%s)...", partition);
  237. run("/boot/fossil", "-m", "20", "-f", partition,
  238. "-c", "srv -A fboot", "-c", "srv -p fscons", nil);
  239. fd = open("#s/fboot", ORDWR);
  240. if(fd < 0){
  241. warning("open #s/fboot");
  242. return -1;
  243. }
  244. remove("#s/fboot"); /* we'll repost fd as #s/boot after fversion(fd) */
  245. return fd;
  246. }
  247. int
  248. connectlocal(void)
  249. {
  250. int fd;
  251. if(bind("#c", "/dev", MREPL) < 0)
  252. fatal("bind #c");
  253. if(bind("#p", "/proc", MREPL) < 0)
  254. fatal("bind #p");
  255. bind("#S", "/dev", MAFTER);
  256. bind("#k", "/dev", MAFTER);
  257. bind("#u", "/dev", MAFTER);
  258. bind("#æ", "/dev", MAFTER);
  259. mountusbparts(); /* make partfs partitions visible again */
  260. if((fd = connectlocalfossil()) < 0)
  261. fd = connectlocalkfs();
  262. return fd;
  263. }