home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / lclint.zip / lclint-2_3h-os2-bin.zip / build / src / osd.c
C/C++ Source or Header  |  1997-09-12  |  11KB  |  452 lines

  1. /*
  2. ** Copyright (c) Massachusetts Institute of Technology 1994-1997.
  3. **          All Rights Reserved.
  4. **          Unpublished rights reserved under the copyright laws of
  5. **          the United States.
  6. **
  7. ** THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  8. ** OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  9. **
  10. ** This code is distributed freely and may be used freely under the 
  11. ** following conditions:
  12. **
  13. **     1. This notice may not be removed or altered.
  14. **
  15. **     2. Works derived from this code are not distributed for
  16. **        commercial gain without explicit permission from MIT 
  17. **        (for permission contact lclint-request@larch.lcs.mit.edu).
  18. */
  19. /*
  20. ** osd.c
  21. **
  22. ** Provide a system-independent interface to system-dependent
  23. ** file operations.
  24. **
  25. **  AUTHORS:
  26. **
  27. **      Gary Feldman, Technical Languages and Environments, DECspec project
  28. **      Joe Wild, Technical Languages and Environments, DECspec project
  29. **
  30. **  CREATION DATE:  17 Sep 1990
  31. **
  32. **  DESIGN ISSUES:
  33. **
  34. **      We use #ifdef macros to implement each function.
  35. **
  36. **    Since we want this module to be shareable, we haven't used LSL memory
  37. **    management routines.  Instead, we use smalloc.  This is less than ideal.
  38. **    A better solution would be to have a project-specific require file that
  39. **    defines macros for the memory management routines.
  40. */
  41. /*
  42.  * This is osd.c from Mike Smith's Win32 port of lclint.
  43.  * Modified by Herbert 04/19/97:
  44.  * - added conditional 'OS2' to conditional 'MSDOS'
  45.  * - added include of new header portab.h.
  46.  * - changed '/' to macro.
  47.  * - added DOS / OS/2 specific stuff in osd_getPath.
  48.  */
  49.  
  50. /*@-allmacros*/
  51. /*@ignore@*/
  52. # include <sys/types.h>
  53. # include <sys/stat.h>
  54. /*@end@*/
  55. /*@=allmacros*/
  56. # include "lclintMacros.nf"
  57. # include "basic.h"
  58. # include "osd.h"
  59. # include "portab.h"
  60.  
  61. /* from stat.h */
  62. /*@ignore@*/
  63. extern int stat (const char *, /*@out@*/ struct stat *);
  64. /*@end@*/
  65.  
  66. static bool unixExeFileExists (char *p_filespec);
  67. static bool nextdir (char **p_current_dir, /*@out@*/ char **p_dir, 
  68.              /*@out@*/ size_t *p_len);
  69. /*
  70. **++
  71. **  FUNCTIONAL DESCRIPTION:
  72. **
  73. **      This function computes the rootname of a file specification, in the
  74. **    sense of the :r modifier of csh.
  75. **
  76. **  FORMAL PARAMETERS:
  77. **
  78. **      char *filespec    -   The file specification from which we will extract a
  79. **    rootname.
  80. **
  81. **  RETURN VALUE:
  82. **
  83. **      char *    - The rootname of the file specification.  The space for this
  84. **    rootname is allocated with smalloc and should be freed by the client with
  85. **    free.
  86. **
  87. **  SIDE EFFECTS:
  88. **
  89. **      Space is allocated.
  90. **
  91. **  DESIGN:
  92. **
  93. **      On VMS, we use sys$parse to parse the file spec, and return the file
  94. **    name.  On Ultrix, we manually parse the file spec, removing everything
  95. **    upto and including the last / (removing nothing if there are no
  96. **    slashes), and removing the last period (if any) to the end of the spec.
  97. **
  98. **    VMS parsing is incomplete, because of the possibility of getting a
  99. **    quoted DECnet file name.  For example, NODE::"/remote/dir/file.ext" will
  100. **    result in "/remote/dir/file.ext" (including the quotes) as the file
  101. **    name; this is not usable for building an output file.  It's not at all
  102. **    clear whether a solution exists for this.
  103. **
  104. **    Memory management is hardwired to smalloc/free.  This ought to be made
  105. **    more flexible, by somehow using a user-defined memory management system.
  106. **
  107. **--
  108. */
  109.  
  110. char *getLarchPath (void)
  111. {
  112.   char *larchpath = getenv (LARCH_PATH);
  113.  
  114.   if (larchpath != NULL)
  115.     {
  116.       return larchpath;
  117.     }
  118.   else
  119.     {
  120.       char *res = DEFAULT_LARCHPATH;
  121.  
  122.       /*
  123.       ** Not just return DEFAULT_LARCHPATH to make sure there
  124.       ** is a compile-time error if DEFAULT_LARCHPATH is not
  125.       ** defined appropriately.
  126.       */
  127.  
  128.       return res;
  129.     }
  130. }
  131.  
  132. extern char *LSLRootName (char *filespec)
  133. {
  134.   char *result, *startName, *tail;
  135.   size_t nameLength;
  136.  
  137.   tail = strrchr (filespec, CONNECTCHAR);
  138.   startName = (tail == NULL ? filespec : &tail[1]);
  139.   tail = strrchr (startName, '.');
  140.   nameLength = (tail == NULL ? strlen (startName) 
  141.         : size_fromInt (tail - startName));
  142.   result = dmalloc (nameLength + 1);
  143.   strncpy (result, startName, nameLength);
  144.   result[(int) nameLength] = '\0';
  145.   return result;
  146. }
  147.  
  148. extern /*@observer@*/ char *
  149. osd_getEnvironment (char *env, /*@returned@*/ char *def)
  150. {
  151.   char *ret = getenv (env);
  152.  
  153.   if (ret == NULL)
  154.     {
  155.       return def;
  156.     }
  157.   else
  158.     {
  159.       return ret;
  160.     }
  161. }
  162.  
  163.  
  164. /*
  165. **++
  166. **  FUNCTIONAL DESCRIPTION:
  167. **
  168. **      This function attempts to locate a file in a search list.  On VMS, it
  169. **    just concatinates the path and file names, and then lets RMS do the
  170. **    searching.  On Ultrix, it searches for the file on the path.
  171. **
  172. **  FORMAL PARAMETERS:
  173. **
  174. **      path:        search path where to look for the file.
  175. **    file:        name of file to search for.
  176. **    returnPath: if a file is found, this is where the concatenated
  177. **            directory and file name are returned.
  178. **
  179. **  RETURN VALUE:
  180. **
  181. **      OSD_FILEFOUND:        the file was found on the search list.
  182. **    OSD_FILENOTFOUND    the file was not found.
  183. **    OSD_PATHTOOLONG        the concatenated directory and file name are too
  184. **                long.
  185. **
  186. **  SIDE EFFECTS:
  187. **
  188. **      None
  189. **
  190. **  PRECONDITIONS:
  191. **
  192. **      Requires that parameters, path and file, are valid C strings.
  193. **
  194. **
  195. **--
  196. */
  197.  
  198. extern /*@null@*/ /*@observer@*/ char *
  199.   osd_getHomeDir ()
  200. {
  201.   return (getenv ("HOME"));
  202. }
  203.  
  204. filestatus osd_getLarchPath (char *file, char **returnPath)
  205. {
  206.   return (osd_getPath (getLarchPath (), file, returnPath));
  207. }
  208.  
  209. extern filestatus
  210. osd_getPath (char *path, char *file, char **returnPath)
  211. {
  212.   char *fullPath;
  213.   char *dirPtr;
  214.   size_t dirLen;
  215.   char aPath[MAXPATHLEN];
  216.   filestatus rVal;        /* return Value */
  217.  
  218.   rVal = OSD_FILENOTFOUND;    /* assume file not found. */
  219.  
  220.   /* get the path for UNIX. */
  221.   fullPath = path;
  222.  
  223.   if (fullPath == NULL || 
  224. # if defined(OS2) || defined(MSDOS)
  225.     /* under OS/2 and MSDOS the includePath may be empty, if so, search 
  226.      * the current directory. */
  227.     *fullPath == '\0' || 
  228.     (*file == CONNECTCHAR || (file[0] != '\0' && file[1] == ':')))
  229. # else
  230.     (*file == CONNECTCHAR))
  231. # endif
  232.     {
  233.      /* No path specified. Look for it in the current directory.        */
  234.  
  235.       strcpy (&aPath[0], file);
  236.  
  237.       if (unixFileExists (&aPath[0]))
  238.     {
  239.       rVal = OSD_FILEFOUND;
  240.          *returnPath = dmalloc (strlen (&aPath[0]) + 1);
  241.       strcpy (*returnPath, &aPath[0]);
  242.     }
  243.     }
  244.   else
  245.     {
  246.      /* Path specified. Loop through directories in path looking for the */
  247.      /* first occurrence of the file.                    */
  248.       while (nextdir (&fullPath, &dirPtr, &dirLen) &&
  249.          rVal == OSD_FILENOTFOUND)
  250.     {
  251.       if ((dirLen + strlen (file) + 2) <= MAXPATHLEN)
  252.         {
  253.          /* Cat directory and filename, and see if file exists.  */
  254.           strncpy (&aPath[0], dirPtr, dirLen);
  255.           strcpy (&aPath[0] + dirLen, "");    /* Null terminate aPath. */
  256.           strcat (&aPath[0], CONNECTSTR);
  257.           strcat (&aPath[0], file);
  258.  
  259.           if (unixFileExists (&aPath[0]))
  260.         {
  261.           rVal = OSD_FILEFOUND;
  262.              *returnPath = (char *) dmalloc (strlen (&aPath[0]) + 1);
  263.           strcpy (*returnPath, &aPath[0]);
  264.         }
  265.         }
  266.       else
  267.         {
  268.           rVal = OSD_PATHTOOLONG;
  269.         }
  270.     }    
  271.     }
  272.  
  273.   return rVal;
  274. }
  275.  
  276. extern filestatus
  277. osd_getExePath (char *path, char *file, char **returnPath)
  278. {
  279.   char *fullPath;
  280.   char *dirPtr;
  281.   size_t dirLen;
  282.   char aPath[MAXPATHLEN];
  283.   filestatus rVal;        /* return Value */
  284.  
  285.   rVal = OSD_FILENOTFOUND;    /* assume file not found. */
  286.  
  287.   /* get the path for UNIX. */
  288.   fullPath = getenv (path);
  289.  
  290.   if (fullPath == NULL)
  291.     {
  292.      /* No path specified. Look for it in the current directory. */
  293.  
  294.       strcpy (&aPath[0], file);
  295.  
  296.       if (unixFileExists (&aPath[0]))
  297.     {
  298.       rVal = OSD_FILEFOUND;
  299.          *returnPath = dmalloc (strlen (&aPath[0]) + 1);
  300.       strcpy (*returnPath, &aPath[0]);
  301.     }
  302.     }
  303.   else
  304.     {
  305.      /* 
  306.      ** Path specified. Loop through directories in path looking
  307.      ** for the first occurrence of the file.                    
  308.      */
  309.  
  310.       while (nextdir (&fullPath, &dirPtr, &dirLen) &&
  311.          rVal == OSD_FILENOTFOUND)
  312.     {
  313.       if ((dirLen + strlen (file) + 2) <= MAXPATHLEN)
  314.         {
  315.           /* Cat directory and filename, and see if file exists.  */
  316.           strncpy (&aPath[0], dirPtr, dirLen);
  317.           strcpy (&aPath[0] + dirLen, ""); /* Null terminate aPath. */
  318.           strcat (&aPath[0], CONNECTSTR);
  319.           strcat (&aPath[0], file);
  320.  
  321.           if (unixExeFileExists (&aPath[0]))
  322.         {
  323.           rVal = OSD_FILEFOUND;
  324.              *returnPath = dmalloc (strlen (&aPath[0]) + 1);
  325.           strcpy (*returnPath, &aPath[0]);
  326.         }
  327.         }
  328.       else
  329.         {
  330.           rVal = OSD_PATHTOOLONG;
  331.         }
  332.     }
  333.     }
  334.  
  335.   return rVal;
  336. }
  337.  
  338. bool
  339. unixFileExists (char *filespec)
  340. {
  341.   struct stat buf;
  342.  
  343.   return (stat (filespec, &buf) == 0);
  344. }
  345.  
  346. /*
  347. ** Isn't really just unix anymore...
  348. */
  349.  
  350. bool
  351. unixExeFileExists (char *filespec)
  352. {
  353.   struct stat buf;
  354. # if defined(__IBMC__) && defined(OS2)
  355. # define S_IFMT (unsigned short)0xFFFF
  356. # endif
  357.   if (stat (filespec, &buf) == 0)
  358.     { 
  359.       /* mask by file type */
  360.       if ((buf.st_mode & S_IFMT) != S_IFDIR) /* not a directory */
  361.     {
  362.       /* as long as it is an executable file */
  363. # if defined(__IBMC__) && defined(OS2)
  364.       int com_or_exe_pos = strlen( filespec) - 4;
  365.       return stricmp( &filespec[com_or_exe_pos], ".exe") == 0
  366.         || stricmp( &filespec[com_or_exe_pos], ".com") == 0
  367.         || stricmp( &filespec[com_or_exe_pos], ".bat") == 0
  368.         || stricmp( &filespec[com_or_exe_pos], ".cmd") == 0;
  369. # else
  370.       return (((buf.st_mode & S_IXUSR)
  371. # if !defined(MSDOS) && !defined(OS2) 
  372.            | (buf.st_mode & S_IXGRP) |
  373.            (buf.st_mode & S_IXOTH)
  374. # endif
  375.            ) != 0);
  376. # endif
  377.     }
  378.     }
  379.  
  380.   return (FALSE);
  381.  
  382. }
  383.  
  384. /*
  385. **++
  386. **  FUNCTIONAL DESCRIPTION:
  387. **
  388. **      Find the next directory from a directory path.
  389. **
  390. **  FORMAL PARAMETERS:
  391. **
  392. **      char ** current_dir :
  393. **        Points to the current position in the path string.  The first time
  394. **        you call this routine, this should point to the first character of
  395. **        the path.  On return, this will be updated to point to the
  396. **        terminating \0 or : of the first directory found.  You can then pass
  397. **        it unchanged for subsequent calls; this routine will correctly skip
  398. **        over the :.
  399. **
  400. **    char ** dir :
  401. **        On exit, this will point to the first character of the directory
  402. **        that was found.  This will be a pointer directly into the client's
  403. **        path string.
  404. **
  405. **    unsigned int * len :
  406. **        On exit, this will contain the length of the directory that was
  407. **        found, not counting any terminating \0 or :.  If no directory was
  408. **        found, this will be 0.
  409. **
  410. **  RETURN VALUE:
  411. **    TRUE if we found another directory.
  412. **    FALSE otherwise.
  413. **
  414. **  DESIGN:
  415. **
  416. **      We return a pointer and length, rather than a string, because of a)
  417. **    historical reasons; and b) this avoids having to allocate storage.
  418. **
  419. **
  420. **
  421. **--
  422. */
  423.  
  424. static bool
  425. nextdir (d_char *current_dir, d_char *dir, size_t *len)
  426. {
  427.   char *tchar;
  428.  
  429.   if (**current_dir == '\0')
  430.     {
  431.       *len = 0;
  432.       return FALSE;
  433.     }
  434.  
  435.   *dir = (**current_dir == SEPCHAR ? *current_dir + 1 : *current_dir);
  436.   
  437.   /* Find next ':' or end of string */
  438.   for (tchar = *dir; *tchar != '\0' && *tchar != SEPCHAR; tchar++)
  439.     {
  440.       ;
  441.     }
  442.   
  443.   *current_dir = tchar;
  444.   *len = size_fromInt (tchar - *dir);
  445.   return TRUE;
  446. }
  447.  
  448.  
  449.  
  450.  
  451.  
  452.