19236
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
1 /* Proxy shell designed for use with Emacs on Windows 95 and NT.
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
2 Copyright (C) 1997 Free Software Foundation, Inc.
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
3
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
4 Accepts subset of Unix sh(1) command-line options, for compatability
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
5 with elisp code written for Unix. When possible, executes external
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
6 programs directly (a common use of /bin/sh by Emacs), otherwise
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
7 invokes the user-specified command processor to handle built-in shell
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
8 commands, batch files and interactive mode.
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
9
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
10 The main function is simply to process the "-c string" option in the
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
11 way /bin/sh does, since the standard Windows command shells use the
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
12 convention that everything after "/c" (the Windows equivalent of
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
13 "-c") is the input string.
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
14
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
15 This file is part of GNU Emacs.
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
16
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
17 GNU Emacs is free software; you can redistribute it and/or modify
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
18 it under the terms of the GNU General Public License as published by
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
19 the Free Software Foundation; either version 2, or (at your option)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
20 any later version.
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
21
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
22 GNU Emacs is distributed in the hope that it will be useful,
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
25 GNU General Public License for more details.
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
26
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
27 You should have received a copy of the GNU General Public License
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
28 along with GNU Emacs; see the file COPYING. If not, write to
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
29 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
30 Boston, MA 02111-1307, USA. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
31
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
32 #include <windows.h>
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
33
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
34 #include <stdarg.h> /* va_args */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
35 #include <malloc.h> /* alloca */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
36 #include <stdlib.h> /* getenv */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
37 #include <string.h> /* strlen */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
38
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
39
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
40 /******* Mock C library routines *********************************/
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
41
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
42 /* These routines are used primarily to minimize the executable size. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
43
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
44 #define stdin GetStdHandle (STD_INPUT_HANDLE)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
45 #define stdout GetStdHandle (STD_OUTPUT_HANDLE)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
46 #define stderr GetStdHandle (STD_ERROR_HANDLE)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
47
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
48 int
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
49 vfprintf(HANDLE hnd, char * msg, va_list args)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
50 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
51 DWORD bytes_written;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
52 char buf[1024];
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
53
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
54 wvsprintf (buf, msg, args);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
55 return WriteFile (hnd, buf, strlen (buf), &bytes_written, NULL);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
56 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
57
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
58 int
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
59 fprintf(HANDLE hnd, char * msg, ...)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
60 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
61 va_list args;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
62 int rc;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
63
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
64 va_start (args, msg);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
65 rc = vfprintf (hnd, msg, args);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
66 va_end (args);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
67
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
68 return rc;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
69 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
70
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
71 int
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
72 printf(char * msg, ...)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
73 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
74 va_list args;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
75 int rc;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
76
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
77 va_start (args, msg);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
78 rc = vfprintf (stdout, msg, args);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
79 va_end (args);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
80
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
81 return rc;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
82 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
83
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
84 void
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
85 fail (char * msg, ...)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
86 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
87 va_list args;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
88
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
89 va_start (args, msg);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
90 vfprintf (stderr, msg, args);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
91 va_end (args);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
92
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
93 exit (1);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
94 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
95
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
96 void
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
97 warn (char * msg, ...)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
98 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
99 va_list args;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
100
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
101 va_start (args, msg);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
102 vfprintf (stderr, msg, args);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
103 va_end (args);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
104 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
105
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
106 /******************************************************************/
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
107
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
108 char *
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
109 canon_filename (char *fname)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
110 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
111 char *p = fname;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
112
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
113 while (*p)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
114 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
115 if (*p == '/')
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
116 *p = '\\';
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
117 p++;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
118 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
119
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
120 return fname;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
121 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
122
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
123 char *
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
124 skip_space (char *str)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
125 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
126 while (isspace (*str)) str++;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
127 return str;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
128 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
129
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
130 char *
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
131 skip_nonspace (char *str)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
132 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
133 while (*str && !isspace (*str)) str++;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
134 return str;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
135 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
136
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
137 int escape_char = '\\';
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
138
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
139 /* Get next token from input, advancing pointer. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
140 int
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
141 get_next_token (char * buf, char ** pSrc)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
142 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
143 char * p = *pSrc;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
144 char * o = buf;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
145
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
146 p = skip_space (p);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
147 if (*p == '"')
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
148 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
149 int escape_char_run = 0;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
150
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
151 /* Go through src until an ending quote is found, unescaping
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
152 quotes along the way. If the escape char is not quote, then do
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
153 special handling of multiple escape chars preceding a quote
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
154 char (ie. the reverse of what Emacs does to escape quotes). */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
155 p++;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
156 while (1)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
157 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
158 if (p[0] == escape_char && escape_char != '"')
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
159 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
160 escape_char_run++;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
161 continue;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
162 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
163 else if (p[0] == '"')
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
164 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
165 while (escape_char_run > 1)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
166 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
167 *o++ = escape_char;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
168 escape_char_run -= 2;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
169 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
170
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
171 if (escape_char_run > 0)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
172 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
173 /* escaped quote */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
174 *o++ = *p++;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
175 escape_char_run = 0;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
176 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
177 else if (p[1] == escape_char && escape_char == '"')
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
178 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
179 /* quote escaped by doubling */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
180 *o++ = *p;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
181 p += 2;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
182 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
183 else
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
184 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
185 /* The ending quote. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
186 *o = '\0';
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
187 /* Leave input pointer after token. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
188 p++;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
189 break;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
190 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
191 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
192 else if (p[0] == '\0')
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
193 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
194 /* End of string, but no ending quote found. We might want to
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
195 flag this as an error, but for now will consider the end as
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
196 the end of the token. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
197 *o = '\0';
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
198 break;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
199 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
200 else
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
201 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
202 *o++ = *p++;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
203 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
204 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
205 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
206 else
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
207 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
208 /* Next token is delimited by whitespace. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
209 char * p1 = skip_nonspace (p);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
210 memcpy (o, p, p1 - p);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
211 o += (p1 - p);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
212 p = p1;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
213 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
214
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
215 *pSrc = p;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
216
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
217 return o - buf;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
218 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
219
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
220 /* Search for EXEC file in DIR. If EXEC does not have an extension,
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
221 DIR is searched for EXEC with the standard extensions appended. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
222 int
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
223 search_dir (char *dir, char *exec, int bufsize, char *buffer)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
224 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
225 char *exts[] = {".bat", ".cmd", ".exe", ".com"};
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
226 int n_exts = sizeof (exts) / sizeof (char *);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
227 char *dummy;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
228 int i, rc;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
229
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
230 /* Search the directory for the program. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
231 for (i = 0; i < n_exts; i++)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
232 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
233 rc = SearchPath (dir, exec, exts[i], bufsize, buffer, &dummy);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
234 if (rc > 0)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
235 return rc;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
236 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
237
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
238 return 0;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
239 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
240
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
241 /* Return the absolute name of executable file PROG, including
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
242 any file extensions. If an absolute name for PROG cannot be found,
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
243 return NULL. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
244 char *
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
245 make_absolute (char *prog)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
246 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
247 char absname[MAX_PATH];
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
248 char dir[MAX_PATH];
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
249 char curdir[MAX_PATH];
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
250 char *p, *fname;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
251 char *path;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
252 int i;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
253
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
254 /* At least partial absolute path specified; search there. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
255 if ((isalpha (prog[0]) && prog[1] == ':') ||
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
256 (prog[0] == '\\'))
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
257 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
258 /* Split the directory from the filename. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
259 fname = strrchr (prog, '\\');
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
260 if (!fname)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
261 /* Only a drive specifier is given. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
262 fname = prog + 2;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
263 strncpy (dir, prog, fname - prog);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
264 dir[fname - prog] = '\0';
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
265
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
266 /* Search the directory for the program. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
267 if (search_dir (dir, prog, MAX_PATH, absname) > 0)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
268 return strdup (absname);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
269 else
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
270 return NULL;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
271 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
272
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
273 if (GetCurrentDirectory (MAX_PATH, curdir) <= 0)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
274 return NULL;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
275
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
276 /* Relative path; search in current dir. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
277 if (strpbrk (prog, "\\"))
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
278 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
279 if (search_dir (curdir, prog, MAX_PATH, absname) > 0)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
280 return strdup (absname);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
281 else
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
282 return NULL;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
283 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
284
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
285 /* Just filename; search current directory then PATH. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
286 path = alloca (strlen (getenv ("PATH")) + strlen (curdir) + 2);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
287 strcpy (path, curdir);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
288 strcat (path, ";");
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
289 strcat (path, getenv ("PATH"));
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
290
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
291 while (*path)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
292 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
293 /* Get next directory from path. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
294 p = path;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
295 while (*p && *p != ';') p++;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
296 strncpy (dir, path, p - path);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
297 dir[p - path] = '\0';
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
298
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
299 /* Search the directory for the program. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
300 if (search_dir (dir, prog, MAX_PATH, absname) > 0)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
301 return strdup (absname);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
302
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
303 /* Move to the next directory. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
304 path = p + 1;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
305 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
306
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
307 return NULL;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
308 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
309
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
310 /*****************************************************************/
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
311
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
312 #if 0
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
313 char ** _argv;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
314 int _argc;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
315
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
316 /* Parse commandline into argv array, allowing proper quoting of args. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
317 void
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
318 setup_argv (void)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
319 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
320 char * cmdline = GetCommandLine ();
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
321 int arg_bytes = 0;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
322
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
323
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
324 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
325 #endif
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
326
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
327 /* Information about child proc is global, to allow for automatic
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
328 termination when interrupted. At the moment, only one child process
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
329 can be running at any one time. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
330
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
331 PROCESS_INFORMATION child;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
332 int interactive = TRUE;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
333
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
334 BOOL
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
335 console_event_handler (DWORD event)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
336 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
337 switch (event)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
338 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
339 case CTRL_C_EVENT:
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
340 case CTRL_BREAK_EVENT:
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
341 if (!interactive)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
342 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
343 /* Both command.com and cmd.exe have the annoying behaviour of
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
344 prompting "Terminate batch job (y/n)?" when interrupted
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
345 while running a batch file, even if running in
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
346 non-interactive (-c) mode. Try to make up for this
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
347 deficiency by forcibly terminating the subprocess if
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
348 running non-interactively. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
349 if (child.hProcess &&
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
350 WaitForSingleObject (child.hProcess, 500) != WAIT_OBJECT_0)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
351 TerminateProcess (child.hProcess, 0);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
352 exit (STATUS_CONTROL_C_EXIT);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
353 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
354 break;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
355
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
356 #if 0
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
357 default:
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
358 /* CLOSE, LOGOFF and SHUTDOWN events - actually we don't get these
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
359 under Windows 95. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
360 fail ("cmdproxy: received %d event\n", event);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
361 if (child.hProcess)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
362 TerminateProcess (child.hProcess, 0);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
363 #endif
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
364 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
365 return TRUE;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
366 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
367
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
368 int
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
369 spawn (char * progname, char * cmdline)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
370 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
371 DWORD rc = 0xff;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
372 SECURITY_ATTRIBUTES sec_attrs;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
373 STARTUPINFO start;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
374
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
375 sec_attrs.nLength = sizeof (sec_attrs);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
376 sec_attrs.lpSecurityDescriptor = NULL;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
377 sec_attrs.bInheritHandle = FALSE;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
378
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
379 memset (&start, 0, sizeof (start));
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
380 start.cb = sizeof (start);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
381
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
382 if (CreateProcess (progname, cmdline, &sec_attrs, NULL, TRUE,
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
383 0, NULL, NULL, &start, &child))
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
384 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
385 /* wait for completion and pass on return code */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
386 WaitForSingleObject (child.hProcess, INFINITE);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
387 GetExitCodeProcess (child.hProcess, &rc);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
388 CloseHandle (child.hThread);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
389 CloseHandle (child.hProcess);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
390 child.hProcess = NULL;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
391 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
392
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
393 return (int) rc;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
394 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
395
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
396 /******* Main program ********************************************/
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
397
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
398 int
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
399 main (int argc, char ** argv)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
400 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
401 int rc;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
402 int need_shell;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
403 char * cmdline;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
404 char * progname;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
405 int envsize;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
406 char modname[MAX_PATH];
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
407 char path[MAX_PATH];
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
408
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
409
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
410 interactive = TRUE;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
411
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
412 SetConsoleCtrlHandler ((PHANDLER_ROUTINE) console_event_handler, TRUE);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
413
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
414 /* We serve double duty: we can be called either as a proxy for the
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
415 real shell (that is, because we are defined to be the user shell),
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
416 or in our role as a helper application for running DOS programs.
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
417 In the former case, we interpret the command line options as if we
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
418 were a Unix shell, but in the latter case we simply pass our
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
419 command line to CreateProcess. We know which case we are dealing
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
420 with by whether argv[0] refers to ourself or to some other program.
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
421 (This relies on an arcane feature of CreateProcess, where we can
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
422 specify cmdproxy as the module to run, but specify a different
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
423 program in the command line - the MSVC startup code sets argv[0]
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
424 from the command line.) */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
425
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
426 if (!GetModuleFileName (NULL, modname, sizeof (modname)))
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
427 fail ("GetModuleFileName failed");
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
428
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
429 /* Although Emacs always sets argv[0] to an absolute pathname, we
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
430 might get run in other ways as well, so convert argv[0] to an
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
431 absolute name before comparing to the module name. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
432 if (!SearchPath (NULL, argv[0], ".exe", sizeof (path), path, &progname)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
433 || stricmp (modname, path) != 0)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
434 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
435 /* We are being used as a helper to run a DOS app; just pass
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
436 command line to DOS app without change. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
437 /* TODO: fill in progname. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
438 return spawn (NULL, GetCommandLine ());
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
439 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
440
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
441 /* Process command line. If running interactively (-c or /c not
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
442 specified) then spawn a real command shell, passing it the command
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
443 line arguments.
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
444
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
445 If not running interactively, then attempt to execute the specified
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
446 command directly. If necessary, spawn a real shell to execute the
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
447 command.
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
448
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
449 */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
450
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
451 progname = NULL;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
452 cmdline = NULL;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
453 /* If no args, spawn real shell for interactive use. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
454 need_shell = TRUE;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
455 interactive = TRUE;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
456 /* Ask for a reasonable size environment for command.com. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
457 envsize = 1024;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
458
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
459 while (--argc > 0)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
460 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
461 ++argv;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
462 /* Only support single letter switches (except for -e); allow / as
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
463 switch char for compatability with cmd.exe. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
464 if ( ((*argv)[0] == '-' || (*argv)[0] == '/')
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
465 && (*argv)[1] != '\0' && (*argv)[2] == '\0' )
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
466 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
467 if ( ((*argv)[1] == 'c') && ((*argv)[2] == '\0') )
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
468 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
469 if (--argc == 0)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
470 fail ("error: expecting arg for %s", *argv);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
471 cmdline = *(++argv);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
472 interactive = FALSE;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
473 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
474 else if ( ((*argv)[1] == 'i') && ((*argv)[2] == '\0') )
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
475 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
476 if (cmdline)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
477 warn ("warning: %s ignored because of -c", *argv);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
478 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
479 else if ( ((*argv)[1] == 'e') && ((*argv)[2] == ':') )
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
480 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
481 envsize = atoi (*argv + 3);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
482 /* Enforce a reasonable minimum size. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
483 if (envsize < 256)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
484 envsize = 256;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
485 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
486 else
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
487 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
488 warn ("warning: unknown option %s ignored", *argv);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
489 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
490 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
491 else
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
492 break;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
493 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
494
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
495 /* If -c option, determine if we must spawn a real shell, or if we can
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
496 execute the command directly ourself. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
497 if (cmdline)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
498 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
499 /* If no redirection or piping, and if program can be found, then
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
500 run program directly. Otherwise invoke a real shell. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
501
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
502 static char copout_chars[] = "|<>&";
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
503
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
504 if (strpbrk (cmdline, copout_chars) == NULL)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
505 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
506 char *args;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
507
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
508 /* The program name is the first token of cmdline. Since
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
509 filenames cannot legally contain embedded quotes, the value
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
510 of escape_char doesn't matter. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
511 args = cmdline;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
512 if (!get_next_token (path, &args))
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
513 fail ("error: no program name specified.\n");
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
514
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
515 canon_filename (path);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
516 progname = make_absolute (path);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
517
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
518 /* If we found the program, run it directly (if not found it
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
519 might be an internal shell command, so don't fail). */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
520 if (progname != NULL)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
521 need_shell = FALSE;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
522 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
523 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
524
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
525 if (need_shell)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
526 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
527 char * p;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
528
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
529 progname = getenv ("COMSPEC");
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
530 if (!progname)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
531 fail ("error: COMSPEC is not set");
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
532
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
533 canon_filename (progname);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
534 progname = make_absolute (progname);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
535
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
536 if (progname == NULL || strchr (progname, '\\') == NULL)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
537 fail ("make_absolute failed");
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
538
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
539 if (cmdline)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
540 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
541 /* Convert to syntax expected by cmd.exe/command.com for
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
542 running non-interactively. Always quote program name in
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
543 case path contains spaces (fortunately it can't contain
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
544 quotes, since they are illegal in path names). */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
545 wsprintf (p = alloca (strlen (cmdline) + strlen (progname) + 7),
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
546 "\"%s\" /c %s", progname, cmdline);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
547 cmdline = p;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
548 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
549 else
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
550 {
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
551 /* Provide dir arg expected by command.com when first started
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
552 interactively (the "command search path"). cmd.exe does
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
553 not require it, but accepts it silently - presumably other
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
554 DOS compatible shells do the same. To avoid potential
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
555 problems with spaces in command dir (which cannot be quoted
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
556 - command.com doesn't like it), we always use the 8.3 form. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
557 GetShortPathName (progname, path, sizeof (path));
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
558 p = strrchr (path, '\\');
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
559 /* Trailing slash is acceptable. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
560 p++;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
561
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
562 /* Set environment size - again cmd.exe ignores this silently. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
563 wsprintf (p, " /e:%d", envsize);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
564
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
565 /* Quote progname in case it contains spaces. */
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
566 wsprintf (cmdline = alloca (strlen (progname) + strlen (path) + 4),
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
567 "\"%s\" %s", progname, path);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
568 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
569 }
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
570
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
571 if (!progname)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
572 fail ("Internal error: program name not defined\n");
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
573
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
574 if (!cmdline)
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
575 cmdline = progname;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
576
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
577 rc = spawn (progname, cmdline);
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
578
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
579 return rc;
|
Geoff Voelker <voelker@cs.washington.edu>
parents:
diff
changeset
|
580 }
|