/********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group **********/ /* * Routines to do execution of unix commands. */ #include #include "ngspice.h" #include "cpdefs.h" #include "unixcom.h" #ifdef HAVE_VFORK_H /* The only reason this exists is efficiency */ # ifdef HAVE_SYS_DIR_H # include # include # else # ifdef HAVE_DIRENT_H # include # include # ifndef direct # define direct dirent # endif # endif # endif #ifdef HAVE_UNISTD_H #include #endif #include #include #include static bool tryexec(char *name, char *argv[]); static int hash(register char *str); struct hashent { char *h_name; char *h_path; struct hashent *h_next; } ; #define HASHSIZE 256 static struct hashent *hashtab[HASHSIZE]; static char *dirbuffer; static int dirlength, dirpos; /* Create the hash table for the given search path. pathlist is a : seperated * list of directories. If docc is TRUE, then all the commands found are * added to the command completion lists. */ void cp_rehash(char *pathlist, bool docc) { register int i; struct hashent *hh, *ht; char buf[BSIZE_SP], pbuf[BSIZE_SP], *curpath; DIR *pdir; struct direct *entry; /* First clear out the old hash table. */ for (i = 0; i < HASHSIZE; i++) { for (hh = hashtab[i]; hh; hh = ht) { ht = hh->h_next; /* Don't free any of the other stuff -- it is too * strange. */ tfree(hh); } hashtab[i] = NULL; } while (pathlist && *pathlist) { /* Copy one path to buf. We have to make sure that the path * is a full path name. */ if (*pathlist == '/') i = 0; else { #ifdef HAVE_GETWD (void) getwd(buf); #else # ifdef HAVE_GETCWD (void) getcwd(buf, sizeof(buf)); # else *buf = 0; # endif #endif i = strlen(buf); } while (*pathlist && (*pathlist != ':')) buf[i++] = *pathlist++; while (*pathlist == ':') pathlist++; buf[i] = '\0'; curpath = copy(buf); if (!(pdir = opendir(curpath))) continue; while (entry = readdir(pdir)) { (void) strcpy(pbuf, curpath); (void) strcat(pbuf, "/"); (void) strcat(pbuf, entry->d_name); /* Now we could make sure that it is really an * executable, but that is too slow * (as if "we" really cared). */ hh = alloc(struct hashent); hh->h_name = copy(entry->d_name); hh->h_path = curpath; i = hash(entry->d_name); /* Make sure this goes at the end, with * possible duplications of names. */ if (hashtab[i]) { ht = hashtab[i]; while (ht->h_next) ht = ht->h_next; ht->h_next = hh; } else hashtab[i] = hh; if (docc) { /* Add to completion hash table. */ cp_addcomm(entry->d_name, (long) 0, (long) 0, (long) 0, (long) 0); } } closedir(pdir); } return; } /* The return value is FALSE if no command was found, and TRUE if it was. */ bool cp_unixcom(wordlist *wl) { int i; register struct hashent *hh; register char *name; char **argv; char buf[BSIZE_SP]; if (!wl) return (FALSE); name = wl->wl_word; argv = wl_mkvec(wl); if (cp_debug) { printf("name: %s, argv: ", name); wl_print(wl, stdout); printf(".\n"); } if (index(name, '/')) return (tryexec(name, argv)); i = hash(name); for (hh = hashtab[i]; hh; hh = hh->h_next) { if (eq(name, hh->h_name)) { (void) sprintf(buf, "%s/%s", hh->h_path, hh->h_name); if (tryexec(buf, argv)) return (TRUE); } } return (FALSE); } static bool tryexec(char *name, char *argv[]) { # ifdef HAVE_SYS_WAIT_H int status; # else union wait status; # endif int pid, j; RETSIGTYPE (*svint)( ), (*svquit)( ), (*svtstp)( ); pid = vfork( ); if (pid == 0) { fixdescriptors(); (void) execv(name, argv); (void) _exit(120); /* A random value. */ /* NOTREACHED */ } else { svint = signal(SIGINT, SIG_DFL); svquit = signal(SIGQUIT, SIG_DFL); svtstp = signal(SIGTSTP, SIG_DFL); do { j = wait(&status); } while (j != pid); (void) signal(SIGINT, (SIGNAL_FUNCTION) svint); (void) signal(SIGQUIT, (SIGNAL_FUNCTION) svquit); (void) signal(SIGTSTP, (SIGNAL_FUNCTION) svtstp); } if (WTERMSIG(status) == 0 && WEXITSTATUS(status) == 120) /*if ((status.w_termsig == 0) && (status.w_retcode == 120)) */ return (FALSE); else return (TRUE); } static int hash(register char *str) { register int i = 0; while (*str) i += *str++; return (i % HASHSIZE); } /* Debugging. */ void cp_hstat(void) { struct hashent *hh; int i; for (i = 0; i < HASHSIZE; i++) for (hh = hashtab[i]; hh; hh = hh->h_next) fprintf(cp_err, "i = %d, name = %s, path = %s\n", i, hh->h_name, hh->h_path); return; } #else void cp_rehash(char *pathlist, bool docc) { } bool cp_unixcom(wordlist *wl) { char *s = wl_flatten(wl); if (system(s)) return (FALSE); else return (TRUE); } #endif