Ccmd.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. #include "stdinc.h"
  2. #include "9.h"
  3. static struct {
  4. VtLock* lock;
  5. Con* con;
  6. int confd[2];
  7. ushort tag;
  8. } cbox;
  9. static ulong
  10. cmd9pStrtoul(char* s)
  11. {
  12. if(strcmp(s, "~0") == 0)
  13. return ~0UL;
  14. return strtoul(s, 0, 0);
  15. }
  16. static uvlong
  17. cmd9pStrtoull(char* s)
  18. {
  19. if(strcmp(s, "~0") == 0)
  20. return ~0ULL;
  21. return strtoull(s, 0, 0);
  22. }
  23. static int
  24. cmd9pTag(Fcall*, int, char **argv)
  25. {
  26. cbox.tag = strtoul(argv[0], 0, 0)-1;
  27. return 1;
  28. }
  29. static int
  30. cmd9pTwstat(Fcall* f, int, char **argv)
  31. {
  32. Dir d;
  33. static uchar buf[DIRMAX];
  34. memset(&d, 0, sizeof d);
  35. nulldir(&d);
  36. d.name = argv[1];
  37. d.uid = argv[2];
  38. d.gid = argv[3];
  39. d.mode = cmd9pStrtoul(argv[4]);
  40. d.mtime = cmd9pStrtoul(argv[5]);
  41. d.length = cmd9pStrtoull(argv[6]);
  42. f->fid = strtol(argv[0], 0, 0);
  43. f->stat = buf;
  44. f->nstat = convD2M(&d, buf, sizeof buf);
  45. if(f->nstat < BIT16SZ){
  46. vtSetError("Twstat: convD2M failed (internal error)");
  47. return 0;
  48. }
  49. return 1;
  50. }
  51. static int
  52. cmd9pTstat(Fcall* f, int, char** argv)
  53. {
  54. f->fid = strtol(argv[0], 0, 0);
  55. return 1;
  56. }
  57. static int
  58. cmd9pTremove(Fcall* f, int, char** argv)
  59. {
  60. f->fid = strtol(argv[0], 0, 0);
  61. return 1;
  62. }
  63. static int
  64. cmd9pTclunk(Fcall* f, int, char** argv)
  65. {
  66. f->fid = strtol(argv[0], 0, 0);
  67. return 1;
  68. }
  69. static int
  70. cmd9pTwrite(Fcall* f, int, char** argv)
  71. {
  72. f->fid = strtol(argv[0], 0, 0);
  73. f->offset = strtoll(argv[1], 0, 0);
  74. f->data = argv[2];
  75. f->count = strlen(argv[2]);
  76. return 1;
  77. }
  78. static int
  79. cmd9pTread(Fcall* f, int, char** argv)
  80. {
  81. f->fid = strtol(argv[0], 0, 0);
  82. f->offset = strtoll(argv[1], 0, 0);
  83. f->count = strtol(argv[2], 0, 0);
  84. return 1;
  85. }
  86. static int
  87. cmd9pTcreate(Fcall* f, int, char** argv)
  88. {
  89. f->fid = strtol(argv[0], 0, 0);
  90. f->name = argv[1];
  91. f->perm = strtol(argv[2], 0, 8);
  92. f->mode = strtol(argv[3], 0, 0);
  93. return 1;
  94. }
  95. static int
  96. cmd9pTopen(Fcall* f, int, char** argv)
  97. {
  98. f->fid = strtol(argv[0], 0, 0);
  99. f->mode = strtol(argv[1], 0, 0);
  100. return 1;
  101. }
  102. static int
  103. cmd9pTwalk(Fcall* f, int argc, char** argv)
  104. {
  105. int i;
  106. if(argc < 2){
  107. vtSetError("usage: Twalk tag fid newfid [name...]");
  108. return 0;
  109. }
  110. f->fid = strtol(argv[0], 0, 0);
  111. f->newfid = strtol(argv[1], 0, 0);
  112. f->nwname = argc-2;
  113. if(f->nwname > MAXWELEM){
  114. vtSetError("Twalk: too many names");
  115. return 0;
  116. }
  117. for(i = 0; i < argc-2; i++)
  118. f->wname[i] = argv[2+i];
  119. return 1;
  120. }
  121. static int
  122. cmd9pTflush(Fcall* f, int, char** argv)
  123. {
  124. f->oldtag = strtol(argv[0], 0, 0);
  125. return 1;
  126. }
  127. static int
  128. cmd9pTattach(Fcall* f, int, char** argv)
  129. {
  130. f->fid = strtol(argv[0], 0, 0);
  131. f->afid = strtol(argv[1], 0, 0);
  132. f->uname = argv[2];
  133. f->aname = argv[3];
  134. return 1;
  135. }
  136. static int
  137. cmd9pTauth(Fcall* f, int, char** argv)
  138. {
  139. f->afid = strtol(argv[0], 0, 0);
  140. f->uname = argv[1];
  141. f->aname = argv[2];
  142. return 1;
  143. }
  144. static int
  145. cmd9pTversion(Fcall* f, int, char** argv)
  146. {
  147. f->msize = strtoul(argv[0], 0, 0);
  148. if(f->msize > cbox.con->msize){
  149. vtSetError("msize too big");
  150. return 0;
  151. }
  152. f->version = argv[1];
  153. return 1;
  154. }
  155. typedef struct Cmd9p Cmd9p;
  156. struct Cmd9p {
  157. char* name;
  158. int type;
  159. int argc;
  160. char* usage;
  161. int (*f)(Fcall*, int, char**);
  162. };
  163. static Cmd9p cmd9pTmsg[] = {
  164. "Tversion", Tversion, 2, "msize version", cmd9pTversion,
  165. "Tauth", Tauth, 3, "afid uname aname", cmd9pTauth,
  166. "Tflush", Tflush, 1, "oldtag", cmd9pTflush,
  167. "Tattach", Tattach, 4, "fid afid uname aname", cmd9pTattach,
  168. "Twalk", Twalk, 0, "fid newfid [name...]", cmd9pTwalk,
  169. "Topen", Topen, 2, "fid mode", cmd9pTopen,
  170. "Tcreate", Tcreate, 4, "fid name perm mode", cmd9pTcreate,
  171. "Tread", Tread, 3, "fid offset count", cmd9pTread,
  172. "Twrite", Twrite, 3, "fid offset data", cmd9pTwrite,
  173. "Tclunk", Tclunk, 1, "fid", cmd9pTclunk,
  174. "Tremove", Tremove, 1, "fid", cmd9pTremove,
  175. "Tstat", Tstat, 1, "fid", cmd9pTstat,
  176. "Twstat", Twstat, 7, "fid name uid gid mode mtime length", cmd9pTwstat,
  177. "nexttag", 0, 0, "", cmd9pTag,
  178. };
  179. static int
  180. cmd9p(int argc, char* argv[])
  181. {
  182. int i, n;
  183. Fcall f, t;
  184. uchar *buf;
  185. char *usage;
  186. u32int msize;
  187. usage = "usage: 9p T-message ...";
  188. ARGBEGIN{
  189. default:
  190. return cliError(usage);
  191. }ARGEND
  192. if(argc < 1)
  193. return cliError(usage);
  194. for(i = 0; i < nelem(cmd9pTmsg); i++){
  195. if(strcmp(cmd9pTmsg[i].name, argv[0]) == 0)
  196. break;
  197. }
  198. if(i == nelem(cmd9pTmsg))
  199. return cliError(usage);
  200. argc--;
  201. argv++;
  202. if(cmd9pTmsg[i].argc && argc != cmd9pTmsg[i].argc){
  203. vtSetError("usage: %s %s",
  204. cmd9pTmsg[i].name, cmd9pTmsg[i].usage);
  205. return 0;
  206. }
  207. memset(&t, 0, sizeof(t));
  208. t.type = cmd9pTmsg[i].type;
  209. if(t.type == Tversion)
  210. t.tag = NOTAG;
  211. else
  212. t.tag = ++cbox.tag;
  213. msize = cbox.con->msize;
  214. if(!cmd9pTmsg[i].f(&t, argc, argv))
  215. return 0;
  216. buf = vtMemAlloc(msize);
  217. n = convS2M(&t, buf, msize);
  218. if(n <= BIT16SZ){
  219. vtSetError("%s: convS2M error", cmd9pTmsg[i].name);
  220. vtMemFree(buf);
  221. return 0;
  222. }
  223. if(write(cbox.confd[0], buf, n) != n){
  224. vtSetError("%s: write error: %r", cmd9pTmsg[i].name);
  225. vtMemFree(buf);
  226. return 0;
  227. }
  228. consPrint("\t-> %F\n", &t);
  229. if((n = read9pmsg(cbox.confd[0], buf, msize)) <= 0){
  230. vtSetError("%s: read error: %r", cmd9pTmsg[i].name);
  231. vtMemFree(buf);
  232. return 0;
  233. }
  234. if(convM2S(buf, n, &f) == 0){
  235. vtSetError("%s: convM2S error", cmd9pTmsg[i].name);
  236. vtMemFree(buf);
  237. return 0;
  238. }
  239. consPrint("\t<- %F\n", &f);
  240. vtMemFree(buf);
  241. return 1;
  242. }
  243. static int
  244. cmdDot(int argc, char* argv[])
  245. {
  246. long l;
  247. Dir *dir;
  248. int fd, r;
  249. vlong length;
  250. char *f, *p, *s, *usage;
  251. usage = "usage: . file";
  252. ARGBEGIN{
  253. default:
  254. return cliError(usage);
  255. }ARGEND
  256. if(argc != 1)
  257. return cliError(usage);
  258. if((dir = dirstat(argv[0])) == nil)
  259. return cliError(". dirstat %s: %r", argv[0]);
  260. length = dir->length;
  261. free(dir);
  262. r = 1;
  263. if(length != 0){
  264. /*
  265. * Read the whole file in.
  266. */
  267. if((fd = open(argv[0], OREAD)) < 0)
  268. return cliError(". open %s: %r", argv[0]);
  269. f = vtMemAlloc(dir->length+1);
  270. if((l = read(fd, f, length)) < 0){
  271. vtMemFree(f);
  272. close(fd);
  273. return cliError(". read %s: %r", argv[0]);
  274. }
  275. close(fd);
  276. f[l] = '\0';
  277. /*
  278. * Call cliExec() for each line.
  279. */
  280. for(p = s = f; *p != '\0'; p++){
  281. if(*p == '\n'){
  282. *p = '\0';
  283. if(cliExec(s) == 0){
  284. r = 0;
  285. consPrint("%s: %R\n", s);
  286. }
  287. s = p+1;
  288. }
  289. }
  290. vtMemFree(f);
  291. }
  292. if(r == 0)
  293. vtSetError("errors in . %#q", argv[0]);
  294. return r;
  295. }
  296. static int
  297. cmdDflag(int argc, char* argv[])
  298. {
  299. char *usage;
  300. usage = "usage: dflag";
  301. ARGBEGIN{
  302. default:
  303. return cliError(usage);
  304. }ARGEND
  305. if(argc)
  306. return cliError(usage);
  307. Dflag ^= 1;
  308. consPrint("dflag %d\n", Dflag);
  309. return 1;
  310. }
  311. static int
  312. cmdEcho(int argc, char* argv[])
  313. {
  314. char *usage;
  315. int i, nflag;
  316. nflag = 0;
  317. usage = "usage: echo [-n] ...";
  318. ARGBEGIN{
  319. default:
  320. return cliError(usage);
  321. case 'n':
  322. nflag = 1;
  323. break;
  324. }ARGEND
  325. for(i = 0; i < argc; i++){
  326. if(i != 0)
  327. consPrint(" %s", argv[i]);
  328. else
  329. consPrint(argv[i]);
  330. }
  331. if(!nflag)
  332. consPrint("\n");
  333. return 1;
  334. }
  335. static int
  336. cmdBind(int argc, char* argv[])
  337. {
  338. ulong flag = 0;
  339. char *usage;
  340. usage = "usage: bind [-b|-a|-c|-bc|-ac] new old";
  341. ARGBEGIN{
  342. case 'a':
  343. flag |= MAFTER;
  344. break;
  345. case 'b':
  346. flag |= MBEFORE;
  347. break;
  348. case 'c':
  349. flag |= MCREATE;
  350. break;
  351. default:
  352. return cliError(usage);
  353. }ARGEND
  354. if(argc != 2 || (flag&MAFTER)&&(flag&MBEFORE))
  355. return cliError(usage);
  356. if(bind(argv[0], argv[1], flag) < 0){
  357. /* try to give a less confusing error than the default */
  358. if(access(argv[0], 0) < 0)
  359. return cliError("bind: %s: %r", argv[0]);
  360. else if(access(argv[1], 0) < 0)
  361. return cliError("bind: %s: %r", argv[1]);
  362. else
  363. return cliError("bind %s %s: %r", argv[0], argv[1]);
  364. }
  365. return 1;
  366. }
  367. int
  368. cmdInit(void)
  369. {
  370. cbox.lock = vtLockAlloc();
  371. cbox.confd[0] = cbox.confd[1] = -1;
  372. cliAddCmd(".", cmdDot);
  373. cliAddCmd("9p", cmd9p);
  374. cliAddCmd("dflag", cmdDflag);
  375. cliAddCmd("echo", cmdEcho);
  376. cliAddCmd("bind", cmdBind);
  377. if(pipe(cbox.confd) < 0)
  378. return 0;
  379. if((cbox.con = conAlloc(cbox.confd[1], "console", 0)) == nil){
  380. close(cbox.confd[0]);
  381. close(cbox.confd[1]);
  382. cbox.confd[0] = cbox.confd[1] = -1;
  383. return 0;
  384. }
  385. cbox.con->isconsole = 1;
  386. return 1;
  387. }