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
Line 
1
2/***********************************************************************
3
4 $Id: pathutil.c 1782 2014-06-28 21:34:01Z gyoung $
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 28 Jun 14 GKY Fix errors identified with CPPCheck;
25
26***********************************************************************/
27
28#include <stdlib.h>
29#include <string.h>
30#include <ctype.h>
31
32#define INCL_WIN
33#define INCL_DOS
34#define INCL_LONGLONG
35
36#include "fm3dll.h" // needs_quoting
37#include "notebook.h" // Data declaration(s)
38#include "init.h" // Data declaration(s)
39#include "fm3str.h"
40#include "srchpath.h" // Search*Path*ForFile
41#include "pathutil.h"
42#include "strips.h" // remove_first_occurence_of_character
43#include "valid.h" // needs_quoting
44#include "errutil.h" // Dos_Error...
45#include "strutil.h" // GetPString
46#include "wrappers.h" // xmalloc
47#include "fortify.h"
48#include "stristr.h" //stristr
49
50static PSZ pszSrcFile = __FILE__;
51
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
65PSZ AddBackslashToPath(PSZ pszPathName)
66{
67 if (pszPathName[strlen(pszPathName) - 1] != '\\')
68 strcat(pszPathName, PCSZ_BACKSLASH);
69 return pszPathName;
70}
71
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
83PSZ BldFullPathName(PSZ pszFullPathName, PCSZ pszPathName, PCSZ pszFileName)
84{
85 UINT c = pszPathName ? strlen(pszPathName) : 0;
86 if (c > 0) {
87 if (pszFullPathName != pszPathName)
88 memcpy(pszFullPathName, pszPathName, c);
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
103PSZ BldQuotedFullPathName(PSZ pszFullPathName, PCSZ pszPathName, PCSZ pszFileName)
104{
105 UINT c = pszPathName ? strlen(pszPathName) : 0;
106 BOOL q = needs_quoting(pszPathName) || needs_quoting(pszFileName);
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
131PSZ BldQuotedFileName(PSZ pszQuotedFileName, PCSZ pszFileName)
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
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
167/** NormalizeCmdLine
168 * Checks a command line for common errors (missing quotes, missing extension,
169 * no space between exe and args etc) Also check for the existance of the file
170 * and checks .com and .exe file headers.
171 * Command line passed as pszCmdLine_
172 * A pointer to a buffer of the size MaxComLineStrg should be supplied in
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{
179 char *szCmdLine, *szArgs;
180 char *offset = '\0', *offsetexe, *offsetcom, *offsetcmd, *offsetbtm, *offsetbat;
181 APIRET ret;
182 ULONG ulAppType;
183 char *pszChar;
184 PSZ pszNewCmdLine = pszWorkBuf;
185
186 szCmdLine = xmalloc(MaxComLineStrg, pszSrcFile, __LINE__);
187 if (!szCmdLine)
188 return pszCmdLine_; //already complained
189 szArgs = xmalloc(MaxComLineStrg, pszSrcFile, __LINE__);
190 if (!szArgs) {
191 free(szCmdLine);
192 return pszCmdLine_; //already complained
193 }
194 bstrip(pszCmdLine_);
195 memset(pszWorkBuf, 0, MaxComLineStrg);
196 strcpy(szCmdLine, pszCmdLine_);
197 if (szCmdLine[0] != '\0') {
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);
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] == ' ') ||
227 (!strstr(pszCmdLine_, "\\:") && strchr(szArgs, '\"') &&
228 strchr(szArgs, '\"') == strrchr(szArgs, '\"')))
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_);
235 if (!offsetexe && !offsetcom) {
236 if (!SearchPathForFile(PCSZ_PATH, szCmdLine, NULL))
237 ret = 0;
238 }
239 else
240 ret = xDosQueryAppType(szCmdLine, &ulAppType);
241 BldQuotedFileName(pszNewCmdLine, szCmdLine);
242 if (ret) {
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);
252 }
253 else{
254 fCancelAction = TRUE;
255 pszNewCmdLine = pszCmdLine_;
256 }
257 }
258 else{
259 if (szArgs[0] != ' ')
260 strcat(pszNewCmdLine, " ");
261 strcat(pszNewCmdLine, szArgs);
262 }
263
264 }
265 // if it doesn't have an extension try it with all the standard ones and add if found
266 else if (!strchr(szCmdLine, '.') ||
267 strrchr(szCmdLine, '.' ) < strrchr(szCmdLine, '\\')) {
268 if (!strchr(szCmdLine, ' ')) {
269 // strip quotes readded by BuildQuotedFileName
270 while (strchr(szCmdLine, '\"'))
271 remove_first_occurence_of_character("\"", szCmdLine);
272 ret = xDosQueryAppType(szCmdLine, &ulAppType); // exe automatically appended
273 if (!ret)
274 strcat(szCmdLine, PCSZ_DOTEXE);
275 else {
276 strcat(szCmdLine, PCSZ_DOTCOM);
277 ret = xDosQueryAppType(szCmdLine, &ulAppType);
278 if (ret) {
279 offset = strrchr(szCmdLine, '.' );
280 *offset = 0;
281 strcat(szCmdLine, PCSZ_DOTCMD);
282 if (!SearchPathForFile(PCSZ_PATH, szCmdLine, NULL))
283 ret = 0;
284 else {
285 *offset = 0;
286 strcat(szCmdLine, PCSZ_DOTBAT);
287 if (!SearchPathForFile(PCSZ_PATH, szCmdLine, NULL))
288 ret = 0;
289 else {
290 *offset = 0;
291 strcat(szCmdLine, PCSZ_DOTBTM);
292 if (!SearchPathForFile(PCSZ_PATH, szCmdLine, NULL))
293 ret = 0;
294 }
295 }
296 }
297 }
298 }
299 else {
300 pszChar = szCmdLine;
301 while (pszChar) {
302 while (strchr(szCmdLine, '\"'))
303 remove_first_occurence_of_character("\"", szCmdLine);
304 if (*pszChar == ' ') { //test at every space for the end of the filename
305 *pszChar = '\0';
306 ret = xDosQueryAppType(szCmdLine, &ulAppType);
307 if (!ret) {
308 strcat(szCmdLine, PCSZ_DOTEXE);
309 break;
310 }
311 else {
312 strcat(szCmdLine, PCSZ_DOTCOM);
313 ret = xDosQueryAppType(szCmdLine, &ulAppType);
314 if (ret) {
315 offset = strrchr(szCmdLine, '.' );
316 *offset = 0;
317 strcat(szCmdLine, PCSZ_DOTCMD);
318 if (!SearchPathForFile(PCSZ_PATH, szCmdLine, NULL)) {
319 ret = 0;
320 break;
321 }
322 else {
323 *offset = 0;
324 strcat(szCmdLine, PCSZ_DOTBAT);
325 if (!SearchPathForFile(PCSZ_PATH, szCmdLine, NULL)) {
326 ret = 0;
327 break;
328 }
329 else {
330 *offset = 0;
331 strcat(szCmdLine, PCSZ_DOTBTM);
332 if (!SearchPathForFile(PCSZ_PATH, szCmdLine, NULL)) {
333 ret = 0;
334 break;
335 }
336 }
337 }
338 }
339 else
340 break;
341 }
342 }
343 strcpy(szCmdLine, pszCmdLine_);
344 pszChar++;
345 }
346 }
347 if (!ret){
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);
362 }
363 else { // fail if no extension can be found runemf2 requires one
364 ret = saymsg(MB_OK,
365 HWND_DESKTOP,
366 NullStr,
367 GetPString(IDS_PROGRAMNOTEXE2TEXT),
368 pszCmdLine_);
369 fCancelAction = TRUE;
370 pszNewCmdLine = pszCmdLine_;
371 }
372 }
373 else { // file has a nonstandard extension for executable
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);
392 if (SearchPathForFile(PCSZ_PATH, szCmdLine, NULL)) {
393 ret = saymsg(MB_YESNO,
394 HWND_DESKTOP,
395 NullStr,
396 GetPString(IDS_PROGRAMNOTFOUNDTEXT),
397 pszCmdLine_);
398 if (ret == MBID_YES) {
399 if (szArgs[0] != ' ')
400 strcat(pszNewCmdLine, " ");
401 strcat(pszNewCmdLine, szArgs);
402 }
403 else {
404 fCancelAction = TRUE;
405 pszWorkBuf = pszCmdLine_;
406 }
407 }
408 else {
409 ret = saymsg(MB_YESNOCANCEL,
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 }
423 }
424 }
425 }
426 free(szArgs);
427 free(szCmdLine);
428 return pszWorkBuf;
429}
430
431#pragma alloc_text(PATHUTIL,BldFullPathName)
432#pragma alloc_text(PATHUTIL,BldQuotedFileName)
433#pragma alloc_text(PATHUTIL,BldQuotedFullPathName)
434#pragma alloc_text(PATHUTIL,NormalizeCmdLine)
435#pragma alloc_text(PATHUTIL,IsAbsolutePath)
Note: See TracBrowser for help on using the repository browser.