Metropoli BBS
VIEWER: slunix.c MODE: TEXT (ASCII)
/* Unix system calls */
/* Copyright (c) 1992, 1995 John E. Davis
 * All rights reserved.
 *
 * You may distribute under the terms of either the GNU General Public
 * License or the Perl Artistic License.
 */

#include "config.h"
#include "sl-feat.h"

#include <stdio.h>
#if defined (__EMX__) || defined(__BORLANDC__)
# include <io.h>		       /* for chmod */
#endif

#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <time.h>

#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif

#include <errno.h>
#include <string.h>

#include "slang.h"
#include "_slang.h"

static int push_stat_struct (struct stat *st)
{
   char *field_names [11];
   unsigned char field_types[11];
   VOID_STAR field_values [11];
   int int_values [11];
   unsigned int i;

   field_names [0] = "st_dev"; int_values [0] = (int) st->st_dev;
   field_names [1] = "st_ino"; int_values [1] = (int) st->st_ino;
   field_names [2] = "st_mode"; int_values [2] = (int) st->st_mode;
   field_names [3] = "st_nlink"; int_values [3] = (int) st->st_nlink;
   field_names [4] = "st_uid"; int_values [4] = (int) st->st_uid;
   field_names [5] = "st_gid"; int_values [5] = (int) st->st_gid;
   field_names [6] = "st_rdev"; int_values [6] = (int) st->st_rdev;
   field_names [7] = "st_size"; int_values [7] = (int) st->st_size;
   field_names [8] = "st_atime"; int_values [8] = (int) st->st_atime;
   field_names [9] = "st_mtime"; int_values [9] = (int) st->st_mtime;
   field_names [10] = "st_ctime"; int_values [10] = (int) st->st_ctime;

   for (i = 0; i < 11; i++)
     {
	field_types [i] = SLANG_INT_TYPE;
	field_values [i] = (VOID_STAR) (int_values + i);
     }

   return _SLstruct_create_struct (11, field_names, field_types, field_values);
}

static void unix_stat_file (char *file)
{
   struct stat st;

   if (-1 == stat (file, &st))
     {
	_SLerrno_errno = errno;
	_SLang_push_null ();
     }
   else push_stat_struct (&st);
}

static void unix_lstat_file (char *file)
{
#ifdef HAVE_LSTAT
   struct stat st;

   if (-1 == lstat (file, &st))
     {
	_SLerrno_errno = errno;
	_SLang_push_null ();
     }
   else push_stat_struct (&st);
#else
   unix_stat_file (file);
#endif
}

/* Well, it appears that on some systems, these are not defined.  Here I
 * provide them.  These are derived from the Linux stat.h file.
 */

#ifndef S_ISLNK
# ifdef S_IFLNK
#   define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
# else
#   define S_ISLNK(m) 0
# endif
#endif

#ifndef S_ISREG
# ifdef S_IFREG
#   define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
# else
#   define S_ISREG(m) 0
# endif
#endif

#ifndef S_ISDIR
# ifdef S_IFDIR
#   define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
# else
#   define S_ISDIR(m) 0
# endif
#endif

#ifndef S_ISCHR
# ifdef S_IFCHR
#   define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
# else
#   define S_ISCHR(m) 0
# endif
#endif

#ifndef S_ISBLK
# ifdef S_IFBLK
#   define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
# else
#   define S_ISBLK(m) 0
# endif
#endif

#ifndef S_ISFIFO
# ifdef S_IFIFO
#   define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
# else
#   define S_ISFIFO(m) 0
# endif
#endif

#ifndef S_ISSOCK
# ifdef S_IFSOCK
#   define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
# else
#   define S_ISSOCK(m) 0
# endif
#endif

static int stat_is (char *what, int *mode_ptr)
{
   int ret;
   int st_mode = *mode_ptr;

   if (!strcmp (what, "sock")) ret = S_ISSOCK(st_mode);
   else if (!strcmp (what, "fifo")) ret = S_ISFIFO(st_mode);
   else if (!strcmp (what, "blk")) ret = S_ISBLK(st_mode);
   else if (!strcmp (what, "chr")) ret = S_ISCHR(st_mode);
   else if (!strcmp (what, "dir")) ret = S_ISDIR(st_mode);
   else if (!strcmp (what, "reg")) ret = S_ISREG(st_mode);
   else if (!strcmp (what, "lnk")) ret = S_ISLNK(st_mode);
   else
     {
	ret = -1;
	SLang_verror (SL_INVALID_PARM, "stat_is: Unrecognized type.");
     }
   SLang_free_slstring (what);
   return ret;
}

static int unix_chmod (char *file, int *mode)
{
   if (-1 == chmod(file, (mode_t) *mode))
     {
	_SLerrno_errno = errno;
	return -1;
     }
   return 0;
}

#if HAVE_CHOWN
static int unix_chown (char *file, int *owner, int *group)
{
   int ret;

   if (-1 == (ret = chown(file, (uid_t) *owner, (gid_t) *group)))
     _SLerrno_errno = errno;
   return ret;
}
#endif

#ifdef HAVE_KILL
/* This is mainly designed to check pids, but who knows.... */
static int unix_kill (int *pid, int *sig)
{
   int ret;

   if (-1 == (ret = kill ((pid_t) *pid, *sig)))
     _SLerrno_errno = errno;
   return ret;
}
#endif

static char *unix_ctime (int *tt)
{
   char *t;

   t = ctime ((time_t *) tt);
   t[24] = 0;  /* knock off \n */
   return (t);
}

static SLang_Intrin_Fun_Type slunix_table[] =
{
#ifdef HAVE_KILL
   MAKE_INTRINSIC_II("unix_kill", unix_kill, SLANG_INT_TYPE),
#endif
   MAKE_INTRINSIC_I("unix_ctime", unix_ctime, SLANG_STRING_TYPE),
   MAKE_INTRINSIC_S("lstat_file", unix_lstat_file, SLANG_VOID_TYPE),
   MAKE_INTRINSIC_S("stat_file", unix_stat_file, SLANG_VOID_TYPE),
   MAKE_INTRINSIC_SI("stat_is", stat_is, SLANG_INT_TYPE),
#if HAVE_CHOWN
   MAKE_INTRINSIC_SII("chown", unix_chown, SLANG_INT_TYPE),
#endif
   MAKE_INTRINSIC_SI("chmod", unix_chmod, SLANG_INT_TYPE),
   SLANG_END_TABLE
};

int SLang_init_slunix (void)
{
   if ((-1 == SLadd_intrin_fun_table (slunix_table, "__SLUNIX__"))
       || (-1 == _SLerrno_init ()))
     return -1;
   return 0;
}
[ RETURN TO DIRECTORY ]