]> andersk Git - splint.git/blob - src/osd.c
*** empty log message ***
[splint.git] / src / osd.c
1 /*
2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2001 University of Virginia,
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@*/
57 extern int stat (const char *, /*@out@*/ struct stat *);
58 /*@end@*/
59
60 static bool osd_executableFileExists (char *);
61
62 static bool nextdir (char **p_current_dir, /*@out@*/ char **p_dir, 
63                      /*@out@*/ size_t *p_len);
64
65 extern cstring LSLRootName (cstring filespec)
66 {
67   /*@access cstring@*/
68   char *result, *startName, *tail;
69   size_t nameLength;
70
71   llassert (cstring_isDefined (filespec));
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;
81   /*@noaccess cstring@*/
82 }
83
84 extern /*@observer@*/ cstring
85 osd_getEnvironment (cstring env, /*@returned@*/ cstring def)
86 {
87   /*@access cstring@*/
88   char *ret = osd_getEnvironmentVariable (env);
89
90   if (ret == NULL)
91     {
92       return def;
93     }
94   else
95     {
96       return ret;
97     }
98   /*@noaccess cstring@*/
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
136 extern /*@observer@*/ cstring osd_getHomeDir ()
137 {
138   /* Would something different be better for windows? */
139   return (osd_getEnvironmentVariable (cstring_makeLiteralTemp ("HOME")));
140 }
141
142 filestatus osd_findOnLarchPath (cstring file, cstring *returnPath)
143 {
144   return (osd_getPath (context_getLarchPath (), file, returnPath));
145 }
146
147 extern filestatus
148 osd_getPath (cstring path, cstring file, cstring *returnPath)
149 {
150   char *fullPath;
151   char *dirPtr;
152   size_t dirLen;
153   char aPath[MAXPATHLEN];
154   filestatus rVal = OSD_FILENOTFOUND;   /* assume file not found. */
155   
156   /*@access cstring@*/
157   
158   fullPath = path;
159   llassert (cstring_isDefined (file));
160   
161   if (fullPath == NULL 
162       || 
163 # if defined(OS2) || defined(MSDOS) || defined(WIN32)
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] == ':'))
168 # else
169     (*file == CONNECTCHAR)
170 # endif
171       )
172     {
173       /* No path specified. Look for it in the current directory.           */
174       
175       strcpy (&aPath[0], file);
176       
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     {
186       /* Path specified. Loop through directories in path looking for the */
187       /* first occurrence of the file.                              */
188       
189       while (nextdir (&fullPath, &dirPtr, &dirLen) &&
190              rVal == OSD_FILENOTFOUND)
191         {
192           if ((dirLen + strlen (file) + 2) <= MAXPATHLEN)
193             {
194               /* Cat directory and filename, and see if file exists.  */
195               strncpy (&aPath[0], dirPtr, dirLen);
196               strcpy (&aPath[0] + dirLen, "");  /* Null terminate aPath. */
197               strcat (&aPath[0], CONNECTSTR);
198               strcat (&aPath[0], file);
199               
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     }
213   
214   return rVal;
215   /*@noaccess cstring@*/
216 }
217
218 extern filestatus
219 osd_getExePath (cstring path, cstring file, cstring *returnPath)
220 {
221   char *fullPath;
222   char *dirPtr;
223   size_t dirLen;
224   char aPath[MAXPATHLEN];
225   filestatus rVal = OSD_FILENOTFOUND;   /* assume file not found. */
226   /*@access cstring@*/ 
227   
228   fullPath = osd_getEnvironmentVariable (path);
229   
230   if (fullPath == NULL)
231     {
232       /* No path specified. Look for it in the current directory. */
233       llassert (cstring_isDefined (file));
234       strcpy (&aPath[0], file);
235       
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         {
253           llassert (cstring_isDefined (file));
254
255           if ((dirLen + cstring_length (file) + 2) <= MAXPATHLEN)
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;
278   /*@noaccess cstring@*/
279 }
280
281 bool
282 osd_fileExists (cstring filespec)
283 {
284 # ifdef UNIX
285   struct stat buf;
286   return (stat (cstring_toCharsSafe (filespec), &buf) == 0);
287 # else
288 # if defined (WIN32) || defined (OS2)
289   FILE *test = fopen (cstring_toCharsSafe (filespec), "r");
290   
291   if (test != NULL) 
292     {
293       (void) fclose (test);
294       return TRUE;
295     } 
296   else
297     { 
298       return FALSE;
299     }
300 # else 
301   return FALSE;
302 # endif
303 # endif
304 }
305
306 bool
307 osd_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
383 static bool
384 nextdir (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 == PATH_SEPARATOR ? *current_dir + 1 : *current_dir);
395   
396   /* Find next ':' or end of string */
397   for (tchar = *dir; *tchar != '\0' && *tchar != PATH_SEPARATOR; tchar++)
398     {
399       ;
400     }
401   
402   *current_dir = tchar;
403   *len = size_fromInt (tchar - *dir);
404   return TRUE;
405 }
406
407 /*@observer@*/ /*@null@*/ cstring osd_getEnvironmentVariable (cstring var)
408 {
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     }
420 # else
421   return cstring_undefined;
422 # endif
423 }
424
425 # ifndef NOLCL
426
427 # ifdef WIN32
428 extern /*@external@*/ int _flushall (void) /*@modifies fileSystem@*/ ;
429 # endif
430
431 # ifndef system
432 extern /*@external@*/ int system (const char *) /*@modifies fileSystem@*/ ;
433 # endif
434 int osd_system (cstring cmd)
435 {
436   int res;
437     /* system ("printenv"); */
438 # ifdef WIN32
439   (void) _flushall (); 
440 # endif
441
442   res = system (cstring_toCharsSafe (cmd));
443   return res;
444 }
445 # endif
446
447 # ifndef unlink
448 /*@-redecl@*/
449 extern /*@external@*/ int unlink (const char *) /*@modifies fileSystem@*/ ;
450 /*@=redecl@*/
451 # endif
452
453 int osd_unlink (cstring fname)
454 {
455   int res;
456
457   res = unlink (cstring_toCharsSafe (fname));
458
459   if (res != 0)
460     {
461       llcontbug (message ("Cannot remove temporary file: %s (%s)",
462                           fname,
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__)
476 int
477 # else
478 int /* pid_t */
479 # endif
480 osd_getPid ()
481 {
482 # if defined (WIN32) || defined (OS2) && defined (__IBMC__)
483   int pid = _getpid ();
484 # else
485   pid_t pid = getpid ();
486 # endif
487
488   return (int) pid;
489 }
490   
491 cstring osd_fixDefine (cstring x)
492 {
493   /*@access cstring@*/
494   llassert (cstring_isDefined (x));
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
528   return cstring_copy (x);
529   /*@noaccess cstring@*/
530 }
531
532 bool osd_fileIsReadable (cstring f)
533 {
534   FILE *fl = fopen (cstring_toCharsSafe (f), "r");
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
547 bool 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.117082 seconds and 5 git commands to generate.