exksh_prpar.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these librararies and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /* $XConsortium: exksh_prpar.c /main/4 1995/11/01 15:54:12 rswiston $ */
  24. /* Copyright (c) 1991, 1992 UNIX System Laboratories, Inc. */
  25. /* All Rights Reserved */
  26. /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF */
  27. /* UNIX System Laboratories, Inc. */
  28. /* The copyright notice above does not evidence any */
  29. /* actual or intended publication of such source code. */
  30. #include "name.h"
  31. #include "shell.h"
  32. #include <sys/types.h>
  33. #include <sys/stat.h>
  34. #include <string.h>
  35. #include <ctype.h>
  36. #include "exksh.h"
  37. #include "stdio.h"
  38. #include "exksh_prpar.h"
  39. #include "symbolic.h"
  40. #include "msgs.h"
  41. static int xk_uppercase(
  42. char *s) ;
  43. static int getsize(
  44. int fd,
  45. int *psize) ;
  46. #define OBJ_END 100
  47. struct symlist Val_list;
  48. unsigned int Pr_format = PRSYMBOLIC|PRMIXED|PRNAMES;
  49. /*
  50. * Takes a pointer to a pointer to a character buffer, and skips any
  51. * whitespace, as defined by isspace(section 3). Increments the
  52. * buf parameter to the first non-whitespace character.
  53. * Returns SUCCESS, there are no known ways for it to fail.
  54. */
  55. int
  56. xk_skipwhite(
  57. char **buf )
  58. {
  59. while (isspace(**buf))
  60. (*buf)++;
  61. return(SUCCESS);
  62. }
  63. int
  64. xk_backskip(
  65. char **buf,
  66. int *n )
  67. {
  68. *n = 0;
  69. while (isspace(**buf)) {
  70. (*buf)--;
  71. *n++;
  72. }
  73. if ((*buf)[0] == '\\')
  74. return(TRUE);
  75. else
  76. return(FALSE);
  77. }
  78. /*
  79. * Takes a pointer to a character buffer and a string. Sees if
  80. * the str is present as the first part of the buffer (minus any
  81. * whitespace), and if so increments the buffer past the string.
  82. * If not, returns FAIL without incrementing buffer (except perhaps
  83. * by eating leading whitespace).
  84. */
  85. int
  86. xk_parexpect(
  87. char **buf,
  88. char *str )
  89. {
  90. RIF(xk_skipwhite(buf));
  91. if (strncmp(*buf, str, strlen(str)) == 0) {
  92. *buf += strlen(str);
  93. } else {
  94. return(FAIL);
  95. }
  96. return(SUCCESS);
  97. }
  98. /*
  99. * Takes a pointer to a char buffer, and a string. Returns
  100. * TRUE if the string appears immediately (after skipping whitespace).
  101. * or FALSE otherwise.
  102. */
  103. int
  104. xk_parpeek(
  105. char **buf,
  106. char *str )
  107. {
  108. RIF(xk_skipwhite(buf));
  109. if (strncmp(*buf, str, strlen(str)) == 0)
  110. return(TRUE);
  111. else
  112. return(FALSE);
  113. }
  114. int
  115. xk_prin_int(
  116. memtbl_t *tbl,
  117. char **buf,
  118. unsigned long *old_v )
  119. {
  120. register int i, printed = 0;
  121. struct symlist *sym;
  122. unsigned long v;
  123. switch (tbl->kind) {
  124. case K_CHAR:
  125. v = *((unsigned char *) old_v);
  126. break;
  127. case K_SHORT:
  128. v = *((unsigned short *) old_v);
  129. break;
  130. case K_INT:
  131. v = *((unsigned int *) old_v);
  132. break;
  133. default:
  134. v = *old_v;
  135. }
  136. **buf = '\0';
  137. if ((Pr_format & PRSYMBOLIC) && ((Val_list.syms != NULL) || ((sym = fsymbolic(tbl)) != NULL))) {
  138. if (Val_list.syms != NULL)
  139. sym = &Val_list;
  140. if (sym->isflag) {
  141. if (v == 0) {
  142. *buf += lsprintf(*buf, "0");
  143. return(SUCCESS);
  144. }
  145. for (i = 0; i < sym->nsyms; i++) {
  146. if (sym->syms[i].addr & v) {
  147. if (Pr_format & PRMIXED_SYMBOLIC) {
  148. if (Pr_format & PRDECIMAL)
  149. *buf += lsprintf(*buf, "%s%s(%d)", printed ? "|" : "", sym->syms[i].str, sym->syms[i].addr);
  150. else
  151. *buf += lsprintf(*buf, "%s%s(0x%x)", printed ? "|" : "", sym->syms[i].str, sym->syms[i].addr);
  152. }
  153. else
  154. *buf += lsprintf(*buf, "%s%s", printed ? "|" : "", sym->syms[i].str);
  155. v &= ~(sym->syms[i].addr);
  156. printed++;
  157. }
  158. }
  159. if (v) {
  160. if (Pr_format & PRMIXED_SYMBOLIC) {
  161. if (Pr_format & PRDECIMAL)
  162. *buf += lsprintf(*buf, "%sNOSYMBOLIC(%d)", printed ? "|" : "", v);
  163. else
  164. *buf += lsprintf(*buf, "%sNOSYMBOLIC(0x%x)", printed ? "|" : "", v);
  165. }
  166. else {
  167. if (Pr_format & PRDECIMAL)
  168. *buf += lsprintf(*buf, "%s%d", printed ? "|" : "", v);
  169. else
  170. *buf += lsprintf(*buf, "%s0x%x", printed ? "|" : "", v);
  171. }
  172. }
  173. return(SUCCESS);
  174. }
  175. else {
  176. for (i = 0; i < sym->nsyms; i++) {
  177. if (sym->syms[i].addr == v) {
  178. if (Pr_format & PRMIXED_SYMBOLIC) {
  179. if (Pr_format & PRDECIMAL)
  180. *buf += lsprintf(*buf, "%s(%d)", sym->syms[i].str, v);
  181. else
  182. *buf += lsprintf(*buf, "%s(0x%x)", sym->syms[i].str, v);
  183. }
  184. else
  185. *buf += lsprintf(*buf, "%s", sym->syms[i].str);
  186. return(SUCCESS);
  187. }
  188. }
  189. }
  190. }
  191. if (Pr_format & PRHEX)
  192. *buf += lsprintf(*buf, "0x%x", v);
  193. else if (Pr_format & PRDECIMAL)
  194. *buf += lsprintf(*buf, "%d", v);
  195. else
  196. *buf += lsprintf(*buf, "%d(0x%x)", v, v);
  197. return(SUCCESS);
  198. }
  199. int
  200. xk_par_int(
  201. char **buf,
  202. long *v,
  203. struct envsymbols *env )
  204. {
  205. register int ret, base;
  206. char *p, *q, *pp;
  207. char nbuf[512];
  208. xk_skipwhite(buf);
  209. strncpy(nbuf, *buf, sizeof(nbuf)-1);
  210. if (strchr(nbuf, '|') == NULL) {
  211. for (p = nbuf; *p && *p != ' ' && *p != ',' && *p != ']'
  212. && *p != '{' && *p != '}' && *p != '/' && *p != '@'
  213. && *p != ':' && *p != '.' && *p != 13 && *p != 10 && *p != 11
  214. && *p != 12 && *p != 9; p++)
  215. ;
  216. *p = '\0';
  217. }
  218. else {
  219. for (p = nbuf; *p && *p != ','
  220. && *p != '{' && *p != '}' && *p != '/' && *p != '@'
  221. && *p != ':' && *p != '.' ; p++)
  222. ;
  223. *p = '\0';
  224. }
  225. ret = strlen(nbuf);
  226. if (ret == 0)
  227. return(OBJ_END);
  228. *v = 0;
  229. if ((p = strchr(nbuf, '"')) != NULL) {
  230. return(FAIL);
  231. }
  232. if ((p = strchr(nbuf, '+')) != NULL) {
  233. char *qq;
  234. long v1, v2;
  235. *p = '\0';
  236. v1 = v2 = 0;
  237. qq = nbuf;
  238. p++;
  239. xk_par_int(&qq, &v1, env);
  240. xk_par_int(&p, &v2, env);
  241. *v = v1 + v2;
  242. *buf += ret;
  243. return(SUCCESS);
  244. }
  245. if ((p = strchr(&nbuf[1], '-')) != NULL) {
  246. long v1, v2;
  247. char *qq;
  248. *p = '\0';
  249. v1 = v2 = 0;
  250. qq = nbuf;
  251. p++;
  252. xk_par_int(&qq, &v1, env);
  253. xk_par_int(&p, &v2, env);
  254. *v = v1 - v2;
  255. *buf += ret;
  256. return(SUCCESS);
  257. }
  258. for (p = strtok(nbuf, " |\t\n"); p; p = strtok(NULL, " |\t\n")) {
  259. for (pp = p; *pp && *pp != ' ' && *pp != ','
  260. && *pp != '{' && *pp != '}' && *pp != '/' && *pp != '@'
  261. && *pp != ':' && *pp != '.' && *pp != 13 &&
  262. *pp != 11 && *pp != 12 && *pp != 9; pp++)
  263. ;
  264. *pp = '\0';
  265. if ((pp = strchr(p, '#')) != NULL) {
  266. base = strtol(p, &p, 10);
  267. if (p != pp)
  268. return(FAIL);
  269. p++;
  270. }
  271. else
  272. base = 0;
  273. xk_skipwhite(&p);
  274. if (*p == '\0')
  275. continue;
  276. if (isdigit(*p) || *p == '-') {
  277. *v |= strtoul(p, (char **)NULL, base);
  278. }
  279. else {
  280. unsigned long val;
  281. /* knock out commentary parenthesized things */
  282. if ((q = strchr(p, '(' /*)*/ )) != NULL)
  283. *q = '\0';
  284. /* Search through available names for partial match */
  285. if (!fdef(p, &val)) {
  286. return(FAIL);
  287. }
  288. else
  289. *v |= val;
  290. }
  291. }
  292. *buf += ret;
  293. return(SUCCESS);
  294. }
  295. int
  296. xk_prin_nts(
  297. char **buf,
  298. char *str )
  299. {
  300. return(xk_prin_charstr(buf, (unsigned char *)str,
  301. str ? strlen(str) : 0));
  302. }
  303. int
  304. xk_prin_charstr(
  305. char **buf,
  306. unsigned char *str,
  307. int len )
  308. {
  309. register int i;
  310. if (str == NULL)
  311. *buf += lsprintf(*buf, "NULL");
  312. else {
  313. *buf += lsprintf(*buf, "\"");
  314. for (i = 0; i < len; i++) {
  315. if (str[i] == '"') {
  316. *buf += lsprintf(*buf, "\\\"");
  317. } else if (isprint(str[i])) {
  318. *buf += lsprintf(*buf, "%c", str[i]);
  319. } else {
  320. switch (str[i]) {
  321. case '\n':
  322. *buf += lsprintf(*buf, "\\n");
  323. break;
  324. case '\t':
  325. *buf += lsprintf(*buf, "\\t");
  326. break;
  327. case '\b':
  328. *buf += lsprintf(*buf, "\\b");
  329. break;
  330. case '\v':
  331. *buf += lsprintf(*buf, "\\v");
  332. break;
  333. case '\f':
  334. *buf += lsprintf(*buf, "\\f");
  335. break;
  336. case '\r':
  337. *buf += lsprintf(*buf, "\\r");
  338. break;
  339. case '\0':
  340. *buf += lsprintf(*buf, "\\00");
  341. break;
  342. default:
  343. *buf += lsprintf(*buf, "\\%x", (unsigned int)str[i]);
  344. break;
  345. }
  346. }
  347. }
  348. *buf += lsprintf(*buf, "\"");
  349. }
  350. return(SUCCESS);
  351. }
  352. int
  353. xk_prin_hexstr(
  354. char **buf,
  355. char *str,
  356. int len )
  357. {
  358. register int i;
  359. unsigned char tempc;
  360. if (str == NULL)
  361. *buf += lsprintf(*buf, "NULL");
  362. else {
  363. *buf += lsprintf(*buf, "%s", "0x");
  364. for (i = 0; i < len; i++) {
  365. tempc = str[i];
  366. if (str[i] & 0xf0) {
  367. *buf += lsprintf(*buf, "%x", tempc);
  368. }
  369. else
  370. *buf += lsprintf(*buf, "0%x", tempc);
  371. }
  372. }
  373. return(SUCCESS);
  374. }
  375. #define MALSIZ 16 /* initial size of string to malloc */
  376. int
  377. xk_par_chararr(
  378. char **buf,
  379. char *str,
  380. int *len )
  381. {
  382. return(xk_par_charstr(buf, &str, len));
  383. }
  384. #define CHAR_QUOTED 0
  385. #define CHAR_HEXSTR 1
  386. #define CHAR_FILE 2
  387. int
  388. xk_par_nts(
  389. char **buf,
  390. char **str )
  391. {
  392. int temp = 0;
  393. RIF(xk_par_charstr(buf, str, &temp));
  394. if (temp >= 0)
  395. str[0][temp] = '\0';
  396. return(SUCCESS);
  397. }
  398. int
  399. xk_par_charstr(
  400. char **buf,
  401. char **str,
  402. int *len )
  403. {
  404. register int i;
  405. char delim;
  406. int didmalloc = FALSE, getmode;
  407. char cbuf[3]; /* conversion buffer for hex strings */
  408. char filename[128];
  409. char * errmsg;
  410. RIF(xk_skipwhite(buf));
  411. if (xk_parpeek(buf, "NULL")) {
  412. RIF(xk_parexpect(buf, "NULL"));
  413. *str = NULL;
  414. *len = -1;
  415. return(SUCCESS);
  416. }
  417. /* this is pure internal feature, no error setting */
  418. if (**buf == '<') {
  419. char *p;
  420. FILE *fp;
  421. char gbuf[BUFSIZ];
  422. int line;
  423. int size;
  424. (*buf)++;
  425. xk_skipwhite(buf);
  426. for (p = &filename[0];
  427. **buf != ',' && **buf != /* { */ '}' && **buf != ' ' &&
  428. **buf != '\t' && p < &filename[sizeof(filename)];
  429. *p++ = *(*buf)++)
  430. ;
  431. *p++ = '\0';
  432. if ((fp = fopen(filename, "r")) == NULL) {
  433. errmsg=strdup(GETMESSAGE(7,1,
  434. "Unable to open the file '%s'; verify that it exists and is readable"));
  435. lsprintf(gbuf, errmsg, filename);
  436. fprintf(stderr, gbuf);
  437. free(errmsg);
  438. return(FAIL);
  439. }
  440. if (*len == 0) {
  441. if (getsize(fileno(fp), &size) == FAIL) {
  442. errmsg=strdup(GETMESSAGE(7,2,
  443. "Unable to access the file '%s'; verify you have permission to access it"));
  444. lsprintf(gbuf, errmsg, filename);
  445. fprintf(stderr, gbuf);
  446. free(errmsg);
  447. return(FAIL);
  448. }
  449. *len = size/2 + 1;
  450. if ((*str = malloc(*len)) == NULL) {
  451. return(FAIL);
  452. }
  453. }
  454. line = i = 0;
  455. while (fgets(gbuf, sizeof(gbuf), fp) != NULL) {
  456. line++;
  457. p = gbuf;
  458. /* eat any leading 0x */
  459. if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
  460. p += 2;
  461. }
  462. for ( ; *p && *p != '\n'; ) {
  463. if (i > *len - 1) {
  464. fclose(fp);
  465. return(FAIL);
  466. }
  467. if (!isxdigit(*p)) {
  468. p++;
  469. continue;
  470. }
  471. if (!isxdigit(p[1])) {
  472. fclose(fp);
  473. return(FAIL);
  474. }
  475. cbuf[0] = p[0];
  476. cbuf[1] = p[1];
  477. cbuf[2] = '\0';
  478. str[0][i++] = (char)strtol(cbuf, (char **)NULL, 16);
  479. p += 2;
  480. xk_skipwhite(&p);
  481. }
  482. }
  483. *len = i;
  484. fclose(fp);
  485. return(SUCCESS);
  486. } else if (!ispunct(**buf)) {
  487. getmode = CHAR_HEXSTR;
  488. if ((*buf)[0] == '0' && ((*buf)[1] == 'x' || (*buf)[1] == 'X'))
  489. (*buf) += 2;
  490. } else {
  491. delim = *((*buf)++);
  492. getmode = CHAR_QUOTED;
  493. }
  494. if (*len == 0) {
  495. if ((*str = malloc(MALSIZ)) == NULL) {
  496. return(FAIL);
  497. }
  498. didmalloc = TRUE;
  499. *len = MALSIZ;
  500. }
  501. i = 0;
  502. while ((*buf)[0] != '\0' && ((getmode == CHAR_QUOTED && (*buf)[0] != delim) ||
  503. (getmode == CHAR_HEXSTR && (isxdigit((*buf)[0]))) ||
  504. (getmode == CHAR_HEXSTR && (isspace((*buf)[0]))))) {
  505. /* NOTE: must always leave 1 additional byte for a null
  506. * termination, because could be called by xk_par_nts!
  507. */
  508. if (i >= *len - 1) {
  509. if (didmalloc == FALSE) {
  510. return(FAIL);
  511. } else {
  512. if ((*str = realloc(*str, *len + MALSIZ)) == NULL) {
  513. return(FAIL);
  514. }
  515. *len += MALSIZ;
  516. }
  517. }
  518. if (getmode == CHAR_QUOTED) {
  519. if ((*buf)[0] == '\\') {
  520. (*buf)++;
  521. switch ((*buf)[0]) {
  522. case 't':
  523. str[0][i++] = '\t';
  524. (*buf)++;
  525. break;
  526. case 'v':
  527. str[0][i++] = '\v';
  528. (*buf)++;
  529. break;
  530. case 'f':
  531. str[0][i++] = '\f';
  532. (*buf)++;
  533. break;
  534. case 'n':
  535. str[0][i++] = '\n';
  536. (*buf)++;
  537. break;
  538. case 'r':
  539. str[0][i++] = '\r';
  540. (*buf)++;
  541. break;
  542. case 'b':
  543. str[0][i++] = '\b';
  544. (*buf)++;
  545. break;
  546. case '0':
  547. str[0][i++] = (char)strtol(*buf, buf, 8);
  548. break;
  549. case 's':
  550. (*buf)++;
  551. break;
  552. default:
  553. str[0][i++] = *(*buf)++;
  554. }
  555. } else
  556. str[0][i++] = *(*buf)++;
  557. } else {
  558. if (!isxdigit((*buf)[1])) {
  559. return(FAIL);
  560. }
  561. cbuf[0] = (*buf)[0];
  562. cbuf[1] = (*buf)[1];
  563. cbuf[2] = '\0';
  564. str[0][i++] = (char)strtol(cbuf, (char **)NULL, 16);
  565. (*buf) += 2;
  566. xk_skipwhite(buf);
  567. }
  568. }
  569. if (getmode == CHAR_QUOTED)
  570. (*buf)++; /* eat the trailing quote */
  571. /*
  572. * NOTE: We leave a malloced buffer the same size rather
  573. * than realloc()'ing it to be the exact size in order
  574. * to save time and avoid malloc arena fragmentation
  575. */
  576. *len = i;
  577. return(SUCCESS);
  578. }
  579. /* Case Ignoring String Functions. */
  580. static int
  581. xk_uppercase(
  582. char *s )
  583. {
  584. while (*s) {
  585. if (islower(*s))
  586. *s = toupper(*s);
  587. s++;
  588. }
  589. }
  590. int
  591. xk_Strncmp(
  592. char *s1,
  593. char *s2,
  594. int len )
  595. {
  596. int diff, i;
  597. for (i=0; i < len && s1[i] != '\0' && s2[i] != '\0'; i++)
  598. if ((diff = tolower(s1[i]) - tolower(s2[i])) != 0)
  599. return (diff);
  600. return(i == len ? 0 : s1[i] - s2[i]);
  601. }
  602. static int
  603. getsize(
  604. int fd,
  605. int *psize )
  606. {
  607. struct stat stat;
  608. if (fstat(fd, &stat) == FAIL)
  609. return(FAIL);
  610. *psize = stat.st_size;
  611. return(SUCCESS);
  612. }