source: trunk/dll/pathutil.c@ 1568

Last change on this file since 1568 was 1568, checked in by Steven Levine, 14 years ago

Avoid extra copy in BuildFullPathName

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