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