2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2000 University of Virginia,
4 ** Massachusetts Institute of Technology
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.
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.
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.
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
27 ** Provide a system-independent interface to system-dependent
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.
38 * - added OS/2 specific includes before osd_getPid()
39 * - handle files like in WIN32 for OS/2 in osd_fileExists()
44 # include <sys/types.h>
45 # include <sys/stat.h>
46 /* Fix suggested by Lars Rasmussen */
50 # include "lclintMacros.nf"
57 extern int stat (const char *, /*@out@*/ struct stat *);
60 static bool osd_executableFileExists (char *);
62 static bool nextdir (char **p_current_dir, /*@out@*/ char **p_dir,
63 /*@out@*/ size_t *p_len);
65 extern char *LSLRootName (char *filespec)
67 char *result, *startName, *tail;
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';
81 extern /*@observer@*/ char *
82 osd_getEnvironment (char *env, /*@returned@*/ char *def)
84 char *ret = osd_getEnvironmentVariable (env);
99 ** FUNCTIONAL DESCRIPTION:
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.
105 ** FORMAL PARAMETERS:
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.
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
125 ** Requires that parameters, path and file, are valid C strings.
131 extern /*@null@*/ /*@observer@*/ char *
134 /* Would something different be better for windows? */
135 return (osd_getEnvironmentVariable ("HOME"));
138 filestatus osd_findOnLarchPath (char *file, char **returnPath)
140 return (osd_getPath (cstring_toCharsSafe (context_getLarchPath ()), file, returnPath));
144 osd_getPath (char *path, char *file, char **returnPath)
149 char aPath[MAXPATHLEN];
150 filestatus rVal = OSD_FILENOTFOUND; /* assume file not found. */
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. */
159 (*file == CONNECTCHAR || (file[0] != '\0' && file[1] == ':')))
161 (*file == CONNECTCHAR))
164 /* No path specified. Look for it in the current directory. */
166 strcpy (&aPath[0], file);
168 if (osd_fileExists (&aPath[0]))
170 rVal = OSD_FILEFOUND;
171 *returnPath = dmalloc (strlen (&aPath[0]) + 1);
172 strcpy (*returnPath, &aPath[0]);
177 /* Path specified. Loop through directories in path looking for the */
178 /* first occurrence of the file. */
180 while (nextdir (&fullPath, &dirPtr, &dirLen) &&
181 rVal == OSD_FILENOTFOUND)
183 if ((dirLen + strlen (file) + 2) <= MAXPATHLEN)
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);
191 if (osd_fileExists (&aPath[0]))
193 rVal = OSD_FILEFOUND;
194 *returnPath = (char *) dmalloc (strlen (&aPath[0]) + 1);
195 strcpy (*returnPath, &aPath[0]);
200 rVal = OSD_PATHTOOLONG;
209 osd_getExePath (char *path, char *file, char **returnPath)
214 char aPath[MAXPATHLEN];
215 filestatus rVal = OSD_FILENOTFOUND; /* assume file not found. */
217 fullPath = osd_getEnvironmentVariable (path);
219 if (fullPath == NULL)
221 /* No path specified. Look for it in the current directory. */
223 strcpy (&aPath[0], file);
225 if (osd_fileExists (&aPath[0]))
227 rVal = OSD_FILEFOUND;
228 *returnPath = dmalloc (strlen (&aPath[0]) + 1);
229 strcpy (*returnPath, &aPath[0]);
235 ** Path specified. Loop through directories in path looking
236 ** for the first occurrence of the file.
239 while (nextdir (&fullPath, &dirPtr, &dirLen) &&
240 rVal == OSD_FILENOTFOUND)
242 if ((dirLen + strlen (file) + 2) <= MAXPATHLEN)
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);
250 if (osd_executableFileExists (&aPath[0]))
252 rVal = OSD_FILEFOUND;
253 *returnPath = dmalloc (strlen (&aPath[0]) + 1);
254 strcpy (*returnPath, &aPath[0]);
259 rVal = OSD_PATHTOOLONG;
268 osd_fileExists (char *filespec)
272 return (stat (filespec, &buf) == 0);
274 # if defined (WIN32) || defined (OS2)
275 FILE *test = fopen (filespec, "r");
278 (void) fclose (test);
292 osd_executableFileExists (/*@unused@*/ char *filespec)
296 # if defined(__IBMC__) && defined(OS2)
297 # define S_IFMT (unsigned short)0xFFFF
299 if (stat (filespec, &buf) == 0)
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 */
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;
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)
330 ** FUNCTIONAL DESCRIPTION:
332 ** Find the next directory from a directory path.
334 ** FORMAL PARAMETERS:
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
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
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.
355 ** TRUE if we found another directory.
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.
369 nextdir (d_char *current_dir, d_char *dir, size_t *len)
373 if (**current_dir == '\0')
379 *dir = (**current_dir == SEPCHAR ? *current_dir + 1 : *current_dir);
381 /* Find next ':' or end of string */
382 for (tchar = *dir; *tchar != '\0' && *tchar != SEPCHAR; tchar++)
387 *current_dir = tchar;
388 *len = size_fromInt (tchar - *dir);
392 /*@observer@*/ /*@null@*/ char *osd_getEnvironmentVariable (char *var)
397 # if defined(OS2) || defined(MSDOS)
412 extern /*@external@*/ int _flushall (void) /*@modifies fileSystem@*/ ;
416 extern /*@external@*/ int system (const char *) /*@modifies fileSystem@*/ ;
418 int osd_system (const char *cmd)
421 /* system ("printenv"); */
433 extern /*@external@*/ int unlink (const char *) /*@modifies fileSystem@*/ ;
437 int osd_unlink (const char *fname)
441 res = unlink (fname);
445 llcontbug (message ("Cannot remove temporary file: %s (%s)",
446 cstring_fromChars (fname),
447 cstring_fromChars (strerror (errno))));
453 # if defined (WIN32) || (defined(OS2) && defined(__IBMC__))
454 # include <process.h>
459 # if defined (WIN32) || defined (OS2) && defined (__IBMC__)
466 # if defined (WIN32) || defined (OS2) && defined (__IBMC__)
467 int pid = _getpid ();
469 pid_t pid = getpid ();
475 cstring osd_fixDefine (char *x)
478 if (strchr (x, '\'') != NULL) {
480 ** If there is a single quote, check for <ident>='<string>' and
481 ** produce <ident>=<string>
484 char *eqs = strchr (x, '=');
487 if (eqs[1] == '\'') {
488 char *endqu = strrchr (x, '\'');
491 if (*(endqu - 1) != '\\') {
492 if (*(endqu + 1) == '\0') {
497 def = cstring_fromChars (eqs + 2);
499 res = cstring_concat (cstring_fromChars (x), def);
510 return cstring_fromCharsNew (x);
513 bool osd_fileIsReadable (char *f)
515 FILE *fl = fopen (f, "r");
517 if (fl != (FILE *) 0)
519 check (fclose (fl) == 0);
528 bool osd_isConnectChar (char c)
530 if (c == CONNECTCHAR)
535 # ifdef HASALTCONNECTCHAR
536 if (c == ALTCONNECTCHAR)