PageRenderTime 75ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 1ms

/usr/src/cmd/sh/macro.c

https://bitbucket.org/dilos/onarm-gate
C | 633 lines | 526 code | 30 blank | 77 comment | 200 complexity | 7421164d95144730d56a6dd9dd358118 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, AGPL-3.0, MIT, Apache-2.0, 0BSD, GPL-2.0, LGPL-2.0, AGPL-1.0, BSD-3-Clause, LGPL-3.0, BSD-3-Clause-No-Nuclear-License-2014
  1. /*
  2. * CDDL HEADER START
  3. *
  4. * The contents of this file are subject to the terms of the
  5. * Common Development and Distribution License (the "License").
  6. * You may not use this file except in compliance with the License.
  7. *
  8. * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  9. * or http://www.opensolaris.org/os/licensing.
  10. * See the License for the specific language governing permissions
  11. * and limitations under the License.
  12. *
  13. * When distributing Covered Code, include this CDDL HEADER in each
  14. * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15. * If applicable, add the following below this CDDL HEADER, with the
  16. * fields enclosed by brackets "[]" replaced with your own identifying
  17. * information: Portions Copyright [yyyy] [name of copyright owner]
  18. *
  19. * CDDL HEADER END
  20. */
  21. /*
  22. * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
  23. * Use is subject to license terms.
  24. */
  25. /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
  26. /* All Rights Reserved */
  27. /*
  28. * Copyright (c) 2008 NEC Corporation
  29. */
  30. #pragma ident "%Z%%M% %I% %E% SMI"
  31. /*
  32. * UNIX shell
  33. */
  34. #include "defs.h"
  35. #include "sym.h"
  36. #include <wait.h>
  37. static unsigned char quote; /* used locally */
  38. static unsigned char quoted; /* used locally */
  39. static int getch();
  40. static void comsubst(int);
  41. static void flush(int);
  42. static void
  43. copyto(unsigned char endch, int trimflag)
  44. /* trimflag - flag to check if argument will be trimmed */
  45. {
  46. unsigned int c;
  47. unsigned int d;
  48. unsigned char *pc;
  49. while ((c = getch(endch, trimflag)) != endch && c)
  50. if (quote) {
  51. if(c == '\\') { /* don't interpret next character */
  52. if (staktop >= brkend)
  53. growstak(staktop);
  54. pushstak(c);
  55. d = readwc();
  56. if(!escchar(d)) { /* both \ and following
  57. character are quoted if next
  58. character is not $, `, ", or \*/
  59. if (staktop >= brkend)
  60. growstak(staktop);
  61. pushstak('\\');
  62. if (staktop >= brkend)
  63. growstak(staktop);
  64. pushstak('\\');
  65. pc = readw(d);
  66. /* push entire multibyte char */
  67. while(*pc) {
  68. if (staktop >= brkend)
  69. growstak(staktop);
  70. pushstak(*pc++);
  71. }
  72. } else {
  73. pc = readw(d);
  74. /* d might be NULL */
  75. /* Evenif d is NULL, we have to save it */
  76. if (*pc) {
  77. while (*pc) {
  78. if (staktop >= brkend)
  79. growstak(staktop);
  80. pushstak(*pc++);
  81. }
  82. } else {
  83. if (staktop >= brkend)
  84. growstak(staktop);
  85. pushstak(*pc);
  86. }
  87. }
  88. } else { /* push escapes onto stack to quote characters */
  89. pc = readw(c);
  90. if (staktop >= brkend)
  91. growstak(staktop);
  92. pushstak('\\');
  93. while(*pc) {
  94. if (staktop >= brkend)
  95. growstak(staktop);
  96. pushstak(*pc++);
  97. }
  98. }
  99. } else if(c == '\\') {
  100. c = readwc(); /* get character to be escaped */
  101. if (staktop >= brkend)
  102. growstak(staktop);
  103. pushstak('\\');
  104. pc = readw(c);
  105. /* c might be NULL */
  106. /* Evenif c is NULL, we have to save it */
  107. if (*pc) {
  108. while (*pc) {
  109. if (staktop >= brkend)
  110. growstak(staktop);
  111. pushstak(*pc++);
  112. }
  113. } else {
  114. if (staktop >= brkend)
  115. growstak(staktop);
  116. pushstak(*pc);
  117. }
  118. } else {
  119. pc = readw(c);
  120. while (*pc) {
  121. if (staktop >= brkend)
  122. growstak(staktop);
  123. pushstak(*pc++);
  124. }
  125. }
  126. if (staktop >= brkend)
  127. growstak(staktop);
  128. zerostak();
  129. if (c != endch)
  130. error(badsub);
  131. }
  132. static void
  133. skipto(unsigned char endch)
  134. {
  135. /*
  136. * skip chars up to }
  137. */
  138. unsigned int c;
  139. while ((c = readwc()) && c != endch)
  140. {
  141. switch (c)
  142. {
  143. case SQUOTE:
  144. skipto(SQUOTE);
  145. break;
  146. case DQUOTE:
  147. skipto(DQUOTE);
  148. break;
  149. case DOLLAR:
  150. if (readwc() == BRACE)
  151. skipto('}');
  152. }
  153. }
  154. if (c != endch)
  155. error(badsub);
  156. }
  157. static
  158. int getch(endch, trimflag)
  159. unsigned char endch;
  160. int trimflag; /* flag to check if an argument is going to be trimmed, here document
  161. output is never trimmed
  162. */
  163. {
  164. unsigned int d;
  165. int atflag = 0; /* flag to check if $@ has already been seen within double
  166. quotes */
  167. retry:
  168. d = readwc();
  169. if (!subchar(d))
  170. return(d);
  171. if (d == DOLLAR)
  172. {
  173. unsigned int c;
  174. if ((c = readwc(), dolchar(c)))
  175. {
  176. struct namnod *n = (struct namnod *)NIL;
  177. int dolg = 0;
  178. BOOL bra;
  179. BOOL nulflg;
  180. unsigned char *argp, *v;
  181. unsigned char idb[2];
  182. unsigned char *id = idb;
  183. if (bra = (c == BRACE))
  184. c = readwc();
  185. if (letter(c))
  186. {
  187. argp = (unsigned char *)relstak();
  188. while (alphanum(c))
  189. {
  190. if (staktop >= brkend)
  191. growstak(staktop);
  192. pushstak(c);
  193. c = readwc();
  194. }
  195. if (staktop >= brkend)
  196. growstak(staktop);
  197. zerostak();
  198. n = lookup(absstak(argp));
  199. setstak(argp);
  200. if (n->namflg & N_FUNCTN)
  201. error(badsub);
  202. v = n->namval;
  203. id = (unsigned char *)n->namid;
  204. peekc = c | MARK;
  205. }
  206. else if (digchar(c))
  207. {
  208. *id = c;
  209. idb[1] = 0;
  210. if (astchar(c))
  211. {
  212. if(c == '@' && !atflag && quote) {
  213. quoted--;
  214. atflag = 1;
  215. }
  216. dolg = 1;
  217. c = '1';
  218. }
  219. c -= '0';
  220. v = ((c == 0) ? cmdadr : ((int)c <= dolc) ? dolv[c] : (unsigned char *)(dolg = 0));
  221. }
  222. else if (c == '$')
  223. v = pidadr;
  224. else if (c == '!')
  225. v = pcsadr;
  226. else if (c == '#')
  227. {
  228. itos(dolc);
  229. v = numbuf;
  230. }
  231. else if (c == '?')
  232. {
  233. itos(retval);
  234. v = numbuf;
  235. }
  236. else if (c == '-')
  237. v = flagadr;
  238. else if (bra)
  239. error(badsub);
  240. else
  241. goto retry;
  242. c = readwc();
  243. if (c == ':' && bra) /* null and unset fix */
  244. {
  245. nulflg = 1;
  246. c = readwc();
  247. }
  248. else
  249. nulflg = 0;
  250. if (!defchar(c) && bra)
  251. error(badsub);
  252. argp = 0;
  253. if (bra)
  254. {
  255. if (c != '}')
  256. {
  257. argp = (unsigned char *)relstak();
  258. if ((v == 0 || (nulflg && *v == 0)) ^ (setchar(c)))
  259. copyto('}', trimflag);
  260. else
  261. skipto('}');
  262. argp = absstak(argp);
  263. }
  264. }
  265. else
  266. {
  267. peekc = c | MARK;
  268. c = 0;
  269. }
  270. if (v && (!nulflg || *v))
  271. {
  272. if (c != '+')
  273. {
  274. for (;;)
  275. {
  276. if (*v == 0 && quote) {
  277. if (staktop >= brkend)
  278. growstak(staktop);
  279. pushstak('\\');
  280. if (staktop >= brkend)
  281. growstak(staktop);
  282. pushstak('\0');
  283. } else {
  284. while (c = *v) {
  285. wchar_t wc;
  286. int length;
  287. if ((length = mbtowc(&wc, (char *)v, MB_LEN_MAX)) <= 0)
  288. length = 1;
  289. if(quote || (c == '\\' && trimflag)) {
  290. if (staktop >= brkend)
  291. growstak(staktop);
  292. pushstak('\\');
  293. }
  294. while(length-- > 0) {
  295. if (staktop >= brkend)
  296. growstak(staktop);
  297. pushstak(*v++);
  298. }
  299. }
  300. }
  301. if (dolg == 0 || (++dolg > dolc))
  302. break;
  303. else /* $* and $@ expansion */
  304. {
  305. v = dolv[dolg];
  306. if(*id == '*' && quote) {
  307. /* push quoted space so that " $* " will not be broken into separate arguments */
  308. if (staktop >= brkend)
  309. growstak(staktop);
  310. pushstak('\\');
  311. }
  312. if (staktop >= brkend)
  313. growstak(staktop);
  314. pushstak(' ');
  315. }
  316. }
  317. }
  318. }
  319. else if (argp)
  320. {
  321. if (c == '?') {
  322. if(trimflag)
  323. trim(argp);
  324. failed(id, *argp ? (const char *)argp :
  325. badparam);
  326. }
  327. else if (c == '=')
  328. {
  329. if (n)
  330. {
  331. int strlngth = staktop - stakbot;
  332. unsigned char *savptr = fixstak();
  333. unsigned char *newargp;
  334. /*
  335. * copy word onto stack, trim it, and then
  336. * do assignment
  337. */
  338. usestak();
  339. while(c = *argp) {
  340. wchar_t wc;
  341. int len;
  342. if ((len = mbtowc(&wc, (char *)argp, MB_LEN_MAX)) <= 0)
  343. len = 1;
  344. if(c == '\\' && trimflag) {
  345. argp++;
  346. if (*argp == 0) {
  347. argp++;
  348. continue;
  349. }
  350. if ((len = mbtowc(&wc, (char *)argp, MB_LEN_MAX)) <= 0)
  351. len = 1;
  352. }
  353. while(len-- > 0) {
  354. if (staktop >= brkend)
  355. growstak(staktop);
  356. pushstak(*argp++);
  357. }
  358. }
  359. newargp = fixstak();
  360. assign(n, newargp);
  361. tdystak(savptr);
  362. (void) memcpystak(stakbot, savptr, strlngth);
  363. staktop = stakbot + strlngth;
  364. }
  365. else
  366. error(badsub);
  367. }
  368. }
  369. else if (flags & setflg)
  370. failed(id, unset);
  371. goto retry;
  372. }
  373. else
  374. peekc = c | MARK;
  375. }
  376. else if (d == endch)
  377. return(d);
  378. else if (d == SQUOTE)
  379. {
  380. comsubst(trimflag);
  381. goto retry;
  382. }
  383. else if (d == DQUOTE && trimflag)
  384. {
  385. if(!quote) {
  386. atflag = 0;
  387. quoted++;
  388. }
  389. quote ^= QUOTE;
  390. goto retry;
  391. }
  392. return(d);
  393. }
  394. unsigned char *
  395. macro(as)
  396. unsigned char *as;
  397. {
  398. /*
  399. * Strip "" and do $ substitution
  400. * Leaves result on top of stack
  401. */
  402. BOOL savqu = quoted;
  403. unsigned char savq = quote;
  404. struct filehdr fb;
  405. push(&fb);
  406. estabf(as);
  407. usestak();
  408. quote = 0;
  409. quoted = 0;
  410. copyto(0, 1);
  411. pop();
  412. if (quoted && (stakbot == staktop)) {
  413. if (staktop >= brkend)
  414. growstak(staktop);
  415. pushstak('\\');
  416. if (staktop >= brkend)
  417. growstak(staktop);
  418. pushstak('\0');
  419. /*
  420. * above is the fix for *'.c' bug
  421. */
  422. }
  423. quote = savq;
  424. quoted = savqu;
  425. return(fixstak());
  426. }
  427. /* Save file descriptor for command substitution */
  428. int savpipe = -1;
  429. static void
  430. comsubst(int trimflag)
  431. /* trimflag - used to determine if argument will later be trimmed */
  432. {
  433. /*
  434. * command substn
  435. */
  436. struct fileblk cb;
  437. unsigned int d;
  438. int strlngth = staktop - stakbot;
  439. unsigned char *oldstaktop;
  440. unsigned char *savptr = fixstak();
  441. unsigned char *pc;
  442. usestak();
  443. while ((d = readwc()) != SQUOTE && d) {
  444. if(d == '\\') {
  445. d = readwc();
  446. if(!escchar(d) || (d == '"' && !quote)) {
  447. /* trim quotes for `, \, or " if command substitution is within
  448. double quotes */
  449. if (staktop >= brkend)
  450. growstak(staktop);
  451. pushstak('\\');
  452. }
  453. }
  454. pc = readw(d);
  455. /* d might be NULL */
  456. if (*pc) {
  457. while (*pc) {
  458. if (staktop >= brkend)
  459. growstak(staktop);
  460. pushstak(*pc++);
  461. }
  462. } else {
  463. if (staktop >= brkend)
  464. growstak(staktop);
  465. pushstak(*pc);
  466. }
  467. }
  468. {
  469. unsigned char *argc;
  470. argc = fixstak();
  471. push(&cb);
  472. estabf(argc); /* read from string */
  473. }
  474. {
  475. struct trenod *t;
  476. int pv[2];
  477. /*
  478. * this is done like this so that the pipe
  479. * is open only when needed
  480. */
  481. t = makefork(FPOU, cmd(EOFSYM, MTFLG | NLFLG ));
  482. chkpipe(pv);
  483. savpipe = pv[OTPIPE];
  484. initf(pv[INPIPE]); /* read from pipe */
  485. execute(t, XEC_NOSTOP, (int)(flags & errflg), 0, pv);
  486. close(pv[OTPIPE]);
  487. savpipe = -1;
  488. }
  489. tdystak(savptr);
  490. (void) memcpystak(stakbot, savptr, strlngth);
  491. oldstaktop = staktop = stakbot + strlngth;
  492. while (d = readwc()) {
  493. if(quote || (d == '\\' && trimflag)) {
  494. unsigned char *rest;
  495. /* quote output from command subst. if within double
  496. quotes or backslash part of output */
  497. rest = readw(d);
  498. if (staktop >= brkend)
  499. growstak(staktop);
  500. pushstak('\\');
  501. while(d = *rest++) {
  502. /* Pick up all of multibyte character */
  503. if (staktop >= brkend)
  504. growstak(staktop);
  505. pushstak(d);
  506. }
  507. }
  508. else {
  509. pc = readw(d);
  510. while (*pc) {
  511. if (staktop >= brkend)
  512. growstak(staktop);
  513. pushstak(*pc++);
  514. }
  515. }
  516. }
  517. {
  518. extern pid_t parent;
  519. int stat;
  520. int rc;
  521. int ret = 0;
  522. while ((ret = waitpid(parent,&stat,0)) != parent) {
  523. /* break out if waitpid(2) has failed */
  524. if (ret == -1)
  525. break;
  526. }
  527. if (WIFEXITED(stat))
  528. rc = WEXITSTATUS(stat);
  529. else
  530. rc = (WTERMSIG(stat) | SIGFLG);
  531. if (rc && (flags & errflg))
  532. exitsh(rc);
  533. exitval = rc;
  534. flags |= eflag;
  535. exitset();
  536. }
  537. while (oldstaktop != staktop)
  538. { /* strip off trailing newlines from command substitution only */
  539. if ((*--staktop) != NL)
  540. {
  541. ++staktop;
  542. break;
  543. } else if(quote)
  544. staktop--; /* skip past backslashes if quoting */
  545. }
  546. pop();
  547. }
  548. #define CPYSIZ 512
  549. void
  550. subst(int in, int ot)
  551. {
  552. unsigned int c;
  553. struct fileblk fb;
  554. int count = CPYSIZ;
  555. unsigned char *pc;
  556. push(&fb);
  557. initf(in);
  558. /*
  559. * DQUOTE used to stop it from quoting
  560. */
  561. while (c = (getch(DQUOTE, 0))) /* read characters from here document
  562. and interpret them */
  563. {
  564. if(c == '\\') {
  565. c = readwc(); /* check if character in here document is
  566. escaped */
  567. if(!escchar(c) || c == '"') {
  568. if (staktop >= brkend)
  569. growstak(staktop);
  570. pushstak('\\');
  571. }
  572. }
  573. pc = readw(c);
  574. /* c might be NULL */
  575. if (*pc) {
  576. while (*pc) {
  577. if (staktop >= brkend)
  578. growstak(staktop);
  579. pushstak(*pc++);
  580. }
  581. } else {
  582. if (staktop >= brkend)
  583. growstak(staktop);
  584. pushstak(*pc);
  585. }
  586. if (--count == 0)
  587. {
  588. flush(ot);
  589. count = CPYSIZ;
  590. }
  591. }
  592. flush(ot);
  593. pop();
  594. }
  595. static void
  596. flush(int ot)
  597. {
  598. write(ot, stakbot, staktop - stakbot);
  599. if (flags & execpr)
  600. write(output, stakbot, staktop - stakbot);
  601. staktop = stakbot;
  602. }