Main Page   Alphabetical List   Compound List   File List   Compound Members   File Members  

osd.c

Go to the documentation of this file.
00001 /*
00002 ** LCLint - annotation-assisted static program checker
00003 ** Copyright (C) 1994-2000 University of Virginia,
00004 **         Massachusetts Institute of Technology
00005 **
00006 ** This program is free software; you can redistribute it and/or modify it
00007 ** under the terms of the GNU General Public License as published by the
00008 ** Free Software Foundation; either version 2 of the License, or (at your
00009 ** option) any later version.
00010 ** 
00011 ** This program is distributed in the hope that it will be useful, but
00012 ** WITHOUT ANY WARRANTY; without even the implied warranty of
00013 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 ** General Public License for more details.
00015 ** 
00016 ** The GNU General Public License is available from http://www.gnu.org/ or
00017 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00018 ** MA 02111-1307, USA.
00019 **
00020 ** For information on lclint: lclint-request@cs.virginia.edu
00021 ** To report a bug: lclint-bug@cs.virginia.edu
00022 ** For more information: http://lclint.cs.virginia.edu
00023 */
00024 /*
00025 ** osd.c
00026 **
00027 ** Provide a system-independent interface to system-dependent
00028 ** file operations.
00029 */
00030 
00031 /*
00032  * Modified by Herbert 04/19/97:
00033  * - added conditional 'OS2' to conditional 'MSDOS'
00034  * - added include of new header portab.h.
00035  * - changed '/' to macro.
00036  * - added DOS / OS/2 specific stuff in osd_getPath.
00037  * Herbert 06/12/2000:
00038  * - added OS/2 specific includes before osd_getPid()
00039  * - handle files like in WIN32 for OS/2 in osd_fileExists()
00040  */
00041 
00042 /*@-allmacros*/
00043 /*@ignore@*/
00044 # include <sys/types.h>
00045 # include <sys/stat.h>
00046 /* Fix suggested by Lars Rasmussen */
00047 # include <errno.h>
00048 /*@end@*/
00049 /*@=allmacros*/
00050 # include "lclintMacros.nf"
00051 # include "basic.h"
00052 # include "osd.h"
00053 # include "portab.h"
00054 
00055 /* from stat.h */
00056 /*@ignore@*/
00057 extern int stat (const char *, /*@out@*/ struct stat *);
00058 /*@end@*/
00059 
00060 static bool osd_executableFileExists (char *);
00061 
00062 static bool nextdir (char **p_current_dir, /*@out@*/ char **p_dir, 
00063                      /*@out@*/ size_t *p_len);
00064 
00065 extern char *LSLRootName (char *filespec)
00066 {
00067   char *result, *startName, *tail;
00068   size_t nameLength;
00069 
00070   tail = strrchr (filespec, CONNECTCHAR);
00071   startName = (tail == NULL ? filespec : &tail[1]);
00072   tail = strrchr (startName, '.');
00073   nameLength = (tail == NULL ? strlen (startName) 
00074                 : size_fromInt (tail - startName));
00075   result = dmalloc (nameLength + 1);
00076   strncpy (result, startName, nameLength);
00077   result[(int) nameLength] = '\0';
00078   return result;
00079 }
00080 
00081 extern /*@observer@*/ char *
00082 osd_getEnvironment (char *env, /*@returned@*/ char *def)
00083 {
00084   char *ret = osd_getEnvironmentVariable (env);
00085 
00086   if (ret == NULL)
00087     {
00088       return def;
00089     }
00090   else
00091     {
00092       return ret;
00093     }
00094 }
00095 
00096 
00097 /*
00098 **++
00099 **  FUNCTIONAL DESCRIPTION:
00100 **
00101 **      This function attempts to locate a file in a search list.  On VMS, it
00102 **      just concatinates the path and file names, and then lets RMS do the
00103 **      searching.  On Ultrix, it searches for the file on the path.
00104 **
00105 **  FORMAL PARAMETERS:
00106 **
00107 **      path:       search path where to look for the file.
00108 **      file:       name of file to search for.
00109 **      returnPath: if a file is found, this is where the concatenated
00110 **                  directory and file name are returned.
00111 **
00112 **  RETURN VALUE:
00113 **
00114 **      OSD_FILEFOUND:      the file was found on the search list.
00115 **      OSD_FILENOTFOUND    the file was not found.
00116 **      OSD_PATHTOOLONG     the concatenated directory and file name are too
00117 **                          long.
00118 **
00119 **  SIDE EFFECTS:
00120 **
00121 **      None
00122 **
00123 **  PRECONDITIONS:
00124 **
00125 **      Requires that parameters, path and file, are valid C strings.
00126 **
00127 **
00128 **--
00129 */
00130 
00131 extern /*@null@*/ /*@observer@*/ char *
00132   osd_getHomeDir ()
00133 {
00134   /* Would something different be better for windows? */
00135   return (osd_getEnvironmentVariable ("HOME"));
00136 }
00137 
00138 filestatus osd_findOnLarchPath (char *file, char **returnPath)
00139 {
00140   return (osd_getPath (cstring_toCharsSafe (context_getLarchPath ()), file, returnPath));
00141 }
00142 
00143 extern filestatus
00144 osd_getPath (char *path, char *file, char **returnPath)
00145 {
00146   char *fullPath;
00147   char *dirPtr;
00148   size_t dirLen;
00149   char aPath[MAXPATHLEN];
00150   filestatus rVal = OSD_FILENOTFOUND;   /* assume file not found. */
00151 
00152   fullPath = path;
00153 
00154   if (fullPath == NULL || 
00155 # if defined(OS2) || defined(MSDOS) || defined(WIN32)
00156     /* under OS/2 and MSDOS the includePath may be empty, if so, search 
00157      * the current directory. */
00158     *fullPath == '\0' || 
00159     (*file == CONNECTCHAR || (file[0] != '\0' && file[1] == ':')))
00160 # else
00161      (*file == CONNECTCHAR))
00162 # endif
00163     {
00164      /* No path specified. Look for it in the current directory.            */
00165 
00166       strcpy (&aPath[0], file);
00167 
00168       if (osd_fileExists (&aPath[0]))
00169         {
00170           rVal = OSD_FILEFOUND;
00171           *returnPath = dmalloc (strlen (&aPath[0]) + 1);
00172           strcpy (*returnPath, &aPath[0]);
00173         }
00174     }
00175   else
00176     {
00177      /* Path specified. Loop through directories in path looking for the */
00178      /* first occurrence of the file.                               */
00179 
00180       while (nextdir (&fullPath, &dirPtr, &dirLen) &&
00181              rVal == OSD_FILENOTFOUND)
00182         {
00183           if ((dirLen + strlen (file) + 2) <= MAXPATHLEN)
00184             {
00185              /* Cat directory and filename, and see if file exists.  */
00186               strncpy (&aPath[0], dirPtr, dirLen);
00187               strcpy (&aPath[0] + dirLen, "");  /* Null terminate aPath. */
00188               strcat (&aPath[0], CONNECTSTR);
00189               strcat (&aPath[0], file);
00190 
00191               if (osd_fileExists (&aPath[0]))
00192                 {
00193                   rVal = OSD_FILEFOUND;
00194                   *returnPath = (char *) dmalloc (strlen (&aPath[0]) + 1);
00195                   strcpy (*returnPath, &aPath[0]);
00196                 }
00197             }
00198           else
00199             {
00200               rVal = OSD_PATHTOOLONG;
00201             }
00202         }       
00203     }
00204 
00205   return rVal;
00206 }
00207 
00208 extern filestatus
00209 osd_getExePath (char *path, char *file, char **returnPath)
00210 {
00211   char *fullPath;
00212   char *dirPtr;
00213   size_t dirLen;
00214   char aPath[MAXPATHLEN];
00215   filestatus rVal = OSD_FILENOTFOUND;   /* assume file not found. */
00216   
00217   fullPath = osd_getEnvironmentVariable (path);
00218 
00219   if (fullPath == NULL)
00220     {
00221      /* No path specified. Look for it in the current directory. */
00222 
00223       strcpy (&aPath[0], file);
00224 
00225       if (osd_fileExists (&aPath[0]))
00226         {
00227           rVal = OSD_FILEFOUND;
00228           *returnPath = dmalloc (strlen (&aPath[0]) + 1);
00229           strcpy (*returnPath, &aPath[0]);
00230         }
00231     }
00232   else
00233     {
00234      /* 
00235      ** Path specified. Loop through directories in path looking
00236      ** for the first occurrence of the file.                               
00237      */
00238 
00239       while (nextdir (&fullPath, &dirPtr, &dirLen) &&
00240              rVal == OSD_FILENOTFOUND)
00241         {
00242           if ((dirLen + strlen (file) + 2) <= MAXPATHLEN)
00243             {
00244               /* Cat directory and filename, and see if file exists.  */
00245               strncpy (&aPath[0], dirPtr, dirLen);
00246               strcpy (&aPath[0] + dirLen, ""); /* Null terminate aPath. */
00247               strcat (&aPath[0], CONNECTSTR);
00248               strcat (&aPath[0], file);
00249 
00250               if (osd_executableFileExists (&aPath[0]))
00251                 {
00252                   rVal = OSD_FILEFOUND;
00253                   *returnPath = dmalloc (strlen (&aPath[0]) + 1);
00254                   strcpy (*returnPath, &aPath[0]);
00255                 }
00256             }
00257           else
00258             {
00259               rVal = OSD_PATHTOOLONG;
00260             }
00261         }
00262     }
00263 
00264   return rVal;
00265 }
00266 
00267 bool
00268 osd_fileExists (char *filespec)
00269 {
00270 # ifdef UNIX
00271   struct stat buf;
00272   return (stat (filespec, &buf) == 0);
00273 # else
00274 # if defined (WIN32) || defined (OS2)
00275   FILE *test = fopen (filespec, "r");
00276   if (test != NULL) 
00277   {
00278         (void) fclose (test);
00279         return TRUE;
00280   } 
00281   else
00282   { 
00283           return FALSE;
00284   }
00285 # else 
00286   return FALSE;
00287 # endif
00288 # endif
00289 }
00290 
00291 bool
00292 osd_executableFileExists (/*@unused@*/ char *filespec)
00293 {
00294 # ifdef UNIX
00295         struct stat buf;
00296 # if defined(__IBMC__) && defined(OS2)
00297 # define S_IFMT (unsigned short)0xFFFF
00298 # endif
00299   if (stat (filespec, &buf) == 0)
00300     { 
00301       /* mask by file type */
00302       /*@-unrecog@*/ /* S_IFMT is not defined */
00303       if ((buf.st_mode & S_IFMT) != S_IFDIR /*@=unrecog@*/) /* not a directory */
00304         {
00305           /* as long as it is an executable file */
00306 # if defined(__IBMC__) && defined(OS2)
00307       int com_or_exe_pos = strlen( filespec) - 4;
00308       return stricmp( &filespec[com_or_exe_pos], ".exe") == 0
00309         || stricmp( &filespec[com_or_exe_pos], ".com") == 0
00310         || stricmp( &filespec[com_or_exe_pos], ".bat") == 0
00311         || stricmp( &filespec[com_or_exe_pos], ".cmd") == 0;
00312 # else
00313           return (((buf.st_mode & S_IXUSR)
00314 # if !defined(MSDOS) && !defined(OS2) 
00315                    | (buf.st_mode & S_IXGRP) |
00316                    (buf.st_mode & S_IXOTH)
00317 # endif
00318                    ) != 0);
00319 # endif
00320         }
00321     }
00322 
00323 # endif
00324   return (FALSE);
00325 
00326 }
00327 
00328 /*
00329 **++
00330 **  FUNCTIONAL DESCRIPTION:
00331 **
00332 **      Find the next directory from a directory path.
00333 **
00334 **  FORMAL PARAMETERS:
00335 **
00336 **      char ** current_dir :
00337 **          Points to the current position in the path string.  The first time
00338 **          you call this routine, this should point to the first character of
00339 **          the path.  On return, this will be updated to point to the
00340 **          terminating \0 or : of the first directory found.  You can then pass
00341 **          it unchanged for subsequent calls; this routine will correctly skip
00342 **          over the :.
00343 **
00344 **      char ** dir :
00345 **          On exit, this will point to the first character of the directory
00346 **          that was found.  This will be a pointer directly into the client's
00347 **          path string.
00348 **
00349 **      unsigned int * len :
00350 **          On exit, this will contain the length of the directory that was
00351 **          found, not counting any terminating \0 or :.  If no directory was
00352 **          found, this will be 0.
00353 **
00354 **  RETURN VALUE:
00355 **      TRUE if we found another directory.
00356 **      FALSE otherwise.
00357 **
00358 **  DESIGN:
00359 **
00360 **      We return a pointer and length, rather than a string, because of a)
00361 **      historical reasons; and b) this avoids having to allocate storage.
00362 **
00363 **
00364 **
00365 **--
00366 */
00367 
00368 static bool
00369 nextdir (d_char *current_dir, d_char *dir, size_t *len)
00370 {
00371   char *tchar;
00372 
00373   if (**current_dir == '\0')
00374     {
00375       *len = 0;
00376       return FALSE;
00377     }
00378 
00379   *dir = (**current_dir == SEPCHAR ? *current_dir + 1 : *current_dir);
00380   
00381   /* Find next ':' or end of string */
00382   for (tchar = *dir; *tchar != '\0' && *tchar != SEPCHAR; tchar++)
00383     {
00384       ;
00385     }
00386   
00387   *current_dir = tchar;
00388   *len = size_fromInt (tchar - *dir);
00389   return TRUE;
00390 }
00391 
00392 /*@observer@*/ /*@null@*/ char *osd_getEnvironmentVariable (char *var)
00393 {
00394 # ifdef UNIX
00395         return getenv (var);
00396 # else
00397 # if defined(OS2) || defined(MSDOS)
00398         return getenv (var);
00399 # else
00400 # if defined(WIN32)
00401         return getenv (var);
00402 # else
00403         return NULL;
00404 # endif
00405 # endif
00406 # endif
00407 }
00408 
00409 # ifndef NOLCL
00410 
00411 # ifdef WIN32
00412 extern /*@external@*/ int _flushall (void) /*@modifies fileSystem@*/ ;
00413 # endif
00414 
00415 # ifndef system
00416 extern /*@external@*/ int system (const char *) /*@modifies fileSystem@*/ ;
00417 # endif
00418 int osd_system (const char *cmd)
00419 {
00420   int res;
00421     /* system ("printenv"); */
00422 # ifdef WIN32
00423   (void) _flushall (); 
00424 # endif
00425 
00426   res = system (cmd);
00427   return res;
00428 }
00429 # endif
00430 
00431 # ifndef unlink
00432 /*@-redecl@*/
00433 extern /*@external@*/ int unlink (const char *) /*@modifies fileSystem@*/ ;
00434 /*@=redecl@*/
00435 # endif
00436 
00437 int osd_unlink (const char *fname)
00438 {
00439   int res;
00440 
00441   res = unlink (fname);
00442 
00443   if (res != 0)
00444     {
00445       llcontbug (message ("Cannot remove temporary file: %s (%s)",
00446                           cstring_fromChars (fname),
00447                           cstring_fromChars (strerror (errno))));
00448     }
00449   
00450   return res;
00451 }
00452 
00453 # if defined (WIN32) || (defined(OS2) && defined(__IBMC__))
00454 # include <process.h>
00455 # elif defined OS2
00456 # include <unistd.h>
00457 # endif
00458 
00459 # if defined (WIN32) || defined (OS2) && defined (__IBMC__)
00460 int
00461 # else
00462 int /* pid_t */
00463 # endif
00464 osd_getPid ()
00465 {
00466 # if defined (WIN32) || defined (OS2) && defined (__IBMC__)
00467   int pid = _getpid ();
00468 # else
00469   pid_t pid = getpid ();
00470 # endif
00471 
00472   return (int) pid;
00473 }
00474   
00475 cstring osd_fixDefine (char *x)
00476 {
00477 # ifdef UNIX
00478   if (strchr (x, '\'') != NULL) {
00479     /*
00480     ** If there is a single quote, check for <ident>='<string>' and 
00481     ** produce <ident>=<string>
00482     */
00483 
00484     char *eqs = strchr (x, '=');
00485 
00486     if (eqs != NULL) {
00487       if (eqs[1] == '\'') {
00488         char *endqu = strrchr (x, '\'');
00489 
00490         if (endqu != NULL) {
00491           if (*(endqu - 1) != '\\') {
00492             if (*(endqu + 1) == '\0') {
00493               cstring res;
00494               cstring def;
00495 
00496               *endqu = '\0';
00497               def = cstring_fromChars (eqs + 2);
00498               eqs[1] = '\0';
00499               res = cstring_concat (cstring_fromChars (x), def);
00500                       return res;
00501             }
00502           }
00503         }
00504       }
00505     }
00506   } 
00507 
00508 # endif
00509 
00510   return cstring_fromCharsNew (x);
00511 }
00512 
00513 bool osd_fileIsReadable (char *f)
00514 {
00515   FILE *fl = fopen (f, "r");
00516 
00517   if (fl != (FILE *) 0)
00518     {
00519       check (fclose (fl) == 0);
00520       return (TRUE);
00521     }
00522   else
00523     {
00524       return (FALSE);
00525     }
00526 }
00527 
00528 bool osd_isConnectChar (char c)
00529 {
00530   if (c == CONNECTCHAR) 
00531     {
00532       return TRUE;
00533     }
00534 
00535 # ifdef HASALTCONNECTCHAR
00536   if (c == ALTCONNECTCHAR)
00537     {
00538       return TRUE;
00539     }
00540 # endif
00541 
00542   return FALSE;
00543 }
00544 

Generated at Fri Nov 3 18:57:43 2000 for LCLint by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000