about summary refs log tree commit diff stats
path: root/src/Xsystem.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/Xsystem.c')
-rw-r--r--src/Xsystem.c598
1 files changed, 598 insertions, 0 deletions
diff --git a/src/Xsystem.c b/src/Xsystem.c
new file mode 100644
index 00000000..e82cc5a4
--- /dev/null
+++ b/src/Xsystem.c
@@ -0,0 +1,598 @@
+/* $Id: Xsystem.c,v 1.1 1999/07/14 16:44:55 tom Exp $
+ *	like system("cmd") but return with exit code of "cmd"
+ *	for Turbo-C/MS-C/LSI-C
+ *  This code is in the public domain.
+ *
+ * $Log: Xsystem.c,v $
+ * Revision 1.1  1999/07/14 16:44:55  tom
+ * Initial revision
+ *
+ *
+ * Revision 1.14  1997/10/17 (Fri) 16:28:24  senshu
+ * *** for Win32 version ***
+ *
+ * Revision 1.13  1992/02/24  06:59:13  serow
+ * *** empty log message ***
+ *
+ * Revision 1.12  1991/04/09  08:48:20  serow
+ * ignore new line at command line tail
+ *
+ * Revision 1.11  1991/03/12  07:12:50  serow
+ * CMDLINE
+ *
+ * Revision 1.10  91/02/24  05:10:14  serow
+ * 2>&1
+ *
+ * Revision 1.9  91/02/22  07:01:17  serow
+ * NEAR for ms-c
+ *
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <io.h>
+#include <process.h>
+#ifndef __CYGWIN__
+#include <dos.h>
+#endif
+
+#ifndef USECMDLINE
+#define USECMDLINE	0
+#endif
+
+#ifndef TRUE
+#define TRUE	1
+#define FALSE	0
+#endif
+
+#define STR_MAX 512	/* MAX command line */
+
+extern char *mktemp(char *);
+
+#define UCH(c)   ((unsigned char)(c))
+#define isk1(c)  ((0x81<=UCH(c)&&UCH(c)<=0x9F)||(0xE0<=UCH(c)&&UCH(c)<=0xFC))
+#define isq(c)   ((c) == '"')
+#define isspc(c) ((c) == ' ' || (c) == '\t')
+#define issep(c) (isspc(c) || (c) == '"' || (c) == '\'' || (c) == '<' || (c) == '>' || (c) == 0)
+#define issep2(c) (issep(c) || (c) == '.' || (c) == '\\' || (c) == '/')
+#define isdeg(c) ('0' <= (c) && (c) <= '9')
+
+#if 0	/* MS-C */
+#define NEAR	_near
+#else
+#define NEAR
+#endif
+
+typedef struct _proc {
+    struct _proc *next;
+    char *line;
+    char *cmd;
+    char *arg;
+    char *inf;
+    int infmod;
+    char *outf;
+    int outfmod;
+    int ored[10];
+    int sred[10];
+} PRO;
+
+static PRO *p1 = 0;
+
+static char *NEAR
+xmalloc(size_t n)
+{
+    char *bp;
+
+    if ((bp = calloc(1, n)) == (char *) 0) {
+	write(2, "xsystem: Out of memory.!\n", 25);
+	exit(1);
+    }
+    return bp;
+}
+
+static char *NEAR
+xrealloc(void *p, size_t n)
+{
+    char *bp;
+
+    if ((bp = realloc(p, n)) == (char *) 0) {
+	write(2, "xsystem: Out of memory!.\n", 25);
+	exit(1);
+    }
+    return bp;
+}
+
+static int NEAR
+is_builtin_command(char *s)
+{
+    extern int system_is_NT;	/* 1997/11/05 (Wed) 22:10:35 */
+
+    static char *cmdtab[]=
+    {
+	"dir", "type", "rem", "ren", "rename", "erase", "del",
+	"copy", "pause", "date", "time", "ver", "vol", "label",
+	"cd", "chdir", "md", "mkdir", "rd", "rmdir", "break",
+	"verify", "set", "prompt", "path", "exit", "ctty", "echo",
+	"if", "for", "cls", "goto", "shift"
+	,"start"	/* start is NT only */
+    };
+    int i, l, lc, count;
+
+    l = strlen(s);
+    count = sizeof(cmdtab) / sizeof(cmdtab[0]);
+    if (!system_is_NT)
+	count--;
+    for (i = 0; i < count; i++) {
+	if (stricmp(s, cmdtab[i]) == 0)
+	    return 1;
+	lc = strlen(cmdtab[i]);
+	if (lc < l && strnicmp(s, cmdtab[i], lc) == 0 && issep2(s[lc]))
+	    return 1;
+    }
+    return 0;
+}
+
+static int NEAR
+getswchar(void)
+{
+#ifdef __WIN32__
+    return '/';
+#else
+    union REGS reg;
+
+    reg.x.ax = 0x3700;
+    intdos(&reg, &reg);
+    return reg.h.dl;
+#endif
+}
+
+static int NEAR
+csystem(PRO * p, int flag)
+{
+    char *cmp;
+    char SW[3];
+    int rc;
+
+    if ((cmp = getenv("COMSPEC")) == 0)
+	return -2;
+    SW[0] = getswchar();
+    SW[1] = 'c';
+    SW[2] = 0;
+    rc = spawnl(flag, cmp, cmp, SW, p->cmd, p->arg, (char *) 0);
+    return rc < 0 ? -2 : rc;
+}
+
+static PRO *NEAR
+pars1c(char *s)
+{
+    PRO *pp;
+    char *fnp;
+    int ms, mi;
+    int fs, fi, inpf;
+    int q;
+
+    pp = (PRO *) xmalloc(sizeof(PRO));
+    for (q = 0; q < sizeof(pp->ored) / sizeof(pp->ored[0]); q++)
+	pp->ored[q] = q;
+    while (isspc(*s))
+	s++;
+    pp->line = strdup(s);
+    pp->cmd = xmalloc(ms = 8);
+    mi = 0;
+    while (!issep(*s)) {
+	if (mi >= ms - 1)
+	    pp->cmd = xrealloc(pp->cmd, ms += 8);
+	pp->cmd[mi++] = *s++;
+    }
+    pp->cmd[mi] = 0;
+    q = 0;
+    pp->arg = xmalloc(ms = 32);
+    if (isspc(*s))
+	s++;
+    mi = 0;
+    while (*s) {
+	if (mi >= ms - 1) {
+	    pp->arg = xrealloc(pp->arg, ms += 32);
+	}
+	if (q == 0) {
+	    inpf = 0;
+	    if ((mi == 0 || isspc(s[-1])) &&
+		isdeg(s[0]) && s[1] == '>' &&
+		s[2] == '&' && isdeg(s[3])) {
+
+		pp->ored[s[0] & 15] = s[3] & 15;
+		s += 4;
+		continue;
+	    } else if (s[0] == '<') {
+		if (pp->inf == 0) {
+		    pp->infmod = O_RDONLY;
+		}
+		inpf = 1;
+	    } else if (s[0] == '>' && s[1] == '>') {
+		if (pp->outf == 0) {
+		    pp->outfmod = O_WRONLY | O_CREAT | O_APPEND;
+		}
+		s++;
+	    } else if (s[0] == '>') {
+		if (pp->outf == 0) {
+		    pp->outfmod = O_WRONLY | O_CREAT | O_TRUNC;
+		}
+	    } else {
+		if (*s == '"')
+		    q = !q;
+		pp->arg[mi++] = *s++;
+		continue;
+	    }
+	    fnp = xmalloc(fs = 16);
+	    fi = 0;
+	    s++;
+	    while (isspc(*s))
+		s++;
+	    while (!issep(*s)) {
+		if (fi >= fs - 1)
+		    fnp = xrealloc(fnp, fs += 16);
+		fnp[fi++] = *s++;
+	    }
+	    fnp[fi] = 0;
+	    if (inpf) {
+		if (pp->inf == 0)
+		    pp->inf = fnp;
+	    } else {
+		if (pp->outf == 0)
+		    pp->outf = fnp;
+	    }
+	} else if (s[0] == '"') {
+	    q = !q;
+	    pp->arg[mi++] = *s++;
+	} else {
+	    pp->arg[mi++] = *s++;
+	}
+    }
+    pp->arg[mi] = 0;
+    return pp;
+}
+
+static PRO *NEAR
+pars(char *s)
+{
+    char *lb;
+    int li, ls, q;
+    int c;
+    PRO *pp;
+
+    lb = xmalloc(ls = STR_MAX);	/* about */
+    li = q = 0;
+    p1 = 0;
+
+    for (;;) {
+	c = *s++;
+	if (li >= ls - 2)
+	    lb = xrealloc(lb, ls += STR_MAX);
+	if (isk1(c) && *s) {
+	    lb[li++] = c;
+	    lb[li++] = *s++;
+	} else if ((!q && c == '|') || c == 0 || (c == '\n' && *s == 0)) {
+	    lb[li++] = 0;
+	    if (p1 == 0) {
+		pp = p1 = pars1c(lb);
+	    } else {
+		pp->next = pars1c(lb);
+		pp = pp->next;
+	    }
+	    li = 0;
+	    if (c == 0 || (c == '\n' && *s == 0))
+		break;
+	} else if (c == '"') {
+	    q = !q;
+	    lb[li++] = c;
+	} else {
+	    lb[li++] = c;
+	}
+    }
+    free(lb);
+    return p1;
+}
+
+static int NEAR
+try3(char *cnm, PRO * p, int flag)
+{
+    char cmdb[STR_MAX];
+    int rc;
+
+    strcat(strcpy(cmdb, cnm), ".com");
+    if ((rc = open(cmdb, O_RDONLY)) >= 0) {
+	close(rc);
+	return spawnl(flag, cmdb, cmdb, p->arg, (char *) 0);
+    }
+    strcat(strcpy(cmdb, cnm), ".exe");
+    if ((rc = open(cmdb, O_RDONLY)) >= 0) {
+	close(rc);
+	return spawnl(flag, cmdb, cmdb, p->arg, (char *) 0);
+    }
+    strcat(strcpy(cmdb, cnm), ".bat");
+    if ((rc = open(cmdb, O_RDONLY)) >= 0) {
+	close(rc);
+	return csystem(p, flag);
+    }
+    return -1;
+}
+
+static int NEAR
+prog_go(PRO * p, int flag)
+{
+    char *s;
+    char *extp = 0;
+    char cmdb[STR_MAX];
+    char *ep;
+    int rc, lc, cmd_len;
+
+    cmd_len = strlen(p->cmd);
+
+    s = p->cmd + cmd_len - 1;
+    while (cmd_len && (*s != '\\') && (*s != '/') && (*s != ':')) {
+	if (*s == '.')
+	    extp = s;
+	cmd_len--;
+	s--;
+    }
+
+    if (is_builtin_command(p->cmd) || (extp && stricmp(extp, ".bat") == 0))
+	return csystem(p, flag);
+
+    if (s < p->cmd) {		/* cmd has no PATH nor Drive */
+	ep = getenv("PATH");
+	strcpy(cmdb, p->cmd);
+	for (;;) {
+	    if (extp) {		/* has extention */
+		if ((rc = open(cmdb, O_RDONLY)) >= 0) {
+		    close(rc);
+		    rc = spawnl(flag, cmdb, cmdb, p->arg, (char *) 0);
+		}
+	    } else {
+		rc = try3(cmdb, p, flag);
+	    }
+	    if (rc >= 0)
+		return rc;
+
+	    if (ep && *ep) {
+		int i;
+		for (i = 0; *ep != ';' && *ep != '\0'; ep++, i++)
+		    lc = cmdb[i] = *ep;
+		if (*ep == ';')
+		    ep++;
+		if (i > 0 && lc != ':' && lc != '\\' && lc != '/')
+		    cmdb[i++] = '\\';
+		cmdb[i] = 0;
+		strcat(cmdb, p->cmd);
+	    } else {
+		if (rc == -2)
+		    return rc;
+		return -1;
+	    }
+	}
+    } else {			/* has PATH or Drive */
+	if (extp) {		/* has extention */
+	    if ((rc = open(p->cmd, O_RDONLY)) >= 0) {
+		close(rc);
+		return spawnl(flag, p->cmd, p->cmd, p->arg, (char *) 0);
+	    }
+	    return -1;
+	} else {
+	    return try3(p->cmd, p, flag);
+	}
+    }
+}
+
+static char *NEAR
+tmpf(char *tp)
+{
+    char tplate[STR_MAX];
+    char *ev;
+    int i;
+
+    if ((ev = getenv("TMP")) != 0) {
+	strcpy(tplate, ev);
+	i = strlen(ev);
+	if (i && ev[i - 1] != '\\' && ev[i - 1] != '/')
+	    strcat(tplate, "\\");
+    } else {
+	tplate[0] = 0;
+    }
+    strcat(tplate, tp);
+    return strdup(mktemp(tplate));
+}
+
+static int NEAR
+redopen(char *fn, int md, int sfd)
+{
+    int rc;
+    int fd;
+
+    if ((fd = open(fn, md, 0666)) != -1) {
+	if (md & O_APPEND)
+	    lseek(fd, 0L, SEEK_END);
+	rc = dup(sfd);
+	if (fd != sfd) {
+	    dup2(fd, sfd);
+	    close(fd);
+	}
+	return rc;
+    }
+    return -1;
+}
+
+static int NEAR
+redclose(int fd, int sfd)
+{
+    if (fd != -1) {
+	dup2(fd, sfd);
+	close(fd);
+    }
+    return -1;
+}
+
+static void NEAR
+redswitch(PRO * p)
+{
+    int d;
+
+    for (d = 0; d < sizeof(p->ored) / sizeof(p->ored[0]); d++) {
+	if (d != p->ored[d]) {
+	    p->sred[d] = dup(d);
+	    dup2(p->ored[d], d);
+	}
+    }
+}
+
+static void NEAR
+redunswitch(PRO * p)
+{
+    int d;
+
+    for (d = 0; d < sizeof(p->ored) / sizeof(p->ored[0]); d++) {
+	if (d != p->ored[d]) {
+	    dup2(p->sred[d], d);
+	    close(p->sred[d]);
+	}
+    }
+}
+
+int
+xsystem(char *cmd)
+{
+    PRO *p, *pn;
+    char *pof, *pif, *pxf;
+    int psstdin, psstdout;
+    int rdstdin, rdstdout;
+    int rc = 0;
+    static char *cmdline = 0;
+#if USECMDLINE
+    char *oldcmdline;
+#endif
+
+#ifdef SH_EX	/* 1997/11/01 (Sat) 10:04:03 add by JH7AYN */
+    pif = cmd;
+    while (*pif++) {
+	if (*pif == '\r') {
+	    *pif = '\0';
+	    break;
+	} else if (*pif ==  '\n') {
+	    *pif = '\0';
+	    break;
+	}
+    }
+#endif
+
+    pof = pif = pxf = 0;
+    p = pars(cmd);
+    pof = tmpf("p1XXXXXX");
+    pif = tmpf("p2XXXXXX");
+    psstdin = psstdout = rdstdin = rdstdout = -1;
+    while (p) {
+#if USECMDLINE
+	if (!getenv("NOCMDLINE")) {
+	    oldcmdline = cmdline;
+	    cmdline = xmalloc(strlen(p->cmd) + strlen(p->arg) + 10);
+	    strcat(strcat(strcat(strcpy(cmdline, "CMDLINE="), p->cmd), " "), p->arg);
+	    putenv(cmdline);
+	    if (oldcmdline)
+		free(oldcmdline);
+	}
+#endif
+	if (p->next)
+	    psstdout = redopen(pof, O_WRONLY | O_CREAT | O_TRUNC, 1);
+	if (p->inf)
+	    rdstdin = redopen(p->inf, p->infmod, 0);
+	if (p->outf)
+	    rdstdout = redopen(p->outf, p->outfmod, 1);
+	redswitch(p);
+	rc = prog_go(p, P_WAIT);
+	redunswitch(p);
+	rdstdin = redclose(rdstdin, 0);
+	rdstdout = redclose(rdstdout, 1);
+	psstdout = redclose(psstdout, 1);
+	psstdin = redclose(psstdin, 0);
+	if ((p = p->next) != 0) {
+	    pxf = pif;
+	    pif = pof;
+	    pof = pxf;
+	    psstdin = redopen(pif, O_RDONLY, 0);
+	}
+    }
+    unlink(pif);
+    free(pif);
+    unlink(pof);
+    free(pof);
+    for (pn = p = p1; p; p = pn) {
+	pn = p->next;
+	if (p->line)
+	    free(p->line);
+	if (p->cmd)
+	    free(p->cmd);
+	if (p->arg)
+	    free(p->arg);
+	if (p->inf)
+	    free(p->inf);
+	if (p->outf)
+	    free(p->outf);
+	free(p);
+    }
+    if (rc == -2)
+	return 127;
+    return rc < 0 ? 0xFF00 : rc;
+}
+
+int exec_command(char * cmd, int wait_flag)
+{
+    PRO *p;
+    char *pif;
+    int rc = 0;
+    int cmd_str;
+
+    pif = cmd;
+    while(*pif == ' ')
+	pif++;
+
+    cmd = pif;
+    cmd_str = TRUE;
+
+    while (*pif++) {
+	if (*pif == '\r') {
+	    *pif = '\0';
+	    break;
+	} else if (*pif ==  '\n') {
+	    *pif = '\0';
+	    break;
+	} else if (cmd_str) {
+	    if (*pif ==  '/')
+		*pif = '\\';
+	} else if (cmd_str) {
+	    if (*pif ==  ' ')
+		cmd_str = FALSE;
+	}
+    }
+    p = pars(cmd);
+
+    if (wait_flag)
+	rc = prog_go(p, P_WAIT);
+    else
+	rc = prog_go(p, P_NOWAIT);
+
+    return rc;
+}
+
+
+#ifdef TEST
+#include <stdio.h>
+
+void
+main()
+{
+    char line_buff[STR_MAX];
+
+    while (gets(line_buff)) {
+	printf("\nreturn %04X\n", xsystem(line_buff));
+    }
+}
+#endif	/* TEST */