source: trunk/dll/pathutil.c@ 1761

Last change on this file since 1761 was 1761, checked in by Steven Levine, 11 years ago

Implement IsAbsolutePath and modify SearchPathForFile to use

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