]> andersk Git - splint.git/blame - src/osd.c
*** empty log message ***
[splint.git] / src / osd.c
CommitLineData
616915dd 1/*
2** LCLint - annotation-assisted static program checker
28bf4b0b 3** Copyright (C) 1994-2001 University of Virginia,
616915dd 4** Massachusetts Institute of Technology
5**
6** This program is free software; you can redistribute it and/or modify it
7** under the terms of the GNU General Public License as published by the
8** Free Software Foundation; either version 2 of the License, or (at your
9** option) any later version.
10**
11** This program is distributed in the hope that it will be useful, but
12** WITHOUT ANY WARRANTY; without even the implied warranty of
13** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14** General Public License for more details.
15**
16** The GNU General Public License is available from http://www.gnu.org/ or
17** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18** MA 02111-1307, USA.
19**
20** For information on lclint: lclint-request@cs.virginia.edu
21** To report a bug: lclint-bug@cs.virginia.edu
22** For more information: http://lclint.cs.virginia.edu
23*/
24/*
25** osd.c
26**
27** Provide a system-independent interface to system-dependent
28** file operations.
29*/
30
31/*
32 * Modified by Herbert 04/19/97:
33 * - added conditional 'OS2' to conditional 'MSDOS'
34 * - added include of new header portab.h.
35 * - changed '/' to macro.
36 * - added DOS / OS/2 specific stuff in osd_getPath.
37 * Herbert 06/12/2000:
38 * - added OS/2 specific includes before osd_getPid()
39 * - handle files like in WIN32 for OS/2 in osd_fileExists()
40 */
41
42/*@-allmacros*/
43/*@ignore@*/
44# include <sys/types.h>
45# include <sys/stat.h>
46/* Fix suggested by Lars Rasmussen */
47# include <errno.h>
48/*@end@*/
49/*@=allmacros*/
50# include "lclintMacros.nf"
51# include "basic.h"
52# include "osd.h"
53# include "portab.h"
54
55/* from stat.h */
56/*@ignore@*/
57extern int stat (const char *, /*@out@*/ struct stat *);
58/*@end@*/
59
60static bool osd_executableFileExists (char *);
61
62static bool nextdir (char **p_current_dir, /*@out@*/ char **p_dir,
63 /*@out@*/ size_t *p_len);
64
28bf4b0b 65extern cstring LSLRootName (cstring filespec)
616915dd 66{
28bf4b0b 67 /*@access cstring@*/
616915dd 68 char *result, *startName, *tail;
69 size_t nameLength;
70
28bf4b0b 71 llassert (cstring_isDefined (filespec));
616915dd 72 tail = strrchr (filespec, CONNECTCHAR);
73 startName = (tail == NULL ? filespec : &tail[1]);
74 tail = strrchr (startName, '.');
75 nameLength = (tail == NULL ? strlen (startName)
76 : size_fromInt (tail - startName));
77 result = dmalloc (nameLength + 1);
78 strncpy (result, startName, nameLength);
79 result[(int) nameLength] = '\0';
80 return result;
28bf4b0b 81 /*@noaccess cstring@*/
616915dd 82}
83
28bf4b0b 84extern /*@observer@*/ cstring
85osd_getEnvironment (cstring env, /*@returned@*/ cstring def)
616915dd 86{
28bf4b0b 87 /*@access cstring@*/
616915dd 88 char *ret = osd_getEnvironmentVariable (env);
89
90 if (ret == NULL)
91 {
92 return def;
93 }
94 else
95 {
96 return ret;
97 }
28bf4b0b 98 /*@noaccess cstring@*/
616915dd 99}
100
101
102/*
103**++
104** FUNCTIONAL DESCRIPTION:
105**
106** This function attempts to locate a file in a search list. On VMS, it
107** just concatinates the path and file names, and then lets RMS do the
108** searching. On Ultrix, it searches for the file on the path.
109**
110** FORMAL PARAMETERS:
111**
112** path: search path where to look for the file.
113** file: name of file to search for.
114** returnPath: if a file is found, this is where the concatenated
115** directory and file name are returned.
116**
117** RETURN VALUE:
118**
119** OSD_FILEFOUND: the file was found on the search list.
120** OSD_FILENOTFOUND the file was not found.
121** OSD_PATHTOOLONG the concatenated directory and file name are too
122** long.
123**
124** SIDE EFFECTS:
125**
126** None
127**
128** PRECONDITIONS:
129**
130** Requires that parameters, path and file, are valid C strings.
131**
132**
133**--
134*/
135
28bf4b0b 136extern /*@observer@*/ cstring osd_getHomeDir ()
616915dd 137{
138 /* Would something different be better for windows? */
28bf4b0b 139 return (osd_getEnvironmentVariable (cstring_makeLiteralTemp ("HOME")));
616915dd 140}
141
28bf4b0b 142filestatus osd_findOnLarchPath (cstring file, cstring *returnPath)
616915dd 143{
28bf4b0b 144 return (osd_getPath (context_getLarchPath (), file, returnPath));
616915dd 145}
146
147extern filestatus
28bf4b0b 148osd_getPath (cstring path, cstring file, cstring *returnPath)
616915dd 149{
150 char *fullPath;
151 char *dirPtr;
152 size_t dirLen;
153 char aPath[MAXPATHLEN];
154 filestatus rVal = OSD_FILENOTFOUND; /* assume file not found. */
28bf4b0b 155
156 /*@access cstring@*/
157
616915dd 158 fullPath = path;
28bf4b0b 159 llassert (cstring_isDefined (file));
160
161 if (fullPath == NULL
162 ||
616915dd 163# if defined(OS2) || defined(MSDOS) || defined(WIN32)
28bf4b0b 164 /* under OS/2 and MSDOS the includePath may be empty, if so, search
165 * the current directory. */
166 *fullPath == '\0' ||
167 (*file == CONNECTCHAR || (file[0] != '\0' && file[1] == ':'))
616915dd 168# else
28bf4b0b 169 (*file == CONNECTCHAR)
616915dd 170# endif
28bf4b0b 171 )
616915dd 172 {
28bf4b0b 173 /* No path specified. Look for it in the current directory. */
174
616915dd 175 strcpy (&aPath[0], file);
28bf4b0b 176
616915dd 177 if (osd_fileExists (&aPath[0]))
178 {
179 rVal = OSD_FILEFOUND;
180 *returnPath = dmalloc (strlen (&aPath[0]) + 1);
181 strcpy (*returnPath, &aPath[0]);
182 }
183 }
184 else
185 {
28bf4b0b 186 /* Path specified. Loop through directories in path looking for the */
187 /* first occurrence of the file. */
188
616915dd 189 while (nextdir (&fullPath, &dirPtr, &dirLen) &&
190 rVal == OSD_FILENOTFOUND)
191 {
192 if ((dirLen + strlen (file) + 2) <= MAXPATHLEN)
193 {
28bf4b0b 194 /* Cat directory and filename, and see if file exists. */
616915dd 195 strncpy (&aPath[0], dirPtr, dirLen);
196 strcpy (&aPath[0] + dirLen, ""); /* Null terminate aPath. */
197 strcat (&aPath[0], CONNECTSTR);
198 strcat (&aPath[0], file);
28bf4b0b 199
616915dd 200 if (osd_fileExists (&aPath[0]))
201 {
202 rVal = OSD_FILEFOUND;
203 *returnPath = (char *) dmalloc (strlen (&aPath[0]) + 1);
204 strcpy (*returnPath, &aPath[0]);
205 }
206 }
207 else
208 {
209 rVal = OSD_PATHTOOLONG;
210 }
211 }
212 }
28bf4b0b 213
616915dd 214 return rVal;
28bf4b0b 215 /*@noaccess cstring@*/
616915dd 216}
217
218extern filestatus
28bf4b0b 219osd_getExePath (cstring path, cstring file, cstring *returnPath)
616915dd 220{
221 char *fullPath;
222 char *dirPtr;
223 size_t dirLen;
224 char aPath[MAXPATHLEN];
225 filestatus rVal = OSD_FILENOTFOUND; /* assume file not found. */
28bf4b0b 226 /*@access cstring@*/
616915dd 227
228 fullPath = osd_getEnvironmentVariable (path);
28bf4b0b 229
616915dd 230 if (fullPath == NULL)
231 {
28bf4b0b 232 /* No path specified. Look for it in the current directory. */
233 llassert (cstring_isDefined (file));
616915dd 234 strcpy (&aPath[0], file);
28bf4b0b 235
616915dd 236 if (osd_fileExists (&aPath[0]))
237 {
238 rVal = OSD_FILEFOUND;
239 *returnPath = dmalloc (strlen (&aPath[0]) + 1);
240 strcpy (*returnPath, &aPath[0]);
241 }
242 }
243 else
244 {
245 /*
246 ** Path specified. Loop through directories in path looking
247 ** for the first occurrence of the file.
248 */
249
250 while (nextdir (&fullPath, &dirPtr, &dirLen) &&
251 rVal == OSD_FILENOTFOUND)
252 {
28bf4b0b 253 llassert (cstring_isDefined (file));
254
255 if ((dirLen + cstring_length (file) + 2) <= MAXPATHLEN)
616915dd 256 {
257 /* Cat directory and filename, and see if file exists. */
258 strncpy (&aPath[0], dirPtr, dirLen);
259 strcpy (&aPath[0] + dirLen, ""); /* Null terminate aPath. */
260 strcat (&aPath[0], CONNECTSTR);
261 strcat (&aPath[0], file);
262
263 if (osd_executableFileExists (&aPath[0]))
264 {
265 rVal = OSD_FILEFOUND;
266 *returnPath = dmalloc (strlen (&aPath[0]) + 1);
267 strcpy (*returnPath, &aPath[0]);
268 }
269 }
270 else
271 {
272 rVal = OSD_PATHTOOLONG;
273 }
274 }
275 }
276
277 return rVal;
28bf4b0b 278 /*@noaccess cstring@*/
616915dd 279}
280
281bool
28bf4b0b 282osd_fileExists (cstring filespec)
616915dd 283{
284# ifdef UNIX
285 struct stat buf;
28bf4b0b 286 return (stat (cstring_toCharsSafe (filespec), &buf) == 0);
616915dd 287# else
288# if defined (WIN32) || defined (OS2)
28bf4b0b 289 FILE *test = fopen (cstring_toCharsSafe (filespec), "r");
290
616915dd 291 if (test != NULL)
28bf4b0b 292 {
293 (void) fclose (test);
294 return TRUE;
295 }
616915dd 296 else
28bf4b0b 297 {
298 return FALSE;
299 }
616915dd 300# else
301 return FALSE;
302# endif
303# endif
304}
305
306bool
307osd_executableFileExists (/*@unused@*/ char *filespec)
308{
309# ifdef UNIX
310 struct stat buf;
311# if defined(__IBMC__) && defined(OS2)
312# define S_IFMT (unsigned short)0xFFFF
313# endif
314 if (stat (filespec, &buf) == 0)
315 {
316 /* mask by file type */
317 /*@-unrecog@*/ /* S_IFMT is not defined */
318 if ((buf.st_mode & S_IFMT) != S_IFDIR /*@=unrecog@*/) /* not a directory */
319 {
320 /* as long as it is an executable file */
321# if defined(__IBMC__) && defined(OS2)
322 int com_or_exe_pos = strlen( filespec) - 4;
323 return stricmp( &filespec[com_or_exe_pos], ".exe") == 0
324 || stricmp( &filespec[com_or_exe_pos], ".com") == 0
325 || stricmp( &filespec[com_or_exe_pos], ".bat") == 0
326 || stricmp( &filespec[com_or_exe_pos], ".cmd") == 0;
327# else
328 return (((buf.st_mode & S_IXUSR)
329# if !defined(MSDOS) && !defined(OS2)
330 | (buf.st_mode & S_IXGRP) |
331 (buf.st_mode & S_IXOTH)
332# endif
333 ) != 0);
334# endif
335 }
336 }
337
338# endif
339 return (FALSE);
340
341}
342
343/*
344**++
345** FUNCTIONAL DESCRIPTION:
346**
347** Find the next directory from a directory path.
348**
349** FORMAL PARAMETERS:
350**
351** char ** current_dir :
352** Points to the current position in the path string. The first time
353** you call this routine, this should point to the first character of
354** the path. On return, this will be updated to point to the
355** terminating \0 or : of the first directory found. You can then pass
356** it unchanged for subsequent calls; this routine will correctly skip
357** over the :.
358**
359** char ** dir :
360** On exit, this will point to the first character of the directory
361** that was found. This will be a pointer directly into the client's
362** path string.
363**
364** unsigned int * len :
365** On exit, this will contain the length of the directory that was
366** found, not counting any terminating \0 or :. If no directory was
367** found, this will be 0.
368**
369** RETURN VALUE:
370** TRUE if we found another directory.
371** FALSE otherwise.
372**
373** DESIGN:
374**
375** We return a pointer and length, rather than a string, because of a)
376** historical reasons; and b) this avoids having to allocate storage.
377**
378**
379**
380**--
381*/
382
383static bool
384nextdir (d_char *current_dir, d_char *dir, size_t *len)
385{
386 char *tchar;
387
388 if (**current_dir == '\0')
389 {
390 *len = 0;
391 return FALSE;
392 }
393
394 *dir = (**current_dir == SEPCHAR ? *current_dir + 1 : *current_dir);
395
396 /* Find next ':' or end of string */
397 for (tchar = *dir; *tchar != '\0' && *tchar != SEPCHAR; tchar++)
398 {
399 ;
400 }
401
402 *current_dir = tchar;
403 *len = size_fromInt (tchar - *dir);
404 return TRUE;
405}
406
28bf4b0b 407/*@observer@*/ /*@null@*/ cstring osd_getEnvironmentVariable (cstring var)
616915dd 408{
28bf4b0b 409# if defined(UNIX) || defined(OS) || defined(MSDOS) || defined(WIN32)
410 char *val = getenv (cstring_toCharsSafe (var));
411
412 if (val == NULL)
413 {
414 return cstring_undefined;
415 }
416 else
417 {
418 return cstring_makeLiteralTemp (val);
419 }
616915dd 420# else
28bf4b0b 421 return cstring_undefined;
616915dd 422# endif
423}
424
425# ifndef NOLCL
426
427# ifdef WIN32
428extern /*@external@*/ int _flushall (void) /*@modifies fileSystem@*/ ;
429# endif
430
431# ifndef system
432extern /*@external@*/ int system (const char *) /*@modifies fileSystem@*/ ;
433# endif
28bf4b0b 434int osd_system (cstring cmd)
616915dd 435{
436 int res;
437 /* system ("printenv"); */
438# ifdef WIN32
439 (void) _flushall ();
440# endif
441
28bf4b0b 442 res = system (cstring_toCharsSafe (cmd));
616915dd 443 return res;
444}
445# endif
446
447# ifndef unlink
448/*@-redecl@*/
449extern /*@external@*/ int unlink (const char *) /*@modifies fileSystem@*/ ;
450/*@=redecl@*/
451# endif
452
28bf4b0b 453int osd_unlink (cstring fname)
616915dd 454{
455 int res;
456
28bf4b0b 457 res = unlink (cstring_toCharsSafe (fname));
616915dd 458
459 if (res != 0)
460 {
461 llcontbug (message ("Cannot remove temporary file: %s (%s)",
28bf4b0b 462 fname,
616915dd 463 cstring_fromChars (strerror (errno))));
464 }
465
466 return res;
467}
468
469# if defined (WIN32) || (defined(OS2) && defined(__IBMC__))
470# include <process.h>
471# elif defined OS2
472# include <unistd.h>
473# endif
474
475# if defined (WIN32) || defined (OS2) && defined (__IBMC__)
476int
477# else
478int /* pid_t */
479# endif
480osd_getPid ()
481{
482# if defined (WIN32) || defined (OS2) && defined (__IBMC__)
483 int pid = _getpid ();
484# else
28bf4b0b 485 pid_t pid = getpid ();
616915dd 486# endif
487
488 return (int) pid;
489}
490
28bf4b0b 491cstring osd_fixDefine (cstring x)
616915dd 492{
28bf4b0b 493 /*@access cstring@*/
494 llassert (cstring_isDefined (x));
616915dd 495# ifdef UNIX
496 if (strchr (x, '\'') != NULL) {
497 /*
498 ** If there is a single quote, check for <ident>='<string>' and
499 ** produce <ident>=<string>
500 */
501
502 char *eqs = strchr (x, '=');
503
504 if (eqs != NULL) {
505 if (eqs[1] == '\'') {
506 char *endqu = strrchr (x, '\'');
507
508 if (endqu != NULL) {
509 if (*(endqu - 1) != '\\') {
510 if (*(endqu + 1) == '\0') {
511 cstring res;
512 cstring def;
513
514 *endqu = '\0';
515 def = cstring_fromChars (eqs + 2);
516 eqs[1] = '\0';
517 res = cstring_concat (cstring_fromChars (x), def);
518 return res;
519 }
520 }
521 }
522 }
523 }
524 }
525
526# endif
527
28bf4b0b 528 return cstring_copy (x);
529 /*@noaccess cstring@*/
616915dd 530}
531
28bf4b0b 532bool osd_fileIsReadable (cstring f)
616915dd 533{
28bf4b0b 534 FILE *fl = fopen (cstring_toCharsSafe (f), "r");
616915dd 535
536 if (fl != (FILE *) 0)
537 {
538 check (fclose (fl) == 0);
539 return (TRUE);
540 }
541 else
542 {
543 return (FALSE);
544 }
545}
546
547bool osd_isConnectChar (char c)
548{
549 if (c == CONNECTCHAR)
550 {
551 return TRUE;
552 }
553
554# ifdef HASALTCONNECTCHAR
555 if (c == ALTCONNECTCHAR)
556 {
557 return TRUE;
558 }
559# endif
560
561 return FALSE;
562}
563
This page took 0.120646 seconds and 5 git commands to generate.