Ccmd.c 8.3 KB

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