source: trunk/dll/pathutil.c@ 1248

Last change on this file since 1248 was 1248, checked in by Gregg Young, 17 years ago

Cleanup of NormalizeCmdLine changes

File size: 12.3 KB
Line 
1
2/***********************************************************************
3
4 $Id: $
5
6 Path handling utility functions
7
8 Copyright (c) 1993-98 M. Kimes
9 Copyright (c) 2001, 2008 Steven H. Levine
10
11 05 Jan 08 SHL Move from arccnrs.c and comp.c to here
12 06 Jan 08 GKY Add NormalizeCmdLine to check program strings on entry
13 29 Feb 08 GKY Changes to enable user settable command line length
14 15 Oct 08 GKY Fix NormalizeCmdLine to check all 5 executible extensions when no extension provided;
15 use searchapath to check for existance of file types not checked by DosQAppType;
16 close DosFind.
17
18***********************************************************************/
19
20#include <stdlib.h>
21#include <string.h>
22
23#define INCL_WIN
24#define INCL_DOS
25#define INCL_LONGLONG
26
27#include "fm3dll.h" // needs_quoting
28#include "notebook.h" // Data declaration(s)
29#include "init.h" // Data declaration(s)
30#include "fm3str.h"
31#include "srchpath.h" // searchapath
32#include "pathutil.h"
33#include "strips.h" // remove_first_occurence_of_character
34#include "valid.h" // needs_quoting
35#include "errutil.h" // Dos_Error...
36#include "strutil.h" // GetPString
37#include "wrappers.h" // xmalloc
38#include "fortify.h"
39
40static PSZ pszSrcFile = __FILE__;
41
42// #pragma data_seg(DATA1)
43
44/**
45 * Build full path name in callers buffer given directory
46 * name and filename
47 * @param pszPathName points to drive/directory if not NULL
48 * @returns pointer to full path name in caller's buffer
49 * @note OK for pszFullPathName and pszPathName to point to same buffer
50 *
51 */
52
53PSZ BldFullPathName(PSZ pszFullPathName, PSZ pszPathName, PSZ pszFileName)
54{
55 UINT c = pszPathName ? strlen(pszPathName) : 0;
56 if (c > 0) {
57 memcpy(pszFullPathName, pszPathName, c);
58 if (pszFullPathName[c - 1] != '\\')
59 pszFullPathName[c++] = '\\';
60 }
61 strcpy(pszFullPathName + c, pszFileName);
62 return pszFullPathName;
63}
64
65/**
66 * Build quoted full path name in callers buffer given
67 * directory name and filename
68 * @param pszPathName points to drive/directory if not NULL
69 * @returns pointer to quoted path name in caller's buffer
70 */
71
72PSZ BldQuotedFullPathName(PSZ pszFullPathName, PSZ pszPathName, PSZ pszFileName)
73{
74 UINT c = pszPathName ? strlen(pszPathName) : 0;
75 BOOL q = needs_quoting(pszPathName) || needs_quoting(pszFileName);
76 PSZ psz = pszFullPathName;
77
78 if (q)
79 *psz++ = '"';
80 if (c > 0) {
81 memcpy(psz, pszPathName, c);
82 psz += c;
83 if (*(psz - 1) != '\\')
84 *psz++ = '\\';
85 }
86 strcpy(psz, pszFileName);
87 if (q) {
88 psz += strlen(psz);
89 *psz++ = '"';
90 *psz = 0;
91 }
92 return pszFullPathName;
93}
94
95/**
96 * Build quoted full path name in callers buffer given a filename
97 * @returns pointer to quoted file name in caller's buffer
98 */
99
100PSZ BldQuotedFileName(PSZ pszQuotedFileName, PSZ pszFileName)
101{
102 BOOL q = needs_quoting(pszFileName);
103 PSZ psz = pszQuotedFileName;
104
105 if (q)
106 *psz++ = '"';
107 strcpy(psz, pszFileName);
108 if (q) {
109 psz += strlen(psz);
110 *psz++ = '"';
111 *psz = 0;
112 }
113 return pszQuotedFileName;
114}
115
116/** NormalizeCmdLine
117 * Checks a command line for common errors (missing quotes, missing extension,
118 * no space between exe and args etc) Also check for the existance of the file
119 * and checks .com and .exe file headers.
120 * Command line passed as pszCmdLine_
121 * A pointer to a buffer of the size MaxComLineStrg should be supplied in
122 * pszWorkBuf. This is where the quoted etc as necessary command
123 * line string will be returned.
124 */
125
126PCSZ NormalizeCmdLine(PSZ pszWorkBuf, PSZ pszCmdLine_)
127{
128 char *szCmdLine, *szArgs;
129 char *offset = '\0', *offsetexe, *offsetcom, *offsetcmd, *offsetbtm, *offsetbat;
130 APIRET ret;
131 ULONG ulAppType;
132 char *pszChar;
133 char *FullPath;
134 PSZ pszNewCmdLine = pszWorkBuf;
135
136 szCmdLine = xmalloc(MaxComLineStrg, pszSrcFile, __LINE__);
137 if (!szCmdLine)
138 return pszCmdLine_; //already complained
139 szArgs = xmalloc(MaxComLineStrg, pszSrcFile, __LINE__);
140 if (!szArgs) {
141 free(szCmdLine);
142 return pszCmdLine_; //already complained
143 }
144 bstrip(pszCmdLine_);
145 memset(pszWorkBuf, 0, MaxComLineStrg);
146 strcpy(szCmdLine, pszCmdLine_);
147 if (szCmdLine[0] != '\0') {
148 offsetexe = strstr(strlwr(pszCmdLine_), ".exe");
149 offsetcmd = strstr(strlwr(pszCmdLine_), ".cmd");
150 offsetcom = strstr(strlwr(pszCmdLine_), ".com");
151 offsetbtm = strstr(strlwr(pszCmdLine_), ".btm");
152 offsetbat = strstr(strlwr(pszCmdLine_), ".bat");
153 if (offsetexe)
154 offset = offsetexe;
155 else {
156 if (offsetcom)
157 offset = offsetcom;
158 else {
159 if (offsetcmd)
160 offset = offsetcmd;
161 else {
162 if (offsetbtm)
163 offset = offsetbtm;
164 else {
165 if (offsetbat)
166 offset = offsetexe;
167 }
168 }
169 }
170 }
171 if (offset) {
172 szCmdLine[offset + 4 - pszCmdLine_] = '\0';
173 strcpy(szArgs, &pszCmdLine_[offset + 4 - pszCmdLine_]);
174 while (strchr(szCmdLine, '\"'))
175 remove_first_occurence_of_character("\"", szCmdLine);
176 if ((szArgs[0] == '\"' && szArgs[1] == ' ') ||
177 !strstr(pszCmdLine_, "\\:")||
178 strchr(szArgs, '\"') == strrchr(szArgs, '\"'))
179 remove_first_occurence_of_character("\"", szArgs);
180 if (strchr(szArgs, '\"') != strrchr(szArgs, '\"'))
181 saymsg(MB_OK, HWND_DESKTOP,
182 NullStr,
183 GetPString(IDS_QUOTESINARGSTEXT),
184 pszCmdLine_);
185 if (!offsetexe && !offsetcom) {
186 FullPath = searchapath("PATH", szCmdLine);
187 if (*FullPath)
188 ret = 0;
189 }
190 else
191 ret = DosQueryAppType(szCmdLine, &ulAppType);
192 BldQuotedFileName(pszNewCmdLine, szCmdLine);
193 //printf("%d A", ret); fflush(stdout);
194 if (ret) {
195 ret = saymsg(MB_YESNO,
196 HWND_DESKTOP,
197 NullStr,
198 GetPString(IDS_PROGRAMNOTFOUNDTEXT),
199 pszCmdLine_);
200 if (ret == MBID_YES){
201 if (szArgs[0] != ' ')
202 strcat(pszNewCmdLine, " ");
203 strcat(pszNewCmdLine, szArgs);
204 }
205 else{
206 fCancelAction = TRUE;
207 pszNewCmdLine = pszCmdLine_;
208 }
209 }
210 else{
211 if (szArgs[0] != ' ')
212 strcat(pszNewCmdLine, " ");
213 strcat(pszNewCmdLine, szArgs);
214 }
215
216 }
217 // if it doesn't have an extension try it with all the standard ones and add if found
218 else if (szCmdLine && (!strchr(szCmdLine, '.') ||
219 strrchr(szCmdLine, '.' ) < strrchr(szCmdLine, '\\'))) {
220 if (!strchr(szCmdLine, ' ')) {
221 // strip quotes readded by BuildQuotedFileName
222 while (strchr(szCmdLine, '\"'))
223 remove_first_occurence_of_character("\"", szCmdLine);
224 ret = DosQueryAppType(szCmdLine, &ulAppType); // exe automatically appended
225 if (!ret)
226 strcat(szCmdLine, ".exe");
227 else {
228 strcat(szCmdLine, ".com");
229 ret = DosQueryAppType(szCmdLine, &ulAppType);
230 if (ret) {
231 offset = strrchr(szCmdLine, '.' );
232 *offset = 0;
233 strcat(szCmdLine, ".cmd");
234 FullPath = searchapath("PATH", szCmdLine);
235 if (*FullPath)
236 ret = 0;
237 else {
238 *offset = 0;
239 strcat(szCmdLine, ".bat");
240 FullPath = searchapath("PATH", szCmdLine);
241 if (*FullPath)
242 ret = 0;
243 else {
244 *offset = 0;
245 strcat(szCmdLine, ".bmt");
246 FullPath = searchapath("PATH", szCmdLine);
247 if (*FullPath)
248 ret = 0;
249 }
250 }
251 }
252 }
253 //printf("%d", ret); fflush(stdout);
254 }
255 else {
256 pszChar = szCmdLine;
257 while (pszChar) {
258 while (strchr(szCmdLine, '\"'))
259 remove_first_occurence_of_character("\"", szCmdLine);
260 if (*pszChar == ' ') { //test at every space for the end of the filename
261 *pszChar = '\0';
262 ret = DosQueryAppType(szCmdLine, &ulAppType);
263 if (!ret) {
264 strcat(szCmdLine, ".exe");
265 break;
266 }
267 else {
268 strcat(szCmdLine, ".com");
269 ret = DosQueryAppType(szCmdLine, &ulAppType);
270 if (ret) {
271 offset = strrchr(szCmdLine, '.' );
272 *offset = 0;
273 strcat(szCmdLine, ".cmd");
274 FullPath = searchapath("PATH", szCmdLine);
275 if (*FullPath) {
276 ret = 0;
277 break;
278 }
279 else {
280 *offset = 0;
281 strcat(szCmdLine, ".bat");
282 FullPath = searchapath("PATH", szCmdLine);
283 if (*FullPath) {
284 ret = 0;
285 break;
286 }
287 else {
288 *offset = 0;
289 strcat(szCmdLine, ".bmt");
290 FullPath = searchapath("PATH", szCmdLine);
291 if (*FullPath) {
292 ret = 0;
293 break;
294 }
295 }
296 }
297 }
298 else
299 break;
300 }
301 //printf("%d %s\n", ret, szCmdLine); fflush(stdout);
302 }
303 strcpy(szCmdLine, pszCmdLine_);
304 pszChar++;
305 }
306 }
307 if (!ret){
308 BldQuotedFileName(pszNewCmdLine, szCmdLine);
309 strcpy(szArgs, pszCmdLine_ + strlen(szCmdLine) - 3);
310 if ((szArgs[0] == '\"' && szArgs[1] == ' ') ||
311 !strstr(pszCmdLine_, "\\:" ) ||
312 strchr(szArgs, '\"') == strrchr(szArgs, '\"'))
313 remove_first_occurence_of_character("\"", szArgs);
314 if (strchr(szArgs, '\"') != strrchr(szArgs, '\"'))
315 saymsg(MB_OK, HWND_DESKTOP,
316 NullStr,
317 GetPString(IDS_QUOTESINARGSTEXT),
318 pszCmdLine_);
319 if (szArgs[0] != ' ')
320 strcat(pszNewCmdLine, " ");
321 strcat(pszNewCmdLine, szArgs);
322 }
323 else { // fail if no extension can be found runemf2 requires one
324 ret = saymsg(MB_OK,
325 HWND_DESKTOP,
326 NullStr,
327 GetPString(IDS_PROGRAMNOTEXE2TEXT),
328 pszCmdLine_);
329 fCancelAction = TRUE;
330 pszNewCmdLine = pszCmdLine_;
331 }
332 }
333 else { // file has a nonstandard extension for executible
334 pszChar = strrchr(szCmdLine, '.');
335 while (pszChar && *pszChar !=' ') {
336 pszChar++;
337 }
338 *pszChar = '\0';
339 strcpy (szArgs, pszCmdLine_ + strlen(szCmdLine));
340 while (strchr(szCmdLine, '\"'))
341 remove_first_occurence_of_character("\"", szCmdLine);
342 if ((szArgs[0] == '\"' && szArgs[1] == ' ') ||
343 !strstr(pszCmdLine_, "\\:")||
344 strchr(szArgs, '\"') == strrchr(szArgs, '\"'))
345 remove_first_occurence_of_character("\"", szArgs);
346 if (strchr(szArgs, '\"') != strrchr(szArgs, '\"'))
347 saymsg(MB_OK, HWND_DESKTOP,
348 NullStr,
349 GetPString(IDS_QUOTESINARGSTEXT),
350 pszCmdLine_);
351 FullPath = searchapath("PATH", szCmdLine);
352 BldQuotedFileName(pszNewCmdLine, szCmdLine);
353 //printf("%d %s ", ret, szCmdLine); fflush(stdout);
354 if (!*FullPath) {
355 ret = saymsg(MB_YESNO,
356 HWND_DESKTOP,
357 NullStr,
358 GetPString(IDS_PROGRAMNOTFOUNDTEXT),
359 pszCmdLine_);
360 if (ret == MBID_YES) {
361 if (szArgs[0] != ' ')
362 strcat(pszNewCmdLine, " ");
363 strcat(pszNewCmdLine, szArgs);
364 }
365 else {
366 fCancelAction = TRUE;
367 pszWorkBuf = pszCmdLine_;
368 }
369 }
370 else {
371 ret = saymsg(MB_YESNOCANCEL,
372 HWND_DESKTOP,
373 NullStr,
374 GetPString(IDS_PROGRAMNOTEXE3TEXT),
375 pszCmdLine_, pszNewCmdLine);
376 if (ret == MBID_YES){
377 if (szArgs[0] != ' ')
378 strcat(pszNewCmdLine, " ");
379 strcat(pszNewCmdLine, szArgs);
380 }
381 if (ret == MBID_CANCEL){
382 fCancelAction = TRUE;
383 pszNewCmdLine = pszCmdLine_;
384 }
385 }
386 }
387 }
388 free(szArgs);
389 free(szCmdLine);
390 return pszWorkBuf;
391}
392
393#pragma alloc_text(PATHUTIL,BldFullPathName)
394#pragma alloc_text(PATHUTIL,BldQuotedFileName)
395#pragma alloc_text(PATHUTIL,BldQuotedFullPathName)
396#pragma alloc_text(PATHUTIL,NormalizeCmdLine)
Note: See TracBrowser for help on using the repository browser.