sh.misc.c revision 65b0c20e9bbaf87a200ce20a4decf18585e61a25
355N/A/*
355N/A * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
355N/A * Use is subject to license terms.
355N/A */
355N/A
355N/A/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
355N/A/* All Rights Reserved */
355N/A
355N/A/*
355N/A * Copyright (c) 1980 Regents of the University of California.
355N/A * All rights reserved. The Berkeley Software License Agreement
355N/A * specifies the terms and conditions for redistribution.
355N/A */
355N/A
355N/A#pragma ident "%Z%%M% %I% %E% SMI"
355N/A
355N/A#include "sh.h"
355N/A#include "sh.tconst.h"
873N/A#include <fcntl.h>
355N/A#include <unistd.h>
355N/A
355N/A/*
355N/A * C Shell
355N/A */
733N/Atchar **blkcat(tchar **, tchar **);
355N/Atchar **blkend(tchar **);
355N/A
355N/Aint
355N/Aany(int c, tchar *s)
355N/A{
355N/A
355N/A while (s && *s)
355N/A if (*s++ == c)
355N/A return (1);
355N/A return (0);
355N/A}
355N/A
355N/Aint
355N/Aonlyread(tchar *cp)
355N/A{
355N/A extern char end[];
355N/A
844N/A return ((char *)cp < end);
355N/A}
355N/A
355N/Atchar *
355N/Asavestr(tchar *s)
355N/A{
723N/A tchar *n;
355N/A tchar *p;
355N/A
355N/A if (s == 0)
355N/A s = S_ /* "" */;
355N/A#ifndef m32
355N/A for (p = s; *p++; )
355N/A ;
355N/A n = p = (tchar *)xalloc((unsigned)(p - s)*sizeof (tchar));
355N/A while (*p++ = *s++)
355N/A ;
777N/A return (n);
355N/A#else
355N/A p = (tchar *) xalloc((strlen_(s) + 1)*sizeof (tchar));
355N/A strcpy_(p, s);
355N/A return (p);
355N/A#endif
1454N/A}
430N/A
355N/Astatic void *
355N/Anomem(size_t i)
355N/A{
355N/A#ifdef debug
355N/A static tchar *av[2] = {0, 0};
408N/A#endif
355N/A
355N/A child++;
355N/A#ifndef debug
1454N/A error("Out of memory");
1454N/A#ifdef lint
1454N/A i = i;
355N/A#endif
355N/A#else
355N/A showall(av);
408N/A printf("i=%d: Out of memory\n", i);
355N/A chdir("/usr/bill/cshcore");
355N/A abort();
355N/A#endif
355N/A return (0); /* fool lint */
355N/A}
355N/A
355N/Atchar **
355N/Ablkend(tchar **up)
355N/A{
355N/A
355N/A while (*up)
355N/A up++;
355N/A return (up);
355N/A}
355N/A
355N/Avoid
355N/Ablkpr(tchar **av)
355N/A{
355N/A
355N/A for (; *av; av++) {
355N/A printf("%t", *av);
355N/A if (av[1])
355N/A printf(" ");
355N/A }
355N/A}
355N/A
355N/Aint
355N/Ablklen(tchar **av)
355N/A{
355N/A int i = 0;
355N/A
355N/A while (*av++)
355N/A i++;
355N/A return (i);
355N/A}
355N/A
355N/Atchar **
355N/Ablkcpy(tchar **oav, tchar **bv)
355N/A{
355N/A tchar **av = oav;
355N/A
355N/A while (*av++ = *bv++)
355N/A continue;
355N/A return (oav);
355N/A}
355N/A
355N/Atchar **
355N/Ablkcat(tchar **up, tchar **vp)
355N/A{
355N/A
355N/A (void) blkcpy(blkend(up), vp);
355N/A return (up);
355N/A}
355N/A
355N/Avoid
355N/Ablkfree(tchar **av0)
777N/A{
777N/A tchar **av = av0;
777N/A
777N/A for (; *av; av++)
777N/A xfree(*av);
777N/A xfree(av0);
777N/A}
777N/A
777N/Atchar **
777N/Asaveblk(tchar **v)
777N/A{
777N/A tchar **newv =
777N/A (tchar **)xcalloc((unsigned)(blklen(v) + 1),
1065N/A sizeof (tchar **));
777N/A tchar **onewv = newv;
777N/A
777N/A while (*v)
777N/A *newv++ = savestr(*v++);
777N/A return (onewv);
777N/A}
355N/A
355N/Atchar *
355N/Astrspl(tchar *cp, tchar *dp)
355N/A{
355N/A tchar *ep;
355N/A tchar *p, *q;
355N/A
355N/A#ifndef m32
355N/A for (p = cp; *p++; )
355N/A ;
355N/A for (q = dp; *q++; )
355N/A ;
355N/A ep = (tchar *) xalloc((unsigned)(((p - cp) +
355N/A (q - dp) - 1))*sizeof (tchar));
355N/A for (p = ep, q = cp; *p++ = *q++; )
355N/A ;
355N/A for (p--, q = dp; *p++ = *q++; )
355N/A ;
1137N/A#else
355N/A int len1 = strlen_(cp);
355N/A int len2 = strlen_(dp);
355N/A
355N/A ep = (tchar *)xalloc((unsigned)(len1 + len2 + 1)*sizeof (tchar));
355N/A strcpy_(ep, cp);
355N/A strcat_(ep, dp);
355N/A#endif
355N/A return (ep);
355N/A}
355N/A
355N/Atchar **
355N/Ablkspl(tchar **up, tchar **vp)
355N/A{
355N/A tchar **wp =
355N/A (tchar **)xcalloc((unsigned)(blklen(up) + blklen(vp) + 1),
355N/A sizeof (tchar **));
355N/A
355N/A (void) blkcpy(wp, up);
355N/A return (blkcat(wp, vp));
355N/A}
1137N/A
355N/Aint
355N/Alastchr(tchar *cp)
355N/A{
355N/A
355N/A if (!*cp)
355N/A return (0);
355N/A while (cp[1])
355N/A cp++;
355N/A return (*cp);
355N/A}
355N/A
355N/Avoid
355N/Adonefds(void)
355N/A{
355N/A (void) close(0);
355N/A (void) close(1);
355N/A (void) close(2);
355N/A
355N/A /*
355N/A * To avoid NIS+ functions to get hold of 0/1/2,
1137N/A * use descriptor 0, and dup it to 1 and 2.
355N/A */
355N/A open("/dev/null", 0);
355N/A dup(0); dup(0);
355N/A didfds = 0;
355N/A}
355N/A
355N/A/*
355N/A * Move descriptor i to j.
355N/A * If j is -1 then we just want to get i to a safe place,
355N/A * i.e. to a unit > 2. This also happens in dcopy.
355N/A */
355N/Aint
355N/Admove(int i, int j)
355N/A{
355N/A int fd;
355N/A
355N/A if (i == j || i < 0)
355N/A return (i);
355N/A if (j >= 0) {
355N/A fd = dup2(i, j);
355N/A if (fd != -1)
355N/A setfd(fd);
355N/A } else
355N/A j = dcopy(i, j);
355N/A if (j != i) {
355N/A (void) close(i);
355N/A unsetfd(i);
355N/A }
355N/A return (j);
355N/A}
355N/A
355N/Aint
355N/Adcopy(int i, int j)
355N/A{
355N/A
355N/A int fd;
355N/A
355N/A if (i == j || i < 0 || j < 0 && i > 2)
355N/A return (i);
355N/A if (j >= 0) {
355N/A fd = dup2(i, j);
355N/A if (fd != -1)
355N/A setfd(fd);
355N/A return (j);
355N/A }
355N/A (void) close(j);
355N/A unsetfd(j);
355N/A return (renum(i, j));
355N/A}
355N/A
355N/Aint
355N/Arenum(int i, int j)
509N/A{
509N/A int k = dup(i);
355N/A
509N/A if (k < 0)
355N/A return (-1);
355N/A if (j == -1 && k > 2) {
355N/A setfd(k);
355N/A return (k);
355N/A }
355N/A if (k != j) {
355N/A j = renum(k, j);
355N/A (void) close(k); /* no need ofr unsetfd() */
355N/A return (j);
355N/A }
355N/A return (k);
355N/A}
355N/A
355N/A#ifndef copy
355N/Avoid
355N/Acopy(tchar *to, tchar *from, int size)
355N/A{
355N/A
355N/A if (size)
355N/A do
355N/A *to++ = *from++;
509N/A while (--size != 0);
509N/A}
355N/A#endif
509N/A
355N/A/*
355N/A * Left shift a command argument list, discarding
355N/A * the first c arguments. Used in "shift" commands
355N/A * as well as by commands like "repeat".
355N/A */
355N/Avoid
355N/Alshift(tchar **v, int c)
355N/A{
355N/A tchar **u = v;
355N/A
355N/A while (*u && --c >= 0)
355N/A xfree((char *)*u++);
355N/A (void) blkcpy(v, u);
355N/A}
355N/A
355N/Aint
355N/Anumber(tchar *cp)
355N/A{
355N/A
355N/A if (*cp == '-') {
355N/A cp++;
355N/A if (!digit(*cp++))
355N/A return (0);
355N/A }
355N/A while (*cp && digit(*cp))
355N/A cp++;
355N/A return (*cp == 0);
355N/A}
355N/A
355N/Atchar **
509N/Acopyblk(tchar **v)
509N/A{
355N/A tchar **nv =
509N/A (tchar **)xcalloc((unsigned)(blklen(v) + 1),
355N/A sizeof (tchar **));
355N/A
355N/A return (blkcpy(nv, v));
355N/A}
355N/A
355N/Atchar *
355N/Astrend(tchar *cp)
355N/A{
355N/A
355N/A while (*cp)
355N/A cp++;
355N/A return (cp);
355N/A}
355N/A
355N/Atchar *
355N/Astrip(tchar *cp)
355N/A{
355N/A tchar *dp = cp;
355N/A
355N/A while (*dp++ &= TRIM)
355N/A continue;
509N/A return (cp);
509N/A}
355N/A
509N/Avoid
355N/Audvar(tchar *name)
355N/A{
355N/A
355N/A setname(name);
355N/A bferr("Undefined variable");
355N/A}
355N/A
355N/Aint
355N/Aprefix(tchar *sub, tchar *str)
355N/A{
355N/A
355N/A for (;;) {
355N/A if (*sub == 0)
355N/A return (1);
355N/A if (*str == 0)
355N/A return (0);
355N/A if (*sub++ != *str++)
355N/A return (0);
355N/A }
355N/A}
355N/A
355N/A/*
355N/A * blk*_ routines
355N/A */
355N/A
355N/Achar **
355N/Ablkend_(char **up)
355N/A{
355N/A
355N/A while (*up)
509N/A up++;
509N/A return (up);
355N/A}
509N/A
355N/Aint
355N/Ablklen_(char **av)
355N/A{
355N/A int i = 0;
355N/A
355N/A while (*av++)
355N/A i++;
355N/A return (i);
355N/A}
355N/A
355N/Achar **
355N/Ablkcpy_(char **oav, char **bv)
355N/A{
355N/A char **av = oav;
355N/A
355N/A while (*av++ = *bv++)
355N/A continue;
355N/A return (oav);
355N/A}
355N/A
355N/Achar **
509N/Ablkcat_(char **up, char **vp)
509N/A{
355N/A
509N/A (void) blkcpy_(blkend_(up), vp);
355N/A return (up);
355N/A}
355N/A
355N/Achar **
355N/Ablkspl_(char **up, char **vp)
355N/A{
355N/A char **wp =
355N/A (char **)xcalloc((unsigned)(blklen_(up) + blklen_(vp) + 1),
355N/A sizeof (char **));
355N/A
355N/A (void) blkcpy_(wp, up);
355N/A return (blkcat_(wp, vp));
355N/A}
355N/A
355N/A/*
355N/A * If stack address was passed to free(), we have no good way to see if
355N/A * they are really in the stack. Therefore, we record the bottom of heap,
355N/A * and filter out the address not within heap's top(end) and bottom
355N/A * (xalloc_bottom).
355N/A */
355N/Aextern char end[];
355N/Astatic char *xalloc_bottom;
355N/A
355N/Avoid *
355N/Axalloc(size_t size)
355N/A{
355N/A char *rptr, *bp;
355N/A
355N/A if ((rptr = malloc(size)) == NULL)
355N/A return (nomem(size));
509N/A bp = rptr + size;
509N/A if (bp > xalloc_bottom)
355N/A xalloc_bottom = bp;
509N/A return (rptr);
355N/A}
355N/A
355N/Avoid *
355N/Axrealloc(void *ptr, size_t size)
355N/A{
355N/A char *rptr = ptr, *bp;
355N/A
355N/A if (ptr == NULL)
355N/A return (xalloc(size));
355N/A if (rptr < end) {
355N/A /* data area, but not in heap area. don't touch it */
355N/Aoob:
355N/A if (size == 0)
355N/A return (NULL);
355N/A rptr = xalloc(size);
355N/A /* copy max size */
355N/A (void) memcpy(rptr, ptr, size);
355N/A return (rptr);
355N/A }
355N/A if (rptr < xalloc_bottom) {
355N/A /* address in the heap */
509N/Ainb:
509N/A if (size == 0) {
355N/A free(ptr);
509N/A return (NULL);
355N/A }
355N/A if ((rptr = realloc(ptr, size)) == NULL)
355N/A return (nomem(size));
355N/A bp = rptr + size;
355N/A if (bp > xalloc_bottom)
355N/A xalloc_bottom = bp;
355N/A return (rptr);
355N/A }
355N/A#if defined(__sparc)
355N/A if (rptr > (char *)&rptr) {
355N/A /* in the stack frame */
355N/A goto oob;
355N/A }
355N/A#endif
355N/A /*
355N/A * can be a memory block returned indirectly from
355N/A * library functions. update bottom, and check it again.
355N/A */
355N/A xalloc_bottom = sbrk(0);
355N/A if (rptr <= xalloc_bottom)
355N/A goto inb;
355N/A else
355N/A goto oob;
355N/A /*NOTREACHED*/
355N/A}
355N/A
355N/Avoid
355N/Axfree(void *ptr)
355N/A{
355N/A char *rptr = ptr;
509N/A
509N/A if (rptr < end) {
355N/A return;
509N/A }
355N/A if (rptr < xalloc_bottom) {
355N/A free(ptr);
355N/A return;
355N/A }
355N/A#if defined(__sparc)
355N/A if (rptr > (char *)&rptr) {
355N/A /* in the stack frame */
355N/A return;
355N/A }
355N/A#endif
355N/A xalloc_bottom = sbrk(0);
355N/A if (rptr <= xalloc_bottom) {
355N/A free(ptr);
355N/A }
355N/A}
355N/A
355N/Avoid *
355N/Axcalloc(size_t i, size_t j)
355N/A{
355N/A char *cp;
355N/A
509N/A i *= j;
509N/A cp = xalloc(i);
355N/A (void) memset(cp, '\0', i);
509N/A return (cp);
355N/A}
355N/A