local.c 6.3 KB

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