home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
GEMini Atari
/
GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso
/
zip
/
mint
/
mntlib16.lzh
/
MNTLIB16
/
SYSTEM.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-08-03
|
4KB
|
199 lines
/*
* system(): execute a command, passed as a string
*
* Written by Eric R. Smith and placed in the public domain.
*
* Modified by Allan Pratt to call _unx2dos on redirect file names
* and to call spawnvp() without calling fork() -- why bother?
*
*/
#include <limits.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <process.h>
#include <errno.h>
#include <file.h>
#include <osbind.h>
#include <unistd.h>
#include "lib.h"
#define isquote(c) ((c) == '\"' || (c) == '\'' || (c) == '`')
#define ARG_ERR ( (Argentry *) -1 )
/* struct. used to build a list of arguments for the command */
typedef struct argentry {
struct argentry *next;
char string[1];
} Argentry;
/* allocate an Argentry that will hold the string "s" */
static Argentry *_argalloc(s)
const char *s;
{
Argentry *x;
x = (Argentry *) malloc((size_t)(sizeof(Argentry) + strlen(s) + 1));
if (!x)
return ARG_ERR;
x->next = (Argentry *) 0;
strcpy(x->string, s);
return x;
}
/* free a list of Argentries */
static void _argfree(p)
Argentry *p;
{
Argentry *oldp;
while (p) {
oldp = p;
p = p->next;
free(oldp);
}
}
/* parse a string into a list of Argentries. Words are defined to be
* (1) any sequence of non-blank characters
* (2) any sequence of characters starting with a ', ", or ` and ending
* with the same character. These quotes are stripped off.
* (3) any spaces after an unquoted > or < are skipped, so
* "ls > junk" is parsed as 'ls' '>junk'.
*/
static Argentry *_parseargs(s)
const char *s;
{
Argentry *cur, *res;
char buf[PATH_MAX];
char *t, quote;
res = cur = _argalloc("");
for(;;) {
t = buf;
again:
while (isspace(*s)) s++;
if (!*s) break;
if (isquote(*s)) {
quote = *s++;
while (*s && *s != quote)
*t++ = *s++;
if (*s) s++; /* skip final quote */
}
else {
while (*s && !isspace(*s))
*t++ = *s++;
if (*s && ( *(s-1) == '>' || *(s-1) == '<' ))
goto again;
}
*t = 0;
cur->next = _argalloc(buf);
if (!(cur = cur->next)) /* couldn't alloc() */
return ARG_ERR;
}
cur->next = (Argentry *) 0;
cur = res; res = res->next; free(cur);
return res;
}
/* Here is system() itself.
* FIXME: we probably should do wildcard expansion.
* also, should errno get set here??
*/
int system(s)
const char *s;
{
Argentry *al, *cur;
char **argv, *p;
int argc, i;
char *infile, *outfile;
int infd = 0, outfd = 1, append = 0;
int oldin = 0, oldout = 1; /* hold the Fdup'd in, out */
char path[PATH_MAX];
int retval;
if (!s) /* check for system() supported ?? */
return 1;
al = _parseargs(s); /* get a list of args */
if (al == ARG_ERR) { /* not enough memory */
return errno = ENOMEM;
return -1;
}
infile = outfile = "";
/* convert the list returned by _parseargs to the normal char *argv[] */
argc = i = 0;
for (cur = al; cur; cur = cur->next)
argc++;
if (!(argv = (char **) malloc((size_t)(argc * sizeof(char *))))) {
errno = ENOMEM; return -1;
}
for (cur = al; cur; cur = cur->next) {
p = cur->string;
if (*p == '>') {
outfile = p+1;
if (*outfile == '>') {
outfile++;
append = 1;
}
else
append = 0;
}
else if (*p == '<') {
infile = p+1;
}
else
argv[i++] = p;
}
argv[i] = (char *)0;
/* now actually run the program */
if (*infile) {
(void)_unx2dos(infile,path);
infd = Fopen(path, 0);
if (infd < __SMALLEST_VALID_HANDLE) {
perror(infile);
_exit(2);
}
oldin = Fdup(0);
(void)Fforce(0, infd);
}
if (*outfile) {
(void)_unx2dos(outfile,path);
if (append) {
outfd = Fopen(path, 2);
if (outfd < __SMALLEST_VALID_HANDLE)
outfd = Fcreate(path, 0);
else
(void)Fseek(0L, outfd, 2);
}
else
outfd = Fcreate(path, 0);
if (outfd < __SMALLEST_VALID_HANDLE) {
perror(outfile);
_exit(2);
}
oldout = Fdup(1);
(void)Fforce(1, outfd);
}
retval = spawnvp(P_WAIT, argv[0], argv);
if (*infile) (void)(Fforce(0,oldin), Fclose(oldin), Fclose(infd));
if (*outfile) (void)(Fforce(1,oldout), Fclose(oldout), Fclose(outfd));
free(argv);
_argfree(al);
return retval;
}