2 * tc.os.c: OS Dependent builtin functions
5 * Copyright (c) 1980, 1991 The Regents of the University of California.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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
35 #include "ed.defns.h" /* for the function names */
39 #define TIOCGPGRP TIOCGETPGRP
40 #define TIOCSPGRP TIOCSETPGRP
48 /* dosetpath -- setpath built-in command
50 **********************************************************************
52 * 08-May-88 Richard Draves (rpd) at Carnegie-Mellon University
53 * Major changes to remove artificial limits on sizes and numbers
56 **********************************************************************
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'};
64 static Char STREPATH
[] = {'E', 'P', 'A', 'T', 'H', '\0'};
67 static Char
*syspaths
[] = {STRKPATH
, STRCPATH
, STRLPATH
, STRMPATH
,
73 #define LOCALSYSPATH "/usr/local"
77 dosetpath(Char
**arglist
, struct command
*c
)
79 extern char *getenv();
80 Char
**pathvars
, **cmdargs
;
81 char **spaths
, **cpaths
, **cmds
;
83 unsigned int npaths
, ncmds
;
87 cleanup_push(&pintr_disabled
, disabled_cleanup
);
90 * setpath(3) uses stdio and we want 0, 1, 2 to work...
93 (void) dcopy(SHIN
, 0);
94 (void) dcopy(SHOUT
, 1);
95 (void) dcopy(SHDIAG
, 2);
99 for (i
= 1; arglist
[i
] && (arglist
[i
][0] != '-'); i
++);
102 cmdargs
= &arglist
[i
];
103 for (; arglist
[i
]; i
++);
104 ncmds
= i
- npaths
- 1;
108 pathvars
= &arglist
[1];
112 npaths
= (sizeof syspaths
/ sizeof *syspaths
) - 1;
116 /* note that npaths != 0 */
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
]));
130 spaths
[i
] = xmalloc((Strlen(pathvars
[i
]) + strlen(val
) + 2) *
132 (void) strcpy(spaths
[i
], short2str(pathvars
[i
]));
133 (void) strcat(spaths
[i
], "=");
134 (void) strcat(spaths
[i
], val
);
135 cpaths
[i
] = spaths
[i
];
138 for (i
= 0; i
< ncmds
; i
++) {
139 Char
*val
= globone(cmdargs
[i
], G_ERROR
);/*FIXRESET*/
143 cmds
[i
] = strsave(short2str(val
));
147 if (setpath(cpaths
, cmds
, LOCALSYSPATH
, sysflag
, 1) < 0) {
150 for (i
= 0; i
< npaths
; i
++)
156 for (i
= 0; i
< ncmds
; i
++)
161 cleanup_until(&pintr_disabled
);
166 for (i
= 0; i
< npaths
; i
++) {
169 name
= str2short(cpaths
[i
]);
170 for (val
= str2short(cpaths
[i
]); val
&& *val
&& *val
!= '='; val
++);
171 if (val
&& *val
== '=') {
174 tsetenv(name
, val
);/*FIXRESET*/
175 if (Strcmp(name
, STRKPATH
) == 0) {
176 importpath(val
);/*FIXRESET*/
178 dohash(NULL
, NULL
);/*FIXRESET*/
183 cleanup_until(&pintr_disabled
);
194 dogetxvers(Char
**v
, struct command
*c
)
196 char xvers
[MAXPATHLEN
];
198 if (getxvers(xvers
, MAXPATHLEN
) == -1)
199 stderror(ERR_SYSTEM
, "getxvers", strerror(errno
));
200 xprintf("%s\n", xvers
);
206 dosetxvers(Char
**v
, struct command
*c
)
211 if (!*v
|| *v
[0] == '\0')
214 xvers
= short2str(*v
);
215 if (setxvers(xvers
) == -1)
216 stderror(ERR_SYSTEM
, "setxvers", strerror(errno
));
221 # define XC_PDP11 0x01
224 # define XC_8086 0x04
228 # define XC_16032 0x08
231 # define XC_S370 0x0b
233 # include <sys/x.out.h>
236 static struct xc_cpu_t
{
241 { XC_PDP11
, "pdp11" },
245 { XC_68K
, "mc68000" },
248 { XC_16032
, "ns16032" },
251 { XC_S370
, "xa370" },
256 * our local hack table, stolen from x.out.h
263 for (i
= 0; xcpu
[i
].xc_name
!= NULL
; i
++)
264 if (xcpu
[i
].xc_id
== xcid
)
265 return (xcpu
[i
].xc_name
);
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
);
283 dogetspath(Char
**v
, struct command
*c
)
286 sitepath_t p
[MAXSITE
];
288 static char *local
= "LOCAL ";
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
)
296 else if ((st
= sfxcode((short) (p
[i
] & SPATH_MASK
))) != NULL
)
297 xprintf("%s ", st
->sf_ctype
);
299 char *xc
= getxcode(p
[i
] & SPATH_MASK
);
304 xprintf("*cpu %d* ", (int) (p
[i
] & SPATH_MASK
));
306 * BUG in the aix code... needs that cause if
307 * sfxcode fails once it fails for ever
313 if (p
[i
] == NULLSITE
)
315 else if ((st
= sfnum(p
[i
])) != NULL
)
316 xprintf("%s ", st
->sf_sname
);
318 xprintf("*site %d* ", (int) (p
[i
] & SPATH_MASK
));
327 dosetspath(Char
**v
, struct command
*c
)
332 sitepath_t p
[MAXSITE
];
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 :-)
343 for (i
= 0, v
++; *v
&& *v
[0] != '\0'; v
++, i
++) {
347 else if (strcmp(s
, "LOCAL") == 0)
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
)
357 stderror(ERR_NAME
| ERR_STRING
, CGETS(23, 1, "Bad cpu/site name"));
359 if (i
== MAXSITE
- 1)
360 stderror(ERR_NAME
| ERR_STRING
, CGETS(23, 2, "Site path too long"));
362 if (setspath(p
, i
) == -1)
363 stderror(ERR_SYSTEM
, "setspath", strerror(errno
));
368 * Return the site name where the process is running
376 if ((ss
= site(pid
)) == -1 || (st
= sfnum(ss
)) == NULL
)
377 return CGETS(23, 3, "unknown");
383 migratepid(pit_t pid
, siteno_t new_site
)
388 need_local
= (pid
== 0) || (pid
== getpid());
390 if (kill3(pid
, SIGMIGRATE
, new_site
) < 0) {
391 xprintf("%d: %s\n", pid
, strerror(errno
));
396 if ((new_site
= site(0)) == -1) {
397 xprintf(CGETS(23, 4, "site: %s\n"), strerror(errno
));
400 if ((st
= sfnum(new_site
)) == NULL
) {
401 xprintf(CGETS(23, 5, "%d: Site not found\n"), new_site
);
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
));
415 domigrate(Char
**v
, struct command
*c
)
423 siteno_t new_site
= 0;
426 cleanup_push(&pchild_disabled
, disabled_cleanup
);
429 cleanup_push(&pintr_disabled
, disabled_cleanup
);
437 s
= short2str(&v
[0][1]);
439 * see comment in setspath()
442 if ((st
= sfname(s
)) == NULL
) {
445 stderror(ERR_NAME
| ERR_STRING
, CGETS(23, 7, "Site not found"));
448 new_site
= st
->sf_id
;
452 if (!*v
|| *v
[0] == '\0') {
453 if (migratepid(0, new_site
) == -1)
459 v
= glob_all_or_error(v
);
461 cleanup_push(globbed
, blk_cleanup
);
463 while (v
&& (cp
= *v
)) {
466 if (kill3(- pp
->p_jobid
, SIGMIGRATE
, new_site
) < 0) {
467 xprintf("%S: %s\n", cp
, strerror(errno
));
471 else if (!(Isdigit(*cp
) || *cp
== '-'))
472 stderror(ERR_NAME
| ERR_JOBARGS
);
474 pid
= atoi(short2str(cp
));
475 if (migratepid(pid
, new_site
) == -1)
480 cleanup_until(globbed
);
484 cleanup_until(&pchild_disabled
);
486 stderror(ERR_SILENT
);
492 *** CRAY ddmode <velo@sesun3.epfl.ch> (Martin Ouwehand EPFL-SIC/SE)
494 #if defined(_CRAY) && !defined(_CRAYMPP)
496 dodmmode(Char
**v
, struct command
*c
)
507 xprintf("%d\n",mode
);
511 stderror(ERR_NAME
| ERR_STRING
,
512 CGETS(23, 30, "Too many arguments"));
522 stderror(ERR_NAME
| ERR_STRING
,
523 CGETS(23, 31, "Invalid argument"));
527 #endif /* _CRAY && !_CRAYMPP */
536 * handle the funky warping of symlinks
539 #include <sys/warp.h>
541 static jmp_buf sigsys_buf
;
547 sigemptyset(&set
, SIGSYS
);
548 (void)sigprocmask(SIG_UNBLOCK
, &set
, NULL
);
549 longjmp(sigsys_buf
, 1);
555 dowarp(Char
**v
, struct command
*c
)
559 volatile struct sigaction old_sigsys_handler
;
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"));
568 sigaction(SIGSYS
, NULL
, &old_sigsys_handler
);
569 signal(SIGSYS
, catch_sigsys
);
574 if (*v
== 0) { /* display warp value */
576 stderror(ERR_NAME
| ERR_STRING
, CGETS(23, 9, "Getwarp failed"));
577 we
= getwarpbyvalue(warp
);
579 printf("%s\n", we
->w_name
);
581 printf("%d\n", warp
);
583 else { /* set warp value */
585 newwarp
= short2str(*v
);
587 warp
= atoi(newwarp
);
589 we
= getwarpbyname(newwarp
);
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"));
602 sigaction(SIGSYS
, &old_sigsys_handler
, NULL
);
609 /* Added, DAS DEC-90. */
610 #if defined(masscomp) || defined(_CX_UX)
612 setuniverse_cleanup(void *xbuf
)
622 douniverse(Char
**v
, struct command
*c
)
625 Char
*cp2
; /* dunno how many elements v comes in with */
629 (void) getuniverse(ubuf
);
630 xprintf("%s\n", ubuf
);
635 if (*cp
== '\0' || setuniverse(short2str(cp
)) != 0)
636 stderror(ERR_NAME
| ERR_STRING
, CGETS(23, 12, "Illegal universe"));
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
);
645 cleanup_push(&pintr_disabled
, disabled_cleanup
);
649 cleanup_until(&pintr_disabled
);
655 #endif /* masscomp || _CX_UX */
658 *** BS2000/OSD POSIX (Fujitsu Siemens Computers)
660 #if defined(_OSD_POSIX)
664 enum { outside
= ' ', singlequote
='\'', doublequote
='"'} string
= outside
;
668 for (white
= str
+ strlen(str
) - 1; isspace(*white
) && white
> str
; --white
)
671 for (; *str
!= '\0'; ++str
)
673 if (string
== outside
)
675 *str
= toupper (*str
);
679 if (string
== outside
)
680 string
= singlequote
;
681 else if (string
!= doublequote
)
684 else if (*str
== '"')
686 if (string
== outside
)
687 string
= doublequote
;
688 else if (string
!= singlequote
)
692 if (string
!= outside
)
694 stderror(ERR_NAME
| ERR_UNMATCHED
, (Char
) string
);
700 bs2cmdlist(char *str
)
702 char *str_beg
= NULL
;
705 enum { outside
= ' ', singlequote
='\'', doublequote
='"'} string
= outside
;
709 while (isspace(*str
))
717 for (; *str
!= '\0'; ++str
)
719 if (string
== outside
&& *str
== ';') /* End of command */
722 break; /* continue with next command */
726 if (string
== outside
)
727 string
= singlequote
;
728 else if (string
!= doublequote
)
731 else if (*str
== '"')
733 if (string
== outside
)
734 string
= doublequote
;
735 else if (string
!= singlequote
)
739 if (strlen(str_beg
) != 0)
741 ret
= bs2system(str_beg
);
743 if (ret
!= 0 /*&& !option.err_ignore*/)
744 break; /* do not continue after errors */
748 if (string
!= outside
)
750 stderror(ERR_NAME
| ERR_UNMATCHED
, (Char
) string
);
758 dobs2cmd(Char
**v
, struct command
*c
)
764 struct command faket
;
767 int icnt
, old_pintr_disabled
;
768 static const Char STRbs2cmd
[] = { 'b','s','2','c','m','d','\0' };
772 pintr_push_enable(&old_pintr_disabled
);
773 v
= glob_all_or_error(v
);
775 cleanup_until(&old_pintr_disabled
);
777 cleanup_push(globbed
, blk_cleanup
);
779 /* First round: count the string lengths */
780 for (i
=0; v
[i
]; ++i
) {
781 len
+= Strlen(v
[i
]) + (v
[i
+1] != NULL
);
784 cmd
= xmalloc(len
+1); /* 1 for the final '\0' *//* FIXME: memory leak? */
786 /* 2nd round: fill cmd buffer */
788 while ((cp
= *v
++) != 0) {
797 /* Make upper case */
800 faket
.t_dtyp
= NODE_COMMAND
;
801 faket
.t_dflg
= F_BACKQ
|F_STDERR
;
805 faket
.t_dcom
= fakecom
;
806 fakecom
[0] = (Char
*)STRbs2cmd
;
810 cleanup_push(&pvec
[0], open_cleanup
);
811 cleanup_push(&pvec
[1], open_cleanup
);
812 if (pfork(&faket
, -1) == 0) {
816 (void) dmove(pvec
[1], 1);
817 (void) dmove(SHDIAG
, 2);
820 sigaddset(&set
, SIGINT
);
821 (void)sigprocmask(SIG_UNBLOCK
, &set
, NULL
);
823 signal(SIGTSTP
, SIG_IGN
);
826 signal(SIGTTIN
, SIG_IGN
);
829 signal(SIGTTOU
, SIG_IGN
);
831 xexit(bs2cmdlist(cmd
));
833 cleanup_until(&pvec
[1]);
835 int old_pintr_disabled
;
838 pintr_push_enable(&old_pintr_disabled
);
839 icnt
= xread(pvec
[0], tibuf
, sizeof(tibuf
));
841 cleanup_until(&old_pintr_disabled
);
844 for (i
= 0; i
< icnt
; i
++)
845 xputchar((unsigned char) tibuf
[i
]);
847 cleanup_until(&pvec
[0]);
852 cleanup_until(globbed
);
854 #endif /* _OSD_POSIX */
858 setuniverse_cleanup(void *xbuf
)
868 doatt(Char
**v
, struct command
*c
)
874 (void) setuniverse("att");
876 (void) getuniverse(ubuf
);
877 (void) setuniverse("att");
878 cleanup_push(ubuf
, setuniverse_cleanup
);
881 cleanup_push(&pintr_disabled
, disabled_cleanup
);
885 cleanup_until(&pintr_disabled
);
893 doucb(Char
**v
, struct command
*c
)
899 (void) setuniverse("ucb");
901 (void) getuniverse(ubuf
);
902 (void) setuniverse("ucb");
903 cleanup_push(ubuf
, setuniverse_cleanup
);
906 cleanup_push(&pintr_disabled
, disabled_cleanup
);
910 cleanup_until(&pintr_disabled
);
919 * Compute the difference in process stats.
922 pr_stat_sub(struct process_stats
*p2
, struct process_stats
*p1
,
923 struct process_stats
*pr
)
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;
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;
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
;
957 #endif /* _SEQUENT_ */
961 /* This is a replacement for a missing memset function */
962 void *xmemset(void *loc
, int value
, size_t len
)
970 #endif /* !HAVE_MEMSET */
975 * This is the ANSI form of bcopy() with the arguments backwards...
976 * Unlike memcpy(), it handles overlaps between source and
980 xmemmove(void *vdst
, const void *vsrc
, size_t len
)
982 const char *src
= vsrc
;
1000 #endif /* HAVE_MEMMOVE */
1003 #ifndef WINNT_NATIVE
1004 #ifdef NEEDtcgetpgrp
1010 /* ioctl will handle setting errno correctly. */
1011 if (ioctl(fd
, TIOCGPGRP
, (ioctl_t
) & pgrp
) < 0)
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
1023 xtcsetpgrp(int fd
, int pgrp
)
1025 return ioctl(fd
, TIOCSPGRP
, (ioctl_t
) &pgrp
);
1028 #endif /* NEEDtcgetpgrp */
1029 #endif /* WINNT_NATIVE */
1038 extern int yp_get_default_domain (char **);
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.)
1044 if (yp_get_default_domain(&mydomain
) == 0) { /* if we got a name */
1045 extern void yp_unbind (const char *);
1047 yp_unbind(mydomain
);
1055 fix_strcoll_bug(void)
1057 #if defined(NLS) && defined(HAVE_STRCOLL)
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...
1064 * Of course it also tries to free the constant locale "C" it initially
1065 * had allocated, with the sequence
1066 * > setenv LANG "fr"
1069 * But we are smarter than that and just print a warning message.
1072 static char *root
= "/";
1075 fd
= xopen(root
, O_RDONLY
|O_LARGEFILE
);
1077 (void) strcoll(root
, root
);
1083 #endif /* STRCOLLBUG */
1095 setcompat(getcompat() & ~COMPAT_EXEC
);
1096 signal(SIGIO
, SIG_IGN
); /* ignore SIGIO */
1101 struct sigstack inst
;
1102 inst
.ss_sp
= xmalloc(4192) + 4192;
1103 inst
.ss_onstack
= 0;
1104 sigstack(&inst
, NULL
);
1114 * kill(SIGCONT) problems, don't know what this syscall does
1115 * [schott@rzg.mpg.de]
1117 syscall(151, getpid(), getpid());
1121 #ifndef HAVE_STRERROR
1122 extern int sys_nerr
;
1123 extern char *sys_errlist
[];
1127 if (i
>= 0 && i
< sys_nerr
) {
1128 return sys_errlist
[i
];
1130 static char *errbuf
; /* = NULL; */
1133 errbuf
= xasprintf(CGETS(23, 13, "Unknown Error: %d"), i
);
1137 #endif /* !HAVE_STRERROR */
1139 #ifndef HAVE_GETHOSTNAME
1140 # if !defined(_MINIX) && !defined(__EMX__) && !defined(WINNT_NATIVE)
1141 # include <sys/utsname.h>
1142 # endif /* !_MINIX && !__EMX__ && !WINNT_NATIVE */
1145 xgethostname(char *name
, int namlen
)
1147 # if !defined(_MINIX) && !defined(__EMX__) && !defined(WINNT_NATIVE)
1151 retval
= uname(&uts
);
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
);
1160 i
= strlen(uts
.nodename
) + 1;
1161 (void) strncpy(name
, uts
.nodename
, i
< namlen
? i
: namlen
);
1164 # else /* !_MINIX && !__EMX__ */
1167 (void) strncpy(name
, "OS/2", namlen
);
1169 (void) strncpy(name
, "minix", namlen
);
1170 # endif /* __EMX__ */
1171 name
[namlen
-1] = '\0';
1174 #endif /* _MINIX && !__EMX__ */
1175 } /* end xgethostname */
1176 #endif /* !HAVE_GETHOSTNAME */
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> */
1184 # endif /* _MINIX && NICE */
1188 #if defined(_MINIX) && defined(NICE)
1189 return callm1(MM
, NICE
, incr
, 0, 0, NIL_PTR
, NIL_PTR
, NIL_PTR
);
1191 return /* incr ? 0 : */ 0;
1192 #endif /* _MINIX && NICE */
1194 #endif /* !HAVE_NICE */
1197 static char *strnrcpy (char *, char *, size_t);
1200 * Return the pathname of the current directory, or return
1201 * an error message in pathname.
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 ".." !!!
1216 xgetcwd(char *pathname
, size_t pathlen
)
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 */
1229 (void) stat("/.", &d
);
1234 if (stat(".", &d
) == -1) {
1235 (void) xsnprintf(pathname
, pathlen
, CGETS(23, 24,
1236 "getcwd: Cannot stat \".\" (%s)"), strerror(errno
));
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
));
1246 if (chdir("..") == -1) {
1247 (void) xsnprintf(pathname
, pathlen
, CGETS(23, 20,
1248 "getcwd: Cannot chdir to \"..\" (%s)"), strerror(errno
));
1252 if ((dir
= readdir(dirp
)) == NULL
) {
1253 (void) xsnprintf(pathname
, pathlen
,
1254 CGETS(23, 21, "getcwd: Read error in \"..\" (%s)"),
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
));
1264 } while (dd
.st_ino
!= d
.st_ino
||
1265 dd
.st_dev
!= d
.st_dev
||
1266 dd
.st_size
!= d
.st_size
);
1269 pnptr
= strnrcpy(dirp
->d_name
, pnptr
, pnptr
- pathbuf
);
1270 pnptr
= strnrcpy("/", pnptr
, pnptr
- pathbuf
);
1273 if (*pnptr
== '\0') /* current dir == root dir */
1274 (void) strncpy(pathname
, "/", pathlen
);
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)"),
1289 (void) chdir(strnrcpy(".", pnptr
, pnptr
- pathbuf
));
1294 # else /* ! hp9000s500 */
1298 xgetcwd(char *pathname
, size_t pathlen
)
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
;
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)"),
1315 pathbuf
[MAXPATHLEN
- 1] = '\0';
1316 pathptr
= &pathbuf
[MAXPATHLEN
- 1];
1317 nextpathbuf
[MAXPATHLEN
- 1] = '\0';
1318 cur_name_add
= nextpathptr
= &nextpathbuf
[MAXPATHLEN
- 1];
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)"),
1327 nextpathptr
= strnrcpy(nextpathptr
, "../", nextpathptr
- nextpathbuf
);
1329 /* Descend to root */
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';
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
));
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
));
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
)) {
1359 if (((unsigned long)d
->d_ino
& 0xffff) == st_cur
.st_ino
)
1362 if (d
->d_ino
== st_cur
.st_ino
)
1369 * Parent has a different device. This is a mount point so we
1370 * need to stat every member
1372 for (d
= readdir(dp
); d
!= NULL
; d
= readdir(dp
)) {
1373 if (ISDOT(d
->d_name
) || ISDOTDOT(d
->d_name
))
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) {
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.
1384 if (save_errno
== 0)
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
))
1395 (void) xsnprintf(pathname
, pathlen
, CGETS(23, 27,
1396 "getcwd: Cannot find \".\" in \"..\" (%s)"),
1397 strerror(save_errno
? save_errno
: ENOENT
));
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';
1411 # endif /* hp9000s500 */
1414 * Like strncpy, going backwards and returning the new pointer
1417 strnrcpy(char *ptr
, char *str
, size_t siz
)
1419 int len
= strlen(str
);
1423 while (len
&& siz
--)
1424 *--ptr
= str
[--len
];
1427 } /* end strnrcpy */
1428 #endif /* !HAVE_GETCWD */
1434 #include <apollo/base.h>
1435 #include <apollo/loader.h>
1436 #include <apollo/error.h>
1440 apperr(status_$t
*st
)
1442 static char *buf
; /* = NULL */
1443 short e_subl
, e_modl
, e_codel
;
1444 error_$string_t e_sub
, e_mod
, e_code
;
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';
1451 buf
= xasprintf("%s (%s/%s)", e_code
, e_sub
, e_mod
);
1459 short len
= Strlen(s
);
1463 loader_$
inlib(t
= short2str(s
), len
, &st
);
1464 if (st
.all
!= status_$ok
)
1465 stderror(ERR_SYSTEM
, t
, apperr(&st
));
1470 doinlib(Char
**v
, struct command
*c
)
1474 setname(short2str(*v
++));
1475 v
= glob_all_or_error(v
);
1477 cleanup_push(globbed
, blk_cleanup
);
1481 cleanup_until(globbed
);
1487 if (eq(v
, STRbsd43
))
1489 else if (eq(v
, STRsys53
))
1492 stderror(ERR_NAME
| ERR_SYSTEM
, short2str(v
),
1493 CGETS(23, 28, "Invalid system type"));
1500 dover(Char
**v
, struct command
*c
)
1504 setname(short2str(*v
++));
1506 if (!(p
= tgetenv(STRSYSTYPE
)))
1507 stderror(ERR_NAME
| ERR_STRING
,
1508 CGETS(23, 29, "System type is not set"));
1512 tsetenv(STRSYSTYPE
, getv(*v
) ? STRbsd43
: STRsys53
);
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.
1523 typedef short enum {
1526 name_$node_dir_type
,
1531 dorootnode(Char
**v
, struct command
*c
)
1533 name_$dir_type_t dirtype
= name_$node_dir_type
;
1539 setname(short2str(*v
++));
1541 name
= short2str(*v
);
1542 namelen
= strlen(name
);
1544 name_$
resolve(name
, &namelen
, &uid
, &st
);
1545 if (st
.all
!= status_$ok
)
1546 stderror(ERR_SYSTEM
, name
, apperr(&st
));
1548 name_$
set_diru(&uid
, "", &namelen
, &dirtype
, &st
);
1549 if (st
.all
!= status_$ok
)
1550 stderror(ERR_SYSTEM
, name
, apperr(&st
));
1557 static int res
= -1;
1558 static status_$t st
;
1570 st
.all
= status_$ok
;
1573 res
= stream_$
isavt(&strm
, &st
);
1577 if (st
.all
!= status_$ok
)
1578 stderror(ERR_SYSTEM
, "stream_$isavt", apperr(&st
));
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>
1590 cygwin_xcrypt(struct passwd
*pw
, const char *password
, const char *expected_pwd
)
1592 static char invalid_password
[] = "\377";
1593 HANDLE token
= cygwin_logon_user(pw
, password
);
1594 if (token
== INVALID_HANDLE_VALUE
)
1595 return invalid_password
;
1597 return (char *) expected_pwd
;
1599 #endif /* __CYGWIN__ && !NO_CRYPT */