con.c 15 KB

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