subr_userconf.c 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363
  1. /* $OpenBSD: subr_userconf.c,v 1.43 2014/11/03 03:08:00 deraadt Exp $ */
  2. /*
  3. * Copyright (c) 1996-2001 Mats O Jansson <moj@stacken.kth.se>
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
  16. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  17. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  19. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  21. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  22. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  23. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  24. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  25. * SUCH DAMAGE.
  26. */
  27. #include <sys/param.h>
  28. #include <sys/systm.h>
  29. #include <sys/device.h>
  30. #include <sys/malloc.h>
  31. #include <sys/time.h>
  32. #include <dev/cons.h>
  33. extern char *locnames[];
  34. extern short locnamp[];
  35. extern short cfroots[];
  36. extern int cfroots_size;
  37. extern int pv_size;
  38. extern short pv[];
  39. extern struct timezone tz;
  40. extern char *pdevnames[];
  41. extern int pdevnames_size;
  42. extern struct pdevinit pdevinit[];
  43. int userconf_base = 16; /* Base for "large" numbers */
  44. int userconf_maxdev = -1; /* # of used device slots */
  45. int userconf_totdev = -1; /* # of device slots */
  46. int userconf_maxlocnames = -1; /* # of locnames */
  47. int userconf_cnt = -1; /* Line counter for ... */
  48. int userconf_lines = 12; /* ... # of lines per page */
  49. int userconf_histlen = 0;
  50. int userconf_histcur = 0;
  51. char userconf_history[1024];
  52. int userconf_histsz = sizeof(userconf_history);
  53. char userconf_argbuf[40]; /* Additional input */
  54. char userconf_cmdbuf[40]; /* Command line */
  55. char userconf_histbuf[40];
  56. void userconf_init(void);
  57. int userconf_more(void);
  58. void userconf_modify(char *, int *);
  59. void userconf_hist_cmd(char);
  60. void userconf_hist_int(int);
  61. void userconf_hist_eoc(void);
  62. void userconf_pnum(int);
  63. void userconf_pdevnam(short);
  64. void userconf_pdev(short);
  65. int userconf_number(char *, int *);
  66. int userconf_device(char *, int *, short *, short *);
  67. int userconf_attr(char *, int *);
  68. void userconf_modify(char *, int *);
  69. void userconf_change(int);
  70. void userconf_disable(int);
  71. void userconf_enable(int);
  72. void userconf_help(void);
  73. void userconf_list(void);
  74. void userconf_show(void);
  75. void userconf_common_attr_val(short, int *, char);
  76. void userconf_show_attr(char *);
  77. void userconf_common_dev(char *, int, short, short, char);
  78. void userconf_common_attr(char *, int, char);
  79. void userconf_add_read(char *, char, char *, int, int *);
  80. void userconf_add(char *, int, short, short);
  81. int userconf_parse(char *);
  82. #define UC_CHANGE 'c'
  83. #define UC_DISABLE 'd'
  84. #define UC_ENABLE 'e'
  85. #define UC_FIND 'f'
  86. #define UC_SHOW 's'
  87. char *userconf_cmds[] = {
  88. "add", "a",
  89. "base", "b",
  90. "change", "c",
  91. #if defined(DDB)
  92. "ddb", "D",
  93. #endif
  94. "disable", "d",
  95. "enable", "e",
  96. "exit", "q",
  97. "find", "f",
  98. "help", "h",
  99. "list", "l",
  100. "lines", "L",
  101. "quit", "q",
  102. "show", "s",
  103. "timezone", "t",
  104. "verbose", "v",
  105. "?", "h",
  106. "", "",
  107. };
  108. void
  109. userconf_init(void)
  110. {
  111. int i = 0;
  112. struct cfdata *cd;
  113. int ln;
  114. while (cfdata[i].cf_attach != 0) {
  115. userconf_maxdev = i;
  116. userconf_totdev = i;
  117. cd = &cfdata[i];
  118. ln = cd->cf_locnames;
  119. while (locnamp[ln] != -1) {
  120. if (locnamp[ln] > userconf_maxlocnames)
  121. userconf_maxlocnames = locnamp[ln];
  122. ln++;
  123. }
  124. i++;
  125. }
  126. while (cfdata[i].cf_attach == 0) {
  127. userconf_totdev = i;
  128. i++;
  129. }
  130. userconf_totdev = userconf_totdev - 1;
  131. }
  132. int
  133. userconf_more(void)
  134. {
  135. int quit = 0;
  136. char c = '\0';
  137. if (userconf_cnt != -1) {
  138. if (userconf_cnt == userconf_lines) {
  139. printf("--- more ---");
  140. c = cngetc();
  141. userconf_cnt = 0;
  142. printf("\r \r");
  143. }
  144. userconf_cnt++;
  145. if (c == 'q' || c == 'Q')
  146. quit = 1;
  147. }
  148. return (quit);
  149. }
  150. void
  151. userconf_hist_cmd(char cmd)
  152. {
  153. userconf_histcur = userconf_histlen;
  154. if (userconf_histcur < userconf_histsz) {
  155. userconf_history[userconf_histcur] = cmd;
  156. userconf_histcur++;
  157. }
  158. }
  159. void
  160. userconf_hist_int(int val)
  161. {
  162. snprintf(userconf_histbuf, sizeof userconf_histbuf, " %d",val);
  163. if (userconf_histcur + strlen(userconf_histbuf) < userconf_histsz) {
  164. bcopy(userconf_histbuf,
  165. &userconf_history[userconf_histcur],
  166. strlen(userconf_histbuf));
  167. userconf_histcur = userconf_histcur + strlen(userconf_histbuf);
  168. }
  169. }
  170. void
  171. userconf_hist_eoc(void)
  172. {
  173. if (userconf_histcur < userconf_histsz) {
  174. userconf_history[userconf_histcur] = '\n';
  175. userconf_histcur++;
  176. userconf_histlen = userconf_histcur;
  177. }
  178. }
  179. void
  180. userconf_pnum(int val)
  181. {
  182. if (val > -2 && val < 16) {
  183. printf("%d",val);
  184. return;
  185. }
  186. switch (userconf_base) {
  187. case 8:
  188. printf("0%o",val);
  189. break;
  190. case 10:
  191. printf("%d",val);
  192. break;
  193. case 16:
  194. default:
  195. printf("0x%x",val);
  196. break;
  197. }
  198. }
  199. void
  200. userconf_pdevnam(short dev)
  201. {
  202. struct cfdata *cd;
  203. cd = &cfdata[dev];
  204. printf("%s", cd->cf_driver->cd_name);
  205. switch (cd->cf_fstate) {
  206. case FSTATE_NOTFOUND:
  207. case FSTATE_DNOTFOUND:
  208. printf("%d", cd->cf_unit);
  209. break;
  210. case FSTATE_FOUND:
  211. printf("*FOUND*");
  212. break;
  213. case FSTATE_STAR:
  214. case FSTATE_DSTAR:
  215. printf("*");
  216. break;
  217. default:
  218. printf("*UNKNOWN*");
  219. break;
  220. }
  221. }
  222. void
  223. userconf_pdev(short devno)
  224. {
  225. struct cfdata *cd;
  226. short *p;
  227. int *l;
  228. int ln;
  229. char c;
  230. if (devno > userconf_maxdev && devno <= userconf_totdev) {
  231. printf("%3d free slot (for add)\n", devno);
  232. return;
  233. }
  234. if (devno > userconf_totdev &&
  235. devno <= userconf_totdev+pdevnames_size) {
  236. printf("%3d %s count %d", devno,
  237. pdevnames[devno-userconf_totdev-1],
  238. abs(pdevinit[devno-userconf_totdev-1].pdev_count));
  239. if (pdevinit[devno-userconf_totdev-1].pdev_count < 1)
  240. printf(" disable");
  241. printf(" (pseudo device)\n");
  242. return;
  243. }
  244. if (devno > userconf_maxdev) {
  245. printf("Unknown devno (max is %d)\n", userconf_maxdev);
  246. return;
  247. }
  248. cd = &cfdata[devno];
  249. printf("%3d ", devno);
  250. userconf_pdevnam(devno);
  251. printf(" at");
  252. c = ' ';
  253. p = cd->cf_parents;
  254. if (*p == -1)
  255. printf(" root");
  256. while (*p != -1) {
  257. printf("%c", c);
  258. userconf_pdevnam(*p++);
  259. c = '|';
  260. }
  261. switch (cd->cf_fstate) {
  262. case FSTATE_NOTFOUND:
  263. case FSTATE_FOUND:
  264. case FSTATE_STAR:
  265. break;
  266. case FSTATE_DNOTFOUND:
  267. case FSTATE_DSTAR:
  268. printf(" disable");
  269. break;
  270. default:
  271. printf(" ???");
  272. break;
  273. }
  274. l = cd->cf_loc;
  275. ln = cd->cf_locnames;
  276. while (locnamp[ln] != -1) {
  277. printf(" %s ", locnames[locnamp[ln]]);
  278. ln++;
  279. userconf_pnum(*l++);
  280. }
  281. printf(" flags 0x%x\n", cd->cf_flags);
  282. }
  283. int
  284. userconf_number(char *c, int *val)
  285. {
  286. u_int num = 0;
  287. int neg = 0;
  288. int base = 10;
  289. if (*c == '-') {
  290. neg = 1;
  291. c++;
  292. }
  293. if (*c == '0') {
  294. base = 8;
  295. c++;
  296. if (*c == 'x' || *c == 'X') {
  297. base = 16;
  298. c++;
  299. }
  300. }
  301. while (*c != '\n' && *c != '\t' && *c != ' ' && *c != '\0') {
  302. u_char cc = *c;
  303. if (cc >= '0' && cc <= '9')
  304. cc = cc - '0';
  305. else if (cc >= 'a' && cc <= 'f')
  306. cc = cc - 'a' + 10;
  307. else if (cc >= 'A' && cc <= 'F')
  308. cc = cc - 'A' + 10;
  309. else
  310. return (-1);
  311. if (cc > base)
  312. return (-1);
  313. num = num * base + cc;
  314. c++;
  315. }
  316. if (neg && num > INT_MAX) /* overflow */
  317. return (1);
  318. *val = neg ? - num : num;
  319. return (0);
  320. }
  321. int
  322. userconf_device(char *cmd, int *len, short *unit, short *state)
  323. {
  324. short u = 0, s = FSTATE_FOUND;
  325. int l = 0;
  326. char *c;
  327. c = cmd;
  328. while (*c >= 'a' && *c <= 'z') {
  329. l++;
  330. c++;
  331. }
  332. if (*c == '*') {
  333. s = FSTATE_STAR;
  334. c++;
  335. } else {
  336. while (*c >= '0' && *c <= '9') {
  337. s = FSTATE_NOTFOUND;
  338. u = u*10 + *c - '0';
  339. c++;
  340. }
  341. }
  342. while (*c == ' ' || *c == '\t' || *c == '\n')
  343. c++;
  344. if (*c == '\0') {
  345. *len = l;
  346. *unit = u;
  347. *state = s;
  348. return(0);
  349. }
  350. return(-1);
  351. }
  352. int
  353. userconf_attr(char *cmd, int *val)
  354. {
  355. char *c;
  356. short attr = -1, i = 0, l = 0;
  357. c = cmd;
  358. while (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\0') {
  359. c++;
  360. l++;
  361. }
  362. while (i <= userconf_maxlocnames) {
  363. if (strlen(locnames[i]) == l) {
  364. if (strncasecmp(cmd, locnames[i], l) == 0)
  365. attr = i;
  366. }
  367. i++;
  368. }
  369. if (attr == -1) {
  370. return (-1);
  371. }
  372. *val = attr;
  373. return(0);
  374. }
  375. void
  376. userconf_modify(char *item, int *val)
  377. {
  378. int ok = 0;
  379. int a;
  380. char *c;
  381. int i;
  382. while (!ok) {
  383. printf("%s [", item);
  384. userconf_pnum(*val);
  385. printf("] ? ");
  386. i = getsn(userconf_argbuf, sizeof(userconf_argbuf));
  387. c = userconf_argbuf;
  388. while (*c == ' ' || *c == '\t' || *c == '\n') c++;
  389. if (*c != '\0') {
  390. if (userconf_number(c, &a) == 0) {
  391. *val = a;
  392. ok = 1;
  393. } else {
  394. printf("Unknown argument\n");
  395. }
  396. } else {
  397. ok = 1;
  398. }
  399. }
  400. }
  401. void
  402. userconf_change(int devno)
  403. {
  404. struct cfdata *cd;
  405. char c = '\0';
  406. int *l;
  407. int ln;
  408. if (devno <= userconf_maxdev) {
  409. userconf_pdev(devno);
  410. while (c != 'y' && c != 'Y' && c != 'n' && c != 'N') {
  411. printf("change (y/n) ?");
  412. c = cngetc();
  413. printf("\n");
  414. }
  415. if (c == 'y' || c == 'Y') {
  416. int share = 0, i, *lk, lklen;
  417. /* XXX add cmd 'c' <devno> */
  418. userconf_hist_cmd('c');
  419. userconf_hist_int(devno);
  420. cd = &cfdata[devno];
  421. l = cd->cf_loc;
  422. ln = cd->cf_locnames;
  423. /*
  424. * Search for some other driver sharing this
  425. * locator table. if one does, we may need to
  426. * replace the locators with a malloc'd copy.
  427. */
  428. for (i = 0; cfdata[i].cf_driver; i++)
  429. if (i != devno && cfdata[i].cf_loc == l)
  430. share = 1;
  431. if (share) {
  432. for (i = 0; locnamp[ln+i] != -1 ; i++)
  433. ;
  434. lk = l = mallocarray(i, sizeof(int),
  435. M_TEMP, M_NOWAIT);
  436. if (lk == NULL) {
  437. printf("out of memory.\n");
  438. return;
  439. }
  440. lklen = i * sizeof(int);
  441. bcopy(cd->cf_loc, l, lklen);
  442. }
  443. while (locnamp[ln] != -1) {
  444. userconf_modify(locnames[locnamp[ln]], l);
  445. /* XXX add *l */
  446. userconf_hist_int(*l);
  447. ln++;
  448. l++;
  449. }
  450. userconf_modify("flags", &cd->cf_flags);
  451. userconf_hist_int(cd->cf_flags);
  452. if (share) {
  453. if (memcmp(cd->cf_loc, lk, lklen))
  454. cd->cf_loc = lk;
  455. else
  456. free(lk, M_TEMP, lklen);
  457. }
  458. printf("%3d ", devno);
  459. userconf_pdevnam(devno);
  460. printf(" changed\n");
  461. userconf_pdev(devno);
  462. }
  463. return;
  464. }
  465. if (devno > userconf_maxdev && devno <= userconf_totdev) {
  466. printf("%3d can't change free slot\n", devno);
  467. return;
  468. }
  469. if (devno > userconf_totdev &&
  470. devno <= userconf_totdev+pdevnames_size) {
  471. userconf_pdev(devno);
  472. while (c != 'y' && c != 'Y' && c != 'n' && c != 'N') {
  473. printf("change (y/n) ?");
  474. c = cngetc();
  475. printf("\n");
  476. }
  477. if (c == 'y' || c == 'Y') {
  478. /* XXX add cmd 'c' <devno> */
  479. userconf_hist_cmd('c');
  480. userconf_hist_int(devno);
  481. userconf_modify("count",
  482. &pdevinit[devno-userconf_totdev-1].pdev_count);
  483. userconf_hist_int(pdevinit[devno-userconf_totdev-1].pdev_count);
  484. printf("%3d %s changed\n", devno,
  485. pdevnames[devno-userconf_totdev-1]);
  486. userconf_pdev(devno);
  487. /* XXX add eoc */
  488. userconf_hist_eoc();
  489. }
  490. return;
  491. }
  492. printf("Unknown devno (max is %d)\n", userconf_totdev+pdevnames_size);
  493. }
  494. void
  495. userconf_disable(int devno)
  496. {
  497. int done = 0;
  498. if (devno <= userconf_maxdev) {
  499. switch (cfdata[devno].cf_fstate) {
  500. case FSTATE_NOTFOUND:
  501. cfdata[devno].cf_fstate = FSTATE_DNOTFOUND;
  502. break;
  503. case FSTATE_STAR:
  504. cfdata[devno].cf_fstate = FSTATE_DSTAR;
  505. break;
  506. case FSTATE_DNOTFOUND:
  507. case FSTATE_DSTAR:
  508. done = 1;
  509. break;
  510. default:
  511. printf("Error unknown state\n");
  512. break;
  513. }
  514. printf("%3d ", devno);
  515. userconf_pdevnam(devno);
  516. if (done) {
  517. printf(" already");
  518. } else {
  519. /* XXX add cmd 'd' <devno> eoc */
  520. userconf_hist_cmd('d');
  521. userconf_hist_int(devno);
  522. userconf_hist_eoc();
  523. }
  524. printf(" disabled\n");
  525. return;
  526. }
  527. if (devno > userconf_maxdev && devno <= userconf_totdev) {
  528. printf("%3d can't disable free slot\n", devno);
  529. return;
  530. }
  531. if (devno > userconf_totdev &&
  532. devno <= userconf_totdev+pdevnames_size) {
  533. printf("%3d %s", devno, pdevnames[devno-userconf_totdev-1]);
  534. if (pdevinit[devno-userconf_totdev-1].pdev_count < 1) {
  535. printf(" already ");
  536. } else {
  537. pdevinit[devno-userconf_totdev-1].pdev_count *= -1;
  538. /* XXX add cmd 'd' <devno> eoc */
  539. userconf_hist_cmd('d');
  540. userconf_hist_int(devno);
  541. userconf_hist_eoc();
  542. }
  543. printf(" disabled\n");
  544. return;
  545. }
  546. printf("Unknown devno (max is %d)\n", userconf_totdev+pdevnames_size);
  547. }
  548. void
  549. userconf_enable(int devno)
  550. {
  551. int done = 0;
  552. if (devno <= userconf_maxdev) {
  553. switch (cfdata[devno].cf_fstate) {
  554. case FSTATE_DNOTFOUND:
  555. cfdata[devno].cf_fstate = FSTATE_NOTFOUND;
  556. break;
  557. case FSTATE_DSTAR:
  558. cfdata[devno].cf_fstate = FSTATE_STAR;
  559. break;
  560. case FSTATE_NOTFOUND:
  561. case FSTATE_STAR:
  562. done = 1;
  563. break;
  564. default:
  565. printf("Error unknown state\n");
  566. break;
  567. }
  568. printf("%3d ", devno);
  569. userconf_pdevnam(devno);
  570. if (done) {
  571. printf(" already");
  572. } else {
  573. /* XXX add cmd 'e' <devno> eoc */
  574. userconf_hist_cmd('e');
  575. userconf_hist_int(devno);
  576. userconf_hist_eoc();
  577. }
  578. printf(" enabled\n");
  579. return;
  580. }
  581. if (devno > userconf_maxdev && devno <= userconf_totdev) {
  582. printf("%3d can't enable free slot\n", devno);
  583. return;
  584. }
  585. if (devno > userconf_totdev &&
  586. devno <= userconf_totdev+pdevnames_size) {
  587. printf("%3d %s", devno, pdevnames[devno-userconf_totdev-1]);
  588. if (pdevinit[devno-userconf_totdev-1].pdev_count > 0) {
  589. printf(" already");
  590. } else {
  591. pdevinit[devno-userconf_totdev-1].pdev_count *= -1;
  592. /* XXX add cmd 'e' <devno> eoc */
  593. userconf_hist_cmd('e');
  594. userconf_hist_int(devno);
  595. userconf_hist_eoc();
  596. }
  597. printf(" enabled\n");
  598. return;
  599. }
  600. printf("Unknown devno (max is %d)\n", userconf_totdev+pdevnames_size);
  601. }
  602. void
  603. userconf_help(void)
  604. {
  605. int j = 0, k;
  606. printf("command args description\n");
  607. while (*userconf_cmds[j] != '\0') {
  608. printf("%s", userconf_cmds[j]);
  609. k = strlen(userconf_cmds[j]);
  610. while (k < 10) {
  611. printf(" ");
  612. k++;
  613. }
  614. switch (*userconf_cmds[j+1]) {
  615. case 'L':
  616. printf("[count] number of lines before more");
  617. break;
  618. case 'a':
  619. printf("dev add a device");
  620. break;
  621. case 'b':
  622. printf("8|10|16 base on large numbers");
  623. break;
  624. case 'c':
  625. printf("devno|dev change devices");
  626. break;
  627. #if defined(DDB)
  628. case 'D':
  629. printf(" enter ddb");
  630. break;
  631. #endif
  632. case 'd':
  633. printf("attr val|devno|dev disable devices");
  634. break;
  635. case 'e':
  636. printf("attr val|devno|dev enable devices");
  637. break;
  638. case 'f':
  639. printf("devno|dev find devices");
  640. break;
  641. case 'h':
  642. printf(" this message");
  643. break;
  644. case 'l':
  645. printf(" list configuration");
  646. break;
  647. case 'q':
  648. printf(" leave UKC");
  649. break;
  650. case 's':
  651. printf("[attr [val]] "
  652. "show attributes (or devices with an attribute)");
  653. break;
  654. case 't':
  655. printf("[mins [dst]] set timezone/dst");
  656. break;
  657. case 'v':
  658. printf(" toggle verbose booting");
  659. break;
  660. default:
  661. printf(" don't know");
  662. break;
  663. }
  664. printf("\n");
  665. j += 2;
  666. }
  667. }
  668. void
  669. userconf_list(void)
  670. {
  671. int i = 0;
  672. userconf_cnt = 0;
  673. while (i <= (userconf_totdev+pdevnames_size)) {
  674. if (userconf_more())
  675. break;
  676. userconf_pdev(i++);
  677. }
  678. userconf_cnt = -1;
  679. }
  680. void
  681. userconf_show(void)
  682. {
  683. int i = 0;
  684. userconf_cnt = 0;
  685. while (i <= userconf_maxlocnames) {
  686. if (userconf_more())
  687. break;
  688. printf("%s\n", locnames[i++]);
  689. }
  690. userconf_cnt = -1;
  691. }
  692. void
  693. userconf_common_attr_val(short attr, int *val, char routine)
  694. {
  695. struct cfdata *cd;
  696. int *l;
  697. int ln;
  698. int i = 0, quit = 0;
  699. userconf_cnt = 0;
  700. while (i <= userconf_maxdev) {
  701. cd = &cfdata[i];
  702. l = cd->cf_loc;
  703. ln = cd->cf_locnames;
  704. while (locnamp[ln] != -1) {
  705. if (locnamp[ln] == attr) {
  706. if (val == NULL) {
  707. quit = userconf_more();
  708. userconf_pdev(i);
  709. } else {
  710. if (*val == *l) {
  711. quit = userconf_more();
  712. switch (routine) {
  713. case UC_ENABLE:
  714. userconf_enable(i);
  715. break;
  716. case UC_DISABLE:
  717. userconf_disable(i);
  718. break;
  719. case UC_SHOW:
  720. userconf_pdev(i);
  721. break;
  722. default:
  723. printf("Unknown routine /%c/\n",
  724. routine);
  725. break;
  726. }
  727. }
  728. }
  729. }
  730. if (quit)
  731. break;
  732. ln++;
  733. l++;
  734. }
  735. if (quit)
  736. break;
  737. i++;
  738. }
  739. userconf_cnt = -1;
  740. }
  741. void
  742. userconf_show_attr(char *cmd)
  743. {
  744. char *c;
  745. short attr = -1, i = 0, l = 0;
  746. int a;
  747. c = cmd;
  748. while (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\0') {
  749. c++;
  750. l++;
  751. }
  752. while (*c == ' ' || *c == '\t' || *c == '\n') {
  753. c++;
  754. }
  755. while (i <= userconf_maxlocnames) {
  756. if (strlen(locnames[i]) == l) {
  757. if (strncasecmp(cmd, locnames[i], l) == 0) {
  758. attr = i;
  759. }
  760. }
  761. i++;
  762. }
  763. if (attr == -1) {
  764. printf("Unknown attribute\n");
  765. return;
  766. }
  767. if (*c == '\0') {
  768. userconf_common_attr_val(attr, NULL, UC_SHOW);
  769. } else {
  770. if (userconf_number(c, &a) == 0) {
  771. userconf_common_attr_val(attr, &a, UC_SHOW);
  772. } else {
  773. printf("Unknown argument\n");
  774. }
  775. }
  776. }
  777. void
  778. userconf_common_dev(char *dev, int len, short unit, short state, char routine)
  779. {
  780. int i = 0;
  781. switch (routine) {
  782. case UC_CHANGE:
  783. break;
  784. default:
  785. userconf_cnt = 0;
  786. break;
  787. }
  788. while (cfdata[i].cf_attach != 0) {
  789. if (strlen(cfdata[i].cf_driver->cd_name) == len) {
  790. /*
  791. * Ok, if device name is correct
  792. * If state == FSTATE_FOUND, look for "dev"
  793. * If state == FSTATE_STAR, look for "dev*"
  794. * If state == FSTATE_NOTFOUND, look for "dev0"
  795. */
  796. if (strncasecmp(dev, cfdata[i].cf_driver->cd_name,
  797. len) == 0 &&
  798. (state == FSTATE_FOUND ||
  799. (state == FSTATE_STAR &&
  800. (cfdata[i].cf_fstate == FSTATE_STAR ||
  801. cfdata[i].cf_fstate == FSTATE_DSTAR)) ||
  802. (state == FSTATE_NOTFOUND &&
  803. cfdata[i].cf_unit == unit &&
  804. (cfdata[i].cf_fstate == FSTATE_NOTFOUND ||
  805. cfdata[i].cf_fstate == FSTATE_DNOTFOUND)))) {
  806. if (userconf_more())
  807. break;
  808. switch (routine) {
  809. case UC_CHANGE:
  810. userconf_change(i);
  811. break;
  812. case UC_ENABLE:
  813. userconf_enable(i);
  814. break;
  815. case UC_DISABLE:
  816. userconf_disable(i);
  817. break;
  818. case UC_FIND:
  819. userconf_pdev(i);
  820. break;
  821. default:
  822. printf("Unknown routine /%c/\n",
  823. routine);
  824. break;
  825. }
  826. }
  827. }
  828. i++;
  829. }
  830. for (i = 0; i < pdevnames_size; i++) {
  831. if (strncasecmp(dev, pdevnames[i], len) == 0 &&
  832. state == FSTATE_FOUND) {
  833. switch(routine) {
  834. case UC_CHANGE:
  835. userconf_change(userconf_totdev+1+i);
  836. break;
  837. case UC_ENABLE:
  838. userconf_enable(userconf_totdev+1+i);
  839. break;
  840. case UC_DISABLE:
  841. userconf_disable(userconf_totdev+1+i);
  842. break;
  843. case UC_FIND:
  844. userconf_pdev(userconf_totdev+1+i);
  845. break;
  846. default:
  847. printf("Unknown pseudo routine /%c/\n",routine);
  848. break;
  849. }
  850. }
  851. }
  852. switch (routine) {
  853. case UC_CHANGE:
  854. break;
  855. default:
  856. userconf_cnt = -1;
  857. break;
  858. }
  859. }
  860. void
  861. userconf_common_attr(char *cmd, int attr, char routine)
  862. {
  863. char *c;
  864. short l = 0;
  865. int a;
  866. c = cmd;
  867. while (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\0') {
  868. c++;
  869. l++;
  870. }
  871. while (*c == ' ' || *c == '\t' || *c == '\n')
  872. c++;
  873. if (*c == '\0') {
  874. printf("Value missing for attribute\n");
  875. return;
  876. }
  877. if (userconf_number(c, &a) == 0) {
  878. userconf_common_attr_val(attr, &a, routine);
  879. } else {
  880. printf("Unknown argument\n");
  881. }
  882. }
  883. void
  884. userconf_add_read(char *prompt, char field, char *dev, int len, int *val)
  885. {
  886. int ok = 0;
  887. int a;
  888. char *c;
  889. int i;
  890. *val = -1;
  891. while (!ok) {
  892. printf("%s ? ", prompt);
  893. i = getsn(userconf_argbuf, sizeof(userconf_argbuf));
  894. c = userconf_argbuf;
  895. while (*c == ' ' || *c == '\t' || *c == '\n')
  896. c++;
  897. if (*c != '\0') {
  898. if (userconf_number(c, &a) == 0) {
  899. if (a > userconf_maxdev) {
  900. printf("Unknown devno (max is %d)\n",
  901. userconf_maxdev);
  902. } else if (strncasecmp(dev,
  903. cfdata[a].cf_driver->cd_name, len) != 0 &&
  904. field == 'a') {
  905. printf("Not same device type\n");
  906. } else {
  907. *val = a;
  908. ok = 1;
  909. }
  910. } else if (*c == '?') {
  911. userconf_common_dev(dev, len, 0,
  912. FSTATE_FOUND, UC_FIND);
  913. } else if (*c == 'q' || *c == 'Q') {
  914. ok = 1;
  915. } else {
  916. printf("Unknown argument\n");
  917. }
  918. } else {
  919. ok = 1;
  920. }
  921. }
  922. }
  923. void
  924. userconf_add(char *dev, int len, short unit, short state)
  925. {
  926. int i = 0, found = 0;
  927. struct cfdata new;
  928. int val, max_unit, star_unit, orig;
  929. memset(&new, 0, sizeof(struct cfdata));
  930. if (userconf_maxdev == userconf_totdev) {
  931. printf("No more space for new devices.\n");
  932. return;
  933. }
  934. if (state == FSTATE_FOUND) {
  935. printf("Device not complete number or * is missing\n");
  936. return;
  937. }
  938. for (i = 0; cfdata[i].cf_driver; i++)
  939. if (strlen(cfdata[i].cf_driver->cd_name) == len &&
  940. strncasecmp(dev, cfdata[i].cf_driver->cd_name, len) == 0)
  941. found = 1;
  942. if (!found) {
  943. printf("No device of this type exists.\n");
  944. return;
  945. }
  946. userconf_add_read("Clone Device (DevNo, 'q' or '?')",
  947. 'a', dev, len, &val);
  948. if (val != -1) {
  949. orig = val;
  950. new = cfdata[val];
  951. new.cf_unit = unit;
  952. new.cf_fstate = state;
  953. userconf_add_read("Insert before Device (DevNo, 'q' or '?')",
  954. 'i', dev, len, &val);
  955. }
  956. if (val != -1) {
  957. /* XXX add cmd 'a' <orig> <val> eoc */
  958. userconf_hist_cmd('a');
  959. userconf_hist_int(orig);
  960. userconf_hist_int(unit);
  961. userconf_hist_int(state);
  962. userconf_hist_int(val);
  963. userconf_hist_eoc();
  964. /* Insert the new record */
  965. for (i = userconf_maxdev; val <= i; i--)
  966. cfdata[i+1] = cfdata[i];
  967. cfdata[val] = new;
  968. /* Fix indexs in pv */
  969. for (i = 0; i < pv_size; i++) {
  970. if (pv[i] != -1 && pv[i] >= val)
  971. pv[i]++;
  972. }
  973. /* Fix indexs in cfroots */
  974. for (i = 0; i < cfroots_size; i++) {
  975. if (cfroots[i] != -1 && cfroots[i] >= val)
  976. cfroots[i]++;
  977. }
  978. userconf_maxdev++;
  979. max_unit = -1;
  980. /* Find max unit number of the device type */
  981. i = 0;
  982. while (cfdata[i].cf_attach != 0) {
  983. if (strlen(cfdata[i].cf_driver->cd_name) == len &&
  984. strncasecmp(dev, cfdata[i].cf_driver->cd_name,
  985. len) == 0) {
  986. switch (cfdata[i].cf_fstate) {
  987. case FSTATE_NOTFOUND:
  988. case FSTATE_DNOTFOUND:
  989. if (cfdata[i].cf_unit > max_unit)
  990. max_unit = cfdata[i].cf_unit;
  991. break;
  992. default:
  993. break;
  994. }
  995. }
  996. i++;
  997. }
  998. /*
  999. * For all * entries set unit number to max+1, and update
  1000. * cf_starunit1 if necessary.
  1001. */
  1002. max_unit++;
  1003. star_unit = -1;
  1004. i = 0;
  1005. while (cfdata[i].cf_attach != 0) {
  1006. if (strlen(cfdata[i].cf_driver->cd_name) == len &&
  1007. strncasecmp(dev, cfdata[i].cf_driver->cd_name,
  1008. len) == 0) {
  1009. switch (cfdata[i].cf_fstate) {
  1010. case FSTATE_NOTFOUND:
  1011. case FSTATE_DNOTFOUND:
  1012. if (cfdata[i].cf_unit > star_unit)
  1013. star_unit = cfdata[i].cf_unit;
  1014. break;
  1015. default:
  1016. break;
  1017. }
  1018. }
  1019. i++;
  1020. }
  1021. star_unit++;
  1022. i = 0;
  1023. while (cfdata[i].cf_attach != 0) {
  1024. if (strlen(cfdata[i].cf_driver->cd_name) == len &&
  1025. strncasecmp(dev, cfdata[i].cf_driver->cd_name,
  1026. len) == 0) {
  1027. switch (cfdata[i].cf_fstate) {
  1028. case FSTATE_STAR:
  1029. case FSTATE_DSTAR:
  1030. cfdata[i].cf_unit = max_unit;
  1031. if (cfdata[i].cf_starunit1 < star_unit)
  1032. cfdata[i].cf_starunit1 =
  1033. star_unit;
  1034. break;
  1035. default:
  1036. break;
  1037. }
  1038. }
  1039. i++;
  1040. }
  1041. userconf_pdev(val);
  1042. }
  1043. /* cf_attach, cf_driver, cf_unit, cf_fstate, cf_loc, cf_flags,
  1044. cf_parents, cf_locnames, and cf_locnames */
  1045. }
  1046. int
  1047. userconf_parse(char *cmd)
  1048. {
  1049. char *c, *v;
  1050. int i = 0, j = 0, k, a;
  1051. short unit, state;
  1052. c = cmd;
  1053. while (*c == ' ' || *c == '\t')
  1054. c++;
  1055. v = c;
  1056. while (*c != ' ' && *c != '\t' && *c != '\n' && *c != '\0') {
  1057. c++;
  1058. i++;
  1059. }
  1060. k = -1;
  1061. while (*userconf_cmds[j] != '\0') {
  1062. if (strlen(userconf_cmds[j]) == i) {
  1063. if (strncasecmp(v, userconf_cmds[j], i) == 0)
  1064. k = j;
  1065. }
  1066. j += 2;
  1067. }
  1068. while (*c == ' ' || *c == '\t' || *c == '\n')
  1069. c++;
  1070. if (k == -1) {
  1071. if (*v != '\n')
  1072. printf("Unknown command, try help\n");
  1073. } else {
  1074. switch (*userconf_cmds[k+1]) {
  1075. case 'L':
  1076. if (*c == '\0')
  1077. printf("Argument expected\n");
  1078. else if (userconf_number(c, &a) == 0)
  1079. userconf_lines = a;
  1080. else
  1081. printf("Unknown argument\n");
  1082. break;
  1083. case 'a':
  1084. if (*c == '\0')
  1085. printf("Dev expected\n");
  1086. else if (userconf_device(c, &a, &unit, &state) == 0)
  1087. userconf_add(c, a, unit, state);
  1088. else
  1089. printf("Unknown argument\n");
  1090. break;
  1091. case 'b':
  1092. if (*c == '\0')
  1093. printf("8|10|16 expected\n");
  1094. else if (userconf_number(c, &a) == 0) {
  1095. if (a == 8 || a == 10 || a == 16) {
  1096. userconf_base = a;
  1097. } else {
  1098. printf("8|10|16 expected\n");
  1099. }
  1100. } else
  1101. printf("Unknown argument\n");
  1102. break;
  1103. case 'c':
  1104. if (*c == '\0')
  1105. printf("DevNo or Dev expected\n");
  1106. else if (userconf_number(c, &a) == 0)
  1107. userconf_change(a);
  1108. else if (userconf_device(c, &a, &unit, &state) == 0)
  1109. userconf_common_dev(c, a, unit, state, UC_CHANGE);
  1110. else
  1111. printf("Unknown argument\n");
  1112. break;
  1113. #if defined(DDB)
  1114. case 'D':
  1115. Debugger();
  1116. break;
  1117. #endif
  1118. case 'd':
  1119. if (*c == '\0')
  1120. printf("Attr, DevNo or Dev expected\n");
  1121. else if (userconf_attr(c, &a) == 0)
  1122. userconf_common_attr(c, a, UC_DISABLE);
  1123. else if (userconf_number(c, &a) == 0)
  1124. userconf_disable(a);
  1125. else if (userconf_device(c, &a, &unit, &state) == 0)
  1126. userconf_common_dev(c, a, unit, state, UC_DISABLE);
  1127. else
  1128. printf("Unknown argument\n");
  1129. break;
  1130. case 'e':
  1131. if (*c == '\0')
  1132. printf("Attr, DevNo or Dev expected\n");
  1133. else if (userconf_attr(c, &a) == 0)
  1134. userconf_common_attr(c, a, UC_ENABLE);
  1135. else if (userconf_number(c, &a) == 0)
  1136. userconf_enable(a);
  1137. else if (userconf_device(c, &a, &unit, &state) == 0)
  1138. userconf_common_dev(c, a, unit, state, UC_ENABLE);
  1139. else
  1140. printf("Unknown argument\n");
  1141. break;
  1142. case 'f':
  1143. if (*c == '\0')
  1144. printf("DevNo or Dev expected\n");
  1145. else if (userconf_number(c, &a) == 0)
  1146. userconf_pdev(a);
  1147. else if (userconf_device(c, &a, &unit, &state) == 0)
  1148. userconf_common_dev(c, a, unit, state, UC_FIND);
  1149. else
  1150. printf("Unknown argument\n");
  1151. break;
  1152. case 'h':
  1153. userconf_help();
  1154. break;
  1155. case 'l':
  1156. if (*c == '\0')
  1157. userconf_list();
  1158. else
  1159. printf("Unknown argument\n");
  1160. break;
  1161. case 'q':
  1162. /* XXX add cmd 'q' eoc */
  1163. userconf_hist_cmd('q');
  1164. userconf_hist_eoc();
  1165. return(-1);
  1166. break;
  1167. case 's':
  1168. if (*c == '\0')
  1169. userconf_show();
  1170. else
  1171. userconf_show_attr(c);
  1172. break;
  1173. case 't':
  1174. if (*c == '\0' || userconf_number(c, &a) == 0) {
  1175. if (*c != '\0') {
  1176. tz.tz_minuteswest = a;
  1177. while (*c != '\n' && *c != '\t' &&
  1178. *c != ' ' && *c != '\0')
  1179. c++;
  1180. while (*c == '\t' || *c == ' ')
  1181. c++;
  1182. if (*c != '\0' &&
  1183. userconf_number(c, &a) == 0)
  1184. tz.tz_dsttime = a;
  1185. userconf_hist_cmd('t');
  1186. userconf_hist_int(tz.tz_minuteswest);
  1187. userconf_hist_int(tz.tz_dsttime);
  1188. userconf_hist_eoc();
  1189. }
  1190. printf("timezone = %d, dst = %d\n",
  1191. tz.tz_minuteswest, tz.tz_dsttime);
  1192. } else
  1193. printf("Unknown argument\n");
  1194. break;
  1195. case 'v':
  1196. autoconf_verbose = !autoconf_verbose;
  1197. printf("autoconf verbose %sabled\n",
  1198. autoconf_verbose ? "en" : "dis");
  1199. break;
  1200. default:
  1201. printf("Unknown command\n");
  1202. break;
  1203. }
  1204. }
  1205. return(0);
  1206. }
  1207. void
  1208. user_config(void)
  1209. {
  1210. userconf_init();
  1211. printf("User Kernel Config\n");
  1212. cnpollc(1);
  1213. while (1) {
  1214. printf("UKC> ");
  1215. if (getsn(userconf_cmdbuf, sizeof(userconf_cmdbuf)) > 0 &&
  1216. userconf_parse(userconf_cmdbuf))
  1217. break;
  1218. }
  1219. cnpollc(0);
  1220. printf("Continuing...\n");
  1221. }