ack/util/int/moncalls.c
George Koehler 36f16b0cb8 Cut down some clang warnings
Edit C code to reduce warnings from clang.  Most warnings are for
implicit declarations of functions, but some warnings want me to add
parentheses or curly braces, or to cast arguments for printf().

Make a few other changes, like declaring float_cst() in h/con_float to
be static, and using C99 bool in ego/ra/makeitems.c and
ego/share/makecldef.c.  Such changes don't silence warnings; I make
such changes while I silence warnings in the same file.  In
float_cst(), rename parameter `str` to `float_str`, so it doesn't
share a name with the global variable `str`.

Remove `const` from `newmodule(const char *)` in mach/proto/as to
silence a warning.  I wrongly added the `const` in d347207.

For warnings about implicit declarations of functions, the fix is to
declare the function before calling it.  For example, my OpenBSD
system needs <sys/wait.h> to declare wait().

In util/int, add "whatever.h" to declare more functions.  Remove old
declarations from "mem.h", to prefer the newer declarations of the
same functions in "data.h" and "stack.h".
2019-10-30 18:36:38 -04:00

1139 lines
24 KiB
C

/*
The MON instruction
*/
/* $Id$ */
#include "sysidf.h"
#include "io.h"
#include "log.h"
#include "alloc.h"
#include "shadow.h"
#include "m_sigtrp.h"
#include "monstruct.h"
#include "whatever.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/times.h>
#include <sys/wait.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <utime.h>
extern int running; /* from main.c */
extern int fd_limit; /* from io.c */
#define good_fd(fd) (fd < fd_limit ? 1 : (errno = 9 /* EBADF */, 0))
#ifdef BSD_X /* from system.h */
#include <sys/timeb.h>
#endif /* BSD_X */
#ifdef SYS_V
struct timeb { /* non-existing; we use an ad-hoc definition */
long time;
unsigned short millitm;
short timezone, dstflag;
};
#endif /* SYS_V */
#ifdef BSD4_2 /* from system.h */
#include <sys/time.h>
#endif /* BSD4_2 */
#ifdef SYS_V
#include <fcntl.h>
#endif /* SYS_V */
#include <em_abs.h>
#include "logging.h"
#include "global.h"
#include "trap.h"
#include "warn.h"
#include "mem.h"
/* Detect supported system calls. */
#if !defined __CYGWIN__
#define HAS_ACCT 1
#else
#define HAS_ACCT 0
#endif
#define INPUT 0
#define OUTPUT 1
#define DUPMASK 0x40
#define INT2SIZE max(wsize, 2L)
#define INT4SIZE max(wsize, 4L)
#define pop_int() ((int) swpop())
#define pop_int2() ((int) spop(INT2SIZE))
#define pop_int4() (spop(INT4SIZE))
#define pop_intp() ((int) spop(psize))
#define pop_uns2() ((unsigned int) upop(INT2SIZE))
#define pop_unsp() ((unsigned int) upop(psize))
#define pop_ptr() (dppop())
#define push_int(a) (wpush((long)(a)))
#define push_i2(a) (npush((long)(a), INT2SIZE))
#define push_i4(a) (npush((long)(a), INT4SIZE))
#define push_unsp(a) (npush((long)(a), psize))
#define push_err() { push_int(errno); push_int(errno); }
/************************************************************************
* Monitor calls. *
* *
* The instruction "MON" expects a wsized integer on top of *
* top of the stack, which identifies the call. Often there *
* are also parameters following this number. The parameters *
* were stacked in reverse order (C convention). *
* The possible parameter types are : *
* *
* 1) int : integer of wordsize *
* 2) int2: integer with size max(2, wordsize) *
* 3) int4: integer with size max(4, wordsize) *
* 4) intp: integer with size of a pointer *
* 5) uns2: unsigned integer with size max(2, wordsize) *
* 6) unsp: unsigned integer with size of a pointer *
* 7) ptr : pointer into data space *
* *
* After the call has been executed, a return code is present *
* on top of the stack. If this return code equals zero, the call *
* succeeded and the results of the call can be found right *
* after the return code. A non zero return code indicates a *
* failure. In this case no results are available and the return *
* code has been pushed twice. *
* *
* Monitor calls such as "ioctl", "stat", "ftime", etc. work *
* with a private buffer to be filled by the call. The fields *
* of the buffer are written to EM-memory separately, possibly *
* with some of the fields aligned. To this end a number of *
* transport routines are assembled in monstruct.[ch]. *
* *
* The EM report specifies a list of UNIX Version 7 -like system *
* calls, not full access to the system calls on the underlying *
* machine. Therefore an attempt has been made to use or emulate *
* the Version 7 system calls on the various machines. A number *
* of 4.1 BSD specific parameters have also been implemented. *
* *
************************************************************************/
PRIVATE size buf_cnt[5]; /* Current sizes of the buffers */
PRIVATE char *buf[5]; /* Pointers to the buffers */
PRIVATE check_buf();
PRIVATE int savestr();
PRIVATE int vec();
void moncall(void)
{
int n; /* number actually read/written */
int status; /* status for wait-call */
int flag; /* various flag parameters */
int mode; /* various mode parameters */
mode_t oldmask; /* for umask call */
int whence; /* parameter for lseek */
int address; /* address parameter typed int2 */
int owner; /* owner parameter typed int2 */
int group; /* group parameter typed int2 */
int pid; /* pid parameter typed int2 */
int ppid; /* parent process pid */
long off; /* offset parameter */
int pfds[2]; /* pipe file descriptors */
long tm; /* for stime call */
long actime, modtime; /* for utime */
int incr; /* for nice call */
int fd, fdnew; /* file descriptors */
int groupid; /* group id */
int userid; /* user id */
int sig; /* killing signal */
ptr dsp1, dsp2, dsp3; /* Data Space Pointers */
int nbytes; /* number to be read/written */
unsigned int seconds; /* for alarm call */
int trap_no; /* for sigtrp; trap number */
int old_trap_no; /* for sigtrp; old trap number */
int sig_no; /* for sigtrp; signal number */
int request; /* ioctl and ptrace request */
char **envvec; /* environment vector (exec) */
char **argvec; /* argument vector (exec) */
struct stat st_buf; /* private stat buffer */
struct tms tm_buf; /* private tms buffer */
struct timeb tb_buf; /* private timeb buffer */
#ifdef BSD4_2 /* from system.h */
struct timeval tv; /* private timeval buffer */
#endif /* BSD4_2 */
#ifdef SYS_V /* from system.h */
struct {time_t x, y;} utimbuf; /* private utime buffer */
#else /* SYS_V */
time_t utimbuf[2]; /* private utime buffer */
#endif /* !SYS_V */
char *cp;
int nr;
ptr addr;
int rc;
switch (pop_int()) {
case 1: /* Exit */
#ifdef LOGGING
ES_def =
((st_sh(SP) == UNDEFINED)
|| (st_sh(SP + wsize-1) == UNDEFINED)) ?
UNDEFINED : DEFINED;
#else
ES_def = DEFINED;
#endif /* LOGGING */
ES = pop_int();
running = 0; /* stop the machine */
LOG(("@m9 Exit: ES = %ld", ES));
break;
case 2: /* Fork */
ppid = getpid();
if ((pid = fork()) == 0) {
/* Child */
init_ofiles(0); /* Reinitialize */
push_int(ppid); /* Pid of parent */
push_int(1); /* Flag = 1 for child */
push_int(0);
LOG(("@m9 Fork: in child, ppid = %d", ppid));
}
else if (pid > 0) { /* Parent */
incr_mess_id(); /* Incr. id for next child */
push_int(pid); /* Pid of child */
push_int(0); /* Flag = 0 for parent */
push_int(0);
LOG(("@m9 Fork: in parent, cpid = %d", pid));
}
else {
/* fork call failed */
push_err();
LOG(("@m4 Fork: failed, pid = %d, errno = %d",
pid, errno));
}
break;
case 3: /* Read */
fd = pop_int();
dsp1 = pop_ptr();
nbytes = pop_intp();
if (!good_fd(fd))
goto read_error;
if (nbytes < 0) {
errno = 22; /* EINVAL */
goto read_error;
}
check_buf(0, (size)nbytes);
if ((n = read(fd, buf[0], nbytes)) == -1)
goto read_error;
#ifdef LOGGING
if (check_log("@m6")) {
register int i;
for (i = 0; i < n; i++) {
LOG(("@m6 Read: char = '%c'", *(buf[0] + i)));
}
}
#endif /* LOGGING */
if (in_gda(dsp1) && !in_gda(dsp1 + (n-1))) {
efault(WRGDAH);
goto read_error;
}
if (!is_in_mem(dsp1, n)) {
efault(WRUMEM);
goto read_error;
}
for ( nr = n, cp = buf[0], addr = dsp1;
nr;
nr--, addr++, cp++
) {
if (in_stack(addr)) {
ch_st_prot(addr);
stack_loc(addr) = *cp;
st_int(addr);
}
else {
ch_dt_prot(addr);
data_loc(addr) = *cp;
dt_int(addr);
}
}
push_unsp(n);
push_int(0);
LOG(("@m9 Read: succeeded, n = %d", n));
break;
read_error:
push_err();
LOG(("@m4 Read: failed, n = %d, errno = %d", n, errno));
break;
case 4: /* Write */
fd = pop_int();
dsp1 = pop_ptr();
nbytes = pop_intp();
if (!good_fd(fd))
goto write_error;
if (nbytes < 0) {
errno = 22; /* EINVAL */
goto read_error;
}
if (in_gda(dsp1) && !in_gda(dsp1 + (nbytes-1))) {
efault(WWGDAH);
goto write_error;
}
if (!is_in_mem(dsp1, nbytes)) {
efault(WWUMEM);
goto write_error;
}
#ifdef LOGGING
for (addr = dsp1; addr < dsp1 + nbytes; addr++) {
if (mem_sh(addr) == UNDEFINED) {
warning(in_stack(addr) ? WWLUNDEF : WWGUNDEF);
}
}
#endif /* LOGGING */
check_buf(0, (size)nbytes);
for ( nr = nbytes, addr = dsp1, cp = buf[0];
nr;
nr--, addr++, cp++
) {
*cp = mem_loc(addr);
}
#ifdef LOGGING
if (check_log("@m6")) {
register int i;
for (i = 0; i < nbytes; i++) {
LOG(("@m6 write: char = '%c'", *(buf[0] + i)));
}
}
#endif /* LOGGING */
if ((n = write(fd, buf[0], nbytes)) == -1)
goto write_error;
push_unsp(n);
push_int(0);
LOG(("@m9 Write: succeeded, n = %d", n));
break;
write_error:
push_err();
LOG(("@m4 Write: failed, n = %d, nbytes = %d, errno = %d",
n, nbytes, errno));
break;
case 5: /* Open */
dsp1 = pop_ptr();
flag = pop_int();
if (!savestr(0, dsp1) || (fd = open(buf[0], flag)) == -1) {
push_err();
LOG(("@m4 Open: failed, file = %lu, flag = %d, fd = %d, errno = %d",
dsp1, flag, fd, errno));
}
else {
push_int(fd);
push_int(0);
LOG(("@m9 Open: succeeded, file = %lu, flag = %d, fd = %d",
dsp1, flag, fd));
}
break;
case 6: /* Close */
fd = pop_int();
if (!good_fd(fd) || close(fd) == -1) {
push_err();
LOG(("@m4 Close: failed, fd = %d, errno = %d",
fd, errno));
}
else {
push_int(0);
LOG(("@m9 Close: succeeded"));
}
break;
case 7: /* Wait */
if ((pid = wait(&status)) == -1) {
push_err();
LOG(("@m4 Wait: failed, status = %d, errno = %d",
status, errno));
}
else {
push_i2(pid);
push_i2(status);
push_int(0);
LOG(("@m9 Wait: succeeded, status = %d, pid = %d",
status, pid));
}
break;
case 8: /* Creat */
dsp1 = pop_ptr();
flag = pop_int();
if (!savestr(0, dsp1) || (fd = creat(buf[0], flag)) == -1) {
push_err();
LOG(("@m4 Creat: failed, dsp1 = %lu, flag = %d, errno = %d",
dsp1, flag, errno));
}
else {
push_int(fd);
push_int(0);
LOG(("@m9 Creat: succeeded, fd = %d", fd));
}
break;
case 9: /* Link */
dsp1 = pop_ptr();
dsp2 = pop_ptr();
if ( !savestr(0, dsp1)
|| !savestr(1, dsp2)
|| link(buf[0], buf[1]) == -1
) {
push_err();
LOG(("@m4 Link: failed, dsp1 = %lu, dsp2 = %lu, errno = %d",
dsp1, dsp2, errno));
}
else {
push_int(0);
LOG(("@m9 Link: succeeded, dsp1 = %lu, dsp2 = %lu",
dsp1, dsp2));
}
break;
case 10: /* Unlink */
dsp1 = pop_ptr();
if (!savestr(0, dsp1) || unlink(buf[0]) == -1) {
push_err();
LOG(("@m4 Unlink: failed, dsp1 = %lu, errno = %d",
dsp1, errno));
}
else {
push_int(0);
LOG(("@m9 Unlink: succeeded, dsp1 = %lu", dsp1));
}
break;
case 12: /* Chdir */
dsp1 = pop_ptr();
if (!savestr(0, dsp1) || chdir(buf[0]) == -1) {
push_err();
LOG(("@m4 Chdir: failed, dsp1 = %lu, errno = %d",
dsp1, errno));
}
else {
push_int(0);
LOG(("@m9 Chdir: succeeded, dsp1 = %lu", dsp1));
}
break;
case 14: /* Mknod */
dsp1 = pop_ptr();
mode = pop_int();
address = pop_int2();
if (!savestr(0, dsp1) || mknod(buf[0], mode, address) == -1) {
push_err();
LOG(("@m4 Mknod: failed, dsp1 = %lu, mode = %d, address = %d, errno = %d",
dsp1, mode, address, errno));
}
else {
push_int(0);
LOG(("@m9 Mknod: succeeded, dsp1 = %lu", dsp1));
}
break;
case 15: /* Chmod */
dsp1 = pop_ptr();
mode = pop_int2();
if (!savestr(0, dsp1) || chmod(buf[0], mode) == -1) {
push_err();
LOG(("@m4 Chmod: failed, dsp1 = %lu, mode = %d, errno = %d",
dsp1, mode, errno));
}
else {
push_int(0);
LOG(("@m9 Chmod: succeeded, dsp1 = %lu", dsp1));
}
break;
case 16: /* Chown */
dsp1 = pop_ptr();
owner = pop_int2();
group = pop_int2();
if (!savestr(0, dsp1) || chown(buf[0], owner, group) == -1) {
push_err();
LOG(("@m4 Chown: failed, dsp1 = %lu, owner = %d, group = %d, errno = %d",
dsp1, owner, group, errno));
}
else {
push_int(0);
LOG(("@m9 Chown: succeeded, dsp1 = %lu", dsp1));
}
break;
case 18: /* Stat */
dsp1 = pop_ptr(); /* points to file-name space */
dsp2 = pop_ptr(); /* points to EM-stat-buffer space */
if ( !savestr(0, dsp1)
|| stat(buf[0], &st_buf) == -1
|| !stat2mem(dsp2, &st_buf)
) {
push_err();
LOG(("@m4 Stat: failed, dsp1 = %lu, dsp2 = %lu, errno = %d",
dsp1, dsp2, errno));
}
else {
push_int(0);
LOG(("@m9 Stat: succeeded, dsp1 = %lu, dsp2 = %lu",
dsp1, dsp2));
}
break;
case 19: /* Lseek */
fd = pop_int();
off = pop_int4();
whence = pop_int();
LOG(("@m4 Lseek: fd = %d, off = %ld, whence = %d",
fd, off, whence));
if (!good_fd(fd) || (off = lseek(fd, off, whence)) == -1) {
push_err();
LOG(("@m9 Lseek: failed, errno = %d", errno));
}
else {
push_i4(off);
push_int(0);
LOG(("@m9 Lseek: succeeded, pushed %ld", off));
}
break;
case 20: /* Getpid */
pid = getpid();
push_i2(pid);
LOG(("@m9 Getpid: succeeded, pid = %d", pid));
break;
#ifdef WANT_MOUNT_UMOUNT
case 21: /* Mount */
dsp1 = pop_ptr();
dsp2 = pop_ptr();
flag = pop_int();
if ( !savestr(0, dsp1)
|| !savestr(1, dsp2)
|| mount(buf[0], buf[1], flag) == -1
) {
push_err();
LOG(("@m4 Mount: failed, dsp1 = %lu, dsp2 = %lu, flag = %d, errno = %d",
dsp1, dsp2, flag, errno));
}
else {
push_int(0);
LOG(("@m9 Mount: succeeded, dsp1 = %lu, dsp2 = %lu, flag = %d",
dsp1, dsp2, flag));
}
break;
case 22: /* Umount */
dsp1 = pop_ptr();
if ( !savestr(0, dsp1)
#ifndef BSD4_2 /* from system.h */
|| umount(buf[0]) == -1
#else /* BSD4_2 */
|| unmount(buf[0]) == -1
#endif /* BSD4_2 */
) {
push_err();
LOG(("@m4 Umount: failed, dsp1 = %lu, errno = %d",
dsp1, errno));
}
else {
push_int(0);
LOG(("@m9 Mount: succeeded, dsp1 = %lu", dsp1));
}
break;
#endif
case 23: /* Setuid */
userid = pop_int2();
if (setuid(userid) == -1) {
push_err();
LOG(("@m4 Setuid: failed, userid = %d, errno = %d",
userid, errno));
}
else {
push_int(0);
LOG(("@m9 Setuid: succeeded, userid = %d", userid));
}
break;
case 24: /* Getuid */
userid = getuid();
push_i2(userid);
LOG(("@m9 Getuid(part 1): real uid = %d", userid));
userid = geteuid();
push_i2(userid);
LOG(("@m9 Getuid(part 2): eff uid = %d", userid));
break;
#ifdef WANT_STIME
case 25: /* Stime */
tm = pop_int4();
#ifndef BSD4_2 /* from system.h */
rc = stime(&tm);
#else /* BSD4_2 */
tv.tv_sec = tm;
tv.tv_usec = 0; /* zero microseconds */
rc = settimeofday(&tv, (struct timezone *)0);
#endif /* BSD4_2 */
if (rc == -1) {
push_err();
LOG(("@m4 Stime: failed, tm = %ld, errno = %d",
tm, errno));
}
else {
push_int(0);
LOG(("@m9 Stime: succeeded, tm = %ld", tm));
}
break;
#endif
case 26: /* Ptrace */
request = pop_int();
pid = pop_int2();
dsp3 = pop_ptr();
n = pop_int(); /* Data */
einval(WPTRACEIMP);
push_err();
LOG(("@m4 Ptrace: failed, request = %d, pid = %d, addr = %lu, data = %d, errno = %d",
request, pid, dsp3, n, errno));
break;
case 27: /* Alarm */
seconds = pop_uns2();
LOG(("@m9 Alarm(part 1) seconds = %u", seconds));
seconds = alarm(seconds);
push_i2(seconds);
LOG(("@m9 Alarm(part 2) seconds = %u", seconds));
break;
case 28: /* Fstat */
fd = pop_int();
dsp2 = pop_ptr();
if ( !good_fd(fd)
|| fstat(fd, &st_buf) == -1
|| !stat2mem(dsp2, &st_buf)
) {
push_err();
LOG(("@m4 Fstat: failed, fd = %d, dsp2 = %lu, errno = %d",
fd, dsp2, errno));
}
else {
push_int(0);
LOG(("@m9 Fstat: succeeded, fd = %d, dsp2 = %lu",
fd, dsp2));
}
break;
case 29: /* Pause */
pause();
LOG(("@m9 Pause: succeeded"));
break;
case 30: /* Utime */
dsp1 = pop_ptr();
dsp2 = pop_ptr();
if (memfault(dsp2, 2*INT4SIZE)) {
push_err();
LOG(("@m4 Utime: failed, dsp1 = %lu, dsp2 = %lu, errno = %d",
dsp1, dsp2, errno));
break;
}
actime = mem_ldu(dsp2, INT4SIZE);
modtime = mem_ldu(dsp2 + INT4SIZE, INT4SIZE);
#ifdef SYS_V /* from system.h */
utimbuf.x = actime;
utimbuf.y = modtime;
if (!savestr(0, dsp1) || utime(buf[0], &utimbuf) == -1) {
#else /* SYS_V */
utimbuf[0] = actime;
utimbuf[1] = modtime;
if (!savestr(0, dsp1) || utime(buf[0], utimbuf) == -1) {
/* may require modification for POSIX ???!!! */
#endif /* !SYS_V */
push_err();
LOG(("@m4 Utime: failed, dsp1 = %lu, dsp2 = %lu, errno = %d",
dsp1, dsp2, errno));
}
else {
push_int(0);
LOG(("@m9 Utime: succeeded, dsp1 = %lu, dsp2 = %lu",
dsp1, dsp2));
}
break;
case 33: /* Access */
dsp1 = pop_ptr();
mode = pop_int();
if (!savestr(0, dsp1) || access(buf[0], mode) == -1) {
push_err();
LOG(("@m4 Access: failed, dsp1 = %lu, mode = %d, errno = %d",
dsp1, mode, errno));
}
else {
push_int(0);
LOG(("@m9 Access: succeeded, dsp1 = %lu, mode = %d",
dsp1, mode));
}
break;
case 34: /* Nice */
incr = pop_int();
nice(incr);
LOG(("@m9 Nice: succeeded, incr = %d", incr));
break;
case 35: /* Ftime */
dsp2 = pop_ptr();
#ifdef BSD_X /* from system.h */
ftime(&tb_buf);
#endif /* BSD_X */
#ifdef SYS_V /* from system.h */
tb_buf.time = time((time_t*)0);
tb_buf.millitm = 0;
tb_buf.timezone = timezone / 60;
tb_buf.dstflag = daylight;
#endif /* SYS_V */
if (!timeb2mem(dsp2, &tb_buf)) {
push_err();
LOG(("@m4 Ftime: failed, dsp2 = %lu, errno = %d",
dsp2, errno));
}
else {
push_int(0);
LOG(("@m9 Ftime: succeeded, dsp2 = %lu", dsp2));
}
break;
case 36: /* Sync */
sync();
LOG(("@m9 Sync: succeeded"));
break;
case 37: /* Kill */
pid = pop_int2();
sig = pop_int();
if (kill(pid, sig) == -1) {
push_err();
LOG(("@m4 Kill: failed, pid = %d, sig = %d, errno = %d",
pid, sig, errno));
}
else {
push_int(0);
LOG(("@m9 Kill: succeeded, pid = %d, sig = %d",
pid, sig));
}
break;
case 41: /* Dup & Dup2 */
fd = pop_int();
fdnew = pop_int();
if (fd & DUPMASK) {
int fd1 = fd & ~DUPMASK;/* stripped */
LOG(("@m4 Dup2: fd1 = %d, fdnew = %d", fd1, fdnew));
if (!good_fd(fd1)) {
fdnew = -1;
goto dup2_error;
}
#ifdef BSD_X /* from system.h */
fdnew = dup2(fd1, fdnew);
#endif /* BSD_X */
#ifdef SYS_V /* from system.h */
{
/* simulating the semantics of dup2 on SYS_V */
int dupped = dup(fd1);
if (dupped < 0 && errno != EMFILE) {
/* the dup failed, but not
because of too many open
file descriptors
*/
fdnew = dupped;
}
else {
close(dupped);
close(fdnew);
fdnew = fcntl(fd1, F_DUPFD, fdnew);
}
}
#endif /* SYS_V */
dup2_error:;
}
else {
LOG(("@m4 Dup: fd = %d, fdnew = %d", fd, fdnew));
fdnew = (!good_fd(fd) ? -1 : dup(fd));
}
if (fdnew == -1) {
push_err();
LOG(("@m4 Dup/Dup2: failed, fdnew = %d, errno = %d",
fdnew, errno));
}
else {
push_int(fdnew);
push_int(0);
LOG(("@m9 Dup/Dup2: succeeded, fdnew = %d", fdnew));
}
break;
case 42: /* Pipe */
if (pipe(pfds) == -1) {
push_err();
LOG(("@m4 Pipe: failed, errno = %d", errno));
}
else {
push_int(pfds[0]);
push_int(pfds[1]);
push_int(0);
LOG(("@m9 Pipe: succeeded, pfds[0] = %d, pfds[1] = %d",
pfds[0], pfds[1]));
}
break;
case 43: /* Times */
dsp2 = pop_ptr();
times(&tm_buf);
if (!tms2mem(dsp2, &tm_buf)) {
push_err();
LOG(("@m4 Times: failed, dsp2 = %lu, errno = %d",
dsp2, errno));
}
else {
LOG(("@m9 Times: succeeded, dsp2 = %lu", dsp2));
}
break;
case 44: /* Profil */
dsp1 = pop_ptr(); /* Buffer */
nbytes = pop_intp(); /* Buffer size */
off = pop_intp(); /* Offset */
n = pop_intp(); /* Scale */
einval(WPROFILIMP);
push_err();
LOG(("@m4 Profil: failed, dsp1 = %lu, nbytes = %d, offset = %d, scale = %d, errno = %d",
dsp1, nbytes, off, n, errno));
break;
case 46: /* Setgid */
groupid = pop_int2();
if (setgid(groupid) == -1) {
push_err();
LOG(("@m4 Setgid: failed, groupid = %d, errno = %d",
groupid, errno));
}
else {
push_int(0);
LOG(("@m9 Setgid: succeeded, groupid = %d", groupid));
}
break;
case 47: /* Getgid */
groupid = getgid();
push_i2(groupid);
LOG(("@m9 Getgid(part 1): succeeded, real groupid = %d",
groupid));
groupid = getegid();
push_i2(groupid);
LOG(("@m9 Getgid(part 2): succeeded, eff groupid = %d",
groupid));
break;
case 48: /* Sigtrp */
trap_no = pop_int();
sig_no = pop_int();
if ((old_trap_no = do_sigtrp(trap_no, sig_no)) == -1) {
push_err();
LOG(("@m4 Sigtrp: failed, trap_no = %d, sig_no = %d, errno = %d",
trap_no, sig_no, errno));
}
else {
push_int(old_trap_no);
push_int(0);
LOG(("@m9 Sigtrp: succeeded, trap_no = %d, sig_no = %d, old_trap_no = %d",
trap_no, sig_no, old_trap_no));
}
break;
case 51: /* Acct */
dsp1 = pop_ptr();
#if HAS_ACCT
if (!savestr(0, dsp1) || acct(buf[0]) == -1) {
push_err();
LOG(("@m4 Acct: failed, dsp1 = %lu, errno = %d",
dsp1, errno));
}
else {
push_int(0);
LOG(("@m9 Acct: succeeded, dsp1 = %lu", dsp1));
}
#else
einval(WMPXIMP);
push_err();
LOG(("@m4 Acct: failed, request = %d, dsp1 = %lu, errno = %d",
request, dsp1, errno));
#endif
break;
case 54: /* Ioctl */
fd = pop_int();
request = pop_int();
dsp2 = pop_ptr();
if (!good_fd(fd) || do_ioctl(fd, request, dsp2) != 0) {
push_err();
LOG(("@m4 Ioctl: failed, fd = %d, request = %d, dsp2 = %lu, errno = %d",
fd, request, dsp2, errno));
}
else {
push_int(0);
LOG(("@m9 Ioctl: succeeded, fd = %d, request = %d, dsp2 = %lu",
fd, request, dsp2));
}
break;
case 56: /* Mpxcall */
request = pop_int(); /* Command */
dsp1 = pop_ptr(); /* Vec */
einval(WMPXIMP);
push_err();
LOG(("@m4 Mpxcall: failed, request = %d, dsp1 = %lu, errno = %d",
request, dsp1, errno));
break;
case 59: /* Exec */
dsp1 = pop_ptr();
dsp2 = pop_ptr();
dsp3 = pop_ptr();
if ( !savestr(0, dsp1)
|| !vec(1, 2, dsp2, &argvec)
|| !vec(3, 4, dsp3, &envvec)
|| /* execute results, ignore return code */
(execve(buf[0], argvec, envvec), 1)
) {
push_err();
LOG(("@m4 Exece: failed, dsp1 = %lu, dsp2 = %lu, dsp2 = %lu, errno = %d",
dsp1, dsp2, dsp3, errno));
}
break;
case 60: /* Umask */
mode = pop_int2();
oldmask = umask((mode_t)mode);
push_int(oldmask);
LOG(("@m9 Umask: succeeded, mode = %d, oldmask = %d",
mode, oldmask));
break;
case 61: /* Chroot */
dsp1 = pop_ptr();
if (!savestr(0, dsp1) || chroot(buf[0]) == -1) {
push_err();
LOG(("@m4 Chroot: failed, dsp1 = %lu, errno = %d",
dsp1, errno));
}
else {
push_int(0);
LOG(("@m9 Chroot: succeeded, dsp1 = %lu", dsp1));
}
break;
default:
trap(EBADMON);
break;
}
}
/* Buffer administration */
PRIVATE check_buf(n, sz)
int n;
size sz;
{
if (buf_cnt[n] == 0) {
buf_cnt[n] = max(128, sz);
buf[n] = Malloc(buf_cnt[n], "moncall buffer");
}
else if (buf_cnt[n] < sz) {
buf_cnt[n] = allocfrac(sz);
buf[n] = Realloc(buf[n], buf_cnt[n], "moncall buffer");
}
}
PRIVATE int savestr(n, addr)
int n;
ptr addr;
{
register size len;
register char *cp, ch;
/* determine the length, carefully */
len = 0;
do {
if (memfault(addr + len, 1L)) {
return 0;
}
ch = mem_loc(addr + len);
len++;
} while (ch);
/* allocate enough buffer space */
check_buf(n, len);
/* copy the string */
cp = buf[n];
do {
*cp++ = ch = mem_loc(addr);
addr++;
} while (ch);
return 1;
}
PRIVATE int vec(n1, n2, addr, vecvec)
int n1, n2;
ptr addr;
char ***vecvec;
{
register char *cp1, *cp2;
ptr p, ldp;
register int n_ent = 0; /* number of entries */
register size str = 0; /* total string length */
/* determine number of elements n_ent */
p = addr;
do {
if (memfault(addr, psize)) {
return 0;
}
ldp = mem_lddp(p);
if (!savestr(n2, ldp)) {
return 0;
}
str += strlen(buf[n2]) + 1;
n_ent++;
p += psize;
} while (ldp);
n_ent++;
*vecvec = (char **) Malloc((size)(n_ent * sizeof (char *)),
"argvec or envvec in exec()");
check_buf(n1, str);
/* copy the elements */
for ( cp1 = buf[n1], n_ent = 0, p = addr;
(ldp = mem_lddp(p)) != 0;
p += psize, n_ent++
) {
if (!savestr(n2, ldp)) {
return 0;
}
(*vecvec)[n_ent] = cp1;
cp2 = buf[n2];
while ((*cp1++ = *cp2++) != '\0') {
/* nothing */
}
}
(*vecvec)[n_ent] = 0;
return 1;
}
int memfault(ptr addr, size length)
{
/* centralizes (almost) all memory access tests in MON */
if (!is_in_mem(addr, length)) {
efault(WMONFLT);
return 1;
}
return 0;
}
void efault(int wrn /* warning number */)
{
warning(wrn);
errno = 14; /* EFAULT */
}
void einval(int wrn /* warning number */)
{
warning(wrn);
errno = 22; /* EINVAL */
}