source: trunk/dll/pathutil.c@ 1750

Last change on this file since 1750 was 1750, checked in by John Small, 11 years ago

Ticket #524: Made "searchapath" thread-safe. Function names and signatures were changed.

So calls to these functions, direct and indirect, had to be changed.

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