/************************************************************************ * * * Copyright (c) 1984, Fred Fish * * All Rights Reserved * * (Major additions by Arnold Robbins at Georgia Tech) * * * * This software and/or documentation is protected by U.S. * * Copyright Law (Title 17 United States Code). Unauthorized * * reproduction and/or sales may result in imprisonment of up * * to 1 year and fines of up to $10,000 (17 USC 506). * * Copyright infringers may also be subject to civil liability. * * * ************************************************************************ */ /* * FILE * * sys.c runtime support library calls * * SCCS * * @(#)sys.c 9.11 5/11/88 * * DESCRIPTION * * Calls to the runtime support library are localized here * to aid portability and modification and/or inclusion * of custom versions. * * This form of interface adds an extra level of function * call overhead, but the benefits for modification or * debugging purposes outweigh the negligible decrease * in efficiency. (Use the profiler to discover just * how little time is actually spent in these routines!) * * There is some question about the best way to deal with * situations in which functions like "printf" return * error results. This generally indicates a severe * problem with the environment or corrupted runtime * data space. In any case, it is probably undesirable * to continue execution under those circumstances, so * we abort with an IOT signal and core dump. * * An additional advantage of having these functions * centralized is that lint will only have one version * of the library call to complain about. This * considerably reduces the typical size and complexity * of the lint output log. * */ #include "autoconfig.h" #include #include #if RMT /* Want remote mag tape support via /etc/rmt */ # if SYSRMTLIB /* Use the installed system version */ # include /* Remote mag tape functions, if available */ # else /* Else use our local internal copy */ # include "rmt.h" /* Local copy's include file */ # endif #endif #if (amiga && LATTICE) #define NARGS /* stdio.h defines some args incompatibly */ #endif #include #if (unix || xenix) # include # include "utsname.h" # include # include # include #else # include "sys.h" # include "utsname.h" #endif #include #if unix || xenix # if BSD4_2 # include /* Used by s_wait() */ # include /* Used by s_timezone() */ # else # include # endif # if HAVE_SYMLINKS # include # endif #endif #if amiga # include #endif #if sgi #include #include #endif #include "typedefs.h" /* Type definitions */ #include "config.h" #include "dbug.h" /* Macro based debugger file */ #include "manifest.h" /* Manifest constants */ #include "macros.h" /* Useful macros */ #include "errors.h" /* Error codes */ /* * FUNCTION * * s_fprintf call the fprintf function * * SYNOPSIS * * * DESCRIPTION * * Invokes the library "fprintf" function. We call the * internal version of vprintf and let it deal with the * variable arguments problem. */ /*VARARGS2*/ int s_fprintf (FILE *stream, char *format, ...) { int rtnval; va_list args; va_start (args, format); rtnval = vfprintf (stream, format, args); va_end (args); return (rtnval); } int s_vfprintf (FILE *stream, char *format, va_list args) { return(vfprintf (stream, format, args)); } /* * FUNCTION * * s_sprintf call the sprintf function * * DESCRIPTION * * Invokes the library "sprintf" function. We call the internal * form of vsprintf and let it deal with the variable arguments * problem. * */ /*VARARGS2*/ int s_sprintf (char *s, char *format, ...) { int rtnval; va_list args; va_start (args, format); rtnval = vsprintf (s, format, args); va_end (args); return (rtnval); } /* * FUNCTION * * s_fflush invoke the library fflush function * * SYNOPSIS * * VOID s_fflush (stream) * FILE *stream; * * DESCRIPTION * * Invokes the library fflush function. Any error is * immediately fatal. * */ VOID s_fflush (stream) FILE *stream; { DBUG_ENTER ("s_flush"); if (fflush (stream) == EOF) { if(stream != stderr) fprintf(stderr, "bru: fflush failed: %s\n", strerror(errno)); exit(2); } DBUG_VOID_RETURN; } /* * FUNCTION * * s_open invoke file open library function * * SYNOPSIS * * int s_open (path, oflag [ , mode ]) * char *path; * int oflag, mode; * * DESCRIPTION * * Invoke the library function to open a file. Path points * to a path name, oflag is for the file status flags, and * mode is the file mode if the file is created. * */ int s_open (path, oflag, mode) char *path; int oflag, mode; { register int rtnval; extern int open (); /* See open(2) */ DBUG_ENTER ("s_open"); DBUG_PRINT ("open", ("file \"%s\", flag %d, mode %o", path, oflag, mode)); #ifdef amiga if (AccessRaw (path, 0) == 0) { DBUG_PRINT ("xopen", ("open '%s' as a raw device file", path)); rtnval = OpenRaw (path, oflag, mode); } else { DBUG_PRINT ("xopen", ("open '%s' as a normal file", path)); rtnval = open (path, oflag, mode); } #else rtnval = open (path, oflag, mode); #endif DBUG_PRINT ("open", ("open on stream %d", rtnval)); DBUG_RETURN (rtnval); } /* * FUNCTION * * s_close invoke the low level file close facility * * SYNOPSIS * * int s_close (fildes) * int fildes; * * DESCRIPTION * * Close the file for the given file descriptor. * */ int s_close (fildes) int fildes; { register int rtnval; extern int close (); /* See close(2) */ DBUG_ENTER ("s_close"); DBUG_PRINT ("close", ("close stream %d", fildes)); #ifdef amiga if (IsRawFd (fildes)) { rtnval = CloseRaw (fildes); } else { rtnval = close (fildes); } #else rtnval = close (fildes); #endif DBUG_RETURN (rtnval); } /* * FUNCTION * * s_access invoke low level access library routine * * SYNOPSIS * * int s_access (path, amode) * char *path; * int amode; * * DESCRIPTION * * Invoke low level library routine "access" to test files * for accessibility. * */ int s_access (path, amode) char *path; int amode; { register int rtnval; extern int access (); /* See access(2) */ DBUG_ENTER ("s_access"); DBUG_PRINT ("access", ("test '%s' for access %d", path, amode)); #ifdef amiga if ((rtnval = AccessRaw (path, amode)) != 0) { rtnval = access (path, amode); } #else rtnval = access (path, amode); #endif DBUG_PRINT ("access", ("result = %d", rtnval)); DBUG_RETURN (rtnval); } /* * FUNCTION * * s_read invoke library function to read from file * * SYNOPSIS * * int s_read (fildes, buf, nbyte) * int fildes; * char *buf; * UINT nbyte; * * DESCRIPTION * * Invoke library function to read from file. * */ int s_read (fildes, buf, nbyte) int fildes; char *buf; UINT nbyte; { register int rtnval; extern int read (); /* See read(2) */ #ifdef amiga if (IsRawFd (fildes)) { rtnval = ReadRaw (fildes, buf, nbyte); } else { rtnval = read (fildes, buf, nbyte); } #else rtnval = read (fildes, buf, nbyte); #endif return (rtnval); } /* * FUNCTION * * s_chown invoke library function to change file owner * * SYNOPSIS * * int s_chown (path, owner, group) * char *path; * int owner, group; * * DESCRIPTION * * Invoke low level library routine to change ownership of file. * */ int s_chown (path, owner, group) char *path; int owner, group; { register int rtnval; extern int chown (); /* See chown(2) */ DBUG_ENTER ("s_chown"); #if unix || xenix rtnval = chown (path, owner, group); #else rtnval = 0; #endif DBUG_RETURN (rtnval); } /* * FUNCTION * * s_sleep invoke library function to sleep for N seconds * * SYNOPSIS * * VOID s_sleep (seconds) * UINT seconds; * * DESCRIPTION * * Invoke library function to sleep for specified number of * seconds. * */ VOID s_sleep (seconds) UINT seconds; { #if unix || xenix #if BSD4_2 extern int sleep (); /* See sleep(3C) */ #else extern UINT sleep (); /* See sleep(3C) */ #endif #endif #ifdef amiga extern int Delay (); #endif DBUG_ENTER ("s_sleep"); #if unix || xenix (VOID) sleep (seconds); #endif #ifdef amiga (VOID) Delay ((long) (50 * seconds)); #endif DBUG_VOID_RETURN; } /* * FUNCTION * * s_uname invoke library function to get system info * * SYNOPSIS * * int s_uname (name) * struct my_utsname *name; * * DESCRIPTION * * Invoke library function to get information about host system. * * Previous versions just either picked up a copy of utsname from * the file, or the faked version. In both cases * the structure was identical, and of the same size. Then along * came xenix release 3.0, with a slightly different layout for * the utsname structure, and I realised that it was a bad idea * to blindly use the utsname structure directly in the declarations * to describe archive blocks. This is really an internal data * structure containing system information, that simply happens * to have a one-to-one mapping with a system structure on some * systems, but not all. Thus was born the my_utsname structure * and the policy of filling the my_utsname structure from the * actual contents of a real utsname structure, if available. * */ int s_uname (name) struct my_utsname *name; { register int rtnval; #ifndef sgi extern int uname (); /* See uname(2) */ #endif extern struct utsname utsname; extern char *s_strncpy (); DBUG_ENTER ("s_uname"); rtnval = uname (&utsname); (VOID) s_strncpy (name -> sysname, utsname.sysname, UTSELSZ - 1); (VOID) s_strncpy (name -> nodename, utsname.nodename, UTSELSZ - 1); (VOID) s_strncpy (name -> release, utsname.release, UTSELSZ - 1); (VOID) s_strncpy (name -> version, utsname.version, UTSELSZ - 1); #ifdef xenix (VOID) s_strncpy (name -> machine, "i80286", UTSELSZ - 1); #else (VOID) s_strncpy (name -> machine, utsname.machine, UTSELSZ - 1); #endif DBUG_RETURN (rtnval); } /* * FUNCTION * * s_umask invoke library function to set/get file mask * * SYNOPSIS * * int s_umask (cmask) * int cmask; * * DESCRIPTION * * Invoke library function to set and get the file creation mask. * */ int s_umask (cmask) int cmask; { register int rtnval; DBUG_ENTER ("s_umask"); #if unix || xenix rtnval = umask (cmask); #else rtnval = 0; #endif DBUG_RETURN (rtnval); } /* * FUNCTION * * s_utime set file access and modification times * * SYNOPSIS * * int s_utime (path, times) * char *path; * struct {time_t x,y;} *times; * * DESCRIPTION * * Invoke the library function utime to set file access and * modification times. * * NOTES * * The structure declaration is used to match that in the * lint library /usr/lib/llib-lc, to shut up lint. * The Unix System V User's Manual has the type of the * second argument as a pointer to a structure "utimbuf", * which is not declared anywhere in the header files. * * For non-unix systems, this is currently a NOP, though * in theory it is possible to change the date for systems * like the Amiga by accessing the raw file system (yetch!). * */ /*VARARGS1*/ int s_utime (path, times) char *path; struct {time_t x, y;} *times; { register int rtnval; extern int utime (); /* See utime(2) */ DBUG_ENTER ("s_utime"); rtnval = utime (path, times); DBUG_RETURN (rtnval); } /* * FUNCTION * * s_chmod change mode of file * * SYNOPSIS * * int s_chmod (path, mode) * char *path; * int mode; * * DESCRIPTION * * Invoke library function to change the access mode of a file. * * NOTES * * On some systems there is a real problem with lint concerning the * type of the second argument (sometimes declared as unsigned short * in the lint library). The declaration used here matches the actual * code in the system V library and the System V Interface Definition * published by AT&T. If your lint complains then either fix your * library or complain to your vender. This has been fixed in the * UniPlus 5.2 lint library. * * For the Amiga, the owner modes are used. Delete permission * is always set. * */ int s_chmod (path, mode) char *path; int mode; { register int rtnval; #if unix || (amiga && LATTICE) #ifndef sgi extern int chmod (); /* See chmod(2) */ #endif #endif DBUG_ENTER ("s_chmod"); #if (amiga && LATTICE) mode >>= 5; mode &= 0xF; mode |= 1; #endif #if unix || (amiga && LATTICE) rtnval = chmod (path, mode); #else rtnval = 0; #endif #if (amiga && LATTICE && VANILLA3_10) /* * Bug in vanilla Lattice 3.10 always gives result of 0 for * mode == 0, or gives 0 for failure and -1 for success for * mode != 0. So map these to correct returns... */ if (mode != 0) { if (rtnval == 0) { rtnval = -1; } else { rtnval = 0; } } #endif DBUG_RETURN (rtnval); } /* * FUNCTION * * s_write write data to a file * * SYNOPSIS * * int s_write (fildes, buf, nbyte) * int fildes; * char *buf; * UINT nbyte; * * DESCRIPTION * * Invoke the low level I/O routine to write to a file. * */ int s_write (fildes, buf, nbyte) int fildes; char *buf; UINT nbyte; { register int rtnval; extern int write (); /* See write(2) */ #ifdef amiga if (IsRawFd (fildes)) { rtnval = WriteRaw (fildes, buf, nbyte); } else { rtnval = write (fildes, buf, nbyte); } #else rtnval = write (fildes, buf, nbyte); #endif return (rtnval); } /* * FUNCTION * * s_unlink remove a directory entry * * SYNOPSIS * * int s_unlink (path) * char *path; * * DESCRIPTION * * Invoke low level routine to remove a directory entry. * */ int s_unlink (path) char *path; { register int rtnval; extern int unlink (); /* See unlink(2) */ DBUG_ENTER ("s_unlink"); rtnval = unlink (path); DBUG_RETURN (rtnval); } /* * FUNCTION * * s_time get current system time * * SYNOPSIS * * long s_time (tloc) * long *tloc; * * DESCRIPTION * * Invoke low level routine to get system time. * * Note that BSD4_2 lint library defines both the argument and result * as typedef time_t, which is an int, and the BSD4_2 online manual * defines the types correctly (grrrrrrrr!!!!!). * */ long s_time (tloc) long *tloc; { register long rtnval; #if BSD4_2 && lint extern time_t time (); /* See time(2) */ #else #ifndef sgi extern long time (); /* See time(2) */ #endif #endif #ifdef MANX extern long manx2unix (); #endif DBUG_ENTER ("s_time"); #if BSD4_2 && lint rtnval = (long) time ((time_t *) tloc); #else rtnval = time (tloc); #endif #ifdef MANX rtnval = manx2unix (rtnval); #endif DBUG_PRINT ("time", ("time is %ld", rtnval)); DBUG_RETURN (rtnval); } /* * FUNCTION * * s_getuid get real user ID of process * * SYNOPSIS * * int s_getuid () * * DESCRIPTION * * Invoke low level routine to get the real user ID of process. * */ int s_getuid () { register int rtnval; #ifndef sgi extern int getuid (); /* See getuid(2) */ #endif DBUG_ENTER ("s_getuid"); #if unix || xenix rtnval = getuid (); #else rtnval = 0; #endif DBUG_RETURN (rtnval); } /* * FUNCTION * * s_getgid get real group ID of process * * SYNOPSIS * * int s_getgid () * * DESCRIPTION * * Invoke low level routine to get the real group ID of process. * */ int s_getgid () { register int rtnval; #ifndef sgi extern int getgid (); /* See getgid(2) */ #endif DBUG_ENTER ("s_getgid"); #if unix || xenix rtnval = getgid (); #else rtnval = 0; #endif DBUG_RETURN (rtnval); } /* * FUNCTION * * s_ctime convert internal time to string * * SYNOPSIS * * char *s_ctime (clock) * long *clock; * * DESCRIPTION * * Call standard library routine to convert from internal time * format to string form. * * Note that BSD4_2 lint library defines the argument as typedef * time_t, which is an int, and the BSD4_2 online manual defines * the type correctly (grrrrrrrr!!!!!). */ char *s_ctime (clock) long *clock; { register char *rtnval; #ifdef MANX auto long myclock; #endif #ifndef sgi extern char *ctime (); /* See ctime(3C) */ #endif DBUG_ENTER ("s_ctime"); #ifdef MANX myclock = unix2manx (*clock); clock = &myclock; DBUG_PRINT ("ctime", ("convert 'Manx' time %ld", *clock)); #endif #if BSD4_2 && lint rtnval = ctime ((time_t *) clock); #else rtnval = ctime (clock); #endif DBUG_PRINT ("ctime", ("converted to '%s'", rtnval)); DBUG_RETURN (rtnval); } /* * FUNCTION * * s_localtime convert internal time to time structure * * SYNOPSIS * * struct tm *s_localtime (clock) * long *clock; * * DESCRIPTION * * Call standard library routine to convert from internal time * format to time structure form. * * Note that BSD4_2 lint library defines the argument as "time_t *" * where time_t is typedef as an int, and the BSD4_2 online manual defines * the type correctly (grrrrrrrr!!!!!). */ struct tm *s_localtime (clock) long *clock; { register struct tm *rtnval; #ifndef sgi extern struct tm *localtime (); /* See ctime(3C) */ #endif #ifdef MANX struct manx_tm *tmp; auto long myclock; static struct tm mytm; #endif DBUG_ENTER ("s_localtime"); DBUG_PRINT ("localtime", ("convert time %ld", *clock)); #ifdef MANX myclock = unix2manx (*clock); clock = &myclock; DBUG_PRINT ("localtime", ("convert 'Manx' time %ld", *clock)); #endif #if BSD4_2 && lint rtnval = localtime ((time_t *) clock); #else rtnval = localtime (clock); #endif #ifdef MANX tmp = (struct manx_tm *) rtnval; mytm.tm_sec = tmp -> tm_sec; mytm.tm_min = tmp -> tm_min; mytm.tm_hour = tmp -> tm_hour; mytm.tm_mday = tmp -> tm_mday; mytm.tm_mon = tmp -> tm_mon; mytm.tm_year = tmp -> tm_year; mytm.tm_wday = tmp -> tm_wday; mytm.tm_yday = tmp -> tm_wday; mytm.tm_isdst = tmp -> tm_isdst; rtnval = &mytm; #endif DBUG_RETURN (rtnval); } /* * FUNCTION * * s_asctime convert time structure to ascii string * * SYNOPSIS * * char *s_asctime (tm) * struct tm *tm; * * DESCRIPTION * * Call standard library routine to convert from time structure form * to an ascii string. * */ char *s_asctime (tm) struct tm *tm; { register char *rtnval; #ifndef sgi extern char *asctime (); /* See ctime(3C) */ #endif #ifdef MANX static struct manx_tm mytm; #endif DBUG_ENTER ("s_asctime"); #ifdef MANX mytm.tm_sec = tm -> tm_sec; mytm.tm_min = tm -> tm_min; mytm.tm_hour = tm -> tm_hour; mytm.tm_mday = tm -> tm_mday; mytm.tm_mon = tm -> tm_mon; mytm.tm_year = tm -> tm_year; mytm.tm_wday = tm -> tm_wday; mytm.tm_yday = tm -> tm_wday; mytm.tm_isdst = tm -> tm_isdst; tm = (struct tm *) &mytm; #endif rtnval = asctime (tm); DBUG_PRINT ("asctime", ("asctime returns '%s'", rtnval)); DBUG_RETURN (rtnval); } /* * FUNCTION * * s_fopen open a stream * * SYNOPSIS * * FILE *s_fopen (file_name, type) * char *file_name; * char *type; * * DESCRIPTION * * Invokes the standard library routine to open a stream. * */ FILE *s_fopen (file_name, type) char *file_name; char *type; { register FILE *rtnval; #ifndef sgi extern FILE *fopen (); /* See fopen(3S) */ #endif DBUG_ENTER ("s_fopen"); rtnval = fopen (file_name, type); DBUG_RETURN (rtnval); } /* * FUNCTION * * s_mknod make a special or ordinary file * * SYNOPSIS * (nuked the code that dealt with dirs; only used for special devices) * * int s_mknod (path, mode, dev) * char *path; * int mode, dev; * * DESCRIPTION * * If called on a symbolic link, report an error, since that code * should go through s_symlink and/or s_csymlink. * */ int s_mknod (path, mode, dev) char *path; int mode, dev; { register int rtnval; extern VOID bru_error (); /* Report an error to user */ DBUG_ENTER ("s_mknod"); DBUG_PRINT ("mknod", ("make node \"%s\" mode %o device %x", path, mode, dev)); if (IS_FLNK (mode)) { bru_error (ERR_BUG, "mknod (symlink)"); rtnval = FALSE; } else rtnval = mknod (path, mode, dev); DBUG_RETURN (rtnval); } /* * FUNCTION * * s_stat get file status * * SYNOPSIS * * int s_stat (path, buf) * char *path; * struct stat64 *buf; * * DESCRIPTION * * Invoke low level routine to get file status. * * Under 4.2BSD, we use the lstat routine instead, which * will tell us whether or not we've found a symbolic link. * An lstat on a normal file acts just like regular stat. * */ /*VARARGS1*/ /* Funny stuff with 2nd arg due to rmt.h define of stat */ int s_stat (path, buf) char *path; struct stat64 *buf; { register int rtnval; #if HAVE_SYMLINKS #ifndef sgi extern int lstat64 (); /* See stat(2) */ #endif #else extern int stat64 (); /* See stat(2) */ #endif DBUG_ENTER ("s_stat"); #if HAVE_SYMLINKS rtnval = lstat64 (path, buf); #else rtnval = stat64 (path, buf); #endif DBUG_RETURN (rtnval); } /* * FUNCTION * * s_fstat get file status * * SYNOPSIS * * int s_fstat (fildes, buf) * int fildes; * struct stat64 *buf; * * DESCRIPTION * * Invoke low level routine to get file status, using an open file * descriptor. Currently only used by the directory access routines * under USG, so we don't need a BSD equivalent (lfstat ?). * */ #if (!HAVE_SEEKDIR) || amiga int s_fstat (fildes, buf) int fildes; struct stat64 *buf; { register int rtnval; #if unix || xenix #ifndef sgi extern int fstat (); /* See stat(2) */ #endif #endif DBUG_ENTER ("s_fstat"); #if unix || xenix rtnval = fstat64 (fildes, buf); #else (VOID) s_fprintf (stderr, "warning -- fstat() not implemented!\n"); rtnval = SYS_ERROR; #endif DBUG_RETURN (rtnval); } #endif /* (!HAVE_SEEKDIR) || amiga */ /* * FUNCTION * * s_malloc allocate memory from system * * SYNOPSIS * * char *s_malloc (size) * UINT size; * * DESCRIPTION * * Call standard library routine to allocate memory. * */ char *s_malloc (size) UINT size; { register char *rtnval; #ifndef sgi extern char *malloc (); /* See malloc(3C) */ #endif rtnval = malloc (size); return (rtnval); } /* * FUNCTION * * s_exit terminate process * * SYNOPSIS * * VOID s_exit (status) * int status; * * DESCRIPTION * * Call the low level routine to terminate process. * */ VOID s_exit (status) int status; { #if BSD4_2 extern int exit (); /* See exit(2) */ #else #ifndef sgi extern VOID exit (); /* See exit(2) */ #endif #endif DBUG_ENTER ("s_exit"); #if BSD4_2 (VOID) exit (status); #else exit (status); #endif DBUG_VOID_RETURN; } /* * FUNCTION * * s_getopt parse command line options * * SYNOPSIS * * int s_getopt (argc, argv, optstring) * int argc; * char **argv; * char *optstring; * */ int s_getopt (argc, argv, optstring) int argc; char **argv; char *optstring; { register int rtnval; #ifndef sgi extern int getopt (); /* See getopt(3C) */ #endif DBUG_ENTER ("s_getopt"); rtnval = getopt (argc, argv, optstring); DBUG_RETURN (rtnval); } /* * FUNCTION * * s_free free memory received via malloc * * SYNOPSIS * * VOID s_free (ptr) * char *ptr; * * DESCRIPTION * * Used to free memory allocated via the standard library * memory allocator (malloc). * */ VOID s_free (ptr) char *ptr; { #if BSD4_2 extern int free (); /* See malloc(3C) */ #else #ifndef sgi extern VOID free (); /* See malloc(3C) */ #endif #endif DBUG_ENTER ("s_free"); #if BSD4_2 (VOID) free (ptr); #else free (ptr); #endif DBUG_VOID_RETURN; } /* * FUNCTION * * s_getpwent get password file entry * * SYNOPSIS * * struct passwd *s_getpwent () * * DESCRIPTION * * Invoke standard library routine to get a password file entry. * */ #ifndef unix static BOOLEAN pwentopen = FALSE; static struct passwd pwentfake = { "root", "NONE", 0, 0, "NONE", "NONE", "NONE", "/", "/bin/sh" }; #endif struct passwd *s_getpwent () { register struct passwd *rtnval; #if unix || xenix #ifndef sgi extern struct passwd *getpwent (); /* See getpwent(3C) */ #endif rtnval = getpwent (); #else if (pwentopen == TRUE) { rtnval = (struct passwd *)NULL; } else { pwentopen = TRUE; rtnval = &pwentfake; } #endif return (rtnval); } /* * FUNCTION * * s_endpwent close password file when done with it * * SYNOPSIS * * VOID s_endpwent () * * DESCRIPTION * * Calls standard library function endpwent to close password * file when done with it. * */ VOID s_endpwent () { #if unix || xenix #if BSD4_2 extern int endpwent (); /* See getpwent(3C) */ (VOID) endpwent (); #else #ifndef sgi extern VOID endpwent (); /* See getpwent(3C) */ #endif endpwent (); #endif #else pwentopen = FALSE; #endif } /* * FUNCTION * * s_getgrent get group file entry * * SYNOPSIS * * struct group *s_getgrent () * * DESCRIPTION * * Invoke standard library routine to get a group file entry. * */ #ifndef unix static BOOLEAN grentopen = FALSE; static struct group grentfake = { "root", "NONE", 0, NULL }; #endif struct group *s_getgrent () { register struct group *rtnval; #if unix || xenix #ifndef sgi extern struct group *getgrent (); /* See getgrent(3C) */ #endif rtnval = getgrent (); #else if (grentopen == TRUE) { rtnval = (struct group *)NULL; } else { grentopen = TRUE; rtnval = &grentfake; } #endif return (rtnval); } /* * FUNCTION * * s_endgrent close group file when done with it * * SYNOPSIS * * VOID s_endgrent () * * DESCRIPTION * * Calls standard library function endpwent to close group * file when done with it. * */ VOID s_endgrent () { #if unix || xenix #if BSD4_2 extern int endgrent (); /* See getgrent(3C) */ (VOID) endgrent (); #else #ifndef sgi extern VOID endgrent (); /* See getgrent(3C) */ #endif endgrent (); #endif #else grentopen = FALSE; #endif } /* * FUNCTION * * s_signal set up signal handling * * SYNOPSIS * * int (*s_signal (sig, func))() * int sig; * int (*func)(); * * DESCRIPTION * * Set signal handling by calling low level routine "signal". * * NOTES * * There is considerable disagreement, between different implementations * and proposed standards, for the declared type of signal() and it's * second argument. For example: * * (1) System V Interface Definition from AT&T * * int (*signal (sig, func)()) { int sig; int (*func)(); * * (2) Proposed ANSI C standard * * void (*signal (sig, func)()) { int sig; void (*func)(); * * (3) 68000 System V generic release (Motorola Microport) * * int (*signal (sig, func)()) { int sig; int (*func)(); * (in library) * * int (*signal (sig, func)()) { int sig; void (*func)(); * (in lint and documentation for signal(2)) * * The inconsistency in (3) has been corrected in UniSoft's UniPlus * based on the 68000 generic release, by fixing the lint library to * be in agreement with the code and header files (change void to int). * * If your lint complains about this then complain to your vendor! * */ int (*s_signal (sig, func))() int sig; #ifdef sgi void (*func)(); #else int (*func)(); #endif { register int (*rtnval)(); #if unix || amiga #ifndef sgi extern int (*signal())(); /* See signal(2) */ #endif #endif DBUG_ENTER ("s_signal"); DBUG_PRINT ("signals", ("set signal (%d,%lx)", sig, func)); #if unix || amiga #ifdef sgi rtnval = (int (*)())signal (sig, func); #else rtnval = signal (sig, func); #endif #else DBUG_PRINT ("signals", ("signals not implemented in this system")); rtnval = (int (*)()) SYS_ERROR; #endif DBUG_PRINT ("signals", ("signal returns %d", rtnval)); DBUG_RETURN (rtnval); } /* * FUNCTION * * s_ioctl issue low level function to control device * * SYNOPSIS * * int s_ioctl (fildes, request, arg) * int fildes; * int request; * int arg; * * DESCRIPTION * * Issue the low level request to control device. * */ int s_ioctl (fildes, request, arg) int fildes, request, arg; { register int rtnval; #if unix || xenix #ifndef sgi extern int ioctl (); /* See ioctl(2) */ #endif #endif DBUG_ENTER ("s_ioctl"); #if unix || xenix #if BSD4_2 rtnval = ioctl (fildes, request, (char *) arg); #else rtnval = ioctl (fildes, request, arg); #endif #else (VOID) s_fprintf (stderr, "warning -- ioctl() not implemented!\n"); rtnval = SYS_ERROR; #endif DBUG_RETURN (rtnval); } /* * FUNCTION * * s_strcat concatenate two strings * * SYNOPSIS * * char *s_strcat (s1, s2) * char *s1, *s2; * * DESCRIPTION * * Append copy of string s2 to end of string s1. * */ char *s_strcat (s1, s2) char *s1, *s2; { register char *rtnval; #ifndef sgi extern char *strcat (); #endif rtnval = strcat (s1, s2); return (rtnval); } /* * FUNCTION * * s_strcmp compare two strings lexicographically * * SYNOPSIS * * int s_strcmp (s1, s2) * char *s1, *s2; * * DESCRIPTION * * Compare string s1 with string s2 and return an integer less * than, equal to, or greater than zero according as s1 is * lexicographically less than, equal to, or greater than s2. * */ int s_strcmp (s1, s2) char *s1, *s2; { register int rtnval; #ifndef sgi extern int strcmp (); #endif rtnval = strcmp (s1, s2); return (rtnval); } /* * FUNCTION * * s_strcpy copy strings from one location to another * * SYNOPSIS * * char *s_strcpy (s1, s2) * char *s1, *s2; * * DESCRIPTION * * Copy string s2 to s1, stopping after the null character has been * copied. * */ char *s_strcpy (s1, s2) char *s1, *s2; { register char *rtnval; #ifndef sgi extern char *strcpy (); #endif rtnval = strcpy (s1, s2); return (rtnval); } /* * FUNCTION * * s_strncpy copy strings from one location to another * * SYNOPSIS * * char *s_strncpy (s1, s2, n) * char *s1, *s2; * int n; * * DESCRIPTION * * Copy n characters from string s2 to s1, truncating s2 or * padding s1 with nulls as required. * */ char *s_strncpy (s1, s2, n) char *s1, *s2; int n; { register char *rtnval; #ifndef sgi extern char *strncpy (); #endif rtnval = strncpy (s1, s2, n); return (rtnval); } /* * FUNCTION * * s_strlen find length of string * * SYNOPSIS * * int s_strlen (s) * char *s; * * DESCRIPTION * * Count characters in string s, not including terminating null. * */ int s_strlen (s) char *s; { register int rtnval; #ifndef sgi extern int strlen (); #endif rtnval = strlen (s); return (rtnval); } /* * FUNCTION * * s_strchr find first occurance of character in string * * SYNOPSIS * * char *s_strchr (s, c) * char *s; * char c; * * DESCRIPTION * * Search forward in string s until first occurance of * string character c, returning pointer. * */ #if BSD4_2 #define strchr index #endif char *s_strchr (s, c) char *s; char c; { register char *rtnval; #if unix || xenix #ifndef sgi extern char *strchr (); #endif rtnval = strchr (s, c); #else rtnval = NULL; if (s != NULL) { while (*s != EOS && *s != c) {s++;} if (*s == c) { rtnval = s; } } #endif return (rtnval); } /* * FUNCTION * * s_strrchr find last given character in string * * SYNOPSIS * * char *s_strrchr (s, c) * char *s; * char c; * * DESCRIPTION * * Find last occurance of the given character c in the string s. * */ #if BSD4_2 #define strrchr rindex #endif char *s_strrchr (s, c) char *s; char c; { register char *rtnval; #if unix || xenix #ifndef sgi extern char *strrchr (); #endif rtnval = strrchr (s, c); #else if (s == NULL) { rtnval = NULL; } else { rtnval = s; while (*s != EOS) {s++;} while (s > rtnval && *s != c) {s--;} if (*s == c) { rtnval = s; } else { rtnval = NULL; } } #endif return (rtnval); } /* * FUNCTION * * s_mkdir make a directory node * * SYNOPSIS * * int s_mkdir (path, mode) * char *path; * int mode; * * DESCRIPTION * * Contains code to make a directory node and its entries * "." and ".." * * This is a system call under 4.2, so we just use it. * Also just a system call under UniPlus with NFS. * * Note that the effective user id must be root for this * to work. Thus this is only usable by root or if the * process is owned by root and has the SUID bit set. * * As an alternative, the system "mkdir" command could * be forked but this is much faster. This is probably * fertile ground for anyone looking for system security * loopholes. * * Note that the parent directory must be writable by the * real user. * * Under 4.2, 'mkdir' is a system call, so this routine will just * use the system call. Using the system call should help * security issues too. Similarly UniPlus with NFS... * * Note, this routine may not be completely bulletproof. How * will it behave if the name ends with a '/', as in * "/usr/bin/"? How will BSD4.2 mkdir() behave in this case? * */ /* the old hack way of doing it is in the RCS history, if you * ever need it... */ int s_mkdir (path, mode) char *path; int mode; { register int rtnval; DBUG_ENTER ("s_mkdir"); rtnval = mkdir (path, mode); DBUG_RETURN (rtnval); } /* * FUNCTION * * s_lseek seek to location in file * * SYNOPSIS * * S32BIT s_lseek (fildes, offset, whence) * int fildes; * S32BIT offset; * int whence; * * DESCRIPTION * * Invoke the standard library function to seek to file * location. * */ S32BIT s_lseek (fildes, offset, whence) int fildes; S32BIT offset; int whence; { register S32BIT rtnval; #ifndef sgi extern S32BIT lseek (); /* See lseek(2) */ #endif DBUG_ENTER ("s_lseek"); #ifdef amiga if (IsRawFd (fildes)) { rtnval = LseekRaw (fildes, offset, whence); } else { rtnval = lseek (fildes, offset, whence); } #else rtnval = lseek (fildes, offset, whence); #endif DBUG_RETURN (rtnval); } /* * FUNCTION * * s_rewind allow mixed read/writes on stream * * SYNOPSIS * * VOID s_rewind (stream) * FILE *stream; * * DESCRIPTION * * Interface to the system "rewind" call, which must * be issued each time the file access mode changes from * read to write and vice-versa. * */ VOID s_rewind (stream) FILE *stream; { #ifndef rewind /* Sometimes macro */ #if BSD4_2 extern int rewind (); /* See fseek(3S) */ #else #ifndef sgi extern VOID rewind (); /* See fseek(3S) */ #endif #endif #endif #if BSD4_2 (VOID) rewind (stream); #else #ifndef MANX /* Hack for possible manx bug on the Amiga */ rewind (stream); #endif #endif } int s_tolower (c) int c; { #ifndef tolower /* A macro on some systems */ #ifndef sgi extern int tolower (); /* See conv(3C) */ #endif #endif #if BSD4_2 /* BSD tolower blindly converts, while S5 checks, so we check for it */ if (!isupper (c)) { return (c); } else { return (tolower (c)); } #else return (tolower (c)); #endif } int s_creat (path, mode) char *path; int mode; { register int rtnval; #ifndef sgi extern int creat (); /* See creat(2) */ #endif DBUG_ENTER ("s_creat"); rtnval = creat (path, mode); DBUG_RETURN (rtnval); } int s_isdigit (c) int c; { return (isdigit (c)); } int s_atoi (str) char *str; { register int rtnval; #ifndef sgi extern int atoi (); /* See strtol(3C) */ #endif DBUG_ENTER ("s_atoi"); rtnval = atoi (str); DBUG_RETURN (rtnval); } int s_fileno (stream) FILE *stream; { return (fileno (stream)); } int s_getc (stream) FILE *stream; { DBUG_ENTER ("s_getc"); DBUG_RETURN ((int) getc (stream)); } char *s_memcpy (s1, s2, n) char *s1, *s2; int n; { #if BSD4_2 (VOID) bcopy (s2, s1, n); return (s1); #else #if xenix || (amiga && MANX) char *saved_s1 = s1; while (n-- > 0) { *s1++ = *s2++; } return (saved_s1); #else #ifndef sgi extern char *memcpy (); /* See memory(3C) */ #endif return (memcpy (s1, s2, n)); #endif #endif } int s_link (path1, path2) char *path1, *path2; { register int rtnval; #if unix || xenix #ifndef sgi extern int link (); /* See link(2) */ #endif #endif DBUG_ENTER ("s_link"); DBUG_PRINT ("link", ("link \"%s\" to existing \"%s\"", path2, path1)); #if unix || xenix rtnval = link (path1, path2); #else rtnval = SYS_ERROR; /* No obvious way to fake it */ #endif DBUG_RETURN (rtnval); } int s_putc (c, stream) char c; FILE *stream; { return (putc (c, stream)); } /* * For the amiga version, we only need to fake a dup for * stdin, stdout, or stderr by simply returning the given fildes. * This should work ok for what we want to do with it... */ int s_dup (fildes) int fildes; { register int rtnval; DBUG_ENTER ("s_dup"); #if unix || xenix rtnval = dup (fildes); #else #if amiga if (fildes == 0 || fildes == 1 || fildes == 2) { rtnval = fildes; } else { errno = EBADF; rtnval = SYS_ERROR; } #else (VOID) s_fprintf (stderr, "warning -- dup() not implemented!\n"); rtnval = SYS_ERROR; #endif #endif DBUG_RETURN (rtnval); } char *s_getenv (name) char *name; { register char *rtnval; #ifndef sgi extern char *getenv (); /* See getenv(3C) */ #endif DBUG_ENTER ("s_getenv"); rtnval = getenv (name); DBUG_RETURN (rtnval); } int s_fork () { register int rtnval; #ifndef sgi extern int fork (); /* See fork(2) */ #endif DBUG_ENTER ("s_fork"); #if unix || xenix rtnval = fork (); #else rtnval = SYS_ERROR; #endif DBUG_RETURN (rtnval); } int s_wait (stat_loc) int *stat_loc; { register int rtnval; #ifndef sgi extern int wait (); /* See wait(2) */ #endif DBUG_ENTER ("s_wait"); #if BSD4_2 rtnval = wait ((union wait *) stat_loc); #else rtnval = wait (stat_loc); #endif DBUG_RETURN (rtnval); } /* * The BSD4_2 lint library has a totally screwed up entry for execv. * It has no explicitly declared return type, so defaults to int, but * then does not explicitly return anything so lint complains about * any code that tries to use the return value. */ int s_execv (path, argv) char *path; char *argv[]; { register int rtnval; #ifndef sgi extern int execv (); /* See exec(2) */ #endif DBUG_ENTER ("s_execv"); #if BSD4_2 && lint (VOID) execv (path, argv); /* Lint library lies! */ rtnval = -1; #else #ifdef amiga (VOID) s_fprintf(stderr, "Sorry, execv not yet implemented!\n"); rtnval = -1; #else rtnval = execv (path, argv); #endif #endif DBUG_RETURN (rtnval); } int s_fclose (stream) FILE *stream; { register int rtnval; #ifndef sgi extern int fclose (); /* See fclose(3S) */ #endif DBUG_ENTER ("s_fclose"); rtnval = fclose (stream); DBUG_RETURN (rtnval); } char *s_fgets (s, n, stream) char *s; int n; FILE *stream; { register char *rtnval; #ifndef sgi extern char *fgets (); /* See gets(3S) */ #endif rtnval = fgets (s, n, stream); return (rtnval); } /* * FUNCTION * * s_readlink read a symbolic link * * SYNOPSIS * * int s_readlink (name, buf, size); * char *name; * char *buf; * int size; * * DESCRIPTION * * Read a symbolic link on systems that have symbolic links. * Is a NOP on other systems and just returns SYS_ERROR. * * Under SUN's 3.2 OS, readlink() may return garbage if the first * argument is one of the special files in /dev. So, we must * avoid calling readlink for anything except real symbolic links. * Readlink is documented to leave ENXIO in errno if the name is * not a symbolic link, so that's what we do also... * */ /*ARGSUSED*/ /* Turn off lint checking for unused args in s_readlink */ int s_readlink (name, buf, size) char *name, *buf; int size; { register int rtnval; #if HAVE_SYMLINKS struct stat64 sbuf; /* Used to avoid SUN 3.2 bug */ #ifndef sgi extern int readlink (); /* See readlink(2) */ #endif extern int errno; /* System error return code */ #endif DBUG_ENTER ("s_readlink"); #if HAVE_SYMLINKS if (s_stat (name, &sbuf) == SYS_ERROR) { rtnval = SYS_ERROR; } else { if (IS_FLNK (sbuf.st_mode)) { rtnval = readlink (name, buf, size); } else { errno = ENXIO; rtnval = SYS_ERROR; } } #else rtnval = SYS_ERROR; #endif DBUG_RETURN (rtnval); } /* * FUNCTION * * s_timezone get local time zone information * * S5 defines an extern long timezone == difference in seconds between * GMT and local standard time. BSD does not have this extern, but it * will tell us what our timezone is in minutes west of GMT. So we * just compute it on the fly. * */ #define SEC_PER_MIN (60) #if BSD4_2 long s_timezone () { auto long timezone; struct timeval tv; struct timezone tz; (VOID) gettimeofday (&tv, &tz); timezone = tz.tz_minuteswest * SEC_PER_MIN; return (timezone); } #endif #if USG5 || (amiga && LATTICE) long s_timezone () { #ifndef sgi extern long timezone; extern VOID tzset (); #endif tzset (); return (timezone); } #endif #if amiga && MANX long s_timezone () { return (0L); } #endif #if HAVE_SYMLINKS /* * Supply these routines on our own for 4.2. Make them static (if * appropriate) to keep this stuff all in one file. */ /* s_symlink --- make a symbolic link */ int s_symlink (name1, name2) char *name1, *name2; { register int rtnval; #ifndef sgi extern int symlink (); /* See symlink(2) */ #endif DBUG_ENTER ("s_symlink"); rtnval = symlink (name1, name2); DBUG_RETURN (rtnval); } #ifdef pyr /* s_csymlink --- make a conditional symbolic link */ int s_csymlink (name1, name2) char *name1, *name2; { register int rtnval; extern int csymlink (); /* See csymlink(2) for OSx */ DBUG_ENTER ("s_symlink"); rtnval = csymlink (name1, name2); DBUG_RETURN (rtnval); } #endif /* pyr */ #endif /* HAVE_SYMLINKS */ #if AUX #include /* Contains special ioctl's for Apple A/UX */ #endif int s_eject (fildes) int fildes; { int rtnval = 0; DBUG_ENTER ("s_eject"); #if AUX rtnval = s_ioctl (fildes, AL_EJECT, 0); #endif DBUG_RETURN (rtnval); } #if AUX #include #include #include #include #endif s_format (fildes) int fildes; { int status = 0; #if AUX auto struct diskformat fmt; fmt.d_secsize = 512; fmt.d_dens = 2; fmt.d_fsec = 0; fmt.d_lsec = 1599; fmt.d_fhead = 0; fmt.d_lhead = 1; fmt.d_fcyl = 0; fmt.d_lcyl = 79; fmt.d_ileave = 1; status = !(ioctl (fildes, UIOCFORMAT, &fmt) == -1); #endif return (status); }