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