summaryrefslogtreecommitdiffstats
path: root/contrib/tcsh/sh.misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/tcsh/sh.misc.c')
-rw-r--r--contrib/tcsh/sh.misc.c668
1 files changed, 668 insertions, 0 deletions
diff --git a/contrib/tcsh/sh.misc.c b/contrib/tcsh/sh.misc.c
new file mode 100644
index 0000000..08ec30d
--- /dev/null
+++ b/contrib/tcsh/sh.misc.c
@@ -0,0 +1,668 @@
+/* $Header: /p/tcsh/cvsroot/tcsh/sh.misc.c,v 3.46 2010/05/08 00:41:58 christos Exp $ */
+/*
+ * sh.misc.c: Miscelaneous functions
+ */
+/*-
+ * Copyright (c) 1980, 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include "sh.h"
+
+RCSID("$tcsh: sh.misc.c,v 3.46 2010/05/08 00:41:58 christos Exp $")
+
+static int renum (int, int);
+static Char **blkend (Char **);
+static Char **blkcat (Char **, Char **);
+static int xdup2 (int, int);
+
+/*
+ * C Shell
+ */
+
+int
+any(const char *s, Char c)
+{
+ if (!s)
+ return (0); /* Check for nil pointer */
+ while (*s)
+ if ((Char)*s++ == c)
+ return (1);
+ return (0);
+}
+
+void
+setzero(void *p, size_t size)
+{
+ memset(p, 0, size);
+}
+
+#ifndef SHORT_STRINGS
+char *
+strnsave(const char *s, size_t len)
+{
+ char *r;
+
+ r = xmalloc(len + 1);
+ memcpy(r, s, len);
+ r[len] = '\0';
+ return r;
+}
+#endif
+
+char *
+strsave(const char *s)
+{
+ char *r;
+ size_t size;
+
+ if (s == NULL)
+ s = "";
+ size = strlen(s) + 1;
+ r = xmalloc(size);
+ memcpy(r, s, size);
+ return (r);
+}
+
+static Char **
+blkend(Char **up)
+{
+
+ while (*up)
+ up++;
+ return (up);
+}
+
+
+void
+blkpr(Char *const *av)
+{
+
+ for (; *av; av++) {
+ xprintf("%S", *av);
+ if (av[1])
+ xprintf(" ");
+ }
+}
+
+Char *
+blkexpand(Char *const *av)
+{
+ struct Strbuf buf = Strbuf_INIT;
+
+ for (; *av; av++) {
+ Strbuf_append(&buf, *av);
+ if (av[1])
+ Strbuf_append1(&buf, ' ');
+ }
+ return Strbuf_finish(&buf);
+}
+
+int
+blklen(Char **av)
+{
+ int i = 0;
+
+ while (*av++)
+ i++;
+ return (i);
+}
+
+Char **
+blkcpy(Char **oav, Char **bv)
+{
+ Char **av = oav;
+
+ while ((*av++ = *bv++) != NULL)
+ continue;
+ return (oav);
+}
+
+static Char **
+blkcat(Char **up, Char **vp)
+{
+
+ (void) blkcpy(blkend(up), vp);
+ return (up);
+}
+
+void
+blkfree(Char **av0)
+{
+ Char **av = av0;
+
+ if (!av0)
+ return;
+ for (; *av; av++)
+ xfree(*av);
+ xfree(av0);
+}
+
+void
+blk_cleanup(void *ptr)
+{
+ blkfree(ptr);
+}
+
+void
+blk_indirect_cleanup(void *xptr)
+{
+ Char ***ptr;
+
+ ptr = xptr;
+ blkfree(*ptr);
+ xfree(ptr);
+}
+
+Char **
+saveblk(Char **v)
+{
+ Char **newv, **onewv;
+
+ if (v == NULL)
+ return NULL;
+
+ onewv = newv = xcalloc(blklen(v) + 1, sizeof(Char **));
+
+ while (*v)
+ *newv++ = Strsave(*v++);
+ return (onewv);
+}
+
+#ifndef HAVE_STRSTR
+char *
+strstr(const char *s, const char *t)
+{
+ do {
+ const char *ss = s;
+ const char *tt = t;
+
+ do
+ if (*tt == '\0')
+ return (s);
+ while (*ss++ == *tt++);
+ } while (*s++ != '\0');
+ return (NULL);
+}
+#endif /* !HAVE_STRSTR */
+
+char *
+strspl(const char *cp, const char *dp)
+{
+ char *ep;
+ size_t cl, dl;
+
+ if (!cp)
+ cp = "";
+ if (!dp)
+ dp = "";
+ cl = strlen(cp);
+ dl = strlen(dp);
+ ep = xmalloc((cl + dl + 1) * sizeof(char));
+ memcpy(ep, cp, cl);
+ memcpy(ep + cl, dp, dl + 1);
+ return (ep);
+}
+
+Char **
+blkspl(Char **up, Char **vp)
+{
+ Char **wp = xcalloc(blklen(up) + blklen(vp) + 1, sizeof(Char **));
+
+ (void) blkcpy(wp, up);
+ return (blkcat(wp, vp));
+}
+
+Char
+lastchr(Char *cp)
+{
+
+ if (!cp)
+ return (0);
+ if (!*cp)
+ return (0);
+ while (cp[1])
+ cp++;
+ return (*cp);
+}
+
+/*
+ * This routine is called after an error to close up
+ * any units which may have been left open accidentally.
+ */
+void
+closem(void)
+{
+ int f, num_files;
+
+#ifdef NLS_BUGS
+#ifdef NLS_CATALOGS
+ nlsclose();
+#endif /* NLS_CATALOGS */
+#endif /* NLS_BUGS */
+#ifdef YPBUGS
+ /* suggested by Justin Bur; thanks to Karl Kleinpaste */
+ fix_yp_bugs();
+#endif /* YPBUGS */
+ num_files = NOFILE;
+ for (f = 0; f < num_files; f++)
+ if (f != SHIN && f != SHOUT && f != SHDIAG && f != OLDSTD &&
+ f != FSHTTY
+#ifdef MALLOC_TRACE
+ && f != 25
+#endif /* MALLOC_TRACE */
+ )
+ {
+ xclose(f);
+#ifdef NISPLUS
+ if(f < 3)
+ (void) xopen(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE);
+#endif /* NISPLUS */
+ }
+#ifdef NLS_BUGS
+#ifdef NLS_CATALOGS
+ nlsinit();
+#endif /* NLS_CATALOGS */
+#endif /* NLS_BUGS */
+}
+
+#ifndef CLOSE_ON_EXEC
+/*
+ * Close files before executing a file.
+ * We could be MUCH more intelligent, since (on a version 7 system)
+ * we need only close files here during a source, the other
+ * shell fd's being in units 16-19 which are closed automatically!
+ */
+void
+closech(void)
+{
+ int f, num_files;
+
+ if (didcch)
+ return;
+ didcch = 1;
+ SHIN = 0;
+ SHOUT = 1;
+ SHDIAG = 2;
+ OLDSTD = 0;
+ isoutatty = isatty(SHOUT);
+ isdiagatty = isatty(SHDIAG);
+ num_files = NOFILE;
+ for (f = 3; f < num_files; f++)
+ xclose(f);
+}
+
+#endif /* CLOSE_ON_EXEC */
+
+void
+donefds(void)
+{
+
+ xclose(0);
+ xclose(1);
+ xclose(2);
+ didfds = 0;
+#ifdef NISPLUS
+ {
+ int fd = xopen(_PATH_DEVNULL, O_RDONLY|O_LARGEFILE);
+ (void)dcopy(fd, 1);
+ (void)dcopy(fd, 2);
+ (void)dmove(fd, 0);
+ }
+#endif /*NISPLUS*/
+}
+
+/*
+ * Move descriptor i to j.
+ * If j is -1 then we just want to get i to a safe place,
+ * i.e. to a unit > FSAFE. This also happens in dcopy.
+ */
+int
+dmove(int i, int j)
+{
+
+ if (i == j || i < 0)
+ return (i);
+#ifdef HAVE_DUP2
+ if (j >= 0) {
+ (void) xdup2(i, j);
+ if (j != i)
+ xclose(i);
+ return (j);
+ }
+#endif
+ j = dcopy(i, j);
+ if (j != i)
+ xclose(i);
+ return (j);
+}
+
+int
+dcopy(int i, int j)
+{
+
+ if (i == j || i < 0 || (j < 0 && i > FSAFE))
+ return (i);
+ if (j >= 0) {
+#ifdef HAVE_DUP2
+ (void) xdup2(i, j);
+ return (j);
+#else
+ xclose(j);
+#endif
+ }
+ return (renum(i, j));
+}
+
+static int
+renum(int i, int j)
+{
+ int k = dup(i);
+
+ if (k < 0)
+ return (-1);
+ if (j == -1 && k > FSAFE)
+ return (k);
+ if (k != j) {
+ j = renum(k, j);
+ xclose(k);
+ return (j);
+ }
+ return (k);
+}
+
+/*
+ * Left shift a command argument list, discarding
+ * the first c arguments. Used in "shift" commands
+ * as well as by commands like "repeat".
+ */
+void
+lshift(Char **v, int c)
+{
+ Char **u;
+
+ for (u = v; *u && --c >= 0; u++)
+ xfree(*u);
+ (void) blkcpy(v, u);
+}
+
+int
+number(Char *cp)
+{
+ if (!cp)
+ return (0);
+ if (*cp == '-') {
+ cp++;
+ if (!Isdigit(*cp))
+ return (0);
+ cp++;
+ }
+ while (*cp && Isdigit(*cp))
+ cp++;
+ return (*cp == 0);
+}
+
+Char **
+copyblk(Char **v)
+{
+ Char **nv = xcalloc(blklen(v) + 1, sizeof(Char **));
+
+ return (blkcpy(nv, v));
+}
+
+char *
+strend(const char *cp)
+{
+ if (!cp)
+ return ((char *)(intptr_t)cp);
+ while (*cp)
+ cp++;
+ return ((char *)(intptr_t)cp);
+}
+
+Char *
+strip(Char *cp)
+{
+ Char *dp = cp;
+
+ if (!cp)
+ return (cp);
+ while ((*dp++ &= TRIM) != '\0')
+ continue;
+ return (cp);
+}
+
+Char *
+quote(Char *cp)
+{
+ Char *dp = cp;
+
+ if (!cp)
+ return (cp);
+ while (*dp != '\0')
+ *dp++ |= QUOTE;
+ return (cp);
+}
+
+const Char *
+quote_meta(struct Strbuf *buf, const Char *s)
+{
+ buf->len = 0;
+ while (*s != '\0') {
+ if (cmap(*s, _META | _DOL | _QF | _QB | _ESC | _GLOB))
+ Strbuf_append1(buf, '\\');
+ Strbuf_append1(buf, *s++);
+ }
+ Strbuf_terminate(buf);
+ return buf->s;
+}
+
+void
+udvar(Char *name)
+{
+ setname(short2str(name));
+ stderror(ERR_NAME | ERR_UNDVAR);
+}
+
+int
+prefix(const Char *sub, const Char *str)
+{
+
+ for (;;) {
+ if (*sub == 0)
+ return (1);
+ if (*str == 0)
+ return (0);
+ if ((*sub++ & TRIM) != (*str++ & TRIM))
+ return (0);
+ }
+}
+#ifndef WINNT_NATIVE
+char *
+areadlink(const char *path)
+{
+ char *buf;
+ size_t size;
+ ssize_t res;
+
+ size = MAXPATHLEN + 1;
+ buf = xmalloc(size);
+ while ((size_t)(res = readlink(path, buf, size)) == size) {
+ size *= 2;
+ buf = xrealloc(buf, size);
+ }
+ if (res == -1) {
+ int err;
+
+ err = errno;
+ xfree(buf);
+ errno = err;
+ return NULL;
+ }
+ buf[res] = '\0';
+ return xrealloc(buf, res + 1);
+}
+#endif /*!WINNT_NATIVE*/
+
+void
+xclose(int fildes)
+{
+ if (fildes < 0)
+ return;
+ while (close(fildes) == -1 && errno == EINTR)
+ handle_pending_signals();
+}
+
+void
+xclosedir(DIR *dirp)
+{
+ while (closedir(dirp) == -1 && errno == EINTR)
+ handle_pending_signals();
+}
+
+int
+xcreat(const char *path, mode_t mode)
+{
+ int res;
+
+ while ((res = creat(path, mode)) == -1 && errno == EINTR)
+ handle_pending_signals();
+ return res;
+}
+
+#ifdef HAVE_DUP2
+static int
+xdup2(int fildes, int fildes2)
+{
+ int res;
+
+ while ((res = dup2(fildes, fildes2)) == -1 && errno == EINTR)
+ handle_pending_signals();
+ return res;
+}
+#endif
+
+struct group *
+xgetgrgid(gid_t xgid)
+{
+ struct group *res;
+
+ errno = 0;
+ while ((res = getgrgid(xgid)) == NULL && errno == EINTR) {
+ handle_pending_signals();
+ errno = 0;
+ }
+ return res;
+}
+
+struct passwd *
+xgetpwnam(const char *name)
+{
+ struct passwd *res;
+
+ errno = 0;
+ while ((res = getpwnam(name)) == NULL && errno == EINTR) {
+ handle_pending_signals();
+ errno = 0;
+ }
+ return res;
+}
+
+struct passwd *
+xgetpwuid(uid_t xuid)
+{
+ struct passwd *res;
+
+ errno = 0;
+ while ((res = getpwuid(xuid)) == NULL && errno == EINTR) {
+ handle_pending_signals();
+ errno = 0;
+ }
+ return res;
+}
+
+int
+xopen(const char *path, int oflag, ...)
+{
+ int res;
+
+ if ((oflag & O_CREAT) == 0) {
+ while ((res = open(path, oflag)) == -1 && errno == EINTR)
+ handle_pending_signals();
+ } else {
+ va_list ap;
+ mode_t mode;
+
+ va_start(ap, oflag);
+ /* "int" should actually be "mode_t after default argument
+ promotions". "int" is the best guess we have, "mode_t" used to be
+ "unsigned short", which we obviously can't use. */
+ mode = va_arg(ap, int);
+ va_end(ap);
+ while ((res = open(path, oflag, mode)) == -1 && errno == EINTR)
+ handle_pending_signals();
+ }
+ return res;
+}
+
+ssize_t
+xread(int fildes, void *buf, size_t nbyte)
+{
+ ssize_t res;
+
+ /* This is where we will be blocked most of the time, so handle signals
+ that didn't interrupt any system call. */
+ do
+ handle_pending_signals();
+ while ((res = read(fildes, buf, nbyte)) == -1 && errno == EINTR);
+ return res;
+}
+
+#ifdef POSIX
+int
+xtcsetattr(int fildes, int optional_actions, const struct termios *termios_p)
+{
+ int res;
+
+ while ((res = tcsetattr(fildes, optional_actions, termios_p)) == -1 &&
+ errno == EINTR)
+ handle_pending_signals();
+ return res;
+}
+#endif
+
+ssize_t
+xwrite(int fildes, const void *buf, size_t nbyte)
+{
+ ssize_t res;
+
+ /* This is where we will be blocked most of the time, so handle signals
+ that didn't interrupt any system call. */
+ do
+ handle_pending_signals();
+ while ((res = write(fildes, buf, nbyte)) == -1 && errno == EINTR);
+ return res;
+}
OpenPOWER on IntegriCloud