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>
19 extern int errno; /* UNIX error number */
21 extern int running; /* from main.c */
22 extern int fd_limit; /* from io.c */
24 #define good_fd(fd) (fd < fd_limit ? 1 : (errno = 9 /* EBADF */, 0))
26 #ifdef BSD_X /* from system.h */
27 #include <sys/timeb.h>
30 struct timeb { /* non-existing; we use an ad-hoc definition */
32 unsigned short millitm;
33 short timezone, dstflag;
37 #ifdef BSD4_2 /* from system.h */
42 #include <sys/errno.h>
43 #undef ERANGE /* collision with trap.h */
62 extern unsigned int alarm();
67 #define INT2SIZE max(wsize, 2L)
68 #define INT4SIZE max(wsize, 4L)
70 #define pop_int() ((int) swpop())
71 #define pop_int2() ((int) spop(INT2SIZE))
72 #define pop_int4() (spop(INT4SIZE))
73 #define pop_intp() ((int) spop(psize))
74 #define pop_uns2() ((unsigned int) upop(INT2SIZE))
75 #define pop_unsp() ((unsigned int) upop(psize))
76 #define pop_ptr() (dppop())
78 #define push_int(a) (wpush((long)(a)))
79 #define push_i2(a) (npush((long)(a), INT2SIZE))
80 #define push_i4(a) (npush((long)(a), INT4SIZE))
81 #define push_unsp(a) (npush((long)(a), psize))
83 #define push_err() { push_int(errno); push_int(errno); }
85 /************************************************************************
88 * The instruction "MON" expects a wsized integer on top of *
89 * top of the stack, which identifies the call. Often there *
90 * are also parameters following this number. The parameters *
91 * were stacked in reverse order (C convention). *
92 * The possible parameter types are : *
94 * 1) int : integer of wordsize *
95 * 2) int2: integer with size max(2, wordsize) *
96 * 3) int4: integer with size max(4, wordsize) *
97 * 4) intp: integer with size of a pointer *
98 * 5) uns2: unsigned integer with size max(2, wordsize) *
99 * 6) unsp: unsigned integer with size of a pointer *
100 * 7) ptr : pointer into data space *
102 * After the call has been executed, a return code is present *
103 * on top of the stack. If this return code equals zero, the call *
104 * succeeded and the results of the call can be found right *
105 * after the return code. A non zero return code indicates a *
106 * failure. In this case no results are available and the return *
107 * code has been pushed twice. *
109 * Monitor calls such as "ioctl", "stat", "ftime", etc. work *
110 * with a private buffer to be filled by the call. The fields *
111 * of the buffer are written to EM-memory separately, possibly *
112 * with some of the fields aligned. To this end a number of *
113 * transport routines are assembled in monstruct.[ch]. *
115 * The EM report specifies a list of UNIX Version 7 -like system *
116 * calls, not full access to the system calls on the underlying *
117 * machine. Therefore an attempt has been made to use or emulate *
118 * the Version 7 system calls on the various machines. A number *
119 * of 4.1 BSD specific parameters have also been implemented. *
121 ************************************************************************/
123 PRIVATE size buf_cnt[5]; /* Current sizes of the buffers */
124 PRIVATE char *buf[5]; /* Pointers to the buffers */
127 PRIVATE int savestr();
132 int n; /* number actually read/written */
133 int status; /* status for wait-call */
134 int flag; /* various flag parameters */
135 int mode; /* various mode parameters */
136 int oldmask; /* for umask call */
137 int whence; /* parameter for lseek */
138 int address; /* address parameter typed int2 */
139 int owner; /* owner parameter typed int2 */
140 int group; /* group parameter typed int2 */
141 int pid; /* pid parameter typed int2 */
142 int ppid; /* parent process pid */
143 long off; /* offset parameter */
144 int pfds[2]; /* pipe file descriptors */
145 long tm; /* for stime call */
146 long actime, modtime; /* for utime */
147 int incr; /* for nice call */
148 int fd, fdnew; /* file descriptors */
149 int groupid; /* group id */
150 int userid; /* user id */
151 int sig; /* killing signal */
152 ptr dsp1, dsp2, dsp3; /* Data Space Pointers */
153 int nbytes; /* number to be read/written */
154 unsigned int seconds; /* for alarm call */
155 int trap_no; /* for sigtrp; trap number */
156 int old_trap_no; /* for sigtrp; old trap number */
157 int sig_no; /* for sigtrp; signal number */
158 int request; /* ioctl and ptrace request */
159 char **envvec; /* environment vector (exec) */
160 char **argvec; /* argument vector (exec) */
162 struct stat st_buf; /* private stat buffer */
163 struct tms tm_buf; /* private tms buffer */
164 struct timeb tb_buf; /* private timeb buffer */
166 #ifdef BSD4_2 /* from system.h */
167 struct timeval tv; /* private timeval buffer */
170 #ifdef SYS_V /* from system.h */
171 struct {time_t x, y;} utimbuf; /* private utime buffer */
173 time_t utimbuf[2]; /* private utime buffer */
187 ((st_sh(SP) == UNDEFINED)
188 || (st_sh(SP + wsize-1) == UNDEFINED)) ?
194 running = 0; /* stop the machine */
195 LOG(("@m9 Exit: ES = %ld", ES));
201 if ((pid = fork()) == 0) {
203 init_ofiles(0); /* Reinitialize */
204 push_int(ppid); /* Pid of parent */
205 push_int(1); /* Flag = 1 for child */
207 LOG(("@m9 Fork: in child, ppid = %d", ppid));
209 else if (pid > 0) { /* Parent */
210 incr_mess_id(); /* Incr. id for next child */
211 push_int(pid); /* Pid of child */
212 push_int(0); /* Flag = 0 for parent */
214 LOG(("@m9 Fork: in parent, cpid = %d", pid));
217 /* fork call failed */
219 LOG(("@m4 Fork: failed, pid = %d, errno = %d",
233 errno = 22; /* EINVAL */
237 check_buf(0, (size)nbytes);
238 if ((n = read(fd, buf[0], nbytes)) == -1)
242 if (check_log("@m6")) {
245 for (i = 0; i < n; i++) {
246 LOG(("@m6 Read: char = '%c'", *(buf[0] + i)));
251 if (in_gda(dsp1) && !in_gda(dsp1 + (n-1))) {
256 if (!is_in_mem(dsp1, n)) {
261 for ( nr = n, cp = buf[0], addr = dsp1;
265 if (in_stack(addr)) {
267 stack_loc(addr) = *cp;
272 data_loc(addr) = *cp;
279 LOG(("@m9 Read: succeeded, n = %d", n));
284 LOG(("@m4 Read: failed, n = %d, errno = %d", n, errno));
296 errno = 22; /* EINVAL */
300 if (in_gda(dsp1) && !in_gda(dsp1 + (nbytes-1))) {
304 if (!is_in_mem(dsp1, nbytes)) {
310 for (addr = dsp1; addr < dsp1 + nbytes; addr++) {
311 if (mem_sh(addr) == UNDEFINED) {
312 warning(in_stack(addr) ? WWLUNDEF : WWGUNDEF);
317 check_buf(0, (size)nbytes);
318 for ( nr = nbytes, addr = dsp1, cp = buf[0];
326 if (check_log("@m6")) {
329 for (i = 0; i < nbytes; i++) {
330 LOG(("@m6 write: char = '%c'", *(buf[0] + i)));
335 if ((n = write(fd, buf[0], nbytes)) == -1)
340 LOG(("@m9 Write: succeeded, n = %d", n));
345 LOG(("@m4 Write: failed, n = %d, nbytes = %d, errno = %d",
353 if (!savestr(0, dsp1) || (fd = open(buf[0], flag)) == -1) {
355 LOG(("@m4 Open: failed, file = %lu, flag = %d, fd = %d, errno = %d",
356 dsp1, flag, fd, errno));
361 LOG(("@m9 Open: succeeded, file = %lu, flag = %d, fd = %d",
369 if (!good_fd(fd) || close(fd) == -1) {
371 LOG(("@m4 Close: failed, fd = %d, errno = %d",
376 LOG(("@m9 Close: succeeded"));
382 if ((pid = wait(&status)) == -1) {
384 LOG(("@m4 Wait: failed, status = %d, errno = %d",
391 LOG(("@m9 Wait: succeeded, status = %d, pid = %d",
400 if (!savestr(0, dsp1) || (fd = creat(buf[0], flag)) == -1) {
402 LOG(("@m4 Creat: failed, dsp1 = %lu, flag = %d, errno = %d",
408 LOG(("@m9 Creat: succeeded, fd = %d", fd));
416 if ( !savestr(0, dsp1)
418 || link(buf[0], buf[1]) == -1
421 LOG(("@m4 Link: failed, dsp1 = %lu, dsp2 = %lu, errno = %d",
426 LOG(("@m9 Link: succeeded, dsp1 = %lu, dsp2 = %lu",
431 case 10: /* Unlink */
434 if (!savestr(0, dsp1) || unlink(buf[0]) == -1) {
436 LOG(("@m4 Unlink: failed, dsp1 = %lu, errno = %d",
441 LOG(("@m9 Unlink: succeeded, dsp1 = %lu", dsp1));
448 if (!savestr(0, dsp1) || chdir(buf[0]) == -1) {
450 LOG(("@m4 Chdir: failed, dsp1 = %lu, errno = %d",
455 LOG(("@m9 Chdir: succeeded, dsp1 = %lu", dsp1));
463 address = pop_int2();
464 if (!savestr(0, dsp1) || mknod(buf[0], mode, address) == -1) {
466 LOG(("@m4 Mknod: failed, dsp1 = %lu, mode = %d, address = %d, errno = %d",
467 dsp1, mode, address, errno));
471 LOG(("@m9 Mknod: succeeded, dsp1 = %lu", dsp1));
479 if (!savestr(0, dsp1) || chmod(buf[0], mode) == -1) {
481 LOG(("@m4 Chmod: failed, dsp1 = %lu, mode = %d, errno = %d",
486 LOG(("@m9 Chmod: succeeded, dsp1 = %lu", dsp1));
495 if (!savestr(0, dsp1) || chown(buf[0], owner, group) == -1) {
497 LOG(("@m4 Chown: failed, dsp1 = %lu, owner = %d, group = %d, errno = %d",
498 dsp1, owner, group, errno));
502 LOG(("@m9 Chown: succeeded, dsp1 = %lu", dsp1));
508 dsp1 = pop_ptr(); /* points to file-name space */
509 dsp2 = pop_ptr(); /* points to EM-stat-buffer space */
510 if ( !savestr(0, dsp1)
511 || stat(buf[0], &st_buf) == -1
512 || !stat2mem(dsp2, &st_buf)
515 LOG(("@m4 Stat: failed, dsp1 = %lu, dsp2 = %lu, errno = %d",
520 LOG(("@m9 Stat: succeeded, dsp1 = %lu, dsp2 = %lu",
530 LOG(("@m4 Lseek: fd = %d, off = %ld, whence = %d",
533 if (!good_fd(fd) || (off = lseek(fd, off, whence)) == -1) {
535 LOG(("@m9 Lseek: failed, errno = %d", errno));
540 LOG(("@m9 Lseek: succeeded, pushed %ld", off));
544 case 20: /* Getpid */
548 LOG(("@m9 Getpid: succeeded, pid = %d", pid));
556 if ( !savestr(0, dsp1)
558 || mount(buf[0], buf[1], flag) == -1
561 LOG(("@m4 Mount: failed, dsp1 = %lu, dsp2 = %lu, flag = %d, errno = %d",
562 dsp1, dsp2, flag, errno));
566 LOG(("@m9 Mount: succeeded, dsp1 = %lu, dsp2 = %lu, flag = %d",
571 case 22: /* Umount */
574 if ( !savestr(0, dsp1)
575 #ifndef BSD4_2 /* from system.h */
576 || umount(buf[0]) == -1
578 || unmount(buf[0]) == -1
582 LOG(("@m4 Umount: failed, dsp1 = %lu, errno = %d",
587 LOG(("@m9 Mount: succeeded, dsp1 = %lu", dsp1));
591 case 23: /* Setuid */
594 if (setuid(userid) == -1) {
596 LOG(("@m4 Setuid: failed, userid = %d, errno = %d",
601 LOG(("@m9 Setuid: succeeded, userid = %d", userid));
605 case 24: /* Getuid */
609 LOG(("@m9 Getuid(part 1): real uid = %d", userid));
612 LOG(("@m9 Getuid(part 2): eff uid = %d", userid));
618 #ifndef BSD4_2 /* from system.h */
622 tv.tv_usec = 0; /* zero microseconds */
623 rc = settimeofday(&tv, (struct timezone *)0);
627 LOG(("@m4 Stime: failed, tm = %ld, errno = %d",
632 LOG(("@m9 Stime: succeeded, tm = %ld", tm));
636 case 26: /* Ptrace */
641 n = pop_int(); /* Data */
644 LOG(("@m4 Ptrace: failed, request = %d, pid = %d, addr = %lu, data = %d, errno = %d",
645 request, pid, dsp3, n, errno));
650 seconds = pop_uns2();
651 LOG(("@m9 Alarm(part 1) seconds = %u", seconds));
652 seconds = alarm(seconds);
654 LOG(("@m9 Alarm(part 2) seconds = %u", seconds));
662 || fstat(fd, &st_buf) == -1
663 || !stat2mem(dsp2, &st_buf)
666 LOG(("@m4 Fstat: failed, fd = %d, dsp2 = %lu, errno = %d",
671 LOG(("@m9 Fstat: succeeded, fd = %d, dsp2 = %lu",
679 LOG(("@m9 Pause: succeeded"));
686 if (memfault(dsp2, 2*INT4SIZE)) {
688 LOG(("@m4 Utime: failed, dsp1 = %lu, dsp2 = %lu, errno = %d",
692 actime = mem_ldu(dsp2, INT4SIZE);
693 modtime = mem_ldu(dsp2 + INT4SIZE, INT4SIZE);
694 #ifdef SYS_V /* from system.h */
697 if (!savestr(0, dsp1) || utime(buf[0], &utimbuf) == -1) {
700 utimbuf[1] = modtime;
701 if (!savestr(0, dsp1) || utime(buf[0], utimbuf) == -1) {
702 /* may require modification for POSIX ???!!! */
705 LOG(("@m4 Utime: failed, dsp1 = %lu, dsp2 = %lu, errno = %d",
710 LOG(("@m9 Utime: succeeded, dsp1 = %lu, dsp2 = %lu",
715 case 33: /* Access */
719 if (!savestr(0, dsp1) || access(buf[0], mode) == -1) {
721 LOG(("@m4 Access: failed, dsp1 = %lu, mode = %d, errno = %d",
726 LOG(("@m9 Access: succeeded, dsp1 = %lu, mode = %d",
735 LOG(("@m9 Nice: succeeded, incr = %d", incr));
741 #ifdef BSD_X /* from system.h */
744 #ifdef SYS_V /* from system.h */
745 tb_buf.time = time((time_t*)0);
747 tb_buf.timezone = timezone / 60;
748 tb_buf.dstflag = daylight;
750 if (!timeb2mem(dsp2, &tb_buf)) {
752 LOG(("@m4 Ftime: failed, dsp2 = %lu, errno = %d",
757 LOG(("@m9 Ftime: succeeded, dsp2 = %lu", dsp2));
764 LOG(("@m9 Sync: succeeded"));
771 if (kill(pid, sig) == -1) {
773 LOG(("@m4 Kill: failed, pid = %d, sig = %d, errno = %d",
778 LOG(("@m9 Kill: succeeded, pid = %d, sig = %d",
783 case 41: /* Dup & Dup2 */
788 int fd1 = fd & ~DUPMASK;/* stripped */
790 LOG(("@m4 Dup2: fd1 = %d, fdnew = %d", fd1, fdnew));
795 #ifdef BSD_X /* from system.h */
796 fdnew = dup2(fd1, fdnew);
799 #ifdef SYS_V /* from system.h */
801 /* simulating the semantics of dup2 on SYS_V */
802 int dupped = dup(fd1);
804 if (dupped < 0 && errno != EMFILE) {
805 /* the dup failed, but not
806 because of too many open
814 fdnew = fcntl(fd1, F_DUPFD, fdnew);
821 LOG(("@m4 Dup: fd = %d, fdnew = %d", fd, fdnew));
822 fdnew = (!good_fd(fd) ? -1 : dup(fd));
827 LOG(("@m4 Dup/Dup2: failed, fdnew = %d, errno = %d",
833 LOG(("@m9 Dup/Dup2: succeeded, fdnew = %d", fdnew));
839 if (pipe(pfds) == -1) {
841 LOG(("@m4 Pipe: failed, errno = %d", errno));
847 LOG(("@m9 Pipe: succeeded, pfds[0] = %d, pfds[1] = %d",
856 if (!tms2mem(dsp2, &tm_buf)) {
858 LOG(("@m4 Times: failed, dsp2 = %lu, errno = %d",
862 LOG(("@m9 Times: succeeded, dsp2 = %lu", dsp2));
866 case 44: /* Profil */
868 dsp1 = pop_ptr(); /* Buffer */
869 nbytes = pop_intp(); /* Buffer size */
870 off = pop_intp(); /* Offset */
871 n = pop_intp(); /* Scale */
874 LOG(("@m4 Profil: failed, dsp1 = %lu, nbytes = %d, offset = %d, scale = %d, errno = %d",
875 dsp1, nbytes, off, n, errno));
878 case 46: /* Setgid */
880 groupid = pop_int2();
881 if (setgid(groupid) == -1) {
883 LOG(("@m4 Setgid: failed, groupid = %d, errno = %d",
888 LOG(("@m9 Setgid: succeeded, groupid = %d", groupid));
892 case 47: /* Getgid */
896 LOG(("@m9 Getgid(part 1): succeeded, real groupid = %d",
900 LOG(("@m9 Getgid(part 2): succeeded, eff groupid = %d",
904 case 48: /* Sigtrp */
909 if ((old_trap_no = do_sigtrp(trap_no, sig_no)) == -1) {
911 LOG(("@m4 Sigtrp: failed, trap_no = %d, sig_no = %d, errno = %d",
912 trap_no, sig_no, errno));
915 push_int(old_trap_no);
917 LOG(("@m9 Sigtrp: succeeded, trap_no = %d, sig_no = %d, old_trap_no = %d",
918 trap_no, sig_no, old_trap_no));
925 if (!savestr(0, dsp1) || acct(buf[0]) == -1) {
927 LOG(("@m4 Acct: failed, dsp1 = %lu, errno = %d",
932 LOG(("@m9 Acct: succeeded, dsp1 = %lu", dsp1));
941 if (!good_fd(fd) || do_ioctl(fd, request, dsp2) != 0) {
943 LOG(("@m4 Ioctl: failed, fd = %d, request = %d, dsp2 = %lu, errno = %d",
944 fd, request, dsp2, errno));
948 LOG(("@m9 Ioctl: succeeded, fd = %d, request = %d, dsp2 = %lu",
953 case 56: /* Mpxcall */
955 request = pop_int(); /* Command */
956 dsp1 = pop_ptr(); /* Vec */
959 LOG(("@m4 Mpxcall: failed, request = %d, dsp1 = %lu, errno = %d",
960 request, dsp1, errno));
968 if ( !savestr(0, dsp1)
969 || !vec(1, 2, dsp2, &argvec)
970 || !vec(3, 4, dsp3, &envvec)
971 || /* execute results, ignore return code */
972 (execve(buf[0], argvec, envvec), 1)
975 LOG(("@m4 Exece: failed, dsp1 = %lu, dsp2 = %lu, dsp2 = %lu, errno = %d",
976 dsp1, dsp2, dsp3, errno));
983 oldmask = umask(mode);
985 LOG(("@m9 Umask: succeeded, mode = %d, oldmask = %d",
989 case 61: /* Chroot */
992 if (!savestr(0, dsp1) || chroot(buf[0]) == -1) {
994 LOG(("@m4 Chroot: failed, dsp1 = %lu, errno = %d",
999 LOG(("@m9 Chroot: succeeded, dsp1 = %lu", dsp1));
1009 /* Buffer administration */
1011 PRIVATE check_buf(n, sz)
1015 if (buf_cnt[n] == 0) {
1016 buf_cnt[n] = max(128, sz);
1017 buf[n] = Malloc(buf_cnt[n], "moncall buffer");
1019 else if (buf_cnt[n] < sz) {
1020 buf_cnt[n] = allocfrac(sz);
1021 buf[n] = Realloc(buf[n], buf_cnt[n], "moncall buffer");
1025 PRIVATE int savestr(n, addr)
1030 register char *cp, ch;
1032 /* determine the length, carefully */
1035 if (memfault(addr + len, 1L)) {
1038 ch = mem_loc(addr + len);
1042 /* allocate enough buffer space */
1045 /* copy the string */
1048 *cp++ = ch = mem_loc(addr);
1055 PRIVATE int vec(n1, n2, addr, vecvec)
1060 register char *cp1, *cp2;
1062 register int n_ent = 0; /* number of entries */
1063 register size str = 0; /* total string length */
1065 /* determine number of elements n_ent */
1068 if (memfault(addr, psize)) {
1072 if (!savestr(n2, ldp)) {
1075 str += strlen(buf[n2]) + 1;
1081 *vecvec = (char **) Malloc((size)(n_ent * sizeof (char *)),
1082 "argvec or envvec in exec()");
1085 /* copy the elements */
1086 for ( cp1 = buf[n1], n_ent = 0, p = addr;
1090 if (!savestr(n2, ldp)) {
1093 (*vecvec)[n_ent] = cp1;
1095 while (*cp1++ = *cp2++) {
1099 (*vecvec)[n_ent] = 0;
1103 int memfault(addr, length)
1107 /* centralizes (almost) all memory access tests in MON */
1108 if (!is_in_mem(addr, length)) {
1116 int wrn; /* warning number */
1119 errno = 14; /* EFAULT */
1123 int wrn; /* warning number */
1126 errno = 22; /* EINVAL */