1: /*_ filespec.c Mon Jul 3 1989 Modified by: Walter Bright */
2: /* Copyright (C) 1986-1987 by Northwest Software */
3: /* All Rights Reserved */
4: /* Written by Walter Bright */
5:
6: /* Package with which to manipulate filespecs */
7:
8: #include <stdio.h>
9: #include "filespec.h"
10:
11: #ifndef MEM_H
12: #include "mem.h"
13: #endif
14:
15: #ifndef VAX11C
16: #include <string.h>
17: #endif
18:
19: #if BSDUNIX
20: #include <pwd.h>
21: #endif
22:
23: #if MSDOS || __OS2__ || __NT__ || _WIN32
24: #include <direct.h>
25: #include <ctype.h>
26: #endif
27:
28: #if M_UNIX || M_XENIX || linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
29: #include <stdlib.h>
30: #include <unistd.h>
31: #endif
32:
33: #ifndef assert
34: #include <assert.h>
35: #endif
36:
37: /* Macro to determine if char is a path or drive delimiter */
38: #if MSDOS || __OS2__ || __NT__ || _WIN32
39: #define ispathdelim(c) ((c) == '\\' || (c) == ':' || (c) == '/')
40: #else
41: #ifdef VMS
42: #define ispathdelim(c) ((c)==':' || (c)=='[' || (c)==']' )
43: #else
44: #ifdef MPW
45: #define ispathdelim(c) ((c) == ':')
46: #else
47: #define ispathdelim(c) ((c) == '/')
48: #endif /* MPW */
49: #endif /* VMS */
50: #endif
51:
52: /**********************/
53:
54: char * filespecaddpath(const char *path,const char *filename)
55: { register char *filespec;
56: register unsigned pathlen;
57:
58: if (!path || (pathlen = strlen(path)) == 0)
59: filespec = mem_strdup(filename);
60: else
61: {
62: filespec = (char *) mem_malloc(pathlen + 1 + strlen(filename) + 1);
63: if (filespec)
64: { strcpy(filespec,path);
warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(105) : see declaration of 'strcpy'
65: #if MSDOS || __OS2__ || __NT__ || _WIN32
66: if (!ispathdelim(filespec[pathlen - 1]))
67: strcat(filespec,"\\");
warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(110) : see declaration of 'strcat'
68: #else
69: #if VMS
70: #else
71: #if MPW
72: if (!ispathdelim(filespec[pathlen - 1]))
73: strcat(filespec,":");
74: #else
75: if (!ispathdelim(filespec[pathlen - 1]))
76: strcat(filespec,"/");
77: #endif /* MPW */
78: #endif /* VMS */
79: #endif
80: strcat(filespec,filename);
warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(110) : see declaration of 'strcat'
81: }
82: }
83: return filespec;
84: }
85:
86: #ifndef MPW
87: /**********************/
88: char * filespecrootpath(char *filespec)
89: {
90: #if SUN || M_UNIX || M_XENIX || linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
91: #define DIRCHAR '/'
92: #endif
93: #if MSDOS || __OS2__ || __NT__ || _WIN32
94: #define DIRCHAR '\\'
95: #endif
96: #ifdef MPW
97: #define DIRCHAR ':'
98: #endif
99:
100: char *cwd, *cwd_t;
101: char *p, *p2;
102:
103: if (!filespec)
104: return filespec;
105: #if MSDOS || __OS2__ || __NT__ || _WIN32
106: /* if already absolute (with \ or drive:) ... */
107: if (*filespec == DIRCHAR || (isalpha(*filespec) && *(filespec+1) == ':'))
warning C6328: 'char' passed as parameter '1' when 'unsigned char' is required in call to 'isalpha'
108: return filespec; /* ... return input string */
109: #else
110: if (*filespec == DIRCHAR) /* already absolute ... */
111: return filespec; /* ... return input string */
112: #endif
113:
114: /* get current working directory path */
115: #if SUN || M_UNIX || M_XENIX || linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
116: cwd_t = (char *)getcwd(NULL, 256);
117: #endif
118: #if MSDOS || __OS2__ || __NT__ || _WIN32
119: char cwd_d[132];
120: if (getcwd(cwd_d, sizeof(cwd_d)))
warning C4996: 'getcwd': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _getcwd. See online help for details.
c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\direct.h(117) : see declaration of 'getcwd'
121: cwd_t = cwd_d;
122: else
123: cwd_t = NULL;
124: #endif
125:
126: if (cwd_t == NULL)
127: {
128: mem_free(filespec);
129: return NULL; /* error - path too long (more than 256 chars !)*/
130: }
131: cwd = mem_strdup(cwd_t); /* convert cwd to mem package */
132: #if MSDOS
133: assert(strlen(cwd) > 0);
134: if (cwd[strlen(cwd) - 1] == DIRCHAR)
135: cwd[strlen(cwd) - 1] = '\0';
136: #endif
137: #if SUN || M_UNIX || M_XENIX || linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
138: free(cwd_t);
139: #endif
140: p = filespec;
141: while (p != NULL)
142: {
143: p2 = (char *)strchr(p, DIRCHAR);
144: if (p2 != NULL)
145: {
146: *p2 = '\0';
147: if (strcmp(p, "..") == 0) /* move up cwd */
148: /* remove last directory from cwd */
149: *((char *)strrchr(cwd, DIRCHAR)) = '\0';
150: else if (strcmp(p, ".") != 0) /* not current directory */
151: {
152: cwd_t = cwd;
153: cwd = (char *)mem_calloc(strlen(cwd_t) + 1 + strlen(p) + 1);
154: #if SUN || M_UNIX || M_XENIX || linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
155: sprintf(cwd, "%s/%s", cwd_t, p); /* add relative directory */
156: #endif
157: #if MSDOS || __OS2__ || __NT__ || _WIN32
158: sprintf(cwd, "%s\\%s", cwd_t, p); /* add relative directory */
warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
159: #endif
160: mem_free(cwd_t);
161: }
162: /* else if ".", then ignore - it means current directory */
163: *p2 = DIRCHAR;
164: p2++;
165: }
166: else if (strcmp(p,"..") == 0) /* move up cwd */
167: {
168: /* remove last directory from cwd */
169: *((char *)strrchr(cwd, DIRCHAR)) = '\0';
170: }
171: else if (strcmp(p,".") != 0) /* no more subdirectories ... */
172: { /* ... save remaining string */
173: cwd_t = cwd;
174: cwd = (char *)mem_calloc(strlen(cwd_t) + 1 + strlen(p) + 1);
175: #if SUN || M_UNIX || M_XENIX || linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
176: sprintf(cwd, "%s/%s", cwd_t, p); /* add relative directory */
177: #endif
178: #if MSDOS || __OS2__ || __NT__ || _WIN32
179: sprintf(cwd, "%s\\%s", cwd_t, p); /* add relative directory */
warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
180: #endif
181: mem_free(cwd_t);
182: }
183: p = p2;
184: }
185: mem_free(filespec);
186:
187: return cwd;
188: #ifdef VMS
189: assert(0);
190: #endif
191: }
192: #endif
193:
194: /**********************/
195:
196: char * filespecdotext(const char *filespec)
197: { register const char *p;
198: register int len;
199:
200: if ((p = filespec) != NULL)
201: { p += (len = strlen(p));
202: while (1)
203: { if (*p == '.')
204: break;
205: if (p <= filespec || ispathdelim(*p))
206: { p = filespec + len;
207: break;
208: }
209: p--;
210: }
211: }
212: return (char *)p;
213: }
214:
215: /**********************/
216:
217: char * filespecname(const char *filespec)
218: { register const char *p;
219:
220: /* Start at end of string and back up till we find the beginning */
221: /* of the filename or a path. */
222: for (p = filespec + strlen(filespec);
223: p != filespec && !ispathdelim(*(p - 1));
224: p--
225: )
226: ;
227: return (char *)p;
228: }
229:
230: /***********************/
231:
232: char * filespecgetroot(const char *name)
233: { char *root,*p,c;
234:
235: p = filespecdotext(name);
236: c = *p;
237: *p = 0;
238: root = mem_strdup(name);
239: *p = c;
240: return root;
241: }
242:
243: /*****************************/
244:
245: char * filespecforceext(const char *filespec,const char *ext)
246: { register char *p;
247: register const char *pext;
248:
249: if (*ext == '.')
250: ext++;
251: if ((p = (char *)filespec) != NULL)
252: { pext = filespecdotext(filespec);
253: if (ext)
254: { int n = pext - filespec;
255: p = (char *) mem_malloc(n + 1 + strlen(ext) + 1);
256: if (p)
257: { memcpy(p,filespec,n);
258: p[n] = '.';
259: strcpy(&p[n + 1],ext);
warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(105) : see declaration of 'strcpy'
260: }
261: }
262: else
263: p = mem_strdup(filespec);
264: }
265: return p;
266: }
267:
268: /*****************************/
269:
270: char * filespecdefaultext(const char *filespec,const char *ext)
271: { register char *p;
272: register const char *pext;
273:
274: pext = filespecdotext(filespec);
275: if (*pext == '.') /* if already got an extension */
276: {
277: p = mem_strdup(filespec);
278: }
279: else
280: { int n = pext - filespec;
281: p = (char *) mem_malloc(n + 1 + strlen(ext) + 1);
282: if (p)
283: {
284: memcpy(p,filespec,n);
285: p[n] = '.';
286: strcpy(&p[n + 1],ext);
warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(105) : see declaration of 'strcpy'
287: }
288: }
289: return p;
290: }
291:
292: /************************************/
293:
294: #if !(MSDOS || __OS2__ || __NT__ || _WIN32)
295:
296: char *filespectilde(char *filespec)
297: {
298: #if BSDUNIX
299: struct passwd *passwdPtr;
300: register char *f;
301:
302: if (filespec && *filespec == '~')
303: {
304: passwdPtr = NULL;
305: if (filespec[1] == '/' || filespec[1] == 0) /* if ~/... or ~ */
306: { f = filespec + 1;
307: passwdPtr = getpwuid(getuid());
308: }
309: else /* else ~name */
310: {
311: char c;
312:
313: f = strpbrk(filespec," /");
314: if (!f)
315: f = filespec + strlen(filespec); /* point at trailing 0 */
316: c = *f;
317: *f = 0;
318: passwdPtr = getpwnam(filespec + 1);
319: *f = c;
320: }
321: if (passwdPtr)
322: { char *p;
323:
324: p = (char *) mem_malloc(strlen(passwdPtr->pw_dir) + strlen(f) + 1);
325: if (p)
326: {
327: strcpy(p,passwdPtr->pw_dir);
328: strcat(p,f);
329: mem_free(filespec);
330: filespec = p;
331: }
332: }
333: }
334: #endif
335: #if MSDOS || __OS2__ || __NT__ || _WIN32
336: #endif
337: #if VMS
338: assert(0);
339: #endif
340: return filespec;
341: }
342:
343: /************************************/
344:
345: char *filespecmultitilde(char *string)
346: {
347: register char *p, *p2, *p3, *p4;
348:
349: string = filespectilde(string); /* expand if first character is a '~' */
350:
351: if (string)
352: {
353: for (p = string; *p != '\0'; p++)
354: {
355: if (*p == '~')
356: {
357: *p = '\0'; /* terminate sub string */
358: p2 = mem_strdup(string); /* get new sub string from old string */
359: *p = '~'; /* reset ~ character */
360: for (p3 = p + 1; *p3 != ' ' && *p3 != '\0'; p3++)
361: ; /* scan to next name, or end of the string */
362: p4 = NULL;
363: if (*p3 == ' ')
364: {
365: p4 = mem_strdup(p3); /* save reminder of the string */
366: *p3 = '\0';
367: }
368: p = mem_strdup(p); /* get tilde string */
369: mem_free(string);
370: p = filespectilde(p);
371:
372: /* reconstruct the string from pieces */
373: if (p4)
374: {
375: string = (char *)
376: mem_calloc(strlen(p2) + strlen(p) + strlen(p4) + 1);
377: sprintf(string, "%s%s%s", p2, p, p4);
378: }
379: else
380: {
381: string = (char *)
382: mem_calloc(strlen(p2) + strlen(p) + 1);
383: sprintf(string, "%s%s", p2, p);
384: }
385: mem_free(p);
386: p = string + strlen(p2) + 2;
387: mem_free(p2);
388: if (p4)
389: mem_free(p4);
390: }
391: }
392: }
393: return string;
394: }
395:
396: #endif
397:
398: #ifndef MPW
399: /************************************/
400:
401: char * filespecbackup(const char *filespec)
402: {
403: #if MSDOS || __OS2__ || __NT__ || _WIN32
404: return filespecforceext(filespec,"BAK");
405: #endif
406: #if BSDUNIX || linux || __APPLE__ || __FreeBSD__ || __OpenBSD__ || __sun&&__SVR4
407: char *p,*f;
408:
409: /* Prepend .B to file name, if it isn't already there */
410: if (!filespec)
411: return (char *)filespec;
412: p = filespecname(filespec);
413: if (p[0] == '.' && p[1] == 'B')
414: return mem_strdup(filespec);
415: f = (char *) mem_malloc(strlen(filespec) + 2 + 1);
416: if (f)
417: { strcpy(f,filespec);
418: strcpy(&f[p - filespec],".B");
419: strcat(f,p);
420: }
421: return f;
422: #endif
423: }
424: #endif
425: