source: trunk/dll/pathutil.c@ 1247

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

Fix issues with NormalizeCmdLine; it now uses searchapath to check for nonexe files in the path, it tries all 5 defined executible extensions when no exetension is provided, it closes dosfind, eliminates extra error message on failure to find extensionless file in commands, improved error message for extensionless file.

File size: 12.8 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)
119 * Command line passed as pszCmdLine_
120 * A pointer to a buffer of the size MaxComLineStrg should be supplied in
121 * pszWorkBuf. This is where the quoted etc as necessary command
122 * line string will be returned.
123 */
124
125PCSZ NormalizeCmdLine(PSZ pszWorkBuf, PSZ pszCmdLine_)
126{
127 char *szCmdLine, *szArgs;
128 char *offset = '\0', *offsetexe, *offsetcom, *offsetcmd, *offsetbtm, *offsetbat;
129 APIRET ret;
130 ULONG ulAppType;
131 char *pszChar;
132 char *FullPath;
133 FILEFINDBUF3 FindBuffer;
134 ULONG ulResultBufLen = sizeof(FILEFINDBUF3);
135 HDIR hdirFindHandle = HDIR_CREATE;
136 ULONG ulFindCount = 1;
137 PSZ pszNewCmdLine = pszWorkBuf;
138
139 szCmdLine = xmalloc(MaxComLineStrg, pszSrcFile, __LINE__);
140 if (!szCmdLine)
141 return pszCmdLine_; //already complained
142 szArgs = xmalloc(MaxComLineStrg, pszSrcFile, __LINE__);
143 if (!szArgs) {
144 free(szCmdLine);
145 return pszCmdLine_; //already complained
146 }
147 bstrip(pszCmdLine_);
148 memset(pszWorkBuf, 0, MaxComLineStrg);
149 strcpy(szCmdLine, pszCmdLine_);
150 if (szCmdLine[0] != '\0') {
151 offsetexe = strstr(strlwr(pszCmdLine_), ".exe");
152 offsetcmd = strstr(strlwr(pszCmdLine_), ".cmd");
153 offsetcom = strstr(strlwr(pszCmdLine_), ".com");
154 offsetbtm = strstr(strlwr(pszCmdLine_), ".btm");
155 offsetbat = strstr(strlwr(pszCmdLine_), ".bat");
156 if (offsetexe)
157 offset = offsetexe;
158 else {
159 if (offsetcom)
160 offset = offsetcom;
161 else {
162 if (offsetcmd)
163 offset = offsetcmd;
164 else {
165 if (offsetbtm)
166 offset = offsetbtm;
167 else {
168 if (offsetbat)
169 offset = offsetexe;
170 }
171 }
172 }
173 }
174 if (offset) {
175 szCmdLine[offset + 4 - pszCmdLine_] = '\0';
176 strcpy(szArgs, &pszCmdLine_[offset + 4 - pszCmdLine_]);
177 while (strchr(szCmdLine, '\"'))
178 remove_first_occurence_of_character("\"", szCmdLine);
179 if ((szArgs[0] == '\"' && szArgs[1] == ' ') ||
180 !strstr(pszCmdLine_, "\\:")||
181 strchr(szArgs, '\"') == strrchr(szArgs, '\"'))
182 remove_first_occurence_of_character("\"", szArgs);
183 if (strchr(szArgs, '\"') != strrchr(szArgs, '\"'))
184 saymsg(MB_OK, HWND_DESKTOP,
185 NullStr,
186 GetPString(IDS_QUOTESINARGSTEXT),
187 pszCmdLine_);
188 if (!offsetexe && !offsetcom) {
189 ret = DosFindFirst(szCmdLine, &hdirFindHandle, FILE_NORMAL, &FindBuffer,
190 ulResultBufLen, &ulFindCount, FIL_STANDARD);
191 if (ret) {
192 FullPath = searchapath("PATH", szCmdLine);
193 if (*FullPath != 0)
194 ret = 0;
195 }
196 DosFindClose(hdirFindHandle);
197 }
198 else
199 ret = DosQueryAppType(szCmdLine, &ulAppType);
200 BldQuotedFileName(pszNewCmdLine, szCmdLine);
201 //printf("%d A", ret); fflush(stdout);
202 if (ret) {
203 ret = saymsg(MB_YESNO,
204 HWND_DESKTOP,
205 NullStr,
206 GetPString(IDS_PROGRAMNOTFOUNDTEXT),
207 pszCmdLine_);
208 if (ret == MBID_YES){
209 if (szArgs[0] != ' ')
210 strcat(pszNewCmdLine, " ");
211 strcat(pszNewCmdLine, szArgs);
212 }
213 else{
214 fCancelAction = TRUE;
215 pszNewCmdLine = pszCmdLine_;
216 }
217 }
218 else{
219 if (szArgs[0] != ' ')
220 strcat(pszNewCmdLine, " ");
221 strcat(pszNewCmdLine, szArgs);
222 }
223
224 }
225 // if it doesn't have an extension try it with all the standard ones and add if found
226 else if (szCmdLine && (!strchr(szCmdLine, '.') ||
227 strrchr(szCmdLine, '.' ) < strrchr(szCmdLine, '\\'))) {
228 if (!strchr(szCmdLine, ' ')) {
229 // strip quotes readded by BuildQuotedFileName
230 while (strchr(szCmdLine, '\"'))
231 remove_first_occurence_of_character("\"", szCmdLine);
232 ret = DosQueryAppType(szCmdLine, &ulAppType);
233 if (!ret)
234 strcat(szCmdLine, ".exe");
235 else {
236 strcat(szCmdLine, ".com");
237 ret = DosQueryAppType(szCmdLine, &ulAppType);
238 if (ret) {
239 offset = strrchr(szCmdLine, '.' );
240 *offset = 0;
241 strcat(szCmdLine, ".cmd");
242 FullPath = searchapath("PATH", szCmdLine);
243 if (*FullPath != 0)
244 ret = 0;
245 else {
246 offset = strrchr(szCmdLine, '.' );
247 *offset = 0;
248 strcat(szCmdLine, ".bat");
249 FullPath = searchapath("PATH", szCmdLine);
250 if (*FullPath != 0)
251 ret = 0;
252 else {
253 offset = strrchr(szCmdLine, '.' );
254 *offset = 0;
255 strcat(szCmdLine, ".bmt");
256 FullPath = searchapath("PATH", szCmdLine);
257 if (*FullPath != 0)
258 ret = 0;
259 }
260 }
261 }
262 }
263 //printf("%d", ret); fflush(stdout);
264 }
265 else {
266 pszChar = szCmdLine;
267 while (pszChar) {
268 while (strchr(szCmdLine, '\"'))
269 remove_first_occurence_of_character("\"", szCmdLine);
270 if (*pszChar == ' ') { //test at every space for the end of the filename
271 *pszChar = '\0';
272 ret = DosQueryAppType(szCmdLine, &ulAppType);
273 if (!ret) {
274 strcat(szCmdLine, ".exe");
275 break;
276 }
277 else {
278 strcat(szCmdLine, ".com");
279 ret = DosQueryAppType(szCmdLine, &ulAppType);
280 if (ret) {
281 offset = strrchr(szCmdLine, '.' );
282 *offset = 0;
283 strcat(szCmdLine, ".cmd");
284 FullPath = searchapath("PATH", szCmdLine);
285 if (*FullPath != 0) {
286 ret = 0;
287 break;
288 }
289 else {
290 offset = strrchr(szCmdLine, '.' );
291 *offset = 0;
292 strcat(szCmdLine, ".bat");
293 FullPath = searchapath("PATH", szCmdLine);
294 if (*FullPath != 0) {
295 ret = 0;
296 break;
297 }
298 else {
299 offset = strrchr(szCmdLine, '.' );
300 *offset = 0;
301 strcat(szCmdLine, ".bmt");
302 FullPath = searchapath("PATH", szCmdLine);
303 if (*FullPath != 0) {
304 ret = 0;
305 break;
306 }
307 }
308 }
309 }
310 else
311 break;
312 }
313 //printf("%d %s\n", ret, szCmdLine); fflush(stdout);
314 }
315 strcpy(szCmdLine, pszCmdLine_);
316 pszChar++;
317 }
318 }
319 if (!ret){
320 BldQuotedFileName(pszNewCmdLine, szCmdLine);
321 strcpy(szArgs, pszCmdLine_ + strlen(szCmdLine) - 3);
322 if ((szArgs[0] == '\"' && szArgs[1] == ' ') ||
323 !strstr(pszCmdLine_, "\\:" ) ||
324 strchr(szArgs, '\"') == strrchr(szArgs, '\"'))
325 remove_first_occurence_of_character("\"", szArgs);
326 if (strchr(szArgs, '\"') != strrchr(szArgs, '\"'))
327 saymsg(MB_OK, HWND_DESKTOP,
328 NullStr,
329 GetPString(IDS_QUOTESINARGSTEXT),
330 pszCmdLine_);
331 if (szArgs[0] != ' ')
332 strcat(pszNewCmdLine, " ");
333 strcat(pszNewCmdLine, szArgs);
334 }
335 else { // fail if no extension can be found we require one
336 ret = saymsg(MB_OK,
337 HWND_DESKTOP,
338 NullStr,
339 GetPString(IDS_PROGRAMNOTEXE2TEXT),
340 pszCmdLine_);
341 fCancelAction = TRUE;
342 pszNewCmdLine = pszCmdLine_;
343 }
344 }
345 else { // file has a nonstandard extension for executible
346 pszChar = strrchr(szCmdLine, '.');
347 while (pszChar && *pszChar !=' ') {
348 pszChar++;
349 }
350 *pszChar = '\0';
351 strcpy (szArgs, pszCmdLine_ + strlen(szCmdLine));
352 while (strchr(szCmdLine, '\"'))
353 remove_first_occurence_of_character("\"", szCmdLine);
354 if ((szArgs[0] == '\"' && szArgs[1] == ' ') ||
355 !strstr(pszCmdLine_, "\\:")||
356 strchr(szArgs, '\"') == strrchr(szArgs, '\"'))
357 remove_first_occurence_of_character("\"", szArgs);
358 if (strchr(szArgs, '\"') != strrchr(szArgs, '\"'))
359 saymsg(MB_OK, HWND_DESKTOP,
360 NullStr,
361 GetPString(IDS_QUOTESINARGSTEXT),
362 pszCmdLine_);
363 ret = DosFindFirst(szCmdLine, &hdirFindHandle, FILE_NORMAL, &FindBuffer,
364 ulResultBufLen, &ulFindCount, FIL_STANDARD);
365 DosFindClose(hdirFindHandle);
366 BldQuotedFileName(pszNewCmdLine, szCmdLine);
367 //printf("%d %s ", ret, szCmdLine); fflush(stdout);
368 if (ret) {
369 ret = saymsg(MB_YESNO,
370 HWND_DESKTOP,
371 NullStr,
372 GetPString(IDS_PROGRAMNOTFOUNDTEXT),
373 pszCmdLine_);
374 if (ret == MBID_YES) {
375 if (szArgs[0] != ' ')
376 strcat(pszNewCmdLine, " ");
377 strcat(pszNewCmdLine, szArgs);
378 }
379 else {
380 fCancelAction = TRUE;
381 pszWorkBuf = pszCmdLine_;
382 }
383 }
384 ret = saymsg(MB_YESNOCANCEL,
385 HWND_DESKTOP,
386 NullStr,
387 GetPString(IDS_PROGRAMNOTEXE3TEXT),
388 pszCmdLine_, pszNewCmdLine);
389 if (ret == MBID_YES){
390 if (szArgs[0] != ' ')
391 strcat(pszNewCmdLine, " ");
392 strcat(pszNewCmdLine, szArgs);
393 }
394 if (ret == MBID_CANCEL){
395 fCancelAction = TRUE;
396 pszNewCmdLine = pszCmdLine_;
397 }
398 }
399 }
400 free(szArgs);
401 free(szCmdLine);
402 return pszWorkBuf;
403}
404
405#pragma alloc_text(PATHUTIL,BldFullPathName)
406#pragma alloc_text(PATHUTIL,BldQuotedFileName)
407#pragma alloc_text(PATHUTIL,BldQuotedFullPathName)
408#pragma alloc_text(PATHUTIL,NormalizeCmdLine)
Note: See TracBrowser for help on using the repository browser.