]> andersk Git - splint.git/blob - src/osd.c
Merged with Dave Evans's changes.
[splint.git] / src / osd.c
1 /*
2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2000 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 char *LSLRootName (char *filespec)
66 {
67   char *result, *startName, *tail;
68   size_t nameLength;
69
70   tail = strrchr (filespec, CONNECTCHAR);
71   startName = (tail == NULL ? filespec : &tail[1]);
72   tail = strrchr (startName, '.');
73   nameLength = (tail == NULL ? strlen (startName) 
74                 : size_fromInt (tail - startName));
75   result = dmalloc (nameLength + 1);
76   strncpy (result, startName, nameLength);
77   result[(int) nameLength] = '\0';
78   return result;
79 }
80
81 extern /*@observer@*/ char *
82 osd_getEnvironment (char *env, /*@returned@*/ char *def)
83 {
84   char *ret = osd_getEnvironmentVariable (env);
85
86   if (ret == NULL)
87     {
88       return def;
89     }
90   else
91     {
92       return ret;
93     }
94 }
95
96
97 /*
98 **++
99 **  FUNCTIONAL DESCRIPTION:
100 **
101 **      This function attempts to locate a file in a search list.  On VMS, it
102 **      just concatinates the path and file names, and then lets RMS do the
103 **      searching.  On Ultrix, it searches for the file on the path.
104 **
105 **  FORMAL PARAMETERS:
106 **
107 **      path:       search path where to look for the file.
108 **      file:       name of file to search for.
109 **      returnPath: if a file is found, this is where the concatenated
110 **                  directory and file name are returned.
111 **
112 **  RETURN VALUE:
113 **
114 **      OSD_FILEFOUND:      the file was found on the search list.
115 **      OSD_FILENOTFOUND    the file was not found.
116 **      OSD_PATHTOOLONG     the concatenated directory and file name are too
117 **                          long.
118 **
119 **  SIDE EFFECTS:
120 **
121 **      None
122 **
123 **  PRECONDITIONS:
124 **
125 **      Requires that parameters, path and file, are valid C strings.
126 **
127 **
128 **--
129 */
130
131 extern /*@null@*/ /*@observer@*/ char *
132   osd_getHomeDir ()
133 {
134   /* Would something different be better for windows? */
135   return (osd_getEnvironmentVariable ("HOME"));
136 }
137
138 filestatus osd_findOnLarchPath (char *file, char **returnPath)
139 {
140   return (osd_getPath (cstring_toCharsSafe (context_getLarchPath ()), file, returnPath));
141 }
142
143 extern filestatus
144 osd_getPath (char *path, char *file, char **returnPath)
145 {
146   char *fullPath;
147   char *dirPtr;
148   size_t dirLen;
149   char aPath[MAXPATHLEN];
150   filestatus rVal = OSD_FILENOTFOUND;   /* assume file not found. */
151
152   fullPath = path;
153
154   if (fullPath == NULL || 
155 # if defined(OS2) || defined(MSDOS) || defined(WIN32)
156     /* under OS/2 and MSDOS the includePath may be empty, if so, search 
157      * the current directory. */
158     *fullPath == '\0' || 
159     (*file == CONNECTCHAR || (file[0] != '\0' && file[1] == ':')))
160 # else
161      (*file == CONNECTCHAR))
162 # endif
163     {
164      /* No path specified. Look for it in the current directory.            */
165
166       strcpy (&aPath[0], file);
167
168       if (osd_fileExists (&aPath[0]))
169         {
170           rVal = OSD_FILEFOUND;
171           *returnPath = dmalloc (strlen (&aPath[0]) + 1);
172           strcpy (*returnPath, &aPath[0]);
173         }
174     }
175   else
176     {
177      /* Path specified. Loop through directories in path looking for the */
178      /* first occurrence of the file.                               */
179
180       while (nextdir (&fullPath, &dirPtr, &dirLen) &&
181              rVal == OSD_FILENOTFOUND)
182         {
183           if ((dirLen + strlen (file) + 2) <= MAXPATHLEN)
184             {
185              /* Cat directory and filename, and see if file exists.  */
186               strncpy (&aPath[0], dirPtr, dirLen);
187               strcpy (&aPath[0] + dirLen, "");  /* Null terminate aPath. */
188               strcat (&aPath[0], CONNECTSTR);
189               strcat (&aPath[0], file);
190
191               if (osd_fileExists (&aPath[0]))
192                 {
193                   rVal = OSD_FILEFOUND;
194                   *returnPath = (char *) dmalloc (strlen (&aPath[0]) + 1);
195                   strcpy (*returnPath, &aPath[0]);
196                 }
197             }
198           else
199             {
200               rVal = OSD_PATHTOOLONG;
201             }
202         }       
203     }
204
205   return rVal;
206 }
207
208 extern filestatus
209 osd_getExePath (char *path, char *file, char **returnPath)
210 {
211   char *fullPath;
212   char *dirPtr;
213   size_t dirLen;
214   char aPath[MAXPATHLEN];
215   filestatus rVal = OSD_FILENOTFOUND;   /* assume file not found. */
216   
217   fullPath = osd_getEnvironmentVariable (path);
218
219   if (fullPath == NULL)
220     {
221      /* No path specified. Look for it in the current directory. */
222
223       strcpy (&aPath[0], file);
224
225       if (osd_fileExists (&aPath[0]))
226         {
227           rVal = OSD_FILEFOUND;
228           *returnPath = dmalloc (strlen (&aPath[0]) + 1);
229           strcpy (*returnPath, &aPath[0]);
230         }
231     }
232   else
233     {
234      /* 
235      ** Path specified. Loop through directories in path looking
236      ** for the first occurrence of the file.                               
237      */
238
239       while (nextdir (&fullPath, &dirPtr, &dirLen) &&
240              rVal == OSD_FILENOTFOUND)
241         {
242           if ((dirLen + strlen (file) + 2) <= MAXPATHLEN)
243             {
244               /* Cat directory and filename, and see if file exists.  */
245               strncpy (&aPath[0], dirPtr, dirLen);
246               strcpy (&aPath[0] + dirLen, ""); /* Null terminate aPath. */
247               strcat (&aPath[0], CONNECTSTR);
248               strcat (&aPath[0], file);
249
250               if (osd_executableFileExists (&aPath[0]))
251                 {
252                   rVal = OSD_FILEFOUND;
253                   *returnPath = dmalloc (strlen (&aPath[0]) + 1);
254                   strcpy (*returnPath, &aPath[0]);
255                 }
256             }
257           else
258             {
259               rVal = OSD_PATHTOOLONG;
260             }
261         }
262     }
263
264   return rVal;
265 }
266
267 bool
268 osd_fileExists (char *filespec)
269 {
270 # ifdef UNIX
271   struct stat buf;
272   return (stat (filespec, &buf) == 0);
273 # else
274 # if defined (WIN32) || defined (OS2)
275   FILE *test = fopen (filespec, "r");
276   if (test != NULL) 
277   {
278         (void) fclose (test);
279         return TRUE;
280   } 
281   else
282   { 
283           return FALSE;
284   }
285 # else 
286   return FALSE;
287 # endif
288 # endif
289 }
290
291 bool
292 osd_executableFileExists (/*@unused@*/ char *filespec)
293 {
294 # ifdef UNIX
295         struct stat buf;
296 # if defined(__IBMC__) && defined(OS2)
297 # define S_IFMT (unsigned short)0xFFFF
298 # endif
299   if (stat (filespec, &buf) == 0)
300     { 
301       /* mask by file type */
302       /*@-unrecog@*/ /* S_IFMT is not defined */
303       if ((buf.st_mode & S_IFMT) != S_IFDIR /*@=unrecog@*/) /* not a directory */
304         {
305           /* as long as it is an executable file */
306 # if defined(__IBMC__) && defined(OS2)
307       int com_or_exe_pos = strlen( filespec) - 4;
308       return stricmp( &filespec[com_or_exe_pos], ".exe") == 0
309         || stricmp( &filespec[com_or_exe_pos], ".com") == 0
310         || stricmp( &filespec[com_or_exe_pos], ".bat") == 0
311         || stricmp( &filespec[com_or_exe_pos], ".cmd") == 0;
312 # else
313           return (((buf.st_mode & S_IXUSR)
314 # if !defined(MSDOS) && !defined(OS2) 
315                    | (buf.st_mode & S_IXGRP) |
316                    (buf.st_mode & S_IXOTH)
317 # endif
318                    ) != 0);
319 # endif
320         }
321     }
322
323 # endif
324   return (FALSE);
325
326 }
327
328 /*
329 **++
330 **  FUNCTIONAL DESCRIPTION:
331 **
332 **      Find the next directory from a directory path.
333 **
334 **  FORMAL PARAMETERS:
335 **
336 **      char ** current_dir :
337 **          Points to the current position in the path string.  The first time
338 **          you call this routine, this should point to the first character of
339 **          the path.  On return, this will be updated to point to the
340 **          terminating \0 or : of the first directory found.  You can then pass
341 **          it unchanged for subsequent calls; this routine will correctly skip
342 **          over the :.
343 **
344 **      char ** dir :
345 **          On exit, this will point to the first character of the directory
346 **          that was found.  This will be a pointer directly into the client's
347 **          path string.
348 **
349 **      unsigned int * len :
350 **          On exit, this will contain the length of the directory that was
351 **          found, not counting any terminating \0 or :.  If no directory was
352 **          found, this will be 0.
353 **
354 **  RETURN VALUE:
355 **      TRUE if we found another directory.
356 **      FALSE otherwise.
357 **
358 **  DESIGN:
359 **
360 **      We return a pointer and length, rather than a string, because of a)
361 **      historical reasons; and b) this avoids having to allocate storage.
362 **
363 **
364 **
365 **--
366 */
367
368 static bool
369 nextdir (d_char *current_dir, d_char *dir, size_t *len)
370 {
371   char *tchar;
372
373   if (**current_dir == '\0')
374     {
375       *len = 0;
376       return FALSE;
377     }
378
379   *dir = (**current_dir == SEPCHAR ? *current_dir + 1 : *current_dir);
380   
381   /* Find next ':' or end of string */
382   for (tchar = *dir; *tchar != '\0' && *tchar != SEPCHAR; tchar++)
383     {
384       ;
385     }
386   
387   *current_dir = tchar;
388   *len = size_fromInt (tchar - *dir);
389   return TRUE;
390 }
391
392 /*@observer@*/ /*@null@*/ char *osd_getEnvironmentVariable (char *var)
393 {
394 # ifdef UNIX
395         return getenv (var);
396 # else
397 # if defined(OS2) || defined(MSDOS)
398         return getenv (var);
399 # else
400 # if defined(WIN32)
401         return getenv (var);
402 # else
403         return NULL;
404 # endif
405 # endif
406 # endif
407 }
408
409 # ifndef NOLCL
410
411 # ifdef WIN32
412 extern /*@external@*/ int _flushall (void) /*@modifies fileSystem@*/ ;
413 # endif
414
415 # ifndef system
416 extern /*@external@*/ int system (const char *) /*@modifies fileSystem@*/ ;
417 # endif
418 int osd_system (const char *cmd)
419 {
420   int res;
421     /* system ("printenv"); */
422 # ifdef WIN32
423   (void) _flushall (); 
424 # endif
425
426   res = system (cmd);
427   return res;
428 }
429 # endif
430
431 # ifndef unlink
432 /*@-redecl@*/
433 extern /*@external@*/ int unlink (const char *) /*@modifies fileSystem@*/ ;
434 /*@=redecl@*/
435 # endif
436
437 int osd_unlink (const char *fname)
438 {
439   int res;
440
441   res = unlink (fname);
442
443   if (res != 0)
444     {
445       llcontbug (message ("Cannot remove temporary file: %s (%s)",
446                           cstring_fromChars (fname),
447                           cstring_fromChars (strerror (errno))));
448     }
449   
450   return res;
451 }
452
453 # if defined (WIN32) || (defined(OS2) && defined(__IBMC__))
454 # include <process.h>
455 # elif defined OS2
456 # include <unistd.h>
457 # endif
458
459 # if defined (WIN32) || defined (OS2) && defined (__IBMC__)
460 int
461 # else
462 int /* pid_t */
463 # endif
464 osd_getPid ()
465 {
466 # if defined (WIN32) || defined (OS2) && defined (__IBMC__)
467   int pid = _getpid ();
468 # else
469    pid_t pid = getpid ();
470 # endif
471
472   return (int) pid;
473 }
474   
475 cstring osd_fixDefine (char *x)
476 {
477 # ifdef UNIX
478   if (strchr (x, '\'') != NULL) {
479     /*
480     ** If there is a single quote, check for <ident>='<string>' and 
481     ** produce <ident>=<string>
482     */
483
484     char *eqs = strchr (x, '=');
485
486     if (eqs != NULL) {
487       if (eqs[1] == '\'') {
488         char *endqu = strrchr (x, '\'');
489
490         if (endqu != NULL) {
491           if (*(endqu - 1) != '\\') {
492             if (*(endqu + 1) == '\0') {
493               cstring res;
494               cstring def;
495
496               *endqu = '\0';
497               def = cstring_fromChars (eqs + 2);
498               eqs[1] = '\0';
499               res = cstring_concat (cstring_fromChars (x), def);
500                       return res;
501             }
502           }
503         }
504       }
505     }
506   } 
507
508 # endif
509
510   return cstring_fromCharsNew (x);
511 }
512
513 bool osd_fileIsReadable (char *f)
514 {
515   FILE *fl = fopen (f, "r");
516
517   if (fl != (FILE *) 0)
518     {
519       check (fclose (fl) == 0);
520       return (TRUE);
521     }
522   else
523     {
524       return (FALSE);
525     }
526 }
527
528 bool osd_isConnectChar (char c)
529 {
530   if (c == CONNECTCHAR) 
531     {
532       return TRUE;
533     }
534
535 # ifdef HASALTCONNECTCHAR
536   if (c == ALTCONNECTCHAR)
537     {
538       return TRUE;
539     }
540 # endif
541
542   return FALSE;
543 }
544
This page took 0.07973 seconds and 5 git commands to generate.