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