con.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853
  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 "all.h"
  10. static Command command[100];
  11. static Flag flag[35];
  12. static char statsdef[20]; /* default stats list */
  13. static int whoflag;
  14. static void consserve1(void *);
  15. static void installcmds(void);
  16. void
  17. consserve(void)
  18. {
  19. int i;
  20. strncpy(cons.chan->whochan, "console", sizeof(cons.chan->whochan));
  21. installcmds();
  22. con_session();
  23. cmd_exec("cfs");
  24. cmd_exec("users");
  25. cmd_exec("version");
  26. for(i = 0; command[i].arg0; i++)
  27. if(strcmp("cwcmd", command[i].arg0) == 0){
  28. cmd_exec("cwcmd touchsb");
  29. break;
  30. }
  31. newproc(consserve1, 0, "con");
  32. }
  33. /* console commands process */
  34. static void
  35. consserve1(void *)
  36. {
  37. char *conline;
  38. for (;;) {
  39. /* conslock(); */
  40. do {
  41. print("%s: ", service);
  42. if ((conline = Brdline(&bin, '\n')) == nil)
  43. print("\n");
  44. else {
  45. conline[Blinelen(&bin)-1] = '\0';
  46. cmd_exec(conline);
  47. }
  48. } while (conline != nil);
  49. }
  50. }
  51. static int
  52. cmdcmp(const void *va, const void *vb)
  53. {
  54. Command *a, *b;
  55. a = va;
  56. b = vb;
  57. return strcmp(a->arg0, b->arg0);
  58. }
  59. void
  60. cmd_install(char *arg0, char *help, void (*func)(int, char*[]))
  61. {
  62. int i;
  63. qlock(&cons);
  64. for(i=0; command[i].arg0; i++)
  65. ;
  66. if(i >= nelem(command)-2) {
  67. qunlock(&cons);
  68. print("cmd_install: too many commands\n");
  69. return;
  70. }
  71. command[i+1].arg0 = 0;
  72. command[i].help = help;
  73. command[i].func = func;
  74. command[i].arg0 = arg0;
  75. qsort(command, i+1, sizeof(Command), cmdcmp);
  76. qunlock(&cons);
  77. }
  78. void
  79. cmd_exec(char *arg)
  80. {
  81. char line[2*Maxword], *s;
  82. char *argv[10];
  83. int argc, i, c;
  84. if(strlen(arg) >= nelem(line)-2) {
  85. print("cmd_exec: line too long\n");
  86. return;
  87. }
  88. strcpy(line, arg);
  89. argc = 0;
  90. s = line;
  91. c = *s++;
  92. for(;;) {
  93. while(isascii(c) && isspace(c))
  94. c = *s++;
  95. if(c == 0)
  96. break;
  97. if(argc >= nelem(argv)-2) {
  98. print("cmd_exec: too many args\n");
  99. return;
  100. }
  101. argv[argc++] = s-1;
  102. while((!isascii(c) || !isspace(c)) && c != '\0')
  103. c = *s++;
  104. s[-1] = 0;
  105. }
  106. if(argc <= 0)
  107. return;
  108. for(i=0; s=command[i].arg0; i++)
  109. if(strcmp(argv[0], s) == 0) {
  110. (*command[i].func)(argc, argv);
  111. prflush();
  112. return;
  113. }
  114. print("cmd_exec: unknown command: %s\n", argv[0]);
  115. }
  116. static void
  117. cmd_halt(int, char *[])
  118. {
  119. wlock(&mainlock); /* halt */
  120. sync("halt");
  121. exit();
  122. }
  123. static void
  124. cmd_duallow(int argc, char *argv[])
  125. {
  126. int uid;
  127. if(argc <= 1) {
  128. duallow = 0;
  129. return;
  130. }
  131. uid = strtouid(argv[1]);
  132. if(uid < 0)
  133. uid = number(argv[1], -2, 10);
  134. if(uid < 0) {
  135. print("bad uid %s\n", argv[1]);
  136. return;
  137. }
  138. duallow = uid;
  139. }
  140. static void
  141. cmd_stats(int argc, char *argv[])
  142. {
  143. int i, c;
  144. char buf[30], *s, *p, *q;
  145. if(argc <= 1) {
  146. if(statsdef[0] == 0)
  147. strcpy(statsdef, "a");
  148. sprint(buf, "stats s%s", statsdef);
  149. cmd_exec(buf);
  150. return;
  151. }
  152. strcpy(buf, "stat");
  153. p = strchr(buf, 0);
  154. p[1] = 0;
  155. q = 0;
  156. for(i = 1; i < argc; i++)
  157. for(s = argv[i]; c = *s; s++) {
  158. if(c == 's')
  159. continue;
  160. if(c == '-') {
  161. q = statsdef;
  162. continue;
  163. }
  164. if(q) {
  165. *q++ = c;
  166. *q = 0;
  167. }
  168. *p = c;
  169. cmd_exec(buf);
  170. }
  171. }
  172. static void
  173. cmd_stata(int, char *[])
  174. {
  175. int i;
  176. print("cons stats\n");
  177. // print("\twork =%7W%7W%7W rps\n", cons.work+0, cons.work+1, cons.work+2);
  178. // print("\trate =%7W%7W%7W tBps\n", cons.rate+0, cons.rate+1, cons.rate+2);
  179. // print("\thits =%7W%7W%7W iops\n", cons.bhit+0, cons.bhit+1, cons.bhit+2);
  180. // print("\tread =%7W%7W%7W iops\n", cons.bread+0, cons.bread+1, cons.bread+2);
  181. // print("\trah =%7W%7W%7W iops\n", cons.brahead+0, cons.brahead+1, cons.brahead+2);
  182. // print("\tinit =%7W%7W%7W iops\n", cons.binit+0, cons.binit+1, cons.binit+2);
  183. print("\tbufs = %3ld sm %3ld lg %ld res\n",
  184. cons.nsmall, cons.nlarge, cons.nreseq);
  185. for(i=0; i<nelem(mballocs); i++)
  186. if(mballocs[i])
  187. print("\t[%d]=%d\n", i, mballocs[i]);
  188. print("\tioerr= %3ld wr %3ld ww %3ld dr %3ld dw\n",
  189. cons.nwormre, cons.nwormwe, cons.nwrenre, cons.nwrenwe);
  190. print("\tcache= %9ld hit %9ld miss\n",
  191. cons.nwormhit, cons.nwormmiss);
  192. }
  193. static int
  194. flagcmp(const void *va, const void *vb)
  195. {
  196. Flag *a, *b;
  197. a = va;
  198. b = vb;
  199. return strcmp(a->arg0, b->arg0);
  200. }
  201. uint32_t
  202. flag_install(char *arg, char *help)
  203. {
  204. int i;
  205. qlock(&cons);
  206. for(i=0; flag[i].arg0; i++)
  207. ;
  208. if(i >= 32) {
  209. qunlock(&cons);
  210. print("flag_install: too many flags\n");
  211. return 0;
  212. }
  213. flag[i+1].arg0 = 0;
  214. flag[i].arg0 = arg;
  215. flag[i].help = help;
  216. flag[i].flag = 1<<i;
  217. qsort(flag, i+1, sizeof(Flag), flagcmp);
  218. qunlock(&cons);
  219. return 1<<i;
  220. }
  221. void
  222. cmd_flag(int argc, char *argv[])
  223. {
  224. int f, n, i, j;
  225. char *s;
  226. Chan *cp;
  227. if(argc <= 1) {
  228. for(i=0; flag[i].arg0; i++)
  229. print("%.4lux %s %s\n",
  230. flag[i].flag, flag[i].arg0, flag[i].help);
  231. if(cons.flags)
  232. print("flag[*] = %.4lux\n", cons.flags);
  233. for(cp = chans; cp; cp = cp->next)
  234. if(cp->flags)
  235. print("flag[%3d] = %.4lux\n", cp->chan, cp->flags);
  236. return;
  237. }
  238. f = 0;
  239. n = -1;
  240. for(i=1; i<argc; i++) {
  241. for(j=0; s=flag[j].arg0; j++)
  242. if(strcmp(s, argv[i]) == 0)
  243. goto found;
  244. j = number(argv[i], -1, 10);
  245. if(j < 0) {
  246. print("bad flag argument: %s\n", argv[i]);
  247. continue;
  248. }
  249. n = j;
  250. continue;
  251. found:
  252. f |= flag[j].flag;
  253. }
  254. if(n < 0) {
  255. cons.flags ^= f;
  256. if(f == 0)
  257. cons.flags = 0;
  258. print("flag = %.8lux\n", cons.flags);
  259. return;
  260. }
  261. for(cp = chans; cp; cp = cp->next)
  262. if(cp->chan == n) {
  263. cp->flags ^= f;
  264. if(f == 0)
  265. cp->flags = 0;
  266. print("flag[%3d] = %.8lux\n", cp->chan, cp->flags);
  267. return;
  268. }
  269. print("no such channel\n");
  270. }
  271. static void
  272. cmd_who(int argc, char *argv[])
  273. {
  274. Chan *cp;
  275. int i, c;
  276. c = 0;
  277. for(cp = chans; cp; cp = cp->next) {
  278. if(cp->whotime == 0 && !(cons.flags & whoflag)) {
  279. c++;
  280. continue;
  281. }
  282. if(argc > 1) {
  283. for(i=1; i<argc; i++)
  284. if(strcmp(argv[i], cp->whoname) == 0)
  285. break;
  286. if(i >= argc) {
  287. c++;
  288. continue;
  289. }
  290. }
  291. print("%3d: %10s %24s", cp->chan,
  292. cp->whoname? cp->whoname: "<nowhoname>", cp->whochan);
  293. if(cp->whoprint)
  294. cp->whoprint(cp);
  295. print("\n");
  296. prflush();
  297. }
  298. if(c > 0)
  299. print("%d chans not listed\n", c);
  300. }
  301. static void
  302. cmd_hangup(int argc, char *argv[])
  303. {
  304. Chan *cp;
  305. int n;
  306. if(argc < 2) {
  307. print("usage: hangup chan-number\n");
  308. return;
  309. }
  310. n = number(argv[1], -1, 10);
  311. for(cp = chans; cp; cp = cp->next) {
  312. if(cp->whotime == 0) {
  313. if(cp->chan == n)
  314. print("that chan is hung up\n");
  315. continue;
  316. }
  317. if(cp->chan == n) {
  318. /* need more than just fileinit with tcp */
  319. chanhangup(cp, "console command", 1);
  320. fileinit(cp);
  321. }
  322. }
  323. }
  324. static void
  325. cmd_sync(int, char *[])
  326. {
  327. wlock(&mainlock); /* sync */
  328. sync("command");
  329. wunlock(&mainlock);
  330. print("\n");
  331. }
  332. static void
  333. cmd_help(int argc, char *argv[])
  334. {
  335. char *arg;
  336. int i, j;
  337. for(i=0; arg=command[i].arg0; i++) {
  338. if(argc > 1) {
  339. for(j=1; j<argc; j++)
  340. if(strcmp(argv[j], arg) == 0)
  341. goto found;
  342. continue;
  343. }
  344. found:
  345. print("\t%s %s\n", arg, command[i].help);
  346. prflush();
  347. }
  348. }
  349. void
  350. cmd_fstat(int argc, char *argv[])
  351. {
  352. int i;
  353. for(i=1; i<argc; i++) {
  354. if(walkto(argv[i])) {
  355. print("cant stat %s\n", argv[i]);
  356. continue;
  357. }
  358. con_fstat(FID2);
  359. }
  360. }
  361. void
  362. cmd_create(int argc, char *argv[])
  363. {
  364. int uid, gid;
  365. int32_t perm;
  366. char elem[NAMELEN], *p;
  367. if(argc < 5) {
  368. print("usage: create path uid gid mode [lad]\n");
  369. return;
  370. }
  371. p = utfrrune(argv[1], '/');
  372. if(p) {
  373. *p++ = 0;
  374. if(walkto(argv[1])) {
  375. print("create failed in walkto: %s\n", p);
  376. return;
  377. }
  378. } else {
  379. if(walkto("/"))
  380. return;
  381. p = argv[1];
  382. }
  383. if(strlen(p) >= NAMELEN) {
  384. print("name too long %s\n", p);
  385. return;
  386. }
  387. memset(elem, 0, sizeof(elem));
  388. strcpy(elem, p);
  389. uid = strtouid(argv[2]);
  390. if(uid < -1)
  391. uid = number(argv[2], -2, 10);
  392. if(uid < -1) {
  393. print("bad uid %s\n", argv[2]);
  394. return;
  395. }
  396. gid = strtouid(argv[3]);
  397. if(gid < -1)
  398. gid = number(argv[3], -2, 10);
  399. if(gid < -1) {
  400. print("bad gid %s\n", argv[3]);
  401. return;
  402. }
  403. perm = number(argv[4], 0777, 8) & 0777;
  404. if(argc > 5) {
  405. if(strchr(argv[5], 'l'))
  406. perm |= PLOCK;
  407. if(strchr(argv[5], 'a'))
  408. perm |= PAPND;
  409. if(strchr(argv[5], 'd'))
  410. perm |= PDIR;
  411. }
  412. if(con_create(FID2, elem, uid, gid, perm, 0))
  413. print("create failed: %s/%s\n", argv[1], p);
  414. }
  415. static void
  416. cmd_clri(int argc, char *argv[])
  417. {
  418. int i;
  419. for(i=1; i<argc; i++) {
  420. if(walkto(argv[i])) {
  421. print("cant remove %s\n", argv[i]);
  422. continue;
  423. }
  424. con_clri(FID2);
  425. }
  426. }
  427. static void
  428. cmd_allow(int, char**)
  429. {
  430. wstatallow = writeallow = 1;
  431. }
  432. static void
  433. cmd_disallow(int, char**)
  434. {
  435. wstatallow = writeallow = 0;
  436. }
  437. void
  438. ckblock(Device *d, Off a, int typ, Off qpath)
  439. {
  440. Iobuf *p;
  441. if(a) {
  442. p = getbuf(d, a, Brd);
  443. if(p) {
  444. checktag(p, typ, qpath);
  445. putbuf(p);
  446. }
  447. }
  448. }
  449. void
  450. doclean(Iobuf *p, Dentry *d, int n, Off a)
  451. {
  452. int i, mod, typ;
  453. Off qpath;
  454. mod = 0;
  455. qpath = d->qid.path;
  456. typ = Tfile;
  457. if(d->mode & DDIR)
  458. typ = Tdir;
  459. for(i=0; i<NDBLOCK; i++) {
  460. print("dblock[%d] = %lld\n", i, (Wideoff)d->dblock[i]);
  461. ckblock(p->dev, d->dblock[i], typ, qpath);
  462. if(i == n) {
  463. d->dblock[i] = a;
  464. mod = 1;
  465. print("dblock[%d] modified %lld\n", i, (Wideoff)a);
  466. }
  467. }
  468. /* add NDBLOCK so user can cite block address by index */
  469. for (i = 0; i < NIBLOCK; i++) {
  470. print("iblocks[%d] = %lld\n", NDBLOCK+i, (Wideoff)d->iblocks[i]);
  471. ckblock(p->dev, d->iblocks[i], Tind1+i, qpath);
  472. if(NDBLOCK+i == n) {
  473. d->iblocks[i] = a;
  474. mod = 1;
  475. print("iblocks[%d] modified %lld\n", NDBLOCK+i, (Wideoff)a);
  476. }
  477. }
  478. if(mod)
  479. p->flags |= Bmod|Bimm;
  480. }
  481. static void
  482. cmd_clean(int argc, char *argv[])
  483. {
  484. int n;
  485. Off a;
  486. Iobuf *p;
  487. Dentry *d;
  488. File *f;
  489. p = 0;
  490. f = 0;
  491. while(argc > 1) {
  492. n = -1;
  493. if(argc > 2)
  494. n = number(argv[2], -1, 10);
  495. a = 0;
  496. if(argc > 3)
  497. a = number(argv[3], 0, 10);
  498. if(walkto(argv[1])) {
  499. print("cant remove %s\n", argv[1]);
  500. break;
  501. }
  502. f = filep(cons.chan, FID2, 0);
  503. if(!f)
  504. break;
  505. if(n >= 0 && f->fs->dev->type == Devro) {
  506. print("readonly %s\n", argv[1]);
  507. break;
  508. }
  509. p = getbuf(f->fs->dev, f->addr, Brd);
  510. d = getdir(p, f->slot);
  511. if(!d || !(d->mode & DALLOC)) {
  512. print("not alloc %s\n", argv[1]);
  513. break;
  514. }
  515. doclean(p, d, n, a);
  516. break;
  517. }
  518. if(f)
  519. qunlock(f);
  520. if(p)
  521. putbuf(p);
  522. }
  523. static void
  524. cmd_remove(int argc, char *argv[])
  525. {
  526. int i;
  527. for(i=1; i<argc; i++) {
  528. if(walkto(argv[i])) {
  529. print("cant remove %s\n", argv[i]);
  530. continue;
  531. }
  532. con_remove(FID2);
  533. }
  534. }
  535. static void
  536. cmd_version(int, char *[])
  537. {
  538. print("%d-bit %s as of %T\n", sizeof(Off)*8 - 1, service, fs_mktime);
  539. print("\tlast boot %T\n", boottime);
  540. }
  541. static void
  542. cmd_cfs(int argc, char *argv[])
  543. {
  544. Filsys *fs;
  545. char *name;
  546. name = "main";
  547. if(argc > 1)
  548. name = argv[1];
  549. fs = fsstr(name);
  550. if(fs == 0) {
  551. print("%s: unknown file system\n", name);
  552. if(cons.curfs)
  553. return;
  554. fs = &filsys[0];
  555. }
  556. if(con_attach(FID1, "adm", fs->name))
  557. panic("FID1 attach to root");
  558. cons.curfs = fs;
  559. print("current fs is \"%s\"\n", cons.curfs->name);
  560. }
  561. static void
  562. cmd_prof(int argc, char *argv[])
  563. {
  564. int n;
  565. int32_t m, o;
  566. char *p;
  567. if(cons.profbuf == 0) {
  568. print("no buffer\n");
  569. return;
  570. }
  571. n = !cons.profile;
  572. if(argc > 1)
  573. n = number(argv[1], n, 10);
  574. if(n && !cons.profile) {
  575. print("clr and start\n");
  576. memset(cons.profbuf, 0, cons.nprofbuf*sizeof(cons.profbuf[0]));
  577. cons.profile = 1;
  578. return;
  579. }
  580. if(!n && cons.profile) {
  581. cons.profile = 0;
  582. print("stop and write\n");
  583. if(walkto("/adm/kprofdata"))
  584. goto bad;
  585. if(con_open(FID2, OWRITE|OTRUNC)) {
  586. bad:
  587. print("cant open /adm/kprofdata\n");
  588. return;
  589. }
  590. p = (char*)cons.profbuf;
  591. for(m=0; m<cons.nprofbuf; m++) {
  592. n = cons.profbuf[m];
  593. p[0] = n>>24;
  594. p[1] = n>>16;
  595. p[2] = n>>8;
  596. p[3] = n>>0;
  597. p += 4;
  598. }
  599. m = cons.nprofbuf*sizeof(cons.profbuf[0]);
  600. o = 0;
  601. while(m > 0) {
  602. n = 8192;
  603. if(n > m)
  604. n = m;
  605. con_write(FID2, (char*)cons.profbuf+o, o, n);
  606. m -= n;
  607. o += n;
  608. }
  609. return;
  610. }
  611. }
  612. static void
  613. cmd_time(int argc, char *argv[])
  614. {
  615. int i, len;
  616. char *cmd;
  617. Timet t1, t2;
  618. t1 = time(nil);
  619. len = 0;
  620. for(i=1; i<argc; i++)
  621. len += 1 + strlen(argv[i]);
  622. cmd = malloc(len + 1);
  623. cmd[0] = 0;
  624. for(i=1; i<argc; i++) {
  625. strcat(cmd, " ");
  626. strcat(cmd, argv[i]);
  627. }
  628. cmd_exec(cmd);
  629. t2 = time(nil);
  630. free(cmd);
  631. print("time = %ld ms\n", TK2MS(t2-t1));
  632. }
  633. void
  634. cmd_noattach(int, char *[])
  635. {
  636. noattach = !noattach;
  637. if(noattach)
  638. print("attaches are DISABLED\n");
  639. }
  640. void
  641. cmd_files(int, char *[])
  642. {
  643. int32_t i, n;
  644. Chan *cp;
  645. for(cp = chans; cp; cp = cp->next)
  646. cp->nfile = 0;
  647. lock(&flock);
  648. n = 0;
  649. for(i=0; i<conf.nfile; i++)
  650. if(files[i].cp) {
  651. n++;
  652. files[i].cp->nfile++;
  653. }
  654. print("%ld out of %ld files used\n", n, conf.nfile);
  655. unlock(&flock);
  656. n = 0;
  657. for(cp = chans; cp; cp = cp->next)
  658. if(cp->nfile) {
  659. print("%3d: %5d\n", cp->chan, cp->nfile);
  660. prflush();
  661. n += cp->nfile;
  662. }
  663. print("%ld out of %ld files used\n", n, conf.nfile);
  664. }
  665. static void
  666. installcmds(void)
  667. {
  668. cmd_install("allow", "-- disable permission checking", cmd_allow);
  669. cmd_install("cfs", "[file] -- set current filesystem", cmd_cfs);
  670. cmd_install("clean", "file [bno [addr]] -- block print/fix", cmd_clean);
  671. cmd_install("check", "[options]", cmd_check);
  672. cmd_install("clri", "[file ...] -- purge files/dirs", cmd_clri);
  673. cmd_install("create", "path uid gid perm [lad] -- make a file/dir", cmd_create);
  674. cmd_install("disallow", "-- enable permission checking", cmd_disallow);
  675. cmd_install("duallow", "uid -- duallow", cmd_duallow);
  676. cmd_install("flag", "-- print set flags", cmd_flag);
  677. cmd_install("fstat", "path -- print info on a file/dir", cmd_fstat);
  678. cmd_install("halt", "-- return to boot rom", cmd_halt);
  679. cmd_install("help", "", cmd_help);
  680. cmd_install("newuser", "username -- add user to /adm/users", cmd_newuser);
  681. cmd_install("profile", "[01] -- fs profile", cmd_prof);
  682. cmd_install("remove", "[file ...] -- remove files/dirs", cmd_remove);
  683. cmd_install("stata", "-- overall stats", cmd_stata);
  684. cmd_install("stats", "[[-]flags ...] -- various stats", cmd_stats);
  685. cmd_install("sync", "", cmd_sync);
  686. cmd_install("time", "command -- time another command", cmd_time);
  687. cmd_install("users", "[file] -- read /adm/users", cmd_users);
  688. cmd_install("version", "-- print time of mk and boot", cmd_version);
  689. cmd_install("who", "[user ...] -- print attaches", cmd_who);
  690. cmd_install("hangup", "chan -- clunk files", cmd_hangup);
  691. cmd_install("printconf", "-- print configuration", cmd_printconf);
  692. cmd_install("noattach", "toggle noattach flag", cmd_noattach);
  693. cmd_install("files", "report on files structure", cmd_files);
  694. attachflag = flag_install("attach", "-- attach calls");
  695. chatflag = flag_install("chat", "-- verbose");
  696. errorflag = flag_install("error", "-- on errors");
  697. whoflag = flag_install("allchans", "-- on who");
  698. authdebugflag = flag_install("authdebug", "-- report authentications");
  699. authdisableflag = flag_install("authdisable", "-- disable authentication");
  700. }
  701. int
  702. walkto(char *name)
  703. {
  704. char elem[NAMELEN], *p;
  705. int n;
  706. if(con_clone(FID1, FID2))
  707. return 1;
  708. for(;;) {
  709. p = utfrune(name, '/');
  710. if(p == nil)
  711. p = strchr(name, '\0');
  712. if(p == name) {
  713. if(*name == '\0')
  714. return 0;
  715. name = p+1;
  716. continue;
  717. }
  718. n = p-name;
  719. if(n > NAMELEN)
  720. return 1;
  721. memset(elem, 0, sizeof(elem));
  722. memmove(elem, name, n);
  723. if(con_walk(FID2, elem))
  724. return 1;
  725. name = p;
  726. }
  727. }
  728. /* needs to parse and return vlongs to cope with new larger block numbers */
  729. int64_t
  730. number(char *arg, int def, int base)
  731. {
  732. int c, sign, any;
  733. int64_t n;
  734. if(arg == nil)
  735. return def;
  736. sign = 0;
  737. any = 0;
  738. n = 0;
  739. for (c = *arg; isascii(c) && isspace(c) && c != '\n'; c = *arg)
  740. arg++;
  741. if(c == '-') {
  742. sign = 1;
  743. arg++;
  744. c = *arg;
  745. }
  746. while (isascii(c) && (isdigit(c) || base == 16 && isxdigit(c))) {
  747. n *= base;
  748. if(c >= 'a' && c <= 'f')
  749. n += c - 'a' + 10;
  750. else if(c >= 'A' && c <= 'F')
  751. n += c - 'A' + 10;
  752. else
  753. n += c - '0';
  754. arg++;
  755. c = *arg;
  756. any = 1;
  757. }
  758. if(!any)
  759. return def;
  760. if(sign)
  761. n = -n;
  762. return n;
  763. }