/* "posix.c" functions only in Posix (unix).
* Copyright (C) 1994, 1995, 1998, 2006 Free Software Foundation, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see
* .
*/
/* Author: Aubrey Jaffer */
#include "scm.h"
#include
#include
#include
/* added by Denys Duchier: for kill */
#include
#ifndef STDC_HEADERS
char *ttyname P((int fd));
FILE *popen P((const char* command, const char* type));
int pclose P((FILE* stream));
#else /* added by Denys Duchier */
# ifdef SVR4
# include
# endif
# ifdef linux
# include
# endif
# ifdef __OpenBSD__
# include
# endif
# ifdef __NetBSD__
# include
# endif
#endif
static char s_chown[] = "chown";
SCM l_chown(path, owner, group)
SCM path, owner, group;
{
int val;
ASRTER(NIMP(path) && STRINGP(path), path, ARG1, s_chown);
ASRTER(INUMP(owner), owner, ARG2, s_chown);
ASRTER(INUMP(group), group, ARG3, s_chown);
SYSCALL(val = chown(CHARS(path), INUM(owner), INUM(group)););
return val ? BOOL_F : BOOL_T;
}
static char s_link[] = "link";
SCM l_link(oldpath, newpath)
SCM oldpath, newpath;
{
int val;
ASRTER(NIMP(oldpath) && STRINGP(oldpath), oldpath, ARG1, s_link);
ASRTER(NIMP(newpath) && STRINGP(newpath), newpath, ARG2, s_link);
SYSCALL(val = link(CHARS(oldpath), CHARS(newpath)););
return val ? BOOL_F : BOOL_T;
}
SCM l_pipe()
{
int fd[2], ret;
FILE *f_rd, *f_wt;
SCM p_rd, p_wt;
NEWCELL(p_rd); NEWCELL(p_wt);
DEFER_INTS;
SYSCALL(ret = pipe(fd););
if (ret) {ALLOW_INTS; return BOOL_F;}
SYSCALL(f_rd = fdopen(fd[0], "r"););
if (!f_rd) {
close(fd[0]);
goto errout;
}
SCM_OPENCALL(f_wt = fdopen(fd[1], "w"));
if (!f_wt) {
fclose(f_rd);
errout:
close(fd[1]);
wta(UNDEFINED, (char *)NALLOC, s_port_type);
}
p_rd = scm_port_entry(f_rd, tc16_fport, mode_bits("r", (char *)0));
p_wt = scm_port_entry(f_wt, tc16_fport, mode_bits("w", (char *)0));
ALLOW_INTS;
return cons(p_rd, p_wt);
}
char s_op_pipe[] = "open-pipe";
SCM open_pipe(pipestr, modes)
SCM pipestr, modes;
{
FILE *f;
register SCM z;
ASRTER(NIMP(pipestr) && STRINGP(pipestr), pipestr, ARG1, s_op_pipe);
ASRTER(NIMP(modes) && (STRINGP(modes) || SYMBOLP(modes)), modes, ARG2, s_op_pipe);
NEWCELL(z);
/* DEFER_INTS, SYSCALL, and ALLOW_INTS are probably paranoid here*/
DEFER_INTS;
ignore_signals();
SCM_OPENCALL(f = popen(CHARS(pipestr), CHARS(modes)));
unignore_signals();
z = f ?
scm_port_entry(f, tc16_pipe,
OPN | (strchr(CHARS(modes), 'r') ? RDNG : WRTNG)) :
BOOL_F;
ALLOW_INTS;
return z;
}
static char scm_s_getgroups[] = "getgroups";
SCM scm_getgroups()
{
SCM grps, ans;
int ngroups = getgroups(0, 0);
if (!ngroups) return BOOL_F;
scm_protect_temp(&grps);
DEFER_INTS;
/* grps is used as a gc protect, its type used to be tc7_string, but
strings are now checked for null termination during gc.
The length needs not be exactly right */
grps = must_malloc_cell((0L + ngroups) * sizeof(gid_t),
MAKE_LENGTH(((0L + ngroups) * sizeof(gid_t))/sizeof(long),
tc7_VfixN32),
scm_s_getgroups);
ALLOW_INTS;
{
gid_t *groups = (gid_t *)CHARS(grps);
int val = getgroups(ngroups, groups);
if (val < 0) return BOOL_F;
ans = make_vector(MAKINUM(ngroups), UNDEFINED);
while (--ngroups >= 0) VELTS(ans)[ngroups] = MAKINUM(groups[ngroups]);
return ans;
}
}
/* These 2 routines are not protected against `entry' being reused
before access to that structure is completed */
static char s_pwinfo[] = "getpw";
SCM l_pwinfo(user)
SCM user;
{
SCM ans = make_vector(MAKINUM(7), UNSPECIFIED);
struct passwd *entry;
SCM *ve = VELTS(ans);
DEFER_INTS;
if (UNBNDP(user)) SYSCALL(entry = getpwent(););
else if (INUMP(user)) SYSCALL(entry = getpwuid(INUM(user)););
else {
ASRTER(NIMP(user) && STRINGP(user), user, ARG1, s_pwinfo);
SYSCALL(entry = getpwnam(CHARS(user)););
}
ALLOW_INTS;
if (!entry) return BOOL_F;
ve[ 0] = makfrom0str(entry->pw_name);
ve[ 1] = makfrom0str(entry->pw_passwd);
ve[ 2] = ulong2num((unsigned long)entry->pw_uid);
ve[ 3] = ulong2num((unsigned long)entry->pw_gid);
ve[ 4] = makfrom0str(entry->pw_gecos);
ve[ 5] = makfrom0str(entry->pw_dir);
ve[ 6] = makfrom0str(entry->pw_shell);
return ans;
}
#include
static char s_grinfo[] = "getgr";
SCM l_grinfo(name)
SCM name;
{
SCM ans = make_vector(MAKINUM(4), UNSPECIFIED);
struct group *entry;
SCM *ve = VELTS(ans);
DEFER_INTS;
if (UNBNDP(name)) SYSCALL(entry = getgrent(););
else if (INUMP(name)) SYSCALL(entry = getgrgid(INUM(name)););
else {
ASRTER(NIMP(name) && STRINGP(name), name, ARG1, s_grinfo);
SYSCALL(entry = getgrnam(CHARS(name)););
}
ALLOW_INTS;
if (!entry) return BOOL_F;
ve[ 0] = makfrom0str(entry->gr_name);
ve[ 1] = makfrom0str(entry->gr_passwd);
ve[ 2] = ulong2num((unsigned long)entry->gr_gid);
ve[ 3] = makfromstrs(-1, entry->gr_mem);
return ans;
}
SCM l_setgr(arg)
SCM arg;
{
if (UNBNDP(arg) || FALSEP(arg)) endgrent();
else setgrent();
return UNSPECIFIED;
}
SCM l_setpw(arg)
SCM arg;
{
if (UNBNDP(arg) || FALSEP(arg)) endpwent();
else setpwent();
return UNSPECIFIED;
}
static char s_kill[] = "kill";
SCM l_kill(pid, sig)
SCM pid, sig;
{
int i;
ASRTER(INUMP(pid), pid, ARG1, s_kill);
ASRTER(INUMP(sig), sig, ARG2, s_kill);
SYSCALL(i = kill((int)INUM(pid), (int)INUM(sig)););
return MAKINUM(0L+i);
}
static char s_waitpid[] = "waitpid";
SCM l_waitpid(pid, options)
SCM pid, options;
{
int i, status;
ASRTER(INUMP(pid), pid, ARG1, s_waitpid);
ASRTER(INUMP(options), options, ARG2, s_waitpid);
SYSCALL(i = waitpid(INUM(pid), &status, INUM(options)););
return i < 0 ? BOOL_F : MAKINUM(0L+status);
}
SCM l_getppid()
{
return MAKINUM(0L+getppid());
}
SCM l_getuid()
{
return MAKINUM(0L+getuid());
}
SCM l_getgid()
{
return MAKINUM(0L+getgid());
}
#ifndef LACK_E_IDs
SCM l_geteuid()
{
return MAKINUM(0L+geteuid());
}
SCM l_getegid()
{
return MAKINUM(0L+getegid());
}
#endif
static char s_setuid[] = "setuid";
SCM l_setuid(id)
SCM id;
{
ASRTER(INUMP(id), id, ARG1, s_setuid);
return setuid(INUM(id)) ? BOOL_F : BOOL_T;
}
static char s_setgid[] = "setgid";
SCM l_setgid(id)
SCM id;
{
ASRTER(INUMP(id), id, ARG1, s_setgid);
return setgid(INUM(id)) ? BOOL_F : BOOL_T;
}
#ifndef LACK_E_IDs
static char s_seteuid[] = "seteuid";
SCM l_seteuid(id)
SCM id;
{
ASRTER(INUMP(id), id, ARG1, s_seteuid);
return seteuid(INUM(id)) ? BOOL_F : BOOL_T;
}
static char s_setegid[] = "setegid";
SCM l_setegid(id)
SCM id;
{
ASRTER(INUMP(id), id, ARG1, s_setegid);
return setegid(INUM(id)) ? BOOL_F : BOOL_T;
}
#endif
static char s_ttyname[] = "ttyname";
SCM l_ttyname(port)
SCM port;
{
char *ans;
ASRTER(NIMP(port) && OPPORTP(port), port, ARG1, s_ttyname);
if (tc16_fport != TYP16(port)) return BOOL_F;
SYSCALL(ans = ttyname(fileno(STREAM(port))););
/* ans could be overwritten by another call to ttyname */
return ans ? makfrom0str(ans) : BOOL_F;
}
SCM l_fork()
{
long pid = 0L + fork();
return -1L==pid ? BOOL_F : MAKINUM(pid);
}
#include
SCM l_uname()
{
struct utsname buf;
SCM ans = make_vector(MAKINUM(5), UNSPECIFIED);
SCM *ve = VELTS(ans);
if (uname(&buf)) return BOOL_F;
ve[ 0] = makfrom0str(buf.sysname);
ve[ 1] = makfrom0str(buf.nodename);
ve[ 2] = makfrom0str(buf.release);
ve[ 3] = makfrom0str(buf.version);
ve[ 4] = makfrom0str(buf.machine);
/* ve[ 5] = makfrom0str(buf.domainname); */
return ans;
}
static iproc subr0s[] = {
{"pipe", l_pipe},
{scm_s_getgroups, scm_getgroups},
{"getppid", l_getppid},
{"getuid", l_getuid},
{"getgid", l_getgid},
#ifndef LACK_E_IDs
{"getegid", l_getegid},
{"geteuid", l_geteuid},
#endif
{"uname", l_uname},
{"fork", l_fork},
{0, 0}};
static iproc subr1os[] = {
{s_pwinfo, l_pwinfo},
{s_grinfo, l_grinfo},
{"setpwent", l_setpw},
{"setgrent", l_setgr},
{0, 0}};
static iproc subr1s[] = {
{"setuid", l_setuid},
{"setgid", l_setgid},
#ifndef LACK_E_IDs
{"setegid", l_setegid},
{"seteuid", l_seteuid},
#endif
{s_ttyname, l_ttyname},
{0, 0}};
static iproc subr2s[] = {
{s_link, l_link},
{s_kill, l_kill},
{s_waitpid, l_waitpid},
{s_op_pipe, open_pipe},
{0, 0}};
static iproc subr3s[] = {
{s_chown, l_chown},
{0, 0}};
void init_posix()
{
init_iprocs(subr0s, tc7_subr_0);
init_iprocs(subr1s, tc7_subr_1);
init_iprocs(subr1os, tc7_subr_1o);
init_iprocs(subr2s, tc7_subr_2);
init_iprocs(subr3s, tc7_subr_3);
add_feature("posix");
ptobs[0x0ff & (tc16_pipe>>8)].name = s_pipe;
ptobs[0x0ff & (tc16_pipe>>8)].fclose = pclose;
ptobs[0x0ff & (tc16_pipe>>8)].free = pclose;
add_feature(s_pipe);
scm_ldstr("\n\
(define (open-input-pipe cmd) (open-pipe cmd \"r\"))\n\
(define (open-output-pipe cmd) (open-pipe cmd \"w\"))\n\
(define (system->line command . tmp)\n\
(define line\n\
(call-with-open-ports\n\
read-line\n\
(open-input-pipe command)))\n\
(if (eof-object? line) \"\" line))\n\
");
}