1999-09-14 09:32:05 -04:00
|
|
|
/* Scheme48/scsh Unix system interface.
|
|
|
|
** Routines that require custom C support.
|
|
|
|
** Copyright (c) 1993,1994 by Olin Shivers.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "sysdep.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <sys/signal.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/times.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <fcntl.h> /* for O_RDWR */
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/param.h> /* For gethostname() */
|
|
|
|
|
|
|
|
#include <netdb.h>
|
|
|
|
/* This lossage brought to you by Solaris and BIND */
|
|
|
|
/* We thank Solaris for forcing users to get a new BIND */
|
|
|
|
/* We thank BIND for blowing away the Solaris includea for MAXHOSTNAMELEN */
|
|
|
|
#ifndef MAXHOSTNAMELEN
|
|
|
|
#include <arpa/nameser.h>
|
|
|
|
#ifndef MAXHOSTNAMELEN
|
|
|
|
#define MAXHOSTNAMELEN MAXDNAME
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <pwd.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <sys/wait.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <utime.h>
|
2000-05-16 04:43:01 -04:00
|
|
|
#ifdef HAVE_CRYPT_H
|
|
|
|
#include <crypt.h>
|
|
|
|
#endif
|
1999-09-14 09:32:05 -04:00
|
|
|
#include "cstuff.h"
|
|
|
|
#include "machine/stdio_dep.h"
|
|
|
|
|
|
|
|
/* Make sure our exports match up w/the implementation: */
|
|
|
|
#include "syscalls1.h"
|
|
|
|
|
|
|
|
extern int errno;
|
|
|
|
extern char **environ;
|
|
|
|
|
|
|
|
/* Sux because it's dependent on 32-bitness. */
|
|
|
|
#define hi8(i) (((i)>>24) & 0xff)
|
|
|
|
#define lo24(i) ((i) & 0xffffff)
|
|
|
|
#define comp8_24(hi, lo) (((hi)<<24) + (lo))
|
|
|
|
|
|
|
|
|
|
|
|
/* Process stuff
|
|
|
|
*******************************************************************************
|
|
|
|
** wait, exec
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Args: pid, flags; returns [retval, status] */
|
|
|
|
|
2000-07-27 09:32:12 -04:00
|
|
|
s48_value wait_pid(s48_value s48_pid, s48_value s48_flags)
|
1999-09-14 09:32:05 -04:00
|
|
|
{
|
2000-07-27 09:32:12 -04:00
|
|
|
int status=0;
|
|
|
|
pid_t pid = (pid_t) s48_extract_integer (s48_pid);
|
|
|
|
int flags = s48_extract_integer (s48_flags);
|
|
|
|
pid_t result_pid;
|
|
|
|
|
|
|
|
result_pid = waitpid(pid, &status, flags);
|
|
|
|
fprintf (stderr, "status was %d \n", status);
|
|
|
|
return s48_cons ((result_pid == -1) ? s48_enter_fixnum(errno) : S48_FALSE,
|
|
|
|
s48_cons (s48_enter_integer (result_pid),
|
|
|
|
s48_cons (s48_enter_integer (status),
|
|
|
|
S48_NULL)));
|
|
|
|
}
|
1999-09-14 09:32:05 -04:00
|
|
|
|
|
|
|
|
|
|
|
/* env: Scheme vector of Scheme strings, e.g., #("TERM=vt100" ...) or #T.
|
|
|
|
** argv: Scheme vector of Scheme strings.
|
|
|
|
** prog: String.
|
|
|
|
**
|
|
|
|
** We don't typecheck the args. You must do the typechecking
|
|
|
|
** on the Scheme side.
|
|
|
|
*/
|
|
|
|
|
1999-09-15 20:20:37 -04:00
|
|
|
int scheme_exec(const char *prog, s48_value argv, s48_value env)
|
1999-09-14 09:32:05 -04:00
|
|
|
{
|
|
|
|
int i, j, e;
|
1999-09-15 20:20:37 -04:00
|
|
|
int argc = S48_VECTOR_LENGTH(argv);
|
1999-09-14 09:32:05 -04:00
|
|
|
|
|
|
|
char **unix_argv = Malloc(char*, argc+1);
|
|
|
|
char **unix_env;
|
|
|
|
|
|
|
|
if( unix_argv == NULL ) return errno;
|
|
|
|
|
|
|
|
/* Scheme->Unix convert the argv parameter. */
|
|
|
|
for(i=0; i<argc; i++)
|
1999-09-15 20:20:37 -04:00
|
|
|
unix_argv[i] = cig_string_body(S48_VECTOR_REF(argv,i));
|
1999-09-14 09:32:05 -04:00
|
|
|
unix_argv[argc] = NULL;
|
|
|
|
|
|
|
|
/* Scheme->Unix convert the env parameter. */
|
1999-09-15 20:20:37 -04:00
|
|
|
if( env == S48_TRUE ) unix_env = environ;
|
1999-09-14 09:32:05 -04:00
|
|
|
else {
|
1999-09-15 20:20:37 -04:00
|
|
|
int envlen = S48_VECTOR_LENGTH(env);
|
1999-09-14 09:32:05 -04:00
|
|
|
unix_env = Malloc(char*, envlen+1);
|
|
|
|
|
|
|
|
if( !unix_env ) goto lose;
|
|
|
|
|
|
|
|
for(j=0; j<envlen; j++)
|
1999-09-15 20:20:37 -04:00
|
|
|
unix_env[j] = cig_string_body(S48_VECTOR_REF(env,j));
|
1999-09-14 09:32:05 -04:00
|
|
|
unix_env[envlen] = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
execve(prog, unix_argv, unix_env); /* Do it. */
|
|
|
|
|
1999-09-15 20:20:37 -04:00
|
|
|
if( env != S48_TRUE ) {
|
1999-09-14 09:32:05 -04:00
|
|
|
e = errno;
|
|
|
|
Free(unix_env);
|
|
|
|
errno = e;
|
|
|
|
}
|
|
|
|
lose:
|
|
|
|
e = errno;
|
|
|
|
Free(unix_argv);
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Random file and I/O stuff
|
|
|
|
*******************************************************************************
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Returns [errno, r, w] */
|
|
|
|
int scheme_pipe(int *r, int *w)
|
|
|
|
{
|
|
|
|
int fds[2];
|
|
|
|
if( pipe(fds) ) {
|
|
|
|
*r = 0; *w = 0;
|
|
|
|
return errno;
|
|
|
|
}
|
|
|
|
|
|
|
|
*r = fds[0]; *w = fds[1];
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Read the symlink into static memory. Return NULL on error. */
|
|
|
|
|
1999-11-04 15:23:25 -05:00
|
|
|
// JMG: static char linkpath[MAXPATHLEN+1]; /* Maybe unaligned. Not reentrant. */
|
1999-09-14 09:32:05 -04:00
|
|
|
|
1999-11-04 15:23:25 -05:00
|
|
|
s48_value scm_readlink(const char *path, s48_value *ret_string)
|
1999-09-14 09:32:05 -04:00
|
|
|
{
|
1999-11-04 15:23:25 -05:00
|
|
|
char linkpath[MAXPATHLEN+1];
|
1999-09-14 09:32:05 -04:00
|
|
|
int retval = readlink(path, linkpath, MAXPATHLEN);
|
1999-11-04 15:23:25 -05:00
|
|
|
if (retval != -1){
|
|
|
|
linkpath[retval] = '\0';
|
|
|
|
*ret_string = s48_enter_string(linkpath);
|
|
|
|
return S48_FALSE;
|
|
|
|
}
|
|
|
|
return s48_enter_fixnum(errno);
|
1999-09-14 09:32:05 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Scheme interfaces to utime().
|
|
|
|
** Complicated by need to pass real 32-bit quantities.
|
|
|
|
*/
|
|
|
|
|
1999-09-28 19:48:36 -04:00
|
|
|
int scm_utime(char const *path, time_t ac, time_t mod)
|
1999-09-14 09:32:05 -04:00
|
|
|
{
|
|
|
|
struct utimbuf t;
|
1999-09-28 19:48:36 -04:00
|
|
|
t.actime = ac;
|
|
|
|
t.modtime = mod;
|
1999-09-14 09:32:05 -04:00
|
|
|
return utime(path, &t);
|
1999-09-28 19:48:36 -04:00
|
|
|
}
|
1999-09-14 09:32:05 -04:00
|
|
|
|
|
|
|
int scm_utime_now(char const *path) {return utime(path, 0);}
|
|
|
|
|
|
|
|
|
|
|
|
int set_cloexec(int fd, int val)
|
|
|
|
{
|
|
|
|
int flags = fcntl(fd, F_GETFD);
|
|
|
|
if( flags == -1 ) return errno;
|
|
|
|
val = -val; /* 0 -> 0 and 1 -> -1 */
|
|
|
|
|
|
|
|
/* If it's already what we want, just return. */
|
|
|
|
if( (flags & FD_CLOEXEC) == (FD_CLOEXEC & val) ) return 0;
|
|
|
|
|
|
|
|
flags = (flags & ~FD_CLOEXEC) | (val & FD_CLOEXEC);
|
|
|
|
return fcntl(fd, F_SETFD, flags) ? errno : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Two versions of CWD
|
|
|
|
*******************************************************************************
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Posix rules: If PATH_MAX is defined, it's the length of longest path.
|
|
|
|
** Otherwise, _POSIX_PATH_MAX = 255, and is a lower bound on said length.
|
|
|
|
** I'm writing out 255 as a literal because HP-UX isn't finding
|
|
|
|
** _POSIX_PATH_MAX.
|
|
|
|
*/
|
|
|
|
#ifdef PATH_MAX
|
|
|
|
#define scsh_path_max (PATH_MAX)
|
|
|
|
#else
|
|
|
|
#define scsh_path_max (255)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Simple-minded POSIX version. */
|
|
|
|
int scheme_cwd(const char **dirp)
|
|
|
|
{
|
|
|
|
char *buf;
|
|
|
|
int size = scsh_path_max + 1; /* +1 for terminating nul byte... */
|
|
|
|
|
|
|
|
buf = Malloc(char,size);
|
|
|
|
if(!buf) goto lose;
|
|
|
|
|
|
|
|
while( !getcwd(buf, size) )
|
|
|
|
if( errno != ERANGE ) goto lose;
|
|
|
|
else {
|
|
|
|
/* Double the buf and retry. */
|
|
|
|
char *nbuf = Realloc(char, buf, size += size);
|
|
|
|
if( !nbuf ) goto lose;
|
|
|
|
buf = nbuf;
|
|
|
|
}
|
|
|
|
|
|
|
|
*dirp = (const char*) buf; /* win */
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
lose:
|
|
|
|
{int e = errno;
|
|
|
|
Free(buf);
|
|
|
|
*dirp = 0;
|
|
|
|
return e;}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
/* Faster SUNOS version. */
|
|
|
|
/* We have to use malloc, because the stub is going to free the string. */
|
|
|
|
|
|
|
|
int scheme_cwd(const char **dirp)
|
|
|
|
{
|
|
|
|
char *buf = Malloc(char,MAXPATHLEN);
|
|
|
|
int e;
|
|
|
|
|
|
|
|
if( buf && getwd(buf) ) {
|
|
|
|
*dirp = (const char*) buf;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* lose */
|
|
|
|
e = errno;
|
|
|
|
Free(buf);
|
|
|
|
*dirp = 0;
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
/* Process times
|
|
|
|
*******************************************************************************
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Sleazing on the types here -- the ret values should be clock_t, not int,
|
|
|
|
** but cig can't handle it.
|
|
|
|
*/
|
|
|
|
|
1999-09-29 18:47:33 -04:00
|
|
|
int process_times(clock_t *utime, clock_t *stime,
|
|
|
|
clock_t *cutime, clock_t *cstime)
|
1999-09-14 09:32:05 -04:00
|
|
|
{
|
|
|
|
struct tms tms;
|
|
|
|
clock_t t = times(&tms);
|
|
|
|
if (t == -1) return -1;
|
|
|
|
*utime = tms.tms_utime;
|
|
|
|
*stime = tms.tms_stime;
|
|
|
|
*cutime = tms.tms_cutime;
|
|
|
|
*cstime = tms.tms_cstime;
|
|
|
|
return t;
|
|
|
|
}
|
|
|
|
|
|
|
|
int cpu_clock_ticks_per_sec()
|
|
|
|
{
|
|
|
|
#ifdef _SC_CLK_TCK
|
|
|
|
static long clock_tick = 0;
|
|
|
|
|
|
|
|
if (clock_tick == 0)
|
|
|
|
clock_tick = sysconf(_SC_CLK_TCK); /* POSIX.1, POSIX.2 */
|
|
|
|
return clock_tick;
|
|
|
|
#else
|
|
|
|
#ifdef CLK_TCK
|
|
|
|
return CLK_TCK;
|
|
|
|
#else
|
|
|
|
return 60;
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Reading and writing
|
|
|
|
*******************************************************************************
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Return a char, #f (EOF), or errno. */
|
1999-09-15 20:20:37 -04:00
|
|
|
s48_value read_fdes_char(int fd)
|
1999-09-14 09:32:05 -04:00
|
|
|
{
|
|
|
|
int i; char c;
|
1999-09-15 20:20:37 -04:00
|
|
|
if( (i=read(fd, &c, 1)) < 0 ) return s48_enter_fixnum(errno);
|
|
|
|
if(i==0) return S48_FALSE;
|
|
|
|
return s48_enter_char(c);
|
1999-09-14 09:32:05 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
int write_fdes_char(char c, int fd) {return write(fd, &c, 1);}
|
|
|
|
|
|
|
|
|
1999-09-29 18:47:33 -04:00
|
|
|
ssize_t read_fdes_substring(s48_value buf, size_t start, size_t end, int fd)
|
1999-09-14 09:32:05 -04:00
|
|
|
{
|
|
|
|
return read(fd, StrByte(buf,start), end-start);
|
|
|
|
}
|
|
|
|
|
1999-09-29 18:47:33 -04:00
|
|
|
ssize_t write_fdes_substring(s48_value buf, size_t start, size_t end, int fd)
|
1999-09-14 09:32:05 -04:00
|
|
|
{
|
|
|
|
return write(fd, StrByte(buf,start), end-start);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* S_ISSOCK(mode) and S_ISLNK(mode) are not POSIX. You lose on a NeXT. Ugh. */
|
|
|
|
#ifndef S_ISSOCK
|
|
|
|
#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
|
|
|
|
#endif
|
|
|
|
#ifndef S_ISLNK
|
|
|
|
#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define low24(x) ((x) & 0xffffff)
|
|
|
|
#define hi_but24(x) (((x) >> 24) & 0xff)
|
|
|
|
|
|
|
|
/* Note that hi_but24 assumes value is a *32 bit* signed value. We have to
|
|
|
|
** do this, because C's right-shift operator exposes word width. A suckful
|
|
|
|
** language.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Internal aux function -- loads stat values into Scheme vector: */
|
1999-09-15 20:20:37 -04:00
|
|
|
static int really_stat(int retval, struct stat *s, s48_value vec)
|
1999-09-14 09:32:05 -04:00
|
|
|
{
|
|
|
|
int modes, typecode = -1;
|
1999-11-04 15:23:25 -05:00
|
|
|
S48_DECLARE_GC_PROTECT(1);
|
2000-05-16 04:43:01 -04:00
|
|
|
if( 11 != S48_VECTOR_LENGTH(vec) ) return -1;
|
1999-09-14 09:32:05 -04:00
|
|
|
if( retval < 0 ) return errno;
|
1999-11-04 15:23:25 -05:00
|
|
|
|
|
|
|
S48_GC_PROTECT_1(vec);
|
|
|
|
|
1999-09-14 09:32:05 -04:00
|
|
|
modes = s->st_mode;
|
|
|
|
if( S_ISBLK(modes) ) typecode = 0;
|
|
|
|
else if( S_ISCHR(modes) ) typecode = 1;
|
|
|
|
else if( S_ISDIR(modes) ) typecode = 2;
|
|
|
|
else if( S_ISFIFO(modes) ) typecode = 3;
|
|
|
|
else if( S_ISREG(modes) ) typecode = 4;
|
|
|
|
else if( S_ISSOCK(modes) ) typecode = 5;
|
|
|
|
else if( S_ISLNK(modes) ) typecode = 6;
|
2000-05-16 04:43:01 -04:00
|
|
|
|
1999-09-15 20:20:37 -04:00
|
|
|
S48_VECTOR_SET(vec,0,s48_enter_fixnum(typecode));
|
2000-05-16 04:43:01 -04:00
|
|
|
S48_VECTOR_SET(vec,1, s48_enter_integer(s->st_dev));
|
|
|
|
S48_VECTOR_SET(vec,2, s48_enter_integer(s->st_ino));
|
|
|
|
S48_VECTOR_SET(vec,3, s48_enter_integer(s->st_mode));
|
|
|
|
S48_VECTOR_SET(vec,4, s48_enter_integer(s->st_nlink));
|
|
|
|
S48_VECTOR_SET(vec,5, s48_enter_integer(s->st_uid));
|
|
|
|
S48_VECTOR_SET(vec,6, s48_enter_integer(s->st_gid));
|
|
|
|
S48_VECTOR_SET(vec,7, s48_enter_integer(s->st_size));
|
1999-09-29 18:47:33 -04:00
|
|
|
S48_VECTOR_SET(vec,8, s48_enter_integer(s->st_atime));
|
|
|
|
S48_VECTOR_SET(vec,9, s48_enter_integer(s->st_mtime));
|
|
|
|
S48_VECTOR_SET(vec,10, s48_enter_integer(s->st_ctime));
|
1999-09-14 09:32:05 -04:00
|
|
|
|
|
|
|
/* We also used to do st_rdev, st_blksize, and st_blocks.
|
|
|
|
These aren't POSIX, and, e.g., are not around on SGI machines.
|
|
|
|
Too bad -- blksize is useful. Unix sux. */
|
1999-11-04 15:23:25 -05:00
|
|
|
S48_GC_UNPROTECT();
|
1999-09-14 09:32:05 -04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1999-09-15 20:20:37 -04:00
|
|
|
int scheme_stat(const char *path, s48_value vec, int chase_p)
|
1999-09-14 09:32:05 -04:00
|
|
|
{
|
|
|
|
struct stat s;
|
|
|
|
return really_stat(chase_p ? stat(path, &s) : lstat(path, &s), &s, vec);
|
|
|
|
}
|
|
|
|
|
1999-09-15 20:20:37 -04:00
|
|
|
int scheme_fstat(int fd, s48_value vec)
|
1999-09-14 09:32:05 -04:00
|
|
|
{
|
|
|
|
struct stat s;
|
|
|
|
return really_stat(fstat(fd,&s), &s, vec);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Supplementary groups access
|
|
|
|
*******************************************************************************
|
|
|
|
*/
|
|
|
|
|
|
|
|
int num_supp_groups(void)
|
|
|
|
{
|
|
|
|
return getgroups(0,NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Load the supplementary groups into GVEC. */
|
|
|
|
|
1999-09-15 20:20:37 -04:00
|
|
|
int get_groups(s48_value gvec)
|
1999-09-14 09:32:05 -04:00
|
|
|
{
|
1999-09-15 20:20:37 -04:00
|
|
|
int veclen = S48_VECTOR_LENGTH(gvec), i, retval;
|
1999-09-14 09:32:05 -04:00
|
|
|
gid_t gvec0[20], *gp = gvec0;
|
|
|
|
|
|
|
|
if( veclen > 20 )
|
|
|
|
if( NULL == (gp=Malloc(gid_t,veclen)) ) return -1;
|
|
|
|
|
|
|
|
retval = getgroups(veclen, gp);
|
|
|
|
|
|
|
|
if( retval != -1 )
|
|
|
|
for( i=veclen; i--; )
|
1999-09-15 20:20:37 -04:00
|
|
|
S48_VECTOR_SET(gvec,i, s48_enter_fixnum(gp[i]));
|
1999-09-14 09:32:05 -04:00
|
|
|
|
|
|
|
if( veclen > 20 ) Free(gp);
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Environment hackery
|
|
|
|
*******************************************************************************
|
|
|
|
*/
|
1999-11-04 15:23:25 -05:00
|
|
|
struct envvec {
|
|
|
|
char **env; /* Null-terminated vector of strings. Malloc'd. */
|
|
|
|
int size; /* Length of env. */
|
|
|
|
int revealed; /* True => exported to C code */
|
|
|
|
int gcable; /* True => no pointers to us from Scheme heap. */
|
|
|
|
};
|
|
|
|
/* Note that the SIZE field tells you how many words of memory are allocated
|
|
|
|
** for the block of memory to which the ENV field points. This includes the
|
|
|
|
** terminating null pointer, and may include more words beyond that. It is
|
|
|
|
** *not* the number of strings stored in ENV; it is always greater than this
|
|
|
|
** value.
|
|
|
|
**
|
|
|
|
** The REVEALED field is incremented if either the ENV block or the entire
|
|
|
|
** struct is handed out to C code.
|
|
|
|
**
|
|
|
|
** If the structure becomes gc'able, but is REVEALED (hence cannot be freed),
|
|
|
|
** the GC simply sets GCABLE and forgets about it.
|
|
|
|
*/
|
1999-09-14 09:32:05 -04:00
|
|
|
|
1999-11-04 15:23:25 -05:00
|
|
|
/* The envvec corresponding to the current environment.
|
|
|
|
** Null if the current environment has no corresponding envvec struct
|
|
|
|
** (which should only be true of the initial environment at process
|
|
|
|
** startup time.) That is,
|
|
|
|
** !current_env || current_env->env == environ
|
|
|
|
*/
|
|
|
|
struct envvec *current_env = 0;
|
|
|
|
|
|
|
|
void align_env(s48_value pointer_to_struct)
|
|
|
|
{
|
|
|
|
struct envvec* thread_env;
|
|
|
|
thread_env = (struct envvec*) s48_extract_integer(pointer_to_struct);
|
|
|
|
environ = thread_env->env;
|
|
|
|
current_env = thread_env;
|
|
|
|
}
|
|
|
|
|
2000-06-28 06:27:34 -04:00
|
|
|
s48_value free_envvec (s48_value pointer_to_struct)
|
|
|
|
{
|
|
|
|
struct envvec* envv = (struct envvec*) s48_extract_integer(pointer_to_struct);
|
|
|
|
int i;
|
|
|
|
if (envv->revealed)
|
|
|
|
{
|
|
|
|
envv->gcable = 1;
|
|
|
|
return S48_FALSE;
|
|
|
|
}
|
|
|
|
for (i=0; i<envv->size; i++)
|
|
|
|
Free(envv->env[i]);
|
|
|
|
Free(envv->env);
|
|
|
|
Free(envv);
|
|
|
|
return S48_TRUE;
|
|
|
|
}
|
1999-11-04 15:23:25 -05:00
|
|
|
|
2000-06-28 06:27:34 -04:00
|
|
|
s48_value envvec_setenv(s48_value scheme_name, s48_value entry){
|
1999-11-04 15:23:25 -05:00
|
|
|
char * name = s48_extract_string(scheme_name);
|
|
|
|
int namelen = strlen(name);
|
|
|
|
char **ptr = environ;
|
|
|
|
char ** newenv;
|
2000-06-28 06:27:34 -04:00
|
|
|
int size;
|
1999-11-04 15:23:25 -05:00
|
|
|
int number_of_entries = 0;
|
|
|
|
char * newentry = Malloc(char, S48_STRING_LENGTH(entry) + 1);
|
|
|
|
if ( !newentry) return s48_enter_fixnum(errno);
|
1999-09-14 09:32:05 -04:00
|
|
|
|
1999-11-04 15:23:25 -05:00
|
|
|
if (!current_env) {
|
|
|
|
fprintf(stderr, "no current_env, giving up" );
|
|
|
|
exit (1);
|
|
|
|
}
|
2000-06-28 06:27:34 -04:00
|
|
|
size = current_env->size;
|
1999-11-04 15:23:25 -05:00
|
|
|
while (*ptr){
|
|
|
|
if ( ( strncmp(*ptr, name, namelen) == 0) && (*ptr)[namelen] == '=')
|
|
|
|
{
|
|
|
|
*ptr = strcpy(newentry,s48_extract_string(entry));
|
|
|
|
return S48_FALSE;
|
|
|
|
}
|
|
|
|
ptr++;
|
|
|
|
number_of_entries++;
|
|
|
|
}
|
|
|
|
if (number_of_entries >= size) { // I never had this problem, but...
|
|
|
|
fprintf(stderr, "currupt env, giving up %d %d", number_of_entries,size);
|
|
|
|
exit (1);
|
|
|
|
}
|
|
|
|
else if (number_of_entries < (size - 1)) // is space left after the NULL ?
|
|
|
|
{
|
|
|
|
*ptr = strcpy(newentry,s48_extract_string(entry));
|
|
|
|
*++ptr = NULL;
|
|
|
|
return S48_FALSE;
|
|
|
|
}
|
|
|
|
else // number_of_entries == (size - 1)
|
|
|
|
{
|
|
|
|
int newsize = size + 1; // TODO: add more
|
|
|
|
char ** newenv = Malloc (char *, newsize);
|
|
|
|
if( !newenv) return s48_enter_fixnum(errno);
|
|
|
|
current_env->env = newenv;
|
|
|
|
current_env->size = newsize;
|
|
|
|
memcpy(newenv, environ, number_of_entries * sizeof (char *));
|
|
|
|
newenv[number_of_entries] = strcpy(newentry, s48_extract_string(entry));
|
|
|
|
newenv[number_of_entries + 1] = NULL;
|
|
|
|
environ = newenv;
|
|
|
|
return S48_FALSE;
|
|
|
|
}
|
1999-09-14 09:32:05 -04:00
|
|
|
}
|
|
|
|
|
2000-05-16 04:43:01 -04:00
|
|
|
s48_value scm_envvec(){
|
|
|
|
return char_pp_2_string_list(environ);
|
1999-09-14 09:32:05 -04:00
|
|
|
}
|
|
|
|
|
2000-05-16 04:43:01 -04:00
|
|
|
|
1999-09-14 09:32:05 -04:00
|
|
|
/* Load the (Scheme) strings in the (Scheme) vector VEC into environ.
|
|
|
|
** Somewhat wasteful of memory: we do not free any of the memory
|
|
|
|
** in the old environ -- don't know if it is being shared elsewhere.
|
|
|
|
*/
|
|
|
|
|
1999-09-15 20:20:37 -04:00
|
|
|
int install_env(s48_value vec)
|
1999-09-14 09:32:05 -04:00
|
|
|
{
|
|
|
|
int i, envsize;
|
|
|
|
char **newenv;
|
|
|
|
|
1999-09-15 20:20:37 -04:00
|
|
|
envsize = S48_VECTOR_LENGTH(vec);
|
1999-11-04 15:23:25 -05:00
|
|
|
|
|
|
|
if (envsize >= (current_env->size))
|
|
|
|
{
|
|
|
|
newenv = Malloc(char*, envsize+1);
|
|
|
|
if( !newenv ) return errno;
|
|
|
|
Free(current_env->env);
|
|
|
|
current_env->env = newenv;
|
|
|
|
}
|
|
|
|
else newenv = current_env->env;
|
|
|
|
|
1999-09-14 09:32:05 -04:00
|
|
|
for( i=0; i<envsize; i++ ) {
|
1999-09-15 20:20:37 -04:00
|
|
|
char *s = scheme2c_strcpy(S48_VECTOR_REF(vec,i));
|
1999-09-14 09:32:05 -04:00
|
|
|
if (!s) {
|
|
|
|
/* Return all the memory and bail out. */
|
|
|
|
int e = errno;
|
|
|
|
while(--i) Free(newenv[i]);
|
|
|
|
Free(newenv);
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
newenv[i] = s;
|
|
|
|
}
|
|
|
|
|
|
|
|
newenv[i] = NULL;
|
|
|
|
environ = newenv;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1999-11-04 15:23:25 -05:00
|
|
|
int create_env(s48_value vec, s48_value * envvec_addr)
|
|
|
|
{
|
|
|
|
int i, envsize;
|
|
|
|
char **newenv;
|
|
|
|
struct envvec* thread_env;
|
|
|
|
|
|
|
|
envsize = S48_VECTOR_LENGTH(vec);
|
|
|
|
|
|
|
|
newenv = Malloc(char*, envsize+1);
|
|
|
|
if( !newenv ) return errno;
|
2000-06-28 06:27:34 -04:00
|
|
|
thread_env = Malloc (struct envvec, 4); // TODO: why 4 ??
|
1999-11-04 15:23:25 -05:00
|
|
|
if( !thread_env ) {
|
|
|
|
Free (newenv);
|
|
|
|
return errno;
|
|
|
|
}
|
1999-09-14 09:32:05 -04:00
|
|
|
|
1999-11-04 15:23:25 -05:00
|
|
|
thread_env->env = newenv;
|
|
|
|
thread_env->size = envsize + 1;
|
|
|
|
thread_env->revealed = 0;
|
|
|
|
thread_env->gcable = 0;
|
|
|
|
|
|
|
|
for( i=0; i<envsize; i++ ) {
|
|
|
|
char *s = scheme2c_strcpy(S48_VECTOR_REF(vec,i));
|
|
|
|
if (!s) {
|
|
|
|
/* Return all the memory and bail out. */
|
|
|
|
int e = errno;
|
|
|
|
while(--i) Free(newenv[i]);
|
|
|
|
Free(newenv);
|
|
|
|
Free(thread_env);
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
newenv[i] = s;
|
|
|
|
}
|
|
|
|
|
|
|
|
newenv[envsize] = NULL;
|
|
|
|
|
|
|
|
*envvec_addr = s48_enter_integer((long) thread_env);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1999-09-14 09:32:05 -04:00
|
|
|
/* Delete the env var. */
|
2000-06-28 06:27:34 -04:00
|
|
|
s48_value delete_env(s48_value name)
|
1999-09-14 09:32:05 -04:00
|
|
|
{
|
2000-06-28 06:27:34 -04:00
|
|
|
int varlen = S48_STRING_LENGTH (name);
|
|
|
|
char * var = s48_extract_string (name);
|
|
|
|
char **ptr = environ;
|
1999-11-04 15:23:25 -05:00
|
|
|
char **ptr2;
|
2000-06-28 06:27:34 -04:00
|
|
|
if (!current_env) {
|
|
|
|
fprintf(stderr, "no current_env, giving up" );
|
|
|
|
exit (1);
|
|
|
|
}
|
|
|
|
do if( !*++ptr ) return S48_FALSE;
|
1999-09-14 09:32:05 -04:00
|
|
|
while( strncmp(*ptr, var, varlen) || (*ptr)[varlen] != '=' );
|
1999-11-04 15:23:25 -05:00
|
|
|
ptr2 = ptr;
|
|
|
|
while (*++ptr2);
|
|
|
|
*ptr = *ptr2;
|
|
|
|
*ptr2 = NULL;
|
2000-06-28 06:27:34 -04:00
|
|
|
return S48_TRUE;
|
1999-09-14 09:32:05 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
1999-11-04 15:23:25 -05:00
|
|
|
/* N.B.: May be unaligned. */
|
1999-09-14 09:32:05 -04:00
|
|
|
|
1999-11-04 15:23:25 -05:00
|
|
|
s48_value scm_gethostname(void)
|
1999-09-14 09:32:05 -04:00
|
|
|
{
|
1999-11-04 15:23:25 -05:00
|
|
|
char hostname[MAXHOSTNAMELEN+1];
|
1999-09-14 09:32:05 -04:00
|
|
|
/* different OS's declare differently, so punt the prototype. */
|
|
|
|
int gethostname();
|
|
|
|
gethostname(hostname, MAXHOSTNAMELEN);
|
1999-11-04 15:23:25 -05:00
|
|
|
return s48_enter_string(hostname);
|
1999-09-14 09:32:05 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
char *errno_msg(int i)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_STRERROR
|
|
|
|
return(strerror(i));
|
|
|
|
#else
|
|
|
|
/* temp hack until we figure out what to do about losing sys_errlist's */
|
|
|
|
extern
|
|
|
|
#ifdef HAVE_CONST_SYS_ERRLIST
|
|
|
|
const
|
|
|
|
#endif
|
|
|
|
char *sys_errlist[];
|
|
|
|
extern int sys_nerr;
|
|
|
|
return ( i < 0 || i > sys_nerr ) ? NULL /* i.e., #f */
|
|
|
|
: (char*) sys_errlist[i];
|
|
|
|
#endif /* !HAVE_STRERROR */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Some of fcntl()
|
|
|
|
******************
|
|
|
|
*/
|
|
|
|
|
|
|
|
int fcntl_read(int fd, int command)
|
|
|
|
{ return fcntl(fd, command); }
|
|
|
|
|
|
|
|
|
|
|
|
int fcntl_write(int fd, int command, int value)
|
|
|
|
{ return fcntl(fd, command, value); }
|
1999-11-04 15:23:25 -05:00
|
|
|
|
|
|
|
/* crypt()
|
|
|
|
******************
|
|
|
|
*/
|
|
|
|
s48_value scm_crypt(s48_value key, s48_value salt)
|
|
|
|
{
|
|
|
|
return s48_enter_string (crypt ( s48_extract_string (key),
|
|
|
|
s48_extract_string(salt)));
|
|
|
|
}
|