1
0
Files
irix-657m-src/eoe/cmd/bru/sys.c
2022-09-29 17:59:04 +03:00

2396 lines
43 KiB
C
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/************************************************************************
* *
* 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 <stdarg.h>
#include <errno.h>
#if RMT /* Want remote mag tape support via /etc/rmt */
# if SYSRMTLIB /* Use the installed system version */
# include <local/rmt.h> /* 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 <stdio.h>
#if (unix || xenix)
# include <sys/types.h>
# include "utsname.h"
# include <sys/stat.h>
# include <pwd.h>
# include <grp.h>
#else
# include "sys.h"
# include "utsname.h"
#endif
#include <ctype.h>
#if unix || xenix
# if BSD4_2
# include <sys/wait.h> /* Used by s_wait() */
# include <sys/time.h> /* Used by s_timezone() */
# else
# include <time.h>
# endif
# if HAVE_SYMLINKS
# include <errno.h>
# endif
#endif
#if amiga
# include <errno.h>
#endif
#if sgi
#include <string.h>
#include <stdlib.h>
#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 <sys/utsname.h> 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 <sys/ssioctl.h> /* 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 <fcntl.h>
#include <sys/diskformat.h>
#include <sys/ioctl.h>
#include <errno.h>
#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);
}