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
RevLine 
[907]1
2/***********************************************************************
3
[1323]4 $Id: pathutil.c 1761 2014-03-21 23:29:52Z stevenhl $
[907]5
6 Path handling utility functions
7
8 Copyright (c) 1993-98 M. Kimes
[1394]9 Copyright (c) 2001, 2009 Steven H. Levine
[907]10
11 05 Jan 08 SHL Move from arccnrs.c and comp.c to here
[920]12 06 Jan 08 GKY Add NormalizeCmdLine to check program strings on entry
[985]13 29 Feb 08 GKY Changes to enable user settable command line length
[1699]14 15 Oct 08 GKY Fix NormalizeCmdLine to check all 5 executable extensions when no extension provided;
[1394]15 use searchapath to check for existance of file types not checked by DosQAppType;
[1761]16 close DosFind.
[1439]17 28 Jun 09 GKY Added AddBackslashToPath() to remove repeatative code
[1480]18 12 Jul 09 GKY Add xDosQueryAppType and xDosAlloc... to allow FM/2 to load in high memory
[1545]19 23 Oct 10 GKY Add ForwardslashToBackslash function to streamline code
[1632]20 17 Sep 11 GKY Fix commandline quoting issues
[1750]21 01 Mar 14 JBS Ticket #524: Made "searchapath" thread-safe. Function names and signatures were changed.
[1761]22 So calls to these functions had to be changed.
23 21 Mar 14 SHL Add IsAbsolutePath
[907]24
25***********************************************************************/
26
[1039]27#include <stdlib.h>
[907]28#include <string.h>
[1761]29#include <ctype.h>
[907]30
31#define INCL_WIN
[920]32#define INCL_DOS
[907]33#define INCL_LONGLONG
34
[1185]35#include "fm3dll.h" // needs_quoting
[1211]36#include "notebook.h" // Data declaration(s)
37#include "init.h" // Data declaration(s)
[1185]38#include "fm3str.h"
[1750]39#include "srchpath.h" // Search*Path*ForFile
[907]40#include "pathutil.h"
[1161]41#include "strips.h" // remove_first_occurence_of_character
[1185]42#include "valid.h" // needs_quoting
[920]43#include "errutil.h" // Dos_Error...
44#include "strutil.h" // GetPString
[1185]45#include "wrappers.h" // xmalloc
[1039]46#include "fortify.h"
[1398]47#include "stristr.h" //stristr
[907]48
[985]49static PSZ pszSrcFile = __FILE__;
50
[1545]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
[1438]64PSZ AddBackslashToPath(PSZ pszPathName)
65{
66 if (pszPathName[strlen(pszPathName) - 1] != '\\')
67 strcat(pszPathName, PCSZ_BACKSLASH);
68 return pszPathName;
69}
70
[907]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
[1398]82PSZ BldFullPathName(PSZ pszFullPathName, PCSZ pszPathName, PCSZ pszFileName)
[907]83{
84 UINT c = pszPathName ? strlen(pszPathName) : 0;
85 if (c > 0) {
[1568]86 if (pszFullPathName != pszPathName)
87 memcpy(pszFullPathName, pszPathName, c);
[907]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
[1398]102PSZ BldQuotedFullPathName(PSZ pszFullPathName, PCSZ pszPathName, PCSZ pszFileName)
[907]103{
104 UINT c = pszPathName ? strlen(pszPathName) : 0;
[1161]105 BOOL q = needs_quoting(pszPathName) || needs_quoting(pszFileName);
[907]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
[1394]130PSZ BldQuotedFileName(PSZ pszQuotedFileName, PCSZ pszFileName)
[907]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
[1761]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
[920]166/** NormalizeCmdLine
167 * Checks a command line for common errors (missing quotes, missing extension,
[1248]168 * no space between exe and args etc) Also check for the existance of the file
169 * and checks .com and .exe file headers.
[920]170 * Command line passed as pszCmdLine_
[985]171 * A pointer to a buffer of the size MaxComLineStrg should be supplied in
[920]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{
[985]178 char *szCmdLine, *szArgs;
[920]179 char *offset = '\0', *offsetexe, *offsetcom, *offsetcmd, *offsetbtm, *offsetbat;
180 APIRET ret;
181 ULONG ulAppType;
182 char *pszChar;
183 PSZ pszNewCmdLine = pszWorkBuf;
184
[985]185 szCmdLine = xmalloc(MaxComLineStrg, pszSrcFile, __LINE__);
186 if (!szCmdLine)
187 return pszCmdLine_; //already complained
188 szArgs = xmalloc(MaxComLineStrg, pszSrcFile, __LINE__);
189 if (!szArgs) {
[1039]190 free(szCmdLine);
[985]191 return pszCmdLine_; //already complained
192 }
[920]193 bstrip(pszCmdLine_);
[985]194 memset(pszWorkBuf, 0, MaxComLineStrg);
[920]195 strcpy(szCmdLine, pszCmdLine_);
196 if (szCmdLine[0] != '\0') {
[1398]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);
[920]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] == ' ') ||
[1631]226 (!strstr(pszCmdLine_, "\\:") && strchr(szArgs, '\"') &&
227 strchr(szArgs, '\"') == strrchr(szArgs, '\"')))
[920]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_);
[1247]234 if (!offsetexe && !offsetcom) {
[1761]235 if (!SearchPathForFile(PCSZ_PATH, szCmdLine, NULL))
236 ret = 0;
[920]237 }
238 else
[1439]239 ret = xDosQueryAppType(szCmdLine, &ulAppType);
[920]240 BldQuotedFileName(pszNewCmdLine, szCmdLine);
241 if (ret) {
[1394]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);
[920]251 }
[1394]252 else{
253 fCancelAction = TRUE;
254 pszNewCmdLine = pszCmdLine_;
255 }
[920]256 }
257 else{
[1394]258 if (szArgs[0] != ' ')
259 strcat(pszNewCmdLine, " ");
260 strcat(pszNewCmdLine, szArgs);
[920]261 }
262
263 }
[1247]264 // if it doesn't have an extension try it with all the standard ones and add if found
[920]265 else if (szCmdLine && (!strchr(szCmdLine, '.') ||
[1247]266 strrchr(szCmdLine, '.' ) < strrchr(szCmdLine, '\\'))) {
[920]267 if (!strchr(szCmdLine, ' ')) {
[1394]268 // strip quotes readded by BuildQuotedFileName
[920]269 while (strchr(szCmdLine, '\"'))
270 remove_first_occurence_of_character("\"", szCmdLine);
[1439]271 ret = xDosQueryAppType(szCmdLine, &ulAppType); // exe automatically appended
[1394]272 if (!ret)
[1398]273 strcat(szCmdLine, PCSZ_DOTEXE);
[1394]274 else {
[1398]275 strcat(szCmdLine, PCSZ_DOTCOM);
[1439]276 ret = xDosQueryAppType(szCmdLine, &ulAppType);
[1394]277 if (ret) {
278 offset = strrchr(szCmdLine, '.' );
279 *offset = 0;
[1398]280 strcat(szCmdLine, PCSZ_DOTCMD);
[1750]281 if (!SearchPathForFile(PCSZ_PATH, szCmdLine, NULL))
[1394]282 ret = 0;
283 else {
284 *offset = 0;
[1398]285 strcat(szCmdLine, PCSZ_DOTBAT);
[1750]286 if (!SearchPathForFile(PCSZ_PATH, szCmdLine, NULL))
[1394]287 ret = 0;
288 else {
289 *offset = 0;
[1398]290 strcat(szCmdLine, PCSZ_DOTBTM);
[1750]291 if (!SearchPathForFile(PCSZ_PATH, szCmdLine, NULL))
[1394]292 ret = 0;
293 }
294 }
295 }
296 }
[920]297 }
298 else {
299 pszChar = szCmdLine;
300 while (pszChar) {
301 while (strchr(szCmdLine, '\"'))
302 remove_first_occurence_of_character("\"", szCmdLine);
[1247]303 if (*pszChar == ' ') { //test at every space for the end of the filename
[920]304 *pszChar = '\0';
[1439]305 ret = xDosQueryAppType(szCmdLine, &ulAppType);
[1394]306 if (!ret) {
[1398]307 strcat(szCmdLine, PCSZ_DOTEXE);
[1394]308 break;
309 }
310 else {
[1398]311 strcat(szCmdLine, PCSZ_DOTCOM);
[1439]312 ret = xDosQueryAppType(szCmdLine, &ulAppType);
[1394]313 if (ret) {
314 offset = strrchr(szCmdLine, '.' );
315 *offset = 0;
[1398]316 strcat(szCmdLine, PCSZ_DOTCMD);
[1750]317 if (!SearchPathForFile(PCSZ_PATH, szCmdLine, NULL)) {
[1394]318 ret = 0;
319 break;
320 }
321 else {
322 *offset = 0;
[1398]323 strcat(szCmdLine, PCSZ_DOTBAT);
[1750]324 if (!SearchPathForFile(PCSZ_PATH, szCmdLine, NULL)) {
[1394]325 ret = 0;
326 break;
327 }
328 else {
329 *offset = 0;
[1398]330 strcat(szCmdLine, PCSZ_DOTBTM);
[1750]331 if (!SearchPathForFile(PCSZ_PATH, szCmdLine, NULL)) {
[1394]332 ret = 0;
333 break;
334 }
335 }
336 }
337 }
338 else
339 break;
340 }
[920]341 }
342 strcpy(szCmdLine, pszCmdLine_);
343 pszChar++;
344 }
345 }
346 if (!ret){
[1394]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);
[920]361 }
[1248]362 else { // fail if no extension can be found runemf2 requires one
[1394]363 ret = saymsg(MB_OK,
364 HWND_DESKTOP,
365 NullStr,
366 GetPString(IDS_PROGRAMNOTEXE2TEXT),
367 pszCmdLine_);
368 fCancelAction = TRUE;
369 pszNewCmdLine = pszCmdLine_;
[920]370 }
371 }
[1699]372 else { // file has a nonstandard extension for executable
[920]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);
[1750]391 if (SearchPathForFile(PCSZ_PATH, szCmdLine, NULL)) {
[920]392 ret = saymsg(MB_YESNO,
393 HWND_DESKTOP,
394 NullStr,
395 GetPString(IDS_PROGRAMNOTFOUNDTEXT),
396 pszCmdLine_);
397 if (ret == MBID_YES) {
[1394]398 if (szArgs[0] != ' ')
399 strcat(pszNewCmdLine, " ");
400 strcat(pszNewCmdLine, szArgs);
[920]401 }
402 else {
403 fCancelAction = TRUE;
404 pszWorkBuf = pszCmdLine_;
405 }
406 }
[1248]407 else {
408 ret = saymsg(MB_YESNOCANCEL,
[1394]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 }
[920]422 }
423 }
424 }
[1039]425 free(szArgs);
426 free(szCmdLine);
[920]427 return pszWorkBuf;
428}
429
[907]430#pragma alloc_text(PATHUTIL,BldFullPathName)
431#pragma alloc_text(PATHUTIL,BldQuotedFileName)
432#pragma alloc_text(PATHUTIL,BldQuotedFullPathName)
[920]433#pragma alloc_text(PATHUTIL,NormalizeCmdLine)
[1761]434#pragma alloc_text(PATHUTIL,IsAbsolutePath)
Note: See TracBrowser for help on using the repository browser.