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
RevLine 
[907]1
2/***********************************************************************
3
[1323]4 $Id: pathutil.c 1699 2013-11-07 17:24:22Z 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;
[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
[907]21
22***********************************************************************/
23
[1039]24#include <stdlib.h>
[907]25#include <string.h>
26
27#define INCL_WIN
[920]28#define INCL_DOS
[907]29#define INCL_LONGLONG
30
[1185]31#include "fm3dll.h" // needs_quoting
[1211]32#include "notebook.h" // Data declaration(s)
33#include "init.h" // Data declaration(s)
[1185]34#include "fm3str.h"
[1247]35#include "srchpath.h" // searchapath
[907]36#include "pathutil.h"
[1161]37#include "strips.h" // remove_first_occurence_of_character
[1185]38#include "valid.h" // needs_quoting
[920]39#include "errutil.h" // Dos_Error...
40#include "strutil.h" // GetPString
[1185]41#include "wrappers.h" // xmalloc
[1039]42#include "fortify.h"
[1398]43#include "stristr.h" //stristr
[907]44
[985]45static PSZ pszSrcFile = __FILE__;
46
[1545]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
[1438]60PSZ AddBackslashToPath(PSZ pszPathName)
61{
62 if (pszPathName[strlen(pszPathName) - 1] != '\\')
63 strcat(pszPathName, PCSZ_BACKSLASH);
64 return pszPathName;
65}
66
[907]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
[1398]78PSZ BldFullPathName(PSZ pszFullPathName, PCSZ pszPathName, PCSZ pszFileName)
[907]79{
80 UINT c = pszPathName ? strlen(pszPathName) : 0;
81 if (c > 0) {
[1568]82 if (pszFullPathName != pszPathName)
83 memcpy(pszFullPathName, pszPathName, c);
[907]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
[1398]98PSZ BldQuotedFullPathName(PSZ pszFullPathName, PCSZ pszPathName, PCSZ pszFileName)
[907]99{
100 UINT c = pszPathName ? strlen(pszPathName) : 0;
[1161]101 BOOL q = needs_quoting(pszPathName) || needs_quoting(pszFileName);
[907]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
[1394]126PSZ BldQuotedFileName(PSZ pszQuotedFileName, PCSZ pszFileName)
[907]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
[920]142/** NormalizeCmdLine
143 * Checks a command line for common errors (missing quotes, missing extension,
[1248]144 * no space between exe and args etc) Also check for the existance of the file
145 * and checks .com and .exe file headers.
[920]146 * Command line passed as pszCmdLine_
[985]147 * A pointer to a buffer of the size MaxComLineStrg should be supplied in
[920]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{
[985]154 char *szCmdLine, *szArgs;
[920]155 char *offset = '\0', *offsetexe, *offsetcom, *offsetcmd, *offsetbtm, *offsetbat;
156 APIRET ret;
157 ULONG ulAppType;
158 char *pszChar;
[1247]159 char *FullPath;
[920]160 PSZ pszNewCmdLine = pszWorkBuf;
161
[985]162 szCmdLine = xmalloc(MaxComLineStrg, pszSrcFile, __LINE__);
163 if (!szCmdLine)
164 return pszCmdLine_; //already complained
165 szArgs = xmalloc(MaxComLineStrg, pszSrcFile, __LINE__);
166 if (!szArgs) {
[1039]167 free(szCmdLine);
[985]168 return pszCmdLine_; //already complained
169 }
[920]170 bstrip(pszCmdLine_);
[985]171 memset(pszWorkBuf, 0, MaxComLineStrg);
[920]172 strcpy(szCmdLine, pszCmdLine_);
173 if (szCmdLine[0] != '\0') {
[1398]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);
[920]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] == ' ') ||
[1631]203 (!strstr(pszCmdLine_, "\\:") && strchr(szArgs, '\"') &&
204 strchr(szArgs, '\"') == strrchr(szArgs, '\"')))
[920]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_);
[1247]211 if (!offsetexe && !offsetcom) {
[1398]212 FullPath = searchapath(PCSZ_PATH, szCmdLine);
[1394]213 if (*FullPath)
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);
259 FullPath = searchapath(PCSZ_PATH, szCmdLine);
[1394]260 if (*FullPath)
261 ret = 0;
262 else {
263 *offset = 0;
[1398]264 strcat(szCmdLine, PCSZ_DOTBAT);
265 FullPath = searchapath(PCSZ_PATH, szCmdLine);
[1394]266 if (*FullPath)
267 ret = 0;
268 else {
269 *offset = 0;
[1398]270 strcat(szCmdLine, PCSZ_DOTBTM);
271 FullPath = searchapath(PCSZ_PATH, szCmdLine);
[1394]272 if (*FullPath)
273 ret = 0;
274 }
275 }
276 }
277 }
[920]278 }
279 else {
280 pszChar = szCmdLine;
281 while (pszChar) {
282 while (strchr(szCmdLine, '\"'))
283 remove_first_occurence_of_character("\"", szCmdLine);
[1247]284 if (*pszChar == ' ') { //test at every space for the end of the filename
[920]285 *pszChar = '\0';
[1439]286 ret = xDosQueryAppType(szCmdLine, &ulAppType);
[1394]287 if (!ret) {
[1398]288 strcat(szCmdLine, PCSZ_DOTEXE);
[1394]289 break;
290 }
291 else {
[1398]292 strcat(szCmdLine, PCSZ_DOTCOM);
[1439]293 ret = xDosQueryAppType(szCmdLine, &ulAppType);
[1394]294 if (ret) {
295 offset = strrchr(szCmdLine, '.' );
296 *offset = 0;
[1398]297 strcat(szCmdLine, PCSZ_DOTCMD);
298 FullPath = searchapath(PCSZ_PATH, szCmdLine);
[1394]299 if (*FullPath) {
300 ret = 0;
301 break;
302 }
303 else {
304 *offset = 0;
[1398]305 strcat(szCmdLine, PCSZ_DOTBAT);
306 FullPath = searchapath(PCSZ_PATH, szCmdLine);
[1394]307 if (*FullPath) {
308 ret = 0;
309 break;
310 }
311 else {
312 *offset = 0;
[1398]313 strcat(szCmdLine, PCSZ_DOTBTM);
314 FullPath = searchapath(PCSZ_PATH, szCmdLine);
[1394]315 if (*FullPath) {
316 ret = 0;
317 break;
318 }
319 }
320 }
321 }
322 else
323 break;
324 }
[920]325 }
326 strcpy(szCmdLine, pszCmdLine_);
327 pszChar++;
328 }
329 }
330 if (!ret){
[1394]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);
[920]345 }
[1248]346 else { // fail if no extension can be found runemf2 requires one
[1394]347 ret = saymsg(MB_OK,
348 HWND_DESKTOP,
349 NullStr,
350 GetPString(IDS_PROGRAMNOTEXE2TEXT),
351 pszCmdLine_);
352 fCancelAction = TRUE;
353 pszNewCmdLine = pszCmdLine_;
[920]354 }
355 }
[1699]356 else { // file has a nonstandard extension for executable
[920]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_);
[1398]374 FullPath = searchapath(PCSZ_PATH, szCmdLine);
[920]375 BldQuotedFileName(pszNewCmdLine, szCmdLine);
[1248]376 if (!*FullPath) {
[920]377 ret = saymsg(MB_YESNO,
378 HWND_DESKTOP,
379 NullStr,
380 GetPString(IDS_PROGRAMNOTFOUNDTEXT),
381 pszCmdLine_);
382 if (ret == MBID_YES) {
[1394]383 if (szArgs[0] != ' ')
384 strcat(pszNewCmdLine, " ");
385 strcat(pszNewCmdLine, szArgs);
[920]386 }
387 else {
388 fCancelAction = TRUE;
389 pszWorkBuf = pszCmdLine_;
390 }
391 }
[1248]392 else {
393 ret = saymsg(MB_YESNOCANCEL,
[1394]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 }
[920]407 }
408 }
409 }
[1039]410 free(szArgs);
411 free(szCmdLine);
[920]412 return pszWorkBuf;
413}
414
[907]415#pragma alloc_text(PATHUTIL,BldFullPathName)
416#pragma alloc_text(PATHUTIL,BldQuotedFileName)
417#pragma alloc_text(PATHUTIL,BldQuotedFullPathName)
[920]418#pragma alloc_text(PATHUTIL,NormalizeCmdLine)
Note: See TracBrowser for help on using the repository browser.