/contrib/tcsh/sh.misc.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 668 lines · 516 code · 89 blank · 63 comment · 147 complexity · a6f38a9b41e0cc1526d990d670731490 MD5 · raw file

  1. /* $Header: /p/tcsh/cvsroot/tcsh/sh.misc.c,v 3.46 2010/05/08 00:41:58 christos Exp $ */
  2. /*
  3. * sh.misc.c: Miscelaneous functions
  4. */
  5. /*-
  6. * Copyright (c) 1980, 1991 The Regents of the University of California.
  7. * All rights reserved.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. * 3. Neither the name of the University nor the names of its contributors
  18. * may be used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. */
  33. #include "sh.h"
  34. RCSID("$tcsh: sh.misc.c,v 3.46 2010/05/08 00:41:58 christos Exp $")
  35. static int renum (int, int);
  36. static Char **blkend (Char **);
  37. static Char **blkcat (Char **, Char **);
  38. static int xdup2 (int, int);
  39. /*
  40. * C Shell
  41. */
  42. int
  43. any(const char *s, Char c)
  44. {
  45. if (!s)
  46. return (0); /* Check for nil pointer */
  47. while (*s)
  48. if ((Char)*s++ == c)
  49. return (1);
  50. return (0);
  51. }
  52. void
  53. setzero(void *p, size_t size)
  54. {
  55. memset(p, 0, size);
  56. }
  57. #ifndef SHORT_STRINGS
  58. char *
  59. strnsave(const char *s, size_t len)
  60. {
  61. char *r;
  62. r = xmalloc(len + 1);
  63. memcpy(r, s, len);
  64. r[len] = '\0';
  65. return r;
  66. }
  67. #endif
  68. char *
  69. strsave(const char *s)
  70. {
  71. char *r;
  72. size_t size;
  73. if (s == NULL)
  74. s = "";
  75. size = strlen(s) + 1;
  76. r = xmalloc(size);
  77. memcpy(r, s, size);
  78. return (r);
  79. }
  80. static Char **
  81. blkend(Char **up)
  82. {
  83. while (*up)
  84. up++;
  85. return (up);
  86. }
  87. void
  88. blkpr(Char *const *av)
  89. {
  90. for (; *av; av++) {
  91. xprintf("%S", *av);
  92. if (av[1])
  93. xprintf(" ");
  94. }
  95. }
  96. Char *
  97. blkexpand(Char *const *av)
  98. {
  99. struct Strbuf buf = Strbuf_INIT;
  100. for (; *av; av++) {
  101. Strbuf_append(&buf, *av);
  102. if (av[1])
  103. Strbuf_append1(&buf, ' ');
  104. }
  105. return Strbuf_finish(&buf);
  106. }
  107. int
  108. blklen(Char **av)
  109. {
  110. int i = 0;
  111. while (*av++)
  112. i++;
  113. return (i);
  114. }
  115. Char **
  116. blkcpy(Char **oav, Char **bv)
  117. {
  118. Char **av = oav;
  119. while ((*av++ = *bv++) != NULL)
  120. continue;
  121. return (oav);
  122. }
  123. static Char **
  124. blkcat(Char **up, Char **vp)
  125. {
  126. (void) blkcpy(blkend(up), vp);
  127. return (up);
  128. }
  129. void
  130. blkfree(Char **av0)
  131. {
  132. Char **av = av0;
  133. if (!av0)
  134. return;
  135. for (; *av; av++)
  136. xfree(*av);
  137. xfree(av0);
  138. }
  139. void
  140. blk_cleanup(void *ptr)
  141. {
  142. blkfree(ptr);
  143. }
  144. void
  145. blk_indirect_cleanup(void *xptr)
  146. {
  147. Char ***ptr;
  148. ptr = xptr;
  149. blkfree(*ptr);
  150. xfree(ptr);
  151. }
  152. Char **
  153. saveblk(Char **v)
  154. {
  155. Char **newv, **onewv;
  156. if (v == NULL)
  157. return NULL;
  158. onewv = newv = xcalloc(blklen(v) + 1, sizeof(Char **));
  159. while (*v)
  160. *newv++ = Strsave(*v++);
  161. return (onewv);
  162. }
  163. #ifndef HAVE_STRSTR
  164. char *
  165. strstr(const char *s, const char *t)
  166. {
  167. do {
  168. const char *ss = s;
  169. const char *tt = t;
  170. do
  171. if (*tt == '\0')
  172. return (s);
  173. while (*ss++ == *tt++);
  174. } while (*s++ != '\0');
  175. return (NULL);
  176. }
  177. #endif /* !HAVE_STRSTR */
  178. char *
  179. strspl(const char *cp, const char *dp)
  180. {
  181. char *ep;
  182. size_t cl, dl;
  183. if (!cp)
  184. cp = "";
  185. if (!dp)
  186. dp = "";
  187. cl = strlen(cp);
  188. dl = strlen(dp);
  189. ep = xmalloc((cl + dl + 1) * sizeof(char));
  190. memcpy(ep, cp, cl);
  191. memcpy(ep + cl, dp, dl + 1);
  192. return (ep);
  193. }
  194. Char **
  195. blkspl(Char **up, Char **vp)
  196. {
  197. Char **wp = xcalloc(blklen(up) + blklen(vp) + 1, sizeof(Char **));
  198. (void) blkcpy(wp, up);
  199. return (blkcat(wp, vp));
  200. }
  201. Char
  202. lastchr(Char *cp)
  203. {
  204. if (!cp)
  205. return (0);
  206. if (!*cp)
  207. return (0);
  208. while (cp[1])
  209. cp++;
  210. return (*cp);
  211. }
  212. /*
  213. * This routine is called after an error to close up
  214. * any units which may have been left open accidentally.
  215. */
  216. void
  217. closem(void)
  218. {
  219. int f, num_files;
  220. #ifdef NLS_BUGS
  221. #ifdef NLS_CATALOGS
  222. nlsclose();
  223. #endif /* NLS_CATALOGS */
  224. #endif /* NLS_BUGS */
  225. #ifdef YPBUGS
  226. /* suggested by Justin Bur; thanks to Karl Kleinpaste */
  227. fix_yp_bugs();
  228. #endif /* YPBUGS */
  229. num_files = NOFILE;
  230. for (f = 0; f < num_files; f++)
  231. if (f != SHIN && f != SHOUT && f != SHDIAG && f != OLDSTD &&
  232. f != FSHTTY
  233. #ifdef MALLOC_TRACE
  234. && f != 25
  235. #endif /* MALLOC_TRACE */
  236. )
  237. {
  238. xclose(f);
  239. #ifdef NISPLUS
  240. if(f < 3)
  241. (void) xopen(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE);
  242. #endif /* NISPLUS */
  243. }
  244. #ifdef NLS_BUGS
  245. #ifdef NLS_CATALOGS
  246. nlsinit();
  247. #endif /* NLS_CATALOGS */
  248. #endif /* NLS_BUGS */
  249. }
  250. #ifndef CLOSE_ON_EXEC
  251. /*
  252. * Close files before executing a file.
  253. * We could be MUCH more intelligent, since (on a version 7 system)
  254. * we need only close files here during a source, the other
  255. * shell fd's being in units 16-19 which are closed automatically!
  256. */
  257. void
  258. closech(void)
  259. {
  260. int f, num_files;
  261. if (didcch)
  262. return;
  263. didcch = 1;
  264. SHIN = 0;
  265. SHOUT = 1;
  266. SHDIAG = 2;
  267. OLDSTD = 0;
  268. isoutatty = isatty(SHOUT);
  269. isdiagatty = isatty(SHDIAG);
  270. num_files = NOFILE;
  271. for (f = 3; f < num_files; f++)
  272. xclose(f);
  273. }
  274. #endif /* CLOSE_ON_EXEC */
  275. void
  276. donefds(void)
  277. {
  278. xclose(0);
  279. xclose(1);
  280. xclose(2);
  281. didfds = 0;
  282. #ifdef NISPLUS
  283. {
  284. int fd = xopen(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE);
  285. (void)dcopy(fd, 1);
  286. (void)dcopy(fd, 2);
  287. (void)dmove(fd, 0);
  288. }
  289. #endif /*NISPLUS*/
  290. }
  291. /*
  292. * Move descriptor i to j.
  293. * If j is -1 then we just want to get i to a safe place,
  294. * i.e. to a unit > FSAFE. This also happens in dcopy.
  295. */
  296. int
  297. dmove(int i, int j)
  298. {
  299. if (i == j || i < 0)
  300. return (i);
  301. #ifdef HAVE_DUP2
  302. if (j >= 0) {
  303. (void) xdup2(i, j);
  304. if (j != i)
  305. xclose(i);
  306. return (j);
  307. }
  308. #endif
  309. j = dcopy(i, j);
  310. if (j != i)
  311. xclose(i);
  312. return (j);
  313. }
  314. int
  315. dcopy(int i, int j)
  316. {
  317. if (i == j || i < 0 || (j < 0 && i > FSAFE))
  318. return (i);
  319. if (j >= 0) {
  320. #ifdef HAVE_DUP2
  321. (void) xdup2(i, j);
  322. return (j);
  323. #else
  324. xclose(j);
  325. #endif
  326. }
  327. return (renum(i, j));
  328. }
  329. static int
  330. renum(int i, int j)
  331. {
  332. int k = dup(i);
  333. if (k < 0)
  334. return (-1);
  335. if (j == -1 && k > FSAFE)
  336. return (k);
  337. if (k != j) {
  338. j = renum(k, j);
  339. xclose(k);
  340. return (j);
  341. }
  342. return (k);
  343. }
  344. /*
  345. * Left shift a command argument list, discarding
  346. * the first c arguments. Used in "shift" commands
  347. * as well as by commands like "repeat".
  348. */
  349. void
  350. lshift(Char **v, int c)
  351. {
  352. Char **u;
  353. for (u = v; *u && --c >= 0; u++)
  354. xfree(*u);
  355. (void) blkcpy(v, u);
  356. }
  357. int
  358. number(Char *cp)
  359. {
  360. if (!cp)
  361. return (0);
  362. if (*cp == '-') {
  363. cp++;
  364. if (!Isdigit(*cp))
  365. return (0);
  366. cp++;
  367. }
  368. while (*cp && Isdigit(*cp))
  369. cp++;
  370. return (*cp == 0);
  371. }
  372. Char **
  373. copyblk(Char **v)
  374. {
  375. Char **nv = xcalloc(blklen(v) + 1, sizeof(Char **));
  376. return (blkcpy(nv, v));
  377. }
  378. char *
  379. strend(const char *cp)
  380. {
  381. if (!cp)
  382. return ((char *)(intptr_t)cp);
  383. while (*cp)
  384. cp++;
  385. return ((char *)(intptr_t)cp);
  386. }
  387. Char *
  388. strip(Char *cp)
  389. {
  390. Char *dp = cp;
  391. if (!cp)
  392. return (cp);
  393. while ((*dp++ &= TRIM) != '\0')
  394. continue;
  395. return (cp);
  396. }
  397. Char *
  398. quote(Char *cp)
  399. {
  400. Char *dp = cp;
  401. if (!cp)
  402. return (cp);
  403. while (*dp != '\0')
  404. *dp++ |= QUOTE;
  405. return (cp);
  406. }
  407. const Char *
  408. quote_meta(struct Strbuf *buf, const Char *s)
  409. {
  410. buf->len = 0;
  411. while (*s != '\0') {
  412. if (cmap(*s, _META | _DOL | _QF | _QB | _ESC | _GLOB))
  413. Strbuf_append1(buf, '\\');
  414. Strbuf_append1(buf, *s++);
  415. }
  416. Strbuf_terminate(buf);
  417. return buf->s;
  418. }
  419. void
  420. udvar(Char *name)
  421. {
  422. setname(short2str(name));
  423. stderror(ERR_NAME | ERR_UNDVAR);
  424. }
  425. int
  426. prefix(const Char *sub, const Char *str)
  427. {
  428. for (;;) {
  429. if (*sub == 0)
  430. return (1);
  431. if (*str == 0)
  432. return (0);
  433. if ((*sub++ & TRIM) != (*str++ & TRIM))
  434. return (0);
  435. }
  436. }
  437. #ifndef WINNT_NATIVE
  438. char *
  439. areadlink(const char *path)
  440. {
  441. char *buf;
  442. size_t size;
  443. ssize_t res;
  444. size = MAXPATHLEN + 1;
  445. buf = xmalloc(size);
  446. while ((size_t)(res = readlink(path, buf, size)) == size) {
  447. size *= 2;
  448. buf = xrealloc(buf, size);
  449. }
  450. if (res == -1) {
  451. int err;
  452. err = errno;
  453. xfree(buf);
  454. errno = err;
  455. return NULL;
  456. }
  457. buf[res] = '\0';
  458. return xrealloc(buf, res + 1);
  459. }
  460. #endif /*!WINNT_NATIVE*/
  461. void
  462. xclose(int fildes)
  463. {
  464. if (fildes < 0)
  465. return;
  466. while (close(fildes) == -1 && errno == EINTR)
  467. handle_pending_signals();
  468. }
  469. void
  470. xclosedir(DIR *dirp)
  471. {
  472. while (closedir(dirp) == -1 && errno == EINTR)
  473. handle_pending_signals();
  474. }
  475. int
  476. xcreat(const char *path, mode_t mode)
  477. {
  478. int res;
  479. while ((res = creat(path, mode)) == -1 && errno == EINTR)
  480. handle_pending_signals();
  481. return res;
  482. }
  483. #ifdef HAVE_DUP2
  484. static int
  485. xdup2(int fildes, int fildes2)
  486. {
  487. int res;
  488. while ((res = dup2(fildes, fildes2)) == -1 && errno == EINTR)
  489. handle_pending_signals();
  490. return res;
  491. }
  492. #endif
  493. struct group *
  494. xgetgrgid(gid_t xgid)
  495. {
  496. struct group *res;
  497. errno = 0;
  498. while ((res = getgrgid(xgid)) == NULL && errno == EINTR) {
  499. handle_pending_signals();
  500. errno = 0;
  501. }
  502. return res;
  503. }
  504. struct passwd *
  505. xgetpwnam(const char *name)
  506. {
  507. struct passwd *res;
  508. errno = 0;
  509. while ((res = getpwnam(name)) == NULL && errno == EINTR) {
  510. handle_pending_signals();
  511. errno = 0;
  512. }
  513. return res;
  514. }
  515. struct passwd *
  516. xgetpwuid(uid_t xuid)
  517. {
  518. struct passwd *res;
  519. errno = 0;
  520. while ((res = getpwuid(xuid)) == NULL && errno == EINTR) {
  521. handle_pending_signals();
  522. errno = 0;
  523. }
  524. return res;
  525. }
  526. int
  527. xopen(const char *path, int oflag, ...)
  528. {
  529. int res;
  530. if ((oflag & O_CREAT) == 0) {
  531. while ((res = open(path, oflag)) == -1 && errno == EINTR)
  532. handle_pending_signals();
  533. } else {
  534. va_list ap;
  535. mode_t mode;
  536. va_start(ap, oflag);
  537. /* "int" should actually be "mode_t after default argument
  538. promotions". "int" is the best guess we have, "mode_t" used to be
  539. "unsigned short", which we obviously can't use. */
  540. mode = va_arg(ap, int);
  541. va_end(ap);
  542. while ((res = open(path, oflag, mode)) == -1 && errno == EINTR)
  543. handle_pending_signals();
  544. }
  545. return res;
  546. }
  547. ssize_t
  548. xread(int fildes, void *buf, size_t nbyte)
  549. {
  550. ssize_t res;
  551. /* This is where we will be blocked most of the time, so handle signals
  552. that didn't interrupt any system call. */
  553. do
  554. handle_pending_signals();
  555. while ((res = read(fildes, buf, nbyte)) == -1 && errno == EINTR);
  556. return res;
  557. }
  558. #ifdef POSIX
  559. int
  560. xtcsetattr(int fildes, int optional_actions, const struct termios *termios_p)
  561. {
  562. int res;
  563. while ((res = tcsetattr(fildes, optional_actions, termios_p)) == -1 &&
  564. errno == EINTR)
  565. handle_pending_signals();
  566. return res;
  567. }
  568. #endif
  569. ssize_t
  570. xwrite(int fildes, const void *buf, size_t nbyte)
  571. {
  572. ssize_t res;
  573. /* This is where we will be blocked most of the time, so handle signals
  574. that didn't interrupt any system call. */
  575. do
  576. handle_pending_signals();
  577. while ((res = write(fildes, buf, nbyte)) == -1 && errno == EINTR);
  578. return res;
  579. }