diff options
Diffstat (limited to 'src/Xsystem.c')
-rw-r--r-- | src/Xsystem.c | 598 |
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(®, ®); + 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 */ |