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
Wrap
C/C++ Source or Header
|
1997-09-12
|
11KB
|
452 lines
/*
** Copyright (c) Massachusetts Institute of Technology 1994-1997.
** All Rights Reserved.
** Unpublished rights reserved under the copyright laws of
** the United States.
**
** THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
** OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
**
** This code is distributed freely and may be used freely under the
** following conditions:
**
** 1. This notice may not be removed or altered.
**
** 2. Works derived from this code are not distributed for
** commercial gain without explicit permission from MIT
** (for permission contact lclint-request@larch.lcs.mit.edu).
*/
/*
** osd.c
**
** Provide a system-independent interface to system-dependent
** file operations.
**
** AUTHORS:
**
** Gary Feldman, Technical Languages and Environments, DECspec project
** Joe Wild, Technical Languages and Environments, DECspec project
**
** CREATION DATE: 17 Sep 1990
**
** DESIGN ISSUES:
**
** We use #ifdef macros to implement each function.
**
** Since we want this module to be shareable, we haven't used LSL memory
** management routines. Instead, we use smalloc. This is less than ideal.
** A better solution would be to have a project-specific require file that
** defines macros for the memory management routines.
*/
/*
* This is osd.c from Mike Smith's Win32 port of lclint.
* Modified by Herbert 04/19/97:
* - added conditional 'OS2' to conditional 'MSDOS'
* - added include of new header portab.h.
* - changed '/' to macro.
* - added DOS / OS/2 specific stuff in osd_getPath.
*/
/*@-allmacros*/
/*@ignore@*/
# include <sys/types.h>
# include <sys/stat.h>
/*@end@*/
/*@=allmacros*/
# include "lclintMacros.nf"
# include "basic.h"
# include "osd.h"
# include "portab.h"
/* from stat.h */
/*@ignore@*/
extern int stat (const char *, /*@out@*/ struct stat *);
/*@end@*/
static bool unixExeFileExists (char *p_filespec);
static bool nextdir (char **p_current_dir, /*@out@*/ char **p_dir,
/*@out@*/ size_t *p_len);
/*
**++
** FUNCTIONAL DESCRIPTION:
**
** This function computes the rootname of a file specification, in the
** sense of the :r modifier of csh.
**
** FORMAL PARAMETERS:
**
** char *filespec - The file specification from which we will extract a
** rootname.
**
** RETURN VALUE:
**
** char * - The rootname of the file specification. The space for this
** rootname is allocated with smalloc and should be freed by the client with
** free.
**
** SIDE EFFECTS:
**
** Space is allocated.
**
** DESIGN:
**
** On VMS, we use sys$parse to parse the file spec, and return the file
** name. On Ultrix, we manually parse the file spec, removing everything
** upto and including the last / (removing nothing if there are no
** slashes), and removing the last period (if any) to the end of the spec.
**
** VMS parsing is incomplete, because of the possibility of getting a
** quoted DECnet file name. For example, NODE::"/remote/dir/file.ext" will
** result in "/remote/dir/file.ext" (including the quotes) as the file
** name; this is not usable for building an output file. It's not at all
** clear whether a solution exists for this.
**
** Memory management is hardwired to smalloc/free. This ought to be made
** more flexible, by somehow using a user-defined memory management system.
**
**--
*/
char *getLarchPath (void)
{
char *larchpath = getenv (LARCH_PATH);
if (larchpath != NULL)
{
return larchpath;
}
else
{
char *res = DEFAULT_LARCHPATH;
/*
** Not just return DEFAULT_LARCHPATH to make sure there
** is a compile-time error if DEFAULT_LARCHPATH is not
** defined appropriately.
*/
return res;
}
}
extern char *LSLRootName (char *filespec)
{
char *result, *startName, *tail;
size_t nameLength;
tail = strrchr (filespec, CONNECTCHAR);
startName = (tail == NULL ? filespec : &tail[1]);
tail = strrchr (startName, '.');
nameLength = (tail == NULL ? strlen (startName)
: size_fromInt (tail - startName));
result = dmalloc (nameLength + 1);
strncpy (result, startName, nameLength);
result[(int) nameLength] = '\0';
return result;
}
extern /*@observer@*/ char *
osd_getEnvironment (char *env, /*@returned@*/ char *def)
{
char *ret = getenv (env);
if (ret == NULL)
{
return def;
}
else
{
return ret;
}
}
/*
**++
** FUNCTIONAL DESCRIPTION:
**
** This function attempts to locate a file in a search list. On VMS, it
** just concatinates the path and file names, and then lets RMS do the
** searching. On Ultrix, it searches for the file on the path.
**
** FORMAL PARAMETERS:
**
** path: search path where to look for the file.
** file: name of file to search for.
** returnPath: if a file is found, this is where the concatenated
** directory and file name are returned.
**
** RETURN VALUE:
**
** OSD_FILEFOUND: the file was found on the search list.
** OSD_FILENOTFOUND the file was not found.
** OSD_PATHTOOLONG the concatenated directory and file name are too
** long.
**
** SIDE EFFECTS:
**
** None
**
** PRECONDITIONS:
**
** Requires that parameters, path and file, are valid C strings.
**
**
**--
*/
extern /*@null@*/ /*@observer@*/ char *
osd_getHomeDir ()
{
return (getenv ("HOME"));
}
filestatus osd_getLarchPath (char *file, char **returnPath)
{
return (osd_getPath (getLarchPath (), file, returnPath));
}
extern filestatus
osd_getPath (char *path, char *file, char **returnPath)
{
char *fullPath;
char *dirPtr;
size_t dirLen;
char aPath[MAXPATHLEN];
filestatus rVal; /* return Value */
rVal = OSD_FILENOTFOUND; /* assume file not found. */
/* get the path for UNIX. */
fullPath = path;
if (fullPath == NULL ||
# if defined(OS2) || defined(MSDOS)
/* under OS/2 and MSDOS the includePath may be empty, if so, search
* the current directory. */
*fullPath == '\0' ||
(*file == CONNECTCHAR || (file[0] != '\0' && file[1] == ':')))
# else
(*file == CONNECTCHAR))
# endif
{
/* No path specified. Look for it in the current directory. */
strcpy (&aPath[0], file);
if (unixFileExists (&aPath[0]))
{
rVal = OSD_FILEFOUND;
*returnPath = dmalloc (strlen (&aPath[0]) + 1);
strcpy (*returnPath, &aPath[0]);
}
}
else
{
/* Path specified. Loop through directories in path looking for the */
/* first occurrence of the file. */
while (nextdir (&fullPath, &dirPtr, &dirLen) &&
rVal == OSD_FILENOTFOUND)
{
if ((dirLen + strlen (file) + 2) <= MAXPATHLEN)
{
/* Cat directory and filename, and see if file exists. */
strncpy (&aPath[0], dirPtr, dirLen);
strcpy (&aPath[0] + dirLen, ""); /* Null terminate aPath. */
strcat (&aPath[0], CONNECTSTR);
strcat (&aPath[0], file);
if (unixFileExists (&aPath[0]))
{
rVal = OSD_FILEFOUND;
*returnPath = (char *) dmalloc (strlen (&aPath[0]) + 1);
strcpy (*returnPath, &aPath[0]);
}
}
else
{
rVal = OSD_PATHTOOLONG;
}
}
}
return rVal;
}
extern filestatus
osd_getExePath (char *path, char *file, char **returnPath)
{
char *fullPath;
char *dirPtr;
size_t dirLen;
char aPath[MAXPATHLEN];
filestatus rVal; /* return Value */
rVal = OSD_FILENOTFOUND; /* assume file not found. */
/* get the path for UNIX. */
fullPath = getenv (path);
if (fullPath == NULL)
{
/* No path specified. Look for it in the current directory. */
strcpy (&aPath[0], file);
if (unixFileExists (&aPath[0]))
{
rVal = OSD_FILEFOUND;
*returnPath = dmalloc (strlen (&aPath[0]) + 1);
strcpy (*returnPath, &aPath[0]);
}
}
else
{
/*
** Path specified. Loop through directories in path looking
** for the first occurrence of the file.
*/
while (nextdir (&fullPath, &dirPtr, &dirLen) &&
rVal == OSD_FILENOTFOUND)
{
if ((dirLen + strlen (file) + 2) <= MAXPATHLEN)
{
/* Cat directory and filename, and see if file exists. */
strncpy (&aPath[0], dirPtr, dirLen);
strcpy (&aPath[0] + dirLen, ""); /* Null terminate aPath. */
strcat (&aPath[0], CONNECTSTR);
strcat (&aPath[0], file);
if (unixExeFileExists (&aPath[0]))
{
rVal = OSD_FILEFOUND;
*returnPath = dmalloc (strlen (&aPath[0]) + 1);
strcpy (*returnPath, &aPath[0]);
}
}
else
{
rVal = OSD_PATHTOOLONG;
}
}
}
return rVal;
}
bool
unixFileExists (char *filespec)
{
struct stat buf;
return (stat (filespec, &buf) == 0);
}
/*
** Isn't really just unix anymore...
*/
bool
unixExeFileExists (char *filespec)
{
struct stat buf;
# if defined(__IBMC__) && defined(OS2)
# define S_IFMT (unsigned short)0xFFFF
# endif
if (stat (filespec, &buf) == 0)
{
/* mask by file type */
if ((buf.st_mode & S_IFMT) != S_IFDIR) /* not a directory */
{
/* as long as it is an executable file */
# if defined(__IBMC__) && defined(OS2)
int com_or_exe_pos = strlen( filespec) - 4;
return stricmp( &filespec[com_or_exe_pos], ".exe") == 0
|| stricmp( &filespec[com_or_exe_pos], ".com") == 0
|| stricmp( &filespec[com_or_exe_pos], ".bat") == 0
|| stricmp( &filespec[com_or_exe_pos], ".cmd") == 0;
# else
return (((buf.st_mode & S_IXUSR)
# if !defined(MSDOS) && !defined(OS2)
| (buf.st_mode & S_IXGRP) |
(buf.st_mode & S_IXOTH)
# endif
) != 0);
# endif
}
}
return (FALSE);
}
/*
**++
** FUNCTIONAL DESCRIPTION:
**
** Find the next directory from a directory path.
**
** FORMAL PARAMETERS:
**
** char ** current_dir :
** Points to the current position in the path string. The first time
** you call this routine, this should point to the first character of
** the path. On return, this will be updated to point to the
** terminating \0 or : of the first directory found. You can then pass
** it unchanged for subsequent calls; this routine will correctly skip
** over the :.
**
** char ** dir :
** On exit, this will point to the first character of the directory
** that was found. This will be a pointer directly into the client's
** path string.
**
** unsigned int * len :
** On exit, this will contain the length of the directory that was
** found, not counting any terminating \0 or :. If no directory was
** found, this will be 0.
**
** RETURN VALUE:
** TRUE if we found another directory.
** FALSE otherwise.
**
** DESIGN:
**
** We return a pointer and length, rather than a string, because of a)
** historical reasons; and b) this avoids having to allocate storage.
**
**
**
**--
*/
static bool
nextdir (d_char *current_dir, d_char *dir, size_t *len)
{
char *tchar;
if (**current_dir == '\0')
{
*len = 0;
return FALSE;
}
*dir = (**current_dir == SEPCHAR ? *current_dir + 1 : *current_dir);
/* Find next ':' or end of string */
for (tchar = *dir; *tchar != '\0' && *tchar != SEPCHAR; tchar++)
{
;
}
*current_dir = tchar;
*len = size_fromInt (tchar - *dir);
return TRUE;
}