/contrib/tcsh/tc.os.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 1625 lines · 1258 code · 174 blank · 193 comment · 330 complexity · a2e35aff151242cb121a62121c7d4c32 MD5 · raw file

  1. /* $Header: /p/tcsh/cvsroot/tcsh/tc.os.c,v 3.72 2011/01/25 13:58:19 christos Exp $ */
  2. /*
  3. * tc.os.c: OS Dependent builtin 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: tc.os.c,v 3.72 2011/01/25 13:58:19 christos Exp $")
  35. #include "tw.h"
  36. #include "ed.h"
  37. #include "ed.defns.h" /* for the function names */
  38. #include "sh.decls.h"
  39. #ifdef _UWIN
  40. #define TIOCGPGRP TIOCGETPGRP
  41. #define TIOCSPGRP TIOCSETPGRP
  42. #endif
  43. /***
  44. *** MACH
  45. ***/
  46. #ifdef MACH
  47. /* dosetpath -- setpath built-in command
  48. *
  49. **********************************************************************
  50. * HISTORY
  51. * 08-May-88 Richard Draves (rpd) at Carnegie-Mellon University
  52. * Major changes to remove artificial limits on sizes and numbers
  53. * of paths.
  54. *
  55. **********************************************************************
  56. */
  57. #ifdef MACH
  58. static Char STRCPATH[] = {'C', 'P', 'A', 'T', 'H', '\0'};
  59. static Char STRLPATH[] = {'L', 'P', 'A', 'T', 'H', '\0'};
  60. static Char STRMPATH[] = {'M', 'P', 'A', 'T', 'H', '\0'};
  61. # if EPATH
  62. static Char STREPATH[] = {'E', 'P', 'A', 'T', 'H', '\0'};
  63. # endif
  64. #endif /* MACH */
  65. static Char *syspaths[] = {STRKPATH, STRCPATH, STRLPATH, STRMPATH,
  66. #if EPATH
  67. STREPATH,
  68. #endif
  69. 0};
  70. #define LOCALSYSPATH "/usr/local"
  71. /*ARGSUSED*/
  72. void
  73. dosetpath(Char **arglist, struct command *c)
  74. {
  75. extern char *getenv();
  76. Char **pathvars, **cmdargs;
  77. char **spaths, **cpaths, **cmds;
  78. char *tcp;
  79. unsigned int npaths, ncmds;
  80. int i, sysflag;
  81. pintr_disabled++;
  82. cleanup_push(&pintr_disabled, disabled_cleanup);
  83. /*
  84. * setpath(3) uses stdio and we want 0, 1, 2 to work...
  85. */
  86. if (!didfds) {
  87. (void) dcopy(SHIN, 0);
  88. (void) dcopy(SHOUT, 1);
  89. (void) dcopy(SHDIAG, 2);
  90. didfds = 1;
  91. }
  92. for (i = 1; arglist[i] && (arglist[i][0] != '-'); i++);
  93. npaths = i - 1;
  94. cmdargs = &arglist[i];
  95. for (; arglist[i]; i++);
  96. ncmds = i - npaths - 1;
  97. if (npaths) {
  98. sysflag = 0;
  99. pathvars = &arglist[1];
  100. }
  101. else {
  102. sysflag = 1;
  103. npaths = (sizeof syspaths / sizeof *syspaths) - 1;
  104. pathvars = syspaths;
  105. }
  106. /* note that npaths != 0 */
  107. spaths = xmalloc(npaths * sizeof *spaths);
  108. setzero(spaths, npaths * sizeof *spaths);
  109. cpaths = xmalloc((npaths + 1) * sizeof *cpaths);
  110. setzero(cpaths, (npaths + 1) * sizeof *cpaths);
  111. cmds = xmalloc((ncmds + 1) * sizeof *cmds);
  112. setzero(cmds, (ncmds + 1) * sizeof *cmds);
  113. for (i = 0; i < npaths; i++) {
  114. char *val = getenv(short2str(pathvars[i]));
  115. if (val == NULL)
  116. val = "";
  117. spaths[i] = xmalloc((Strlen(pathvars[i]) + strlen(val) + 2) *
  118. sizeof **spaths);
  119. (void) strcpy(spaths[i], short2str(pathvars[i]));
  120. (void) strcat(spaths[i], "=");
  121. (void) strcat(spaths[i], val);
  122. cpaths[i] = spaths[i];
  123. }
  124. for (i = 0; i < ncmds; i++) {
  125. Char *val = globone(cmdargs[i], G_ERROR);/*FIXRESET*/
  126. if (val == NULL)
  127. goto abortpath;
  128. cmds[i] = strsave(short2str(val));
  129. }
  130. if (setpath(cpaths, cmds, LOCALSYSPATH, sysflag, 1) < 0) {
  131. abortpath:
  132. if (spaths) {
  133. for (i = 0; i < npaths; i++)
  134. xfree(spaths[i]);
  135. xfree(spaths);
  136. }
  137. xfree(cpaths);
  138. if (cmds) {
  139. for (i = 0; i < ncmds; i++)
  140. xfree(cmds[i]);
  141. xfree(cmds);
  142. }
  143. cleanup_until(&pintr_disabled);
  144. donefds();
  145. return;
  146. }
  147. for (i = 0; i < npaths; i++) {
  148. Char *val, *name;
  149. name = str2short(cpaths[i]);
  150. for (val = str2short(cpaths[i]); val && *val && *val != '='; val++);
  151. if (val && *val == '=') {
  152. *val++ = '\0';
  153. tsetenv(name, val);/*FIXRESET*/
  154. if (Strcmp(name, STRKPATH) == 0) {
  155. importpath(val);/*FIXRESET*/
  156. if (havhash)
  157. dohash(NULL, NULL);/*FIXRESET*/
  158. }
  159. *--val = '=';
  160. }
  161. }
  162. cleanup_until(&pintr_disabled);
  163. donefds();
  164. }
  165. #endif /* MACH */
  166. /***
  167. *** AIX
  168. ***/
  169. #ifdef TCF
  170. /* ARGSUSED */
  171. void
  172. dogetxvers(Char **v, struct command *c)
  173. {
  174. char xvers[MAXPATHLEN];
  175. if (getxvers(xvers, MAXPATHLEN) == -1)
  176. stderror(ERR_SYSTEM, "getxvers", strerror(errno));
  177. xprintf("%s\n", xvers);
  178. flush();
  179. }
  180. /*ARGSUSED*/
  181. void
  182. dosetxvers(Char **v, struct command *c)
  183. {
  184. char *xvers;
  185. ++v;
  186. if (!*v || *v[0] == '\0')
  187. xvers = "";
  188. else
  189. xvers = short2str(*v);
  190. if (setxvers(xvers) == -1)
  191. stderror(ERR_SYSTEM, "setxvers", strerror(errno));
  192. }
  193. #include <sf.h>
  194. #ifdef _AIXPS2
  195. # define XC_PDP11 0x01
  196. # define XC_23 0x02
  197. # define XC_Z8K 0x03
  198. # define XC_8086 0x04
  199. # define XC_68K 0x05
  200. # define XC_Z80 0x06
  201. # define XC_VAX 0x07
  202. # define XC_16032 0x08
  203. # define XC_286 0x09
  204. # define XC_386 0x0a
  205. # define XC_S370 0x0b
  206. #else
  207. # include <sys/x.out.h>
  208. #endif /* _AIXPS2 */
  209. static struct xc_cpu_t {
  210. short xc_id;
  211. char *xc_name;
  212. } xcpu[] =
  213. {
  214. { XC_PDP11, "pdp11" },
  215. { XC_23, "i370" },
  216. { XC_Z8K, "z8000" },
  217. { XC_8086, "i86" },
  218. { XC_68K, "mc68000" },
  219. { XC_Z80, "x80" },
  220. { XC_VAX, "vax" },
  221. { XC_16032, "ns16032" },
  222. { XC_286, "i286" },
  223. { XC_386, "i386" },
  224. { XC_S370, "xa370" },
  225. { 0, NULL }
  226. };
  227. /*
  228. * our local hack table, stolen from x.out.h
  229. */
  230. static char *
  231. getxcode(short xcid)
  232. {
  233. int i;
  234. for (i = 0; xcpu[i].xc_name != NULL; i++)
  235. if (xcpu[i].xc_id == xcid)
  236. return (xcpu[i].xc_name);
  237. return (NULL);
  238. }
  239. static short
  240. getxid(char *xcname)
  241. {
  242. int i;
  243. for (i = 0; xcpu[i].xc_name != NULL; i++)
  244. if (strcmp(xcpu[i].xc_name, xcname) == 0)
  245. return (xcpu[i].xc_id);
  246. return ((short) -1);
  247. }
  248. /*ARGSUSED*/
  249. void
  250. dogetspath(Char **v, struct command *c)
  251. {
  252. int i, j;
  253. sitepath_t p[MAXSITE];
  254. struct sf *st;
  255. static char *local = "LOCAL ";
  256. if ((j = getspath(p, MAXSITE)) == -1)
  257. stderror(ERR_SYSTEM, "getspath", strerror(errno));
  258. for (i = 0; i < j && (p[i] & SPATH_CPU) != NOSITE; i++) {
  259. if (p[i] & SPATH_CPU) {
  260. if ((p[i] & SPATH_MASK) == NULLSITE)
  261. xprintf(local);
  262. else if ((st = sfxcode((short) (p[i] & SPATH_MASK))) != NULL)
  263. xprintf("%s ", st->sf_ctype);
  264. else {
  265. char *xc = getxcode(p[i] & SPATH_MASK);
  266. if (xc != NULL)
  267. xprintf("%s ", xc);
  268. else
  269. xprintf("*cpu %d* ", (int) (p[i] & SPATH_MASK));
  270. /*
  271. * BUG in the aix code... needs that cause if
  272. * sfxcode fails once it fails for ever
  273. */
  274. endsf();
  275. }
  276. }
  277. else {
  278. if (p[i] == NULLSITE)
  279. xprintf(local);
  280. else if ((st = sfnum(p[i])) != NULL)
  281. xprintf("%s ", st->sf_sname);
  282. else
  283. xprintf("*site %d* ", (int) (p[i] & SPATH_MASK));
  284. }
  285. }
  286. xputchar('\n');
  287. flush();
  288. }
  289. /*ARGSUSED*/
  290. void
  291. dosetspath(Char **v, struct command *c)
  292. {
  293. int i;
  294. short j;
  295. char *s;
  296. sitepath_t p[MAXSITE];
  297. struct sf *st;
  298. /*
  299. * sfname() on AIX G9.9 at least, mallocs too pointers p, q
  300. * then does the equivalent of while (*p++ == *q++) continue;
  301. * and then tries to free(p,q) them! Congrats to the wizard who
  302. * wrote that one. I bet he tested it really well too.
  303. * Sooo, we set dont_free :-)
  304. */
  305. dont_free = 1;
  306. for (i = 0, v++; *v && *v[0] != '\0'; v++, i++) {
  307. s = short2str(*v);
  308. if (isdigit(*s))
  309. p[i] = atoi(s);
  310. else if (strcmp(s, "LOCAL") == 0)
  311. p[i] = NULLSITE;
  312. else if ((st = sfctype(s)) != NULL)
  313. p[i] = SPATH_CPU | st->sf_ccode;
  314. else if ((j = getxid(s)) != -1)
  315. p[i] = SPATH_CPU | j;
  316. else if ((st = sfname(s)) != NULL)
  317. p[i] = st->sf_id;
  318. else {
  319. setname(s);
  320. stderror(ERR_NAME | ERR_STRING, CGETS(23, 1, "Bad cpu/site name"));
  321. }
  322. if (i == MAXSITE - 1)
  323. stderror(ERR_NAME | ERR_STRING, CGETS(23, 2, "Site path too long"));
  324. }
  325. if (setspath(p, i) == -1)
  326. stderror(ERR_SYSTEM, "setspath", strerror(errno));
  327. dont_free = 0;
  328. }
  329. /* sitename():
  330. * Return the site name where the process is running
  331. */
  332. char *
  333. sitename(pid_t pid)
  334. {
  335. siteno_t ss;
  336. struct sf *st;
  337. if ((ss = site(pid)) == -1 || (st = sfnum(ss)) == NULL)
  338. return CGETS(23, 3, "unknown");
  339. else
  340. return st->sf_sname;
  341. }
  342. static int
  343. migratepid(pit_t pid, siteno_t new_site)
  344. {
  345. struct sf *st;
  346. int need_local;
  347. need_local = (pid == 0) || (pid == getpid());
  348. if (kill3(pid, SIGMIGRATE, new_site) < 0) {
  349. xprintf("%d: %s\n", pid, strerror(errno));
  350. return (-1);
  351. }
  352. if (need_local) {
  353. if ((new_site = site(0)) == -1) {
  354. xprintf(CGETS(23, 4, "site: %s\n"), strerror(errno));
  355. return (-1);
  356. }
  357. if ((st = sfnum(new_site)) == NULL) {
  358. xprintf(CGETS(23, 5, "%d: Site not found\n"), new_site);
  359. return (-1);
  360. }
  361. if (setlocal(st->sf_local, strlen(st->sf_local)) == -1) {
  362. xprintf(CGETS(23, 6, "setlocal: %s: %s\n"),
  363. st->sf_local, strerror(errno));
  364. return (-1);
  365. }
  366. }
  367. return (0);
  368. }
  369. /*ARGSUSED*/
  370. void
  371. domigrate(Char **v, struct command *c)
  372. {
  373. struct sf *st;
  374. char *s;
  375. Char *cp;
  376. struct process *pp;
  377. int err1 = 0;
  378. int pid = 0;
  379. siteno_t new_site = 0;
  380. pchild_disabled++;
  381. cleanup_push(&pchild_disabled, disabled_cleanup);
  382. if (setintr) {
  383. pintr_disabled++;
  384. cleanup_push(&pintr_disabled, disabled_cleanup);
  385. }
  386. ++v;
  387. if (*v[0] == '-') {
  388. /*
  389. * Do the -site.
  390. */
  391. s = short2str(&v[0][1]);
  392. /*
  393. * see comment in setspath()
  394. */
  395. dont_free = 1;
  396. if ((st = sfname(s)) == NULL) {
  397. dont_free = 0;
  398. setname(s);
  399. stderror(ERR_NAME | ERR_STRING, CGETS(23, 7, "Site not found"));
  400. }
  401. dont_free = 0;
  402. new_site = st->sf_id;
  403. ++v;
  404. }
  405. if (!*v || *v[0] == '\0') {
  406. if (migratepid(0, new_site) == -1)
  407. err1++;
  408. }
  409. else {
  410. Char **globbed;
  411. v = glob_all_or_error(v);
  412. globbed = v;
  413. cleanup_push(globbed, blk_cleanup);
  414. while (v && (cp = *v)) {
  415. if (*cp == '%') {
  416. pp = pfind(cp);
  417. if (kill3(- pp->p_jobid, SIGMIGRATE, new_site) < 0) {
  418. xprintf("%S: %s\n", cp, strerror(errno));
  419. err1++;
  420. }
  421. }
  422. else if (!(Isdigit(*cp) || *cp == '-'))
  423. stderror(ERR_NAME | ERR_JOBARGS);
  424. else {
  425. pid = atoi(short2str(cp));
  426. if (migratepid(pid, new_site) == -1)
  427. err1++;
  428. }
  429. v++;
  430. }
  431. cleanup_until(globbed);
  432. }
  433. done:
  434. cleanup_until(&pchild_disabled);
  435. if (err1)
  436. stderror(ERR_SILENT);
  437. }
  438. #endif /* TCF */
  439. /***
  440. *** CRAY ddmode <velo@sesun3.epfl.ch> (Martin Ouwehand EPFL-SIC/SE)
  441. ***/
  442. #if defined(_CRAY) && !defined(_CRAYMPP)
  443. void
  444. dodmmode(Char **v, struct command *c)
  445. {
  446. Char *cp = v[1];
  447. USE(c);
  448. if ( !cp ) {
  449. int mode;
  450. mode = dmmode(0);
  451. dmmode(mode);
  452. xprintf("%d\n",mode);
  453. }
  454. else {
  455. if (cp[1] != '\0')
  456. stderror(ERR_NAME | ERR_STRING,
  457. CGETS(23, 30, "Too many arguments"));
  458. else
  459. switch(*cp) {
  460. case '0':
  461. dmmode(0);
  462. break;
  463. case '1':
  464. dmmode(1);
  465. break;
  466. default:
  467. stderror(ERR_NAME | ERR_STRING,
  468. CGETS(23, 31, "Invalid argument"));
  469. }
  470. }
  471. }
  472. #endif /* _CRAY && !_CRAYMPP */
  473. /***
  474. *** CONVEX Warps.
  475. ***/
  476. #ifdef WARP
  477. /*
  478. * handle the funky warping of symlinks
  479. */
  480. #include <warpdb.h>
  481. #include <sys/warp.h>
  482. static jmp_buf sigsys_buf;
  483. static void
  484. catch_sigsys(void)
  485. {
  486. sigset_t set;
  487. sigemptyset(&set, SIGSYS);
  488. (void)sigprocmask(SIG_UNBLOCK, &set, NULL);
  489. longjmp(sigsys_buf, 1);
  490. }
  491. /*ARGSUSED*/
  492. void
  493. dowarp(Char **v, struct command *c)
  494. {
  495. int warp, oldwarp;
  496. struct warpent *we;
  497. volatile struct sigaction old_sigsys_handler;
  498. char *newwarp;
  499. if (setjmp(sigsys_buf)) {
  500. sigaction(SIGSYS, &old_sigsys_handler, NULL);
  501. stderror(ERR_NAME | ERR_STRING,
  502. CGETS(23, 8, "You're trapped in a universe you never made"));
  503. return;
  504. }
  505. sigaction(SIGSYS, NULL, &old_sigsys_handler);
  506. signal(SIGSYS, catch_sigsys);
  507. warp = getwarp();
  508. v++;
  509. if (*v == 0) { /* display warp value */
  510. if (warp < 0)
  511. stderror(ERR_NAME | ERR_STRING, CGETS(23, 9, "Getwarp failed"));
  512. we = getwarpbyvalue(warp);
  513. if (we)
  514. printf("%s\n", we->w_name);
  515. else
  516. printf("%d\n", warp);
  517. }
  518. else { /* set warp value */
  519. oldwarp = warp;
  520. newwarp = short2str(*v);
  521. if (Isdigit(*v[0]))
  522. warp = atoi(newwarp);
  523. else {
  524. we = getwarpbyname(newwarp);
  525. if (we)
  526. warp = we->w_value;
  527. else
  528. warp = -1;
  529. }
  530. if ((warp < 0) || (warp >= WARP_MAXLINK))
  531. stderror(ERR_NAME | ERR_STRING, CGETS(23, 10, "Invalid warp"));
  532. if ((setwarp(warp) < 0) || (getwarp() != warp)) {
  533. (void) setwarp(oldwarp);
  534. stderror(ERR_NAME | ERR_STRING, CGETS(23, 11, "Setwarp failed"));
  535. }
  536. }
  537. sigaction(SIGSYS, &old_sigsys_handler, NULL);
  538. }
  539. #endif /* WARP */
  540. /***
  541. *** Masscomp or HCX
  542. ***/
  543. /* Added, DAS DEC-90. */
  544. #if defined(masscomp) || defined(_CX_UX)
  545. static void
  546. setuniverse_cleanup(void *xbuf)
  547. {
  548. char *buf;
  549. buf = xbuf;
  550. setuniverse(buf);
  551. }
  552. /*ARGSUSED*/
  553. void
  554. douniverse(Char **v, struct command *c)
  555. {
  556. Char *cp = v[1];
  557. Char *cp2; /* dunno how many elements v comes in with */
  558. char ubuf[100];
  559. if (cp == 0) {
  560. (void) getuniverse(ubuf);
  561. xprintf("%s\n", ubuf);
  562. }
  563. else {
  564. cp2 = v[2];
  565. if (cp2 == 0) {
  566. if (*cp == '\0' || setuniverse(short2str(cp)) != 0)
  567. stderror(ERR_NAME | ERR_STRING, CGETS(23, 12, "Illegal universe"));
  568. }
  569. else {
  570. (void) getuniverse(ubuf);
  571. if (*cp == '\0' || setuniverse(short2str(cp)) != 0)
  572. stderror(ERR_NAME | ERR_STRING, CGETS(23, 12, "Illegal universe"));
  573. cleanup_push(ubuf, setuniverse_cleanup);
  574. if (setintr) {
  575. pintr_disabled++;
  576. cleanup_push(&pintr_disabled, disabled_cleanup);
  577. }
  578. lshift(v, 2);
  579. if (setintr)
  580. cleanup_until(&pintr_disabled);
  581. reexecute(c);
  582. cleanup_until(ubuf);
  583. }
  584. }
  585. }
  586. #endif /* masscomp || _CX_UX */
  587. /***
  588. *** BS2000/OSD POSIX (Fujitsu Siemens Computers)
  589. ***/
  590. #if defined(_OSD_POSIX)
  591. static int
  592. bs2upcase(char *str)
  593. {
  594. enum { outside = ' ', singlequote='\'', doublequote='"'} string = outside;
  595. char *white;
  596. for (white = str + strlen(str) - 1; isspace(*white) && white > str; --white)
  597. *white = '\0';
  598. for (; *str != '\0'; ++str)
  599. {
  600. if (string == outside)
  601. {
  602. *str = toupper (*str);
  603. }
  604. if (*str == '\'')
  605. {
  606. if (string == outside)
  607. string = singlequote;
  608. else if (string != doublequote)
  609. string = outside;
  610. }
  611. else if (*str == '"')
  612. {
  613. if (string == outside)
  614. string = doublequote;
  615. else if (string != singlequote)
  616. string = outside;
  617. }
  618. }
  619. if (string != outside)
  620. {
  621. stderror(ERR_NAME | ERR_UNMATCHED, (Char) string);
  622. return 1;
  623. }
  624. return 0;
  625. }
  626. static int
  627. bs2cmdlist(char *str)
  628. {
  629. char *str_beg = NULL;
  630. int ret = 0;
  631. enum { outside = ' ', singlequote='\'', doublequote='"'} string = outside;
  632. while (*str != '\0')
  633. {
  634. while (isspace(*str))
  635. ++str;
  636. if (*str == '\0')
  637. break;
  638. str_beg = str;
  639. for (; *str != '\0'; ++str)
  640. {
  641. if (string == outside && *str == ';') /* End of command */
  642. {
  643. *str++ = '\0';
  644. break; /* continue with next command */
  645. }
  646. if (*str == '\'')
  647. {
  648. if (string == outside)
  649. string = singlequote;
  650. else if (string != doublequote)
  651. string = outside;
  652. }
  653. else if (*str == '"')
  654. {
  655. if (string == outside)
  656. string = doublequote;
  657. else if (string != singlequote)
  658. string = outside;
  659. }
  660. }
  661. if (strlen(str_beg) != 0)
  662. {
  663. ret = bs2system(str_beg);
  664. flush();
  665. if (ret != 0 /*&& !option.err_ignore*/)
  666. break; /* do not continue after errors */
  667. }
  668. }
  669. if (string != outside)
  670. {
  671. stderror(ERR_NAME | ERR_UNMATCHED, (Char) string);
  672. return -1;
  673. }
  674. return ret;
  675. }
  676. /*ARGSUSED*/
  677. void
  678. dobs2cmd(Char **v, struct command *c)
  679. {
  680. Char *cp, **globbed;
  681. int i = 0, len = 0;
  682. char *cmd = NULL;
  683. int pvec[2];
  684. struct command faket;
  685. Char *fakecom[2];
  686. char tibuf[BUFSIZE];
  687. int icnt, old_pintr_disabled;
  688. static const Char STRbs2cmd[] = { 'b','s','2','c','m','d','\0' };
  689. v++;
  690. if (setintr)
  691. pintr_push_enable(&old_pintr_disabled);
  692. v = glob_all_or_error(v);
  693. if (setintr)
  694. cleanup_until(&old_pintr_disabled);
  695. globbed = v;
  696. cleanup_push(globbed, blk_cleanup);
  697. /* First round: count the string lengths */
  698. for (i=0; v[i]; ++i) {
  699. len += Strlen(v[i]) + (v[i+1] != NULL);
  700. }
  701. cmd = xmalloc(len+1); /* 1 for the final '\0' *//* FIXME: memory leak? */
  702. /* 2nd round: fill cmd buffer */
  703. i = 0;
  704. while ((cp = *v++) != 0) {
  705. int c;
  706. while (c = *cp++)
  707. cmd[i++] = (char)c;
  708. if (*v)
  709. cmd[i++] = ' ';
  710. }
  711. cmd[i] = '\0';
  712. /* Make upper case */
  713. bs2upcase(cmd);
  714. faket.t_dtyp = NODE_COMMAND;
  715. faket.t_dflg = F_BACKQ|F_STDERR;
  716. faket.t_dlef = 0;
  717. faket.t_drit = 0;
  718. faket.t_dspr = 0;
  719. faket.t_dcom = fakecom;
  720. fakecom[0] = (Char *)STRbs2cmd;
  721. fakecom[1] = 0;
  722. mypipe(pvec);
  723. cleanup_push(&pvec[0], open_cleanup);
  724. cleanup_push(&pvec[1], open_cleanup);
  725. if (pfork(&faket, -1) == 0) {
  726. sigset_t set;
  727. /* child */
  728. xclose(pvec[0]);
  729. (void) dmove(pvec[1], 1);
  730. (void) dmove(SHDIAG, 2);
  731. initdesc();
  732. sigemptyset(&set);
  733. sigaddset(&set, SIGINT);
  734. (void)sigprocmask(SIG_UNBLOCK, &set, NULL);
  735. #ifdef SIGTSTP
  736. signal(SIGTSTP, SIG_IGN);
  737. #endif
  738. #ifdef SIGTTIN
  739. signal(SIGTTIN, SIG_IGN);
  740. #endif
  741. #ifdef SIGTTOU
  742. signal(SIGTTOU, SIG_IGN);
  743. #endif
  744. xexit(bs2cmdlist(cmd));
  745. }
  746. cleanup_until(&pvec[1]);
  747. for(;;) {
  748. int old_pintr_disabled;
  749. if (setintr)
  750. pintr_push_enable(&old_pintr_disabled);
  751. icnt = xread(pvec[0], tibuf, sizeof(tibuf));
  752. if (setintr)
  753. cleanup_until(&old_pintr_disabled);
  754. if (icnt <= 0)
  755. break;
  756. for (i = 0; i < icnt; i++)
  757. xputchar((unsigned char) tibuf[i]);
  758. }
  759. cleanup_until(&pvec[0]);
  760. pwait();
  761. flush();
  762. cleanup_until(globbed);
  763. }
  764. #endif /* _OSD_POSIX */
  765. #if defined(_CX_UX)
  766. static void
  767. setuniverse_cleanup(void *xbuf)
  768. {
  769. char *buf;
  770. buf = xbuf;
  771. setuniverse(buf);
  772. }
  773. /*ARGSUSED*/
  774. void
  775. doatt(Char **v, struct command *c)
  776. {
  777. Char *cp = v[1];
  778. char ubuf[100];
  779. if (cp == 0)
  780. (void) setuniverse("att");
  781. else {
  782. (void) getuniverse(ubuf);
  783. (void) setuniverse("att");
  784. cleanup_push(ubuf, setuniverse_cleanup);
  785. if (setintr) {
  786. pintr_disabled++;
  787. cleanup_push(&pintr_disabled, disabled_cleanup);
  788. }
  789. lshift(v, 1);
  790. if (setintr)
  791. cleanup_until(&pintr_disabled);
  792. reexecute(c);
  793. cleanup_until(ubuf);
  794. }
  795. }
  796. /*ARGSUSED*/
  797. void
  798. doucb(Char **v, struct command *c)
  799. {
  800. Char *cp = v[1];
  801. char ubuf[100];
  802. if (cp == 0)
  803. (void) setuniverse("ucb");
  804. else {
  805. (void) getuniverse(ubuf);
  806. (void) setuniverse("ucb");
  807. cleanup_push(ubuf, setuniverse_cleanup);
  808. if (setintr) {
  809. pintr_disabled++;
  810. cleanup_push(&pintr_disabled, disabled_cleanup);
  811. }
  812. lshift(v, 1);
  813. if (setintr)
  814. cleanup_until(&pintr_disabled);
  815. reexecute(c);
  816. cleanup_until(ubuf);
  817. }
  818. }
  819. #endif /* _CX_UX */
  820. #ifdef _SEQUENT_
  821. /*
  822. * Compute the difference in process stats.
  823. */
  824. void
  825. pr_stat_sub(struct process_stats *p2, struct process_stats *p1,
  826. struct process_stats *pr)
  827. {
  828. pr->ps_utime.tv_sec = p2->ps_utime.tv_sec - p1->ps_utime.tv_sec;
  829. pr->ps_utime.tv_usec = p2->ps_utime.tv_usec - p1->ps_utime.tv_usec;
  830. if (pr->ps_utime.tv_usec < 0) {
  831. pr->ps_utime.tv_sec -= 1;
  832. pr->ps_utime.tv_usec += 1000000;
  833. }
  834. pr->ps_stime.tv_sec = p2->ps_stime.tv_sec - p1->ps_stime.tv_sec;
  835. pr->ps_stime.tv_usec = p2->ps_stime.tv_usec - p1->ps_stime.tv_usec;
  836. if (pr->ps_stime.tv_usec < 0) {
  837. pr->ps_stime.tv_sec -= 1;
  838. pr->ps_stime.tv_usec += 1000000;
  839. }
  840. pr->ps_maxrss = p2->ps_maxrss - p1->ps_maxrss;
  841. pr->ps_pagein = p2->ps_pagein - p1->ps_pagein;
  842. pr->ps_reclaim = p2->ps_reclaim - p1->ps_reclaim;
  843. pr->ps_zerofill = p2->ps_zerofill - p1->ps_zerofill;
  844. pr->ps_pffincr = p2->ps_pffincr - p1->ps_pffincr;
  845. pr->ps_pffdecr = p2->ps_pffdecr - p1->ps_pffdecr;
  846. pr->ps_swap = p2->ps_swap - p1->ps_swap;
  847. pr->ps_syscall = p2->ps_syscall - p1->ps_syscall;
  848. pr->ps_volcsw = p2->ps_volcsw - p1->ps_volcsw;
  849. pr->ps_involcsw = p2->ps_involcsw - p1->ps_involcsw;
  850. pr->ps_signal = p2->ps_signal - p1->ps_signal;
  851. pr->ps_lread = p2->ps_lread - p1->ps_lread;
  852. pr->ps_lwrite = p2->ps_lwrite - p1->ps_lwrite;
  853. pr->ps_bread = p2->ps_bread - p1->ps_bread;
  854. pr->ps_bwrite = p2->ps_bwrite - p1->ps_bwrite;
  855. pr->ps_phread = p2->ps_phread - p1->ps_phread;
  856. pr->ps_phwrite = p2->ps_phwrite - p1->ps_phwrite;
  857. }
  858. #endif /* _SEQUENT_ */
  859. #ifndef HAVE_MEMSET
  860. /* This is a replacement for a missing memset function */
  861. void *xmemset(void *loc, int value, size_t len)
  862. {
  863. char *ptr = loc;
  864. while (len--)
  865. *ptr++ = value;
  866. return loc;
  867. }
  868. #endif /* !HAVE_MEMSET */
  869. #ifndef HAVE_MEMMOVE
  870. /* memmove():
  871. * This is the ANSI form of bcopy() with the arguments backwards...
  872. * Unlike memcpy(), it handles overlaps between source and
  873. * destination memory
  874. */
  875. void *
  876. xmemmove(void *vdst, const void *vsrc, size_t len)
  877. {
  878. const char *src = vsrc;
  879. char *dst = vdst;
  880. if (src == dst)
  881. return vdst;
  882. if (src > dst) {
  883. while (len--)
  884. *dst++ = *src++;
  885. }
  886. else {
  887. src += len;
  888. dst += len;
  889. while (len--)
  890. *--dst = *--src;
  891. }
  892. return vdst;
  893. }
  894. #endif /* HAVE_MEMMOVE */
  895. #ifndef WINNT_NATIVE
  896. #ifdef NEEDtcgetpgrp
  897. pid_t
  898. xtcgetpgrp(int fd)
  899. {
  900. int pgrp;
  901. /* ioctl will handle setting errno correctly. */
  902. if (ioctl(fd, TIOCGPGRP, (ioctl_t) & pgrp) < 0)
  903. return (-1);
  904. return (pgrp);
  905. }
  906. /*
  907. * XXX: tcsetpgrp is not a macro any more cause on some systems,
  908. * pid_t is a short, but the ioctl() takes a pointer to int (pyr)
  909. * Thanks to Simon Day (simon@pharaoh.cyborg.bt.co.uk) for pointing
  910. * this out.
  911. */
  912. int
  913. xtcsetpgrp(int fd, int pgrp)
  914. {
  915. return ioctl(fd, TIOCSPGRP, (ioctl_t) &pgrp);
  916. }
  917. #endif /* NEEDtcgetpgrp */
  918. #endif /* WINNT_NATIVE */
  919. #ifdef YPBUGS
  920. void
  921. fix_yp_bugs(void)
  922. {
  923. char *mydomain;
  924. extern int yp_get_default_domain (char **);
  925. /*
  926. * PWP: The previous version assumed that yp domain was the same as the
  927. * internet name domain. This isn't allways true. (Thanks to Mat Landau
  928. * <mlandau@bbn.com> for the original version of this.)
  929. */
  930. if (yp_get_default_domain(&mydomain) == 0) { /* if we got a name */
  931. extern void yp_unbind (const char *);
  932. yp_unbind(mydomain);
  933. }
  934. }
  935. #endif /* YPBUGS */
  936. #ifdef STRCOLLBUG
  937. void
  938. fix_strcoll_bug(void)
  939. {
  940. #if defined(NLS) && defined(HAVE_STRCOLL)
  941. /*
  942. * SunOS4 checks the file descriptor from openlocale() for <= 0
  943. * instead of == -1. Someone should tell sun that file descriptor 0
  944. * is valid! Our portable hack: open one so we call it with 0 used...
  945. * We have to call this routine every time the locale changes...
  946. *
  947. * Of course it also tries to free the constant locale "C" it initially
  948. * had allocated, with the sequence
  949. * > setenv LANG "fr"
  950. * > ls^D
  951. * > unsetenv LANG
  952. * But we are smarter than that and just print a warning message.
  953. */
  954. int fd = -1;
  955. static char *root = "/";
  956. if (!didfds)
  957. fd = xopen(root, O_RDONLY|O_LARGEFILE);
  958. (void) strcoll(root, root);
  959. if (fd != -1)
  960. xclose(fd);
  961. #endif
  962. }
  963. #endif /* STRCOLLBUG */
  964. #ifdef OREO
  965. #include <compat.h>
  966. #endif /* OREO */
  967. void
  968. osinit(void)
  969. {
  970. #ifdef OREO
  971. set42sig();
  972. setcompat(getcompat() & ~COMPAT_EXEC);
  973. signal(SIGIO, SIG_IGN); /* ignore SIGIO */
  974. #endif /* OREO */
  975. #ifdef aiws
  976. {
  977. struct sigstack inst;
  978. inst.ss_sp = xmalloc(4192) + 4192;
  979. inst.ss_onstack = 0;
  980. sigstack(&inst, NULL);
  981. }
  982. #endif /* aiws */
  983. #ifdef apollo
  984. (void) isapad();
  985. #endif
  986. #ifdef _SX
  987. /*
  988. * kill(SIGCONT) problems, don't know what this syscall does
  989. * [schott@rzg.mpg.de]
  990. */
  991. syscall(151, getpid(), getpid());
  992. #endif /* _SX */
  993. }
  994. #ifndef HAVE_STRERROR
  995. extern int sys_nerr;
  996. extern char *sys_errlist[];
  997. char *
  998. xstrerror(int i)
  999. {
  1000. if (i >= 0 && i < sys_nerr) {
  1001. return sys_errlist[i];
  1002. } else {
  1003. static char *errbuf; /* = NULL; */
  1004. xfree(errbuf);
  1005. errbuf = xasprintf(CGETS(23, 13, "Unknown Error: %d"), i);
  1006. return errbuf;
  1007. }
  1008. }
  1009. #endif /* !HAVE_STRERROR */
  1010. #ifndef HAVE_GETHOSTNAME
  1011. # if !defined(_MINIX) && !defined(__EMX__) && !defined(WINNT_NATIVE)
  1012. # include <sys/utsname.h>
  1013. # endif /* !_MINIX && !__EMX__ && !WINNT_NATIVE */
  1014. int
  1015. xgethostname(char *name, int namlen)
  1016. {
  1017. # if !defined(_MINIX) && !defined(__EMX__) && !defined(WINNT_NATIVE)
  1018. int i, retval;
  1019. struct utsname uts;
  1020. retval = uname(&uts);
  1021. # ifdef DEBUG
  1022. xprintf(CGETS(23, 14, "sysname: %s\n"), uts.sysname);
  1023. xprintf(CGETS(23, 15, "nodename: %s\n"), uts.nodename);
  1024. xprintf(CGETS(23, 16, "release: %s\n"), uts.release);
  1025. xprintf(CGETS(23, 17, "version: %s\n"), uts.version);
  1026. xprintf(CGETS(23, 18, "machine: %s\n"), uts.machine);
  1027. # endif /* DEBUG */
  1028. i = strlen(uts.nodename) + 1;
  1029. (void) strncpy(name, uts.nodename, i < namlen ? i : namlen);
  1030. return retval;
  1031. # else /* !_MINIX && !__EMX__ */
  1032. if (namlen > 0) {
  1033. # ifdef __EMX__
  1034. (void) strncpy(name, "OS/2", namlen);
  1035. # else /* _MINIX */
  1036. (void) strncpy(name, "minix", namlen);
  1037. # endif /* __EMX__ */
  1038. name[namlen-1] = '\0';
  1039. }
  1040. return(0);
  1041. #endif /* _MINIX && !__EMX__ */
  1042. } /* end xgethostname */
  1043. #endif /* !HAVE_GETHOSTNAME */
  1044. #ifndef HAVE_NICE
  1045. # if defined(_MINIX) && defined(NICE)
  1046. # undef _POSIX_SOURCE /* redefined in <lib.h> */
  1047. # undef _MINIX /* redefined in <lib.h> */
  1048. # undef HZ /* redefined in <minix/const.h> */
  1049. # include <lib.h>
  1050. # endif /* _MINIX && NICE */
  1051. int
  1052. xnice(int incr)
  1053. {
  1054. #if defined(_MINIX) && defined(NICE)
  1055. return callm1(MM, NICE, incr, 0, 0, NIL_PTR, NIL_PTR, NIL_PTR);
  1056. #else
  1057. return /* incr ? 0 : */ 0;
  1058. #endif /* _MINIX && NICE */
  1059. } /* end xnice */
  1060. #endif /* !HAVE_NICE */
  1061. #ifndef HAVE_GETCWD
  1062. static char *strnrcpy (char *, char *, size_t);
  1063. /* xgetcwd():
  1064. * Return the pathname of the current directory, or return
  1065. * an error message in pathname.
  1066. */
  1067. # ifdef hp9000s500
  1068. /*
  1069. * From: Bernd Mohr <mohr@faui77.informatik.uni-erlangen.de>
  1070. * I also ported the tcsh to the HP9000 Series 500. This computer
  1071. * is a little bit different than the other HP 9000 computer. It has
  1072. * a HP Chip instead of a Motorola CPU and it is no "real" UNIX. It runs
  1073. * HP-UX which is emulated in top of a HP operating system. So, the last
  1074. * supported version of HP-UX is 5.2 on the HP9000s500. This has two
  1075. * consequences: it supports no job control and it has a filesystem
  1076. * without "." and ".." !!!
  1077. */
  1078. char *
  1079. xgetcwd(char *pathname, size_t pathlen)
  1080. {
  1081. char pathbuf[MAXPATHLEN]; /* temporary pathname buffer */
  1082. char *pnptr = &pathbuf[(sizeof pathbuf)-1]; /* pathname pointer */
  1083. dev_t rdev; /* root device number */
  1084. DIR *dirp = NULL; /* directory stream */
  1085. ino_t rino; /* root inode number */
  1086. off_t rsize; /* root size */
  1087. struct direct *dir; /* directory entry struct */
  1088. struct stat d, dd; /* file status struct */
  1089. int serrno;
  1090. *pnptr = '\0';
  1091. (void) stat("/.", &d);
  1092. rdev = d.st_dev;
  1093. rino = d.st_ino;
  1094. rsize = d.st_size;
  1095. for (;;) {
  1096. if (stat(".", &d) == -1) {
  1097. (void) xsnprintf(pathname, pathlen, CGETS(23, 24,
  1098. "getcwd: Cannot stat \".\" (%s)"), strerror(errno));
  1099. goto fail;
  1100. }
  1101. if (d.st_ino == rino && d.st_dev == rdev && d.st_size == rsize)
  1102. break; /* reached root directory */
  1103. if ((dirp = opendir("..")) == NULL) {
  1104. (void) xsnprintf(pathname, pathlen, CGETS(23, 19,
  1105. "getcwd: Cannot open \"..\" (%s)"), strerror(errno));
  1106. goto fail;
  1107. }
  1108. if (chdir("..") == -1) {
  1109. (void) xsnprintf(pathname, pathlen, CGETS(23, 20,
  1110. "getcwd: Cannot chdir to \"..\" (%s)"), strerror(errno));
  1111. goto fail;
  1112. }
  1113. do {
  1114. if ((dir = readdir(dirp)) == NULL) {
  1115. (void) xsnprintf(pathname, pathlen,
  1116. CGETS(23, 21, "getcwd: Read error in \"..\" (%s)"),
  1117. strerror(errno));
  1118. goto fail;
  1119. }
  1120. if (stat(dir->d_name, &dd) == -1) {
  1121. (void) xsnprintf(pathname, pathlen,
  1122. CGETS(23, 25, "getcwd: Cannot stat directory \"%s\" (%s)"),
  1123. dir->d_name, strerror(errno));
  1124. goto fail;
  1125. }
  1126. } while (dd.st_ino != d.st_ino ||
  1127. dd.st_dev != d.st_dev ||
  1128. dd.st_size != d.st_size);
  1129. closedir(dirp);
  1130. dirp = NULL;
  1131. pnptr = strnrcpy(dirp->d_name, pnptr, pnptr - pathbuf);
  1132. pnptr = strnrcpy("/", pnptr, pnptr - pathbuf);
  1133. }
  1134. if (*pnptr == '\0') /* current dir == root dir */
  1135. (void) strncpy(pathname, "/", pathlen);
  1136. else {
  1137. (void) strncpy(pathname, pnptr, pathlen);
  1138. pathname[pathlen - 1] = '\0';
  1139. if (chdir(pnptr) == -1) {
  1140. (void) xsnprintf(pathname, MAXPATHLEN, CGETS(23, 22,
  1141. "getcwd: Cannot change back to \".\" (%s)"),
  1142. strerror(errno));
  1143. return NULL;
  1144. }
  1145. }
  1146. return pathname;
  1147. fail:
  1148. serrno = errno;
  1149. (void) chdir(strnrcpy(".", pnptr, pnptr - pathbuf));
  1150. errno = serrno;
  1151. return NULL;
  1152. }
  1153. # else /* ! hp9000s500 */
  1154. char *
  1155. xgetcwd(char *pathname, size_t pathlen)
  1156. {
  1157. DIR *dp;
  1158. struct dirent *d;
  1159. struct stat st_root, st_cur, st_next, st_dotdot;
  1160. char pathbuf[MAXPATHLEN], nextpathbuf[MAXPATHLEN * 2];
  1161. char *pathptr, *nextpathptr, *cur_name_add;
  1162. int save_errno = 0;
  1163. /* find the inode of root */
  1164. if (stat("/", &st_root) == -1) {
  1165. (void) xsnprintf(pathname, pathlen, CGETS(23, 23,
  1166. "getcwd: Cannot stat \"/\" (%s)"),
  1167. strerror(errno));
  1168. return NULL;
  1169. }
  1170. pathbuf[MAXPATHLEN - 1] = '\0';
  1171. pathptr = &pathbuf[MAXPATHLEN - 1];
  1172. nextpathbuf[MAXPATHLEN - 1] = '\0';
  1173. cur_name_add = nextpathptr = &nextpathbuf[MAXPATHLEN - 1];
  1174. /* find the inode of the current directory */
  1175. if (lstat(".", &st_cur) == -1) {
  1176. (void) xsnprintf(pathname, pathlen, CGETS(23, 24,
  1177. "getcwd: Cannot stat \".\" (%s)"),
  1178. strerror(errno));
  1179. return NULL;
  1180. }
  1181. nextpathptr = strnrcpy(nextpathptr, "../", nextpathptr - nextpathbuf);
  1182. /* Descend to root */
  1183. for (;;) {
  1184. /* look if we found root yet */
  1185. if (st_cur.st_ino == st_root.st_ino &&
  1186. DEV_DEV_COMPARE(st_cur.st_dev, st_root.st_dev)) {
  1187. (void) strncpy(pathname, *pathptr != '/' ? "/" : pathptr, pathlen);
  1188. pathname[pathlen - 1] = '\0';
  1189. return pathname;
  1190. }
  1191. /* open the parent directory */
  1192. if (stat(nextpathptr, &st_dotdot) == -1) {
  1193. (void) xsnprintf(pathname, pathlen, CGETS(23, 25,
  1194. "getcwd: Cannot stat directory \"%s\" (%s)"),
  1195. nextpathptr, strerror(errno));
  1196. return NULL;
  1197. }
  1198. if ((dp = opendir(nextpathptr)) == NULL) {
  1199. (void) xsnprintf(pathname, pathlen, CGETS(23, 26,
  1200. "getcwd: Cannot open directory \"%s\" (%s)"),
  1201. nextpathptr, strerror(errno));
  1202. return NULL;
  1203. }
  1204. /* look in the parent for the entry with the same inode */
  1205. if (DEV_DEV_COMPARE(st_dotdot.st_dev, st_cur.st_dev)) {
  1206. /* Parent has same device. No need to stat every member */
  1207. for (d = readdir(dp); d != NULL; d = readdir(dp)) {
  1208. #ifdef __clipper__
  1209. if (((unsigned long)d->d_ino & 0xffff) == st_cur.st_ino)
  1210. break;
  1211. #else
  1212. if (d->d_ino == st_cur.st_ino)
  1213. break;
  1214. #endif
  1215. }
  1216. }
  1217. else {
  1218. /*
  1219. * Parent has a different device. This is a mount point so we
  1220. * need to stat every member
  1221. */
  1222. for (d = readdir(dp); d != NULL; d = readdir(dp)) {
  1223. if (ISDOT(d->d_name) || ISDOTDOT(d->d_name))
  1224. continue;
  1225. (void)strncpy(cur_name_add, d->d_name,
  1226. (size_t) (&nextpathbuf[sizeof(nextpathbuf) - 1] - cur_name_add));
  1227. if (lstat(nextpathptr, &st_next) == -1) {
  1228. /*
  1229. * We might not be able to stat() some path components
  1230. * if we are using afs, but this is not an error as
  1231. * long as we find the one we need; we also save the
  1232. * first error to report it if we don't finally succeed.
  1233. */
  1234. if (save_errno == 0)
  1235. save_errno = errno;
  1236. continue;
  1237. }
  1238. /* check if we found it yet */
  1239. if (st_next.st_ino == st_cur.st_ino &&
  1240. DEV_DEV_COMPARE(st_next.st_dev, st_cur.st_dev))
  1241. break;
  1242. }
  1243. }
  1244. if (d == NULL) {
  1245. (void) xsnprintf(pathname, pathlen, CGETS(23, 27,
  1246. "getcwd: Cannot find \".\" in \"..\" (%s)"),
  1247. strerror(save_errno ? save_errno : ENOENT));
  1248. closedir(dp);
  1249. return NULL;
  1250. }
  1251. else
  1252. save_errno = 0;
  1253. st_cur = st_dotdot;
  1254. pathptr = strnrcpy(pathptr, d->d_name, pathptr - pathbuf);
  1255. pathptr = strnrcpy(pathptr, "/", pathptr - pathbuf);
  1256. nextpathptr = strnrcpy(nextpathptr, "../", nextpathptr - nextpathbuf);
  1257. *cur_name_add = '\0';
  1258. closedir(dp);
  1259. }
  1260. } /* end getcwd */
  1261. # endif /* hp9000s500 */
  1262. /* strnrcpy():
  1263. * Like strncpy, going backwards and returning the new pointer
  1264. */
  1265. static char *
  1266. strnrcpy(char *ptr, char *str, size_t siz)
  1267. {
  1268. int len = strlen(str);
  1269. if (siz == 0)
  1270. return ptr;
  1271. while (len && siz--)
  1272. *--ptr = str[--len];
  1273. return (ptr);
  1274. } /* end strnrcpy */
  1275. #endif /* !HAVE_GETCWD */
  1276. #ifdef apollo
  1277. /***
  1278. *** Domain/OS
  1279. ***/
  1280. #include <apollo/base.h>
  1281. #include <apollo/loader.h>
  1282. #include <apollo/error.h>
  1283. static char *
  1284. apperr(status_$t *st)
  1285. {
  1286. static char *buf; /* = NULL */
  1287. short e_subl, e_modl, e_codel;
  1288. error_$string_t e_sub, e_mod, e_code;
  1289. error_$get_text(*st, e_sub, &e_subl, e_mod, &e_modl, e_code, &e_codel);
  1290. e_sub[e_subl] = '\0';
  1291. e_code[e_codel] = '\0';
  1292. e_mod[e_modl] = '\0';
  1293. xfree(buf);
  1294. buf = xasprintf("%s (%s/%s)", e_code, e_sub, e_mod);
  1295. return(buf);
  1296. }
  1297. static int
  1298. llib(Char *s)
  1299. {
  1300. short len = Strlen(s);
  1301. status_$t st;
  1302. char *t;
  1303. loader_$inlib(t = short2str(s), len, &st);
  1304. if (st.all != status_$ok)
  1305. stderror(ERR_SYSTEM, t, apperr(&st));
  1306. }
  1307. /*ARGSUSED*/
  1308. void
  1309. doinlib(Char **v, struct command *c)
  1310. {
  1311. Char **globbed;
  1312. setname(short2str(*v++));
  1313. v = glob_all_or_error(v);
  1314. globbed = v;
  1315. cleanup_push(globbed, blk_cleanup);
  1316. while (v && *v)
  1317. llib(*v++);
  1318. cleanup_until(globbed);
  1319. }
  1320. int
  1321. getv(Char *v)
  1322. {
  1323. if (eq(v, STRbsd43))
  1324. return(1);
  1325. else if (eq(v, STRsys53))
  1326. return(0);
  1327. else
  1328. stderror(ERR_NAME | ERR_SYSTEM, short2str(v),
  1329. CGETS(23, 28, "Invalid system type"));
  1330. /*NOTREACHED*/
  1331. return(0);
  1332. }
  1333. /*ARGSUSED*/
  1334. void
  1335. dover(Char **v, struct command *c)
  1336. {
  1337. Char *p;
  1338. setname(short2str(*v++));
  1339. if (!*v) {
  1340. if (!(p = tgetenv(STRSYSTYPE)))
  1341. stderror(ERR_NAME | ERR_STRING,
  1342. CGETS(23, 29, "System type is not set"));
  1343. xprintf("%S\n", p);
  1344. }
  1345. else {
  1346. tsetenv(STRSYSTYPE, getv(*v) ? STRbsd43 : STRsys53);
  1347. dohash(NULL, NULL);
  1348. }
  1349. }
  1350. /*
  1351. * Many thanks to rees@citi.umich.edu (Jim Rees) and
  1352. * mathys@ssdt-tempe.sps.mot.com (Yves Mathys)
  1353. * For figuring out how to do this... I could have never done
  1354. * it without their help.
  1355. */
  1356. typedef short enum {
  1357. name_$wdir_type,
  1358. name_$ndir_type,
  1359. name_$node_dir_type,
  1360. } name_$dir_type_t;
  1361. /*ARGSUSED*/
  1362. void
  1363. dorootnode(Char **v, struct command *c)
  1364. {
  1365. name_$dir_type_t dirtype = name_$node_dir_type;
  1366. uid_$t uid;
  1367. status_$t st;
  1368. char *name;
  1369. short namelen;
  1370. setname(short2str(*v++));
  1371. name = short2str(*v);
  1372. namelen = strlen(name);
  1373. name_$resolve(name, &namelen, &uid, &st);
  1374. if (st.all != status_$ok)
  1375. stderror(ERR_SYSTEM, name, apperr(&st));
  1376. namelen = 0;
  1377. name_$set_diru(&uid, "", &namelen, &dirtype, &st);
  1378. if (st.all != status_$ok)
  1379. stderror(ERR_SYSTEM, name, apperr(&st));
  1380. dohash(NULL, NULL);
  1381. }
  1382. int
  1383. isapad(void)
  1384. {
  1385. static int res = -1;
  1386. static status_$t st;
  1387. if (res == -1) {
  1388. int strm;
  1389. if (isatty(0))
  1390. strm = 0;
  1391. if (isatty(1))
  1392. strm = 1;
  1393. if (isatty(2))
  1394. strm = 2;
  1395. else {
  1396. res = 0;
  1397. st.all = status_$ok;
  1398. return(res);
  1399. }
  1400. res = stream_$isavt(&strm, &st);
  1401. res = res ? 1 : 0;
  1402. }
  1403. else {
  1404. if (st.all != status_$ok)
  1405. stderror(ERR_SYSTEM, "stream_$isavt", apperr(&st));
  1406. }
  1407. return(res);
  1408. }
  1409. #endif
  1410. #ifdef __ANDROID__
  1411. #include <stdio.h>
  1412. /* Android (<= 2.1?) has an incomplete ttyname implementation. */
  1413. char *
  1414. ttyname(int fd)
  1415. {
  1416. char path[64];
  1417. ssize_t siz;
  1418. static char ttyname[32];
  1419. if (!isatty(fd))
  1420. return NULL;
  1421. (void)snprintf(path, sizeof(path), "/proc/self/fd/%d", fd);
  1422. siz = readlink(path, ttyname, sizeof(ttyname));
  1423. if (siz < 0 || siz == sizeof(ttyname))
  1424. return NULL;
  1425. ttyname[siz] = '\0';
  1426. return ttyname;
  1427. }
  1428. #endif /* __ANDROID__ */
  1429. #if defined(__CYGWIN__) && !defined(NO_CRYPT)
  1430. #undef CHAR /* Collides with Win32 API */
  1431. #define WIN32_LEAN_AND_MEAN
  1432. #include <windows.h>
  1433. #include <sys/cygwin.h>
  1434. char *
  1435. cygwin_xcrypt(struct passwd *pw, const char *password, const char *expected_pwd)
  1436. {
  1437. static char invalid_password[] = "\377";
  1438. HANDLE token = cygwin_logon_user(pw, password);
  1439. if (token == INVALID_HANDLE_VALUE)
  1440. return invalid_password;
  1441. CloseHandle(token);
  1442. return (char *) expected_pwd;
  1443. }
  1444. #endif /* __CYGWIN__ && !NO_CRYPT */