1 /********************************************
2 dosexec.c
3 copyright 2009,2010,2014, Thomas E. Dickey
4 copyright 1991-1994,1995, Michael D. Brennan
5 
6 This is a source file for mawk, an implementation of
7 the AWK programming language.
8 
9 Mawk is distributed without warranty under the terms of
10 the GNU General Public License, version 2, 1991.
11 ********************************************/
12 
13 /*
14  * $MawkId: dosexec.c,v 1.5 2014/09/14 22:29:49 tom Exp $
15  *
16  * @Log: dosexec.c,v @
17  * Revision 1.3  1995/08/20  16:37:22  mike
18  * exit(1) -> exit(2)
19  *
20  * Revision 1.2  1994/10/08  18:50:03  mike
21  * remove SM_DOS
22  *
23  * Revision 1.1.1.1  1993/07/03  18:58:47  mike
24  * move source to cvs
25  *
26  * Revision 1.4  1992/12/05  22:29:43  mike
27  * dos patch 112d:
28  * don't use string_buff
29  * check COMSPEC
30  *
31  * Revision 1.3  1992/07/10  16:21:57  brennan
32  * store exit code of input pipes
33  *
34  * Revision 1.2  1991/11/16  10:27:18  brennan
35  * BINMODE
36  *
37  * Revision 1.1  91/10/29  09:45:56  brennan
38  * Initial revision
39  */
40 
41 /* system() and pipes() for MSDOS and Win32 console */
42 
43 #include "mawk.h"
44 
45 #if defined(MSDOS) || defined(_WINNT)
46 #include "memory.h"
47 #include "files.h"
48 #include "fin.h"
49 
50 #undef _POSIX_
51 
52 #include <process.h>
53 
54 #ifndef P_WAIT
55 #define P_WAIT _P_WAIT		/* works with VS2008 */
56 #endif
57 
58 static char *my_shell;		/* e.g.   "c:\\sys\\command.com"  */
59 static char *command_opt;	/*  " /c"  */
60 
61 static void
get_shell(void)62 get_shell(void)
63 {
64     char *s, *p;
65     int len;
66 
67     if ((s = getenv("MAWKSHELL")) != 0) {
68 	/* break into shell part and option part */
69 	p = s;
70 	while (*p != ' ' && *p != '\t')
71 	    p++;
72 	len = p - s;
73 	my_shell = (char *) zmalloc(len + 1);
74 	memcpy(my_shell, s, len);
75 	my_shell[len] = 0;
76 	command_opt = p;
77     } else if ((s = getenv("COMSPEC")) != 0) {
78 	my_shell = s;
79 	command_opt = " /c";
80 	/* leading space needed because of bug in command.com */
81     } else {
82 	errmsg(0,
83 	       "cannot exec(), must set MAWKSHELL or COMSPEC in environment");
84 	exit(2);
85     }
86 }
87 
88 int
DOSexec(char * command)89 DOSexec(char *command)
90 {
91     char xbuff[256];
92 
93     if (!my_shell)
94 	get_shell();
95 
96     sprintf(xbuff, "%s %s", command_opt, command);
97 
98     fflush(stderr);
99     fflush(stdout);
100 
101     return spawnl(P_WAIT, my_shell, my_shell, xbuff, (char *) 0);
102 }
103 
104 static int next_tmp;		/* index for naming temp files */
105 static char *tmpdir;		/* directory to hold temp files */
106 static unsigned mawkid;		/* unique to this mawk process */
107 
108 /* compute the unique temp file name associated with id */
109 char *
tmp_file_name(int id,char * buffer)110 tmp_file_name(int id,
111 	      char *buffer)
112 {
113     if (mawkid == 0) {
114 	/* first time */
115 	union {
116 	    void *ptr;
117 	    unsigned w[2];
118 	} xptr;
119 
120 	memset(&xptr, 0, sizeof(xptr));
121 	xptr.ptr = (void *) &mawkid;
122 	mawkid = xptr.w[1];
123 
124 	tmpdir = getenv("MAWKTMPDIR");
125 	if (!tmpdir || strlen(tmpdir) > 80)
126 	    tmpdir = "";
127     }
128 
129     (void) sprintf(buffer, "%sMAWK%04X.%03X", tmpdir, mawkid, id);
130     return buffer;
131 }
132 
133 /* open a pipe, returning a temp file identifier by
134    reference
135 */
136 
137 PTR
get_pipe(char * command,int type,int * tmp_idp)138 get_pipe(char *command,
139 	 int type, int *tmp_idp)
140 {
141     PTR retval;
142     char xbuff[256];
143     char *tmpname;
144 
145     *tmp_idp = next_tmp;
146     tmpname = tmp_file_name(next_tmp, xbuff + 163);
147 
148     if (type == PIPE_OUT) {
149 	retval = (PTR) fopen(tmpname, (binmode() & 2) ? "wb" : "w");
150     } else {
151 	sprintf(xbuff, "%s > %s", command, tmpname);
152 	tmp_idp[1] = DOSexec(xbuff);
153 	retval = (PTR) FINopen(tmpname, 0);
154     }
155 
156     next_tmp++;
157     return retval;
158 }
159 
160 /* closing a fake pipes involves running the out pipe
161    command
162 */
163 
164 int
close_fake_outpipe(char * command,int tid)165 close_fake_outpipe(char *command,
166 		   int tid)	/* identifies the temp file */
167 {
168     char xbuff[256];
169     char *tmpname = tmp_file_name(tid, xbuff + 163);
170     int retval;
171 
172     sprintf(xbuff, "%s < %s", command, tmpname);
173     retval = DOSexec(xbuff);
174     (void) unlink(tmpname);
175     return retval;
176 }
177 
178 #endif /* MSDOS */
179