source: trunk/dll/pathutil.c@ 1782

Last change on this file since 1782 was 1782, checked in by Gregg Young, 11 years ago

Addition code issues found based on cppcheck warnings

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