ngspice/src/parser/unixcom.c

256 lines
5.6 KiB
C
Raw Normal View History

2000-04-27 22:03:57 +02:00
/**********
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 <config.h>
#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 <sys/types.h>
# include <sys/dir.h>
# else
# ifdef HAVE_DIRENT_H
# include <sys/types.h>
# include <dirent.h>
# ifndef direct
# define direct dirent
# endif
# endif
# endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <sys/file.h>
#include <sys/wait.h>
#include <signal.h>
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