You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

267 lines
5.7 KiB

/**********
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 "ngspice/ngspice.h"
#include "ngspice/cpdefs.h"
#include "unixcom.h"
#include "../frontend/streams.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 = TMALLOC(struct hashent, 1);
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);
}
}
/* 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 (strchr(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;
void (*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);
}
#else
void
cp_rehash(char *pathlist, bool docc)
{
NG_IGNORE(docc);
NG_IGNORE(pathlist);
}
bool
cp_unixcom(wordlist *wl)
{
char *s = wl_flatten(wl);
if (system(s))
return (FALSE);
else
return (TRUE);
}
#endif