5 /* $Id: moncalls.c,v 2.9 1994/06/24 10:48:17 ceriel Exp $ */
12 #include <sys/types.h>
17 #include <sys/times.h>
20 /*extern int errno;*/ /* UNIX error number */
22 extern int running; /* from main.c */
23 extern int fd_limit; /* from io.c */
25 #define good_fd(fd) (fd < fd_limit ? 1 : (errno = 9 /* EBADF */, 0))
27 #ifdef BSD_X /* from system.h */
28 #include <sys/timeb.h>
31 struct timeb { /* non-existing; we use an ad-hoc definition */
33 unsigned short millitm;
34 short timezone, dstflag;
38 #ifdef BSD4_2 /* from system.h */
43 #include <sys/errno.h>
44 #undef ERANGE /* collision with trap.h */
63 extern unsigned int alarm();
68 #define INT2SIZE max(wsize, 2L)
69 #define INT4SIZE max(wsize, 4L)
71 #define pop_int() ((int) swpop())
72 #define pop_int2() ((int) spop(INT2SIZE))
73 #define pop_int4() (spop(INT4SIZE))
74 #define pop_intp() ((int) spop(psize))
75 #define pop_uns2() ((unsigned int) upop(INT2SIZE))
76 #define pop_unsp() ((unsigned int) upop(psize))
77 #define pop_ptr() (dppop())
79 #define push_int(a) (wpush((long)(a)))
80 #define push_i2(a) (npush((long)(a), INT2SIZE))
81 #define push_i4(a) (npush((long)(a), INT4SIZE))
82 #define push_unsp(a) (npush((long)(a), psize))
84 #define push_err() { push_int(errno); push_int(errno); }
86 /************************************************************************
89 * The instruction "MON" expects a wsized integer on top of *
90 * top of the stack, which identifies the call. Often there *
91 * are also parameters following this number. The parameters *
92 * were stacked in reverse order (C convention). *
93 * The possible parameter types are : *
95 * 1) int : integer of wordsize *
96 * 2) int2: integer with size max(2, wordsize) *
97 * 3) int4: integer with size max(4, wordsize) *
98 * 4) intp: integer with size of a pointer *
99 * 5) uns2: unsigned integer with size max(2, wordsize) *
100 * 6) unsp: unsigned integer with size of a pointer *
101 * 7) ptr : pointer into data space *
103 * After the call has been executed, a return code is present *
104 * on top of the stack. If this return code equals zero, the call *
105 * succeeded and the results of the call can be found right *
106 * after the return code. A non zero return code indicates a *
107 * failure. In this case no results are available and the return *
108 * code has been pushed twice. *
110 * Monitor calls such as "ioctl", "stat", "ftime", etc. work *
111 * with a private buffer to be filled by the call. The fields *
112 * of the buffer are written to EM-memory separately, possibly *
113 * with some of the fields aligned. To this end a number of *
114 * transport routines are assembled in monstruct.[ch]. *
116 * The EM report specifies a list of UNIX Version 7 -like system *
117 * calls, not full access to the system calls on the underlying *
118 * machine. Therefore an attempt has been made to use or emulate *
119 * the Version 7 system calls on the various machines. A number *
120 * of 4.1 BSD specific parameters have also been implemented. *
122 ************************************************************************/
124 PRIVATE size buf_cnt[5]; /* Current sizes of the buffers */
125 PRIVATE char *buf[5]; /* Pointers to the buffers */
128 PRIVATE int savestr();
133 int n; /* number actually read/written */
134 int status; /* status for wait-call */
135 int flag; /* various flag parameters */
136 int mode; /* various mode parameters */
137 int oldmask; /* for umask call */
138 int whence; /* parameter for lseek */
139 int address; /* address parameter typed int2 */
140 int owner; /* owner parameter typed int2 */
141 int group; /* group parameter typed int2 */
142 int pid; /* pid parameter typed int2 */
143 int ppid; /* parent process pid */
144 long off; /* offset parameter */
145 int pfds[2]; /* pipe file descriptors */
146 long tm; /* for stime call */
147 long actime, modtime; /* for utime */
148 int incr; /* for nice call */
149 int fd, fdnew; /* file descriptors */
150 int groupid; /* group id */
151 int userid; /* user id */
152 int sig; /* killing signal */
153 ptr dsp1, dsp2, dsp3; /* Data Space Pointers */
154 int nbytes; /* number to be read/written */
155 unsigned int seconds; /* for alarm call */
156 int trap_no; /* for sigtrp; trap number */
157 int old_trap_no; /* for sigtrp; old trap number */
158 int sig_no; /* for sigtrp; signal number */
159 int request; /* ioctl and ptrace request */
160 char **envvec; /* environment vector (exec) */
161 char **argvec; /* argument vector (exec) */
163 struct stat st_buf; /* private stat buffer */
164 struct tms tm_buf; /* private tms buffer */
165 struct timeb tb_buf; /* private timeb buffer */
167 #ifdef BSD4_2 /* from system.h */
168 struct timeval tv; /* private timeval buffer */
171 #ifdef SYS_V /* from system.h */
172 struct {time_t x, y;} utimbuf; /* private utime buffer */
174 time_t utimbuf[2]; /* private utime buffer */
188 ((st_sh(SP) == UNDEFINED)
189 || (st_sh(SP + wsize-1) == UNDEFINED)) ?
195 running = 0; /* stop the machine */
196 LOG(("@m9 Exit: ES = %ld", ES));
202 if ((pid = fork()) == 0) {
204 init_ofiles(0); /* Reinitialize */
205 push_int(ppid); /* Pid of parent */
206 push_int(1); /* Flag = 1 for child */
208 LOG(("@m9 Fork: in child, ppid = %d", ppid));
210 else if (pid > 0) { /* Parent */
211 incr_mess_id(); /* Incr. id for next child */
212 push_int(pid); /* Pid of child */
213 push_int(0); /* Flag = 0 for parent */
215 LOG(("@m9 Fork: in parent, cpid = %d", pid));
218 /* fork call failed */
220 LOG(("@m4 Fork: failed, pid = %d, errno = %d",
234 errno = 22; /* EINVAL */
238 check_buf(0, (size)nbytes);
239 if ((n = read(fd, buf[0], nbytes)) == -1)
243 if (check_log("@m6")) {
246 for (i = 0; i < n; i++) {
247 LOG(("@m6 Read: char = '%c'", *(buf[0] + i)));
252 if (in_gda(dsp1) && !in_gda(dsp1 + (n-1))) {
257 if (!is_in_mem(dsp1, n)) {
262 for ( nr = n, cp = buf[0], addr = dsp1;
266 if (in_stack(addr)) {
268 stack_loc(addr) = *cp;
273 data_loc(addr) = *cp;
280 LOG(("@m9 Read: succeeded, n = %d", n));
285 LOG(("@m4 Read: failed, n = %d, errno = %d", n, errno));
297 errno = 22; /* EINVAL */
301 if (in_gda(dsp1) && !in_gda(dsp1 + (nbytes-1))) {
305 if (!is_in_mem(dsp1, nbytes)) {
311 for (addr = dsp1; addr < dsp1 + nbytes; addr++) {
312 if (mem_sh(addr) == UNDEFINED) {
313 warning(in_stack(addr) ? WWLUNDEF : WWGUNDEF);
318 check_buf(0, (size)nbytes);
319 for ( nr = nbytes, addr = dsp1, cp = buf[0];
327 if (check_log("@m6")) {
330 for (i = 0; i < nbytes; i++) {
331 LOG(("@m6 write: char = '%c'", *(buf[0] + i)));
336 if ((n = write(fd, buf[0], nbytes)) == -1)
341 LOG(("@m9 Write: succeeded, n = %d", n));
346 LOG(("@m4 Write: failed, n = %d, nbytes = %d, errno = %d",
354 if (!savestr(0, dsp1) || (fd = open(buf[0], flag)) == -1) {
356 LOG(("@m4 Open: failed, file = %lu, flag = %d, fd = %d, errno = %d",
357 dsp1, flag, fd, errno));
362 LOG(("@m9 Open: succeeded, file = %lu, flag = %d, fd = %d",
370 if (!good_fd(fd) || close(fd) == -1) {
372 LOG(("@m4 Close: failed, fd = %d, errno = %d",
377 LOG(("@m9 Close: succeeded"));
383 if ((pid = wait(&status)) == -1) {
385 LOG(("@m4 Wait: failed, status = %d, errno = %d",
392 LOG(("@m9 Wait: succeeded, status = %d, pid = %d",
401 if (!savestr(0, dsp1) || (fd = creat(buf[0], flag)) == -1) {
403 LOG(("@m4 Creat: failed, dsp1 = %lu, flag = %d, errno = %d",
409 LOG(("@m9 Creat: succeeded, fd = %d", fd));
417 if ( !savestr(0, dsp1)
419 || link(buf[0], buf[1]) == -1
422 LOG(("@m4 Link: failed, dsp1 = %lu, dsp2 = %lu, errno = %d",
427 LOG(("@m9 Link: succeeded, dsp1 = %lu, dsp2 = %lu",
432 case 10: /* Unlink */
435 if (!savestr(0, dsp1) || unlink(buf[0]) == -1) {
437 LOG(("@m4 Unlink: failed, dsp1 = %lu, errno = %d",
442 LOG(("@m9 Unlink: succeeded, dsp1 = %lu", dsp1));
449 if (!savestr(0, dsp1) || chdir(buf[0]) == -1) {
451 LOG(("@m4 Chdir: failed, dsp1 = %lu, errno = %d",
456 LOG(("@m9 Chdir: succeeded, dsp1 = %lu", dsp1));
464 address = pop_int2();
465 if (!savestr(0, dsp1) || mknod(buf[0], mode, address) == -1) {
467 LOG(("@m4 Mknod: failed, dsp1 = %lu, mode = %d, address = %d, errno = %d",
468 dsp1, mode, address, errno));
472 LOG(("@m9 Mknod: succeeded, dsp1 = %lu", dsp1));
480 if (!savestr(0, dsp1) || chmod(buf[0], mode) == -1) {
482 LOG(("@m4 Chmod: failed, dsp1 = %lu, mode = %d, errno = %d",
487 LOG(("@m9 Chmod: succeeded, dsp1 = %lu", dsp1));
496 if (!savestr(0, dsp1) || chown(buf[0], owner, group) == -1) {
498 LOG(("@m4 Chown: failed, dsp1 = %lu, owner = %d, group = %d, errno = %d",
499 dsp1, owner, group, errno));
503 LOG(("@m9 Chown: succeeded, dsp1 = %lu", dsp1));
509 dsp1 = pop_ptr(); /* points to file-name space */
510 dsp2 = pop_ptr(); /* points to EM-stat-buffer space */
511 if ( !savestr(0, dsp1)
512 || stat(buf[0], &st_buf) == -1
513 || !stat2mem(dsp2, &st_buf)
516 LOG(("@m4 Stat: failed, dsp1 = %lu, dsp2 = %lu, errno = %d",
521 LOG(("@m9 Stat: succeeded, dsp1 = %lu, dsp2 = %lu",
531 LOG(("@m4 Lseek: fd = %d, off = %ld, whence = %d",
534 if (!good_fd(fd) || (off = lseek(fd, off, whence)) == -1) {
536 LOG(("@m9 Lseek: failed, errno = %d", errno));
541 LOG(("@m9 Lseek: succeeded, pushed %ld", off));
545 case 20: /* Getpid */
549 LOG(("@m9 Getpid: succeeded, pid = %d", pid));
557 if ( !savestr(0, dsp1)
559 || mount(buf[0], buf[1], flag) == -1
562 LOG(("@m4 Mount: failed, dsp1 = %lu, dsp2 = %lu, flag = %d, errno = %d",
563 dsp1, dsp2, flag, errno));
567 LOG(("@m9 Mount: succeeded, dsp1 = %lu, dsp2 = %lu, flag = %d",
572 case 22: /* Umount */
575 if ( !savestr(0, dsp1)
576 #ifndef BSD4_2 /* from system.h */
577 || umount(buf[0]) == -1
579 || unmount(buf[0]) == -1
583 LOG(("@m4 Umount: failed, dsp1 = %lu, errno = %d",
588 LOG(("@m9 Mount: succeeded, dsp1 = %lu", dsp1));
592 case 23: /* Setuid */
595 if (setuid(userid) == -1) {
597 LOG(("@m4 Setuid: failed, userid = %d, errno = %d",
602 LOG(("@m9 Setuid: succeeded, userid = %d", userid));
606 case 24: /* Getuid */
610 LOG(("@m9 Getuid(part 1): real uid = %d", userid));
613 LOG(("@m9 Getuid(part 2): eff uid = %d", userid));
619 #ifndef BSD4_2 /* from system.h */
623 tv.tv_usec = 0; /* zero microseconds */
624 rc = settimeofday(&tv, (struct timezone *)0);
628 LOG(("@m4 Stime: failed, tm = %ld, errno = %d",
633 LOG(("@m9 Stime: succeeded, tm = %ld", tm));
637 case 26: /* Ptrace */
642 n = pop_int(); /* Data */
645 LOG(("@m4 Ptrace: failed, request = %d, pid = %d, addr = %lu, data = %d, errno = %d",
646 request, pid, dsp3, n, errno));
651 seconds = pop_uns2();
652 LOG(("@m9 Alarm(part 1) seconds = %u", seconds));
653 seconds = alarm(seconds);
655 LOG(("@m9 Alarm(part 2) seconds = %u", seconds));
663 || fstat(fd, &st_buf) == -1
664 || !stat2mem(dsp2, &st_buf)
667 LOG(("@m4 Fstat: failed, fd = %d, dsp2 = %lu, errno = %d",
672 LOG(("@m9 Fstat: succeeded, fd = %d, dsp2 = %lu",
680 LOG(("@m9 Pause: succeeded"));
687 if (memfault(dsp2, 2*INT4SIZE)) {
689 LOG(("@m4 Utime: failed, dsp1 = %lu, dsp2 = %lu, errno = %d",
693 actime = mem_ldu(dsp2, INT4SIZE);
694 modtime = mem_ldu(dsp2 + INT4SIZE, INT4SIZE);
695 #ifdef SYS_V /* from system.h */
698 if (!savestr(0, dsp1) || utime(buf[0], &utimbuf) == -1) {
701 utimbuf[1] = modtime;
702 if (!savestr(0, dsp1) || utime(buf[0], utimbuf) == -1) {
703 /* may require modification for POSIX ???!!! */
706 LOG(("@m4 Utime: failed, dsp1 = %lu, dsp2 = %lu, errno = %d",
711 LOG(("@m9 Utime: succeeded, dsp1 = %lu, dsp2 = %lu",
716 case 33: /* Access */
720 if (!savestr(0, dsp1) || access(buf[0], mode) == -1) {
722 LOG(("@m4 Access: failed, dsp1 = %lu, mode = %d, errno = %d",
727 LOG(("@m9 Access: succeeded, dsp1 = %lu, mode = %d",
736 LOG(("@m9 Nice: succeeded, incr = %d", incr));
742 #ifdef BSD_X /* from system.h */
745 #ifdef SYS_V /* from system.h */
746 tb_buf.time = time((time_t*)0);
748 tb_buf.timezone = timezone / 60;
749 tb_buf.dstflag = daylight;
751 if (!timeb2mem(dsp2, &tb_buf)) {
753 LOG(("@m4 Ftime: failed, dsp2 = %lu, errno = %d",
758 LOG(("@m9 Ftime: succeeded, dsp2 = %lu", dsp2));
765 LOG(("@m9 Sync: succeeded"));
772 if (kill(pid, sig) == -1) {
774 LOG(("@m4 Kill: failed, pid = %d, sig = %d, errno = %d",
779 LOG(("@m9 Kill: succeeded, pid = %d, sig = %d",
784 case 41: /* Dup & Dup2 */
789 int fd1 = fd & ~DUPMASK;/* stripped */
791 LOG(("@m4 Dup2: fd1 = %d, fdnew = %d", fd1, fdnew));
796 #ifdef BSD_X /* from system.h */
797 fdnew = dup2(fd1, fdnew);
800 #ifdef SYS_V /* from system.h */
802 /* simulating the semantics of dup2 on SYS_V */
803 int dupped = dup(fd1);
805 if (dupped < 0 && errno != EMFILE) {
806 /* the dup failed, but not
807 because of too many open
815 fdnew = fcntl(fd1, F_DUPFD, fdnew);
822 LOG(("@m4 Dup: fd = %d, fdnew = %d", fd, fdnew));
823 fdnew = (!good_fd(fd) ? -1 : dup(fd));
828 LOG(("@m4 Dup/Dup2: failed, fdnew = %d, errno = %d",
834 LOG(("@m9 Dup/Dup2: succeeded, fdnew = %d", fdnew));
840 if (pipe(pfds) == -1) {
842 LOG(("@m4 Pipe: failed, errno = %d", errno));
848 LOG(("@m9 Pipe: succeeded, pfds[0] = %d, pfds[1] = %d",
857 if (!tms2mem(dsp2, &tm_buf)) {
859 LOG(("@m4 Times: failed, dsp2 = %lu, errno = %d",
863 LOG(("@m9 Times: succeeded, dsp2 = %lu", dsp2));
867 case 44: /* Profil */
869 dsp1 = pop_ptr(); /* Buffer */
870 nbytes = pop_intp(); /* Buffer size */
871 off = pop_intp(); /* Offset */
872 n = pop_intp(); /* Scale */
875 LOG(("@m4 Profil: failed, dsp1 = %lu, nbytes = %d, offset = %d, scale = %d, errno = %d",
876 dsp1, nbytes, off, n, errno));
879 case 46: /* Setgid */
881 groupid = pop_int2();
882 if (setgid(groupid) == -1) {
884 LOG(("@m4 Setgid: failed, groupid = %d, errno = %d",
889 LOG(("@m9 Setgid: succeeded, groupid = %d", groupid));
893 case 47: /* Getgid */
897 LOG(("@m9 Getgid(part 1): succeeded, real groupid = %d",
901 LOG(("@m9 Getgid(part 2): succeeded, eff groupid = %d",
905 case 48: /* Sigtrp */
910 if ((old_trap_no = do_sigtrp(trap_no, sig_no)) == -1) {
912 LOG(("@m4 Sigtrp: failed, trap_no = %d, sig_no = %d, errno = %d",
913 trap_no, sig_no, errno));
916 push_int(old_trap_no);
918 LOG(("@m9 Sigtrp: succeeded, trap_no = %d, sig_no = %d, old_trap_no = %d",
919 trap_no, sig_no, old_trap_no));
926 if (!savestr(0, dsp1) || acct(buf[0]) == -1) {
928 LOG(("@m4 Acct: failed, dsp1 = %lu, errno = %d",
933 LOG(("@m9 Acct: succeeded, dsp1 = %lu", dsp1));
942 if (!good_fd(fd) || do_ioctl(fd, request, dsp2) != 0) {
944 LOG(("@m4 Ioctl: failed, fd = %d, request = %d, dsp2 = %lu, errno = %d",
945 fd, request, dsp2, errno));
949 LOG(("@m9 Ioctl: succeeded, fd = %d, request = %d, dsp2 = %lu",
954 case 56: /* Mpxcall */
956 request = pop_int(); /* Command */
957 dsp1 = pop_ptr(); /* Vec */
960 LOG(("@m4 Mpxcall: failed, request = %d, dsp1 = %lu, errno = %d",
961 request, dsp1, errno));
969 if ( !savestr(0, dsp1)
970 || !vec(1, 2, dsp2, &argvec)
971 || !vec(3, 4, dsp3, &envvec)
972 || /* execute results, ignore return code */
973 (execve(buf[0], argvec, envvec), 1)
976 LOG(("@m4 Exece: failed, dsp1 = %lu, dsp2 = %lu, dsp2 = %lu, errno = %d",
977 dsp1, dsp2, dsp3, errno));
984 oldmask = umask(mode);
986 LOG(("@m9 Umask: succeeded, mode = %d, oldmask = %d",
990 case 61: /* Chroot */
993 if (!savestr(0, dsp1) || chroot(buf[0]) == -1) {
995 LOG(("@m4 Chroot: failed, dsp1 = %lu, errno = %d",
1000 LOG(("@m9 Chroot: succeeded, dsp1 = %lu", dsp1));
1010 /* Buffer administration */
1012 PRIVATE check_buf(n, sz)
1016 if (buf_cnt[n] == 0) {
1017 buf_cnt[n] = max(128, sz);
1018 buf[n] = Malloc(buf_cnt[n], "moncall buffer");
1020 else if (buf_cnt[n] < sz) {
1021 buf_cnt[n] = allocfrac(sz);
1022 buf[n] = Realloc(buf[n], buf_cnt[n], "moncall buffer");
1026 PRIVATE int savestr(n, addr)
1031 register char *cp, ch;
1033 /* determine the length, carefully */
1036 if (memfault(addr + len, 1L)) {
1039 ch = mem_loc(addr + len);
1043 /* allocate enough buffer space */
1046 /* copy the string */
1049 *cp++ = ch = mem_loc(addr);
1056 PRIVATE int vec(n1, n2, addr, vecvec)
1061 register char *cp1, *cp2;
1063 register int n_ent = 0; /* number of entries */
1064 register size str = 0; /* total string length */
1066 /* determine number of elements n_ent */
1069 if (memfault(addr, psize)) {
1073 if (!savestr(n2, ldp)) {
1076 str += strlen(buf[n2]) + 1;
1082 *vecvec = (char **) Malloc((size)(n_ent * sizeof (char *)),
1083 "argvec or envvec in exec()");
1086 /* copy the elements */
1087 for ( cp1 = buf[n1], n_ent = 0, p = addr;
1091 if (!savestr(n2, ldp)) {
1094 (*vecvec)[n_ent] = cp1;
1096 while (*cp1++ = *cp2++) {
1100 (*vecvec)[n_ent] = 0;
1104 int memfault(addr, length)
1108 /* centralizes (almost) all memory access tests in MON */
1109 if (!is_in_mem(addr, length)) {
1117 int wrn; /* warning number */
1120 errno = 14; /* EFAULT */
1124 int wrn; /* warning number */
1127 errno = 22; /* EINVAL */