source: trunk/dll/pathutil.c@ 1699

Last change on this file since 1699 was 1699, checked in by Steven Levine, 12 years ago

Update comments

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