Pristine Ack-5.5
[Ack-5.5.git] / util / int / moncalls.c
1 /*
2         The MON instruction
3 */
4
5 /* $Id: moncalls.c,v 2.9 1994/06/24 10:48:17 ceriel Exp $ */
6
7 #include        "sysidf.h"
8 #include        "log.h"
9 #include        "alloc.h"
10 #include        "shadow.h"
11
12 #include        <sys/types.h>
13 #include        <sys/stat.h>
14 #if __STDC__
15 #include        <time.h>
16 #endif
17 #include        <sys/times.h>
18
19 extern int errno;                       /* UNIX error number */
20
21 extern int running;                     /* from main.c */
22 extern int fd_limit;                    /* from io.c */
23
24 #define good_fd(fd)     (fd < fd_limit ? 1 : (errno = 9 /* EBADF */, 0))
25
26 #ifdef  BSD_X                           /* from system.h */
27 #include        <sys/timeb.h>
28 #endif  /* BSD_X */
29 #ifdef  SYS_V
30 struct timeb {                  /* non-existing; we use an ad-hoc definition */
31         long time;
32         unsigned short millitm;
33         short timezone, dstflag;
34 };
35 #endif  /* SYS_V */
36
37 #ifdef  BSD4_2                          /* from system.h */
38 #include        <sys/time.h>
39 #endif  /* BSD4_2 */
40
41 #ifdef  SYS_V
42 #include        <sys/errno.h>
43 #undef          ERANGE                  /* collision with trap.h */
44 #include        <fcntl.h>
45 #include        <time.h>
46 #endif  /* SYS_V */
47
48 #include        <em_abs.h>
49 #include        "logging.h"
50 #include        "global.h"
51 #include        "trap.h"
52 #include        "warn.h"
53 #include        "mem.h"
54
55 #define INPUT           0
56 #define OUTPUT          1
57
58 #define DUPMASK         0x40
59
60 extern long lseek();
61 #ifdef  SYS_V
62 extern unsigned int alarm();
63 extern long time();
64 extern void sync();
65 #endif  /* SYS_V */
66
67 #define INT2SIZE        max(wsize, 2L)
68 #define INT4SIZE        max(wsize, 4L)
69
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())
77
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))
82
83 #define push_err()      { push_int(errno); push_int(errno); }
84
85 /************************************************************************
86  *                              Monitor calls.                          *
87  *                                                                      *
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 :                              *
93  *                                                                      *
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                        *
101  *                                                                      *
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.                                     *
108  *                                                                      *
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].             *
114  *                                                                      *
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.      *
120  *                                                                      *
121  ************************************************************************/
122
123 PRIVATE size buf_cnt[5];                /* Current sizes of the buffers */
124 PRIVATE char *buf[5];                   /* Pointers to the buffers */
125
126 PRIVATE check_buf();
127 PRIVATE int savestr();
128 PRIVATE int vec();
129
130 moncall()
131 {
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) */
161
162         struct stat st_buf;             /* private stat buffer */
163         struct tms tm_buf;              /* private tms buffer */
164         struct timeb tb_buf;            /* private timeb buffer */
165
166 #ifdef  BSD4_2                          /* from system.h */
167         struct timeval tv;              /* private timeval buffer */
168 #endif  /* BSD4_2                        */
169
170 #ifdef  SYS_V                           /* from system.h */
171         struct {time_t x, y;} utimbuf;  /* private utime buffer */
172 #else   /* SYS_V */
173         time_t utimbuf[2];              /* private utime buffer */
174 #endif  /* !SYS_V */
175
176         char *cp;
177         int nr;
178         ptr addr;
179         int rc;
180
181         switch (pop_int()) {
182
183         case 1:                         /* Exit */
184
185 #ifdef  LOGGING
186                 ES_def =
187                         ((st_sh(SP) == UNDEFINED)
188                                 || (st_sh(SP + wsize-1) == UNDEFINED)) ?
189                         UNDEFINED : DEFINED;
190 #else
191                 ES_def = DEFINED;
192 #endif  /* LOGGING */
193                 ES = pop_int();
194                 running = 0;            /* stop the machine */
195                 LOG(("@m9 Exit: ES = %ld", ES));
196                 break;
197
198         case 2:                         /* Fork */
199
200                 ppid = getpid();
201                 if ((pid = fork()) == 0) {
202                         /* Child */
203                         init_ofiles(0); /* Reinitialize */
204                         push_int(ppid); /* Pid of parent */
205                         push_int(1);    /* Flag = 1 for child */
206                         push_int(0);
207                         LOG(("@m9 Fork: in child, ppid = %d", ppid));
208                 }
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 */
213                         push_int(0);
214                         LOG(("@m9 Fork: in parent, cpid = %d", pid));
215                 }
216                 else {
217                         /* fork call failed */
218                         push_err();
219                         LOG(("@m4 Fork: failed, pid = %d, errno = %d",
220                                 pid, errno));
221                 }
222                 break;
223
224         case 3:                         /* Read */
225
226                 fd = pop_int();
227                 dsp1 = pop_ptr();
228                 nbytes = pop_intp();
229
230                 if (!good_fd(fd))
231                         goto read_error;
232                 if (nbytes < 0) {
233                         errno = 22;     /* EINVAL */
234                         goto read_error;
235                 }
236
237                 check_buf(0, (size)nbytes);
238                 if ((n = read(fd, buf[0], nbytes)) == -1)
239                         goto read_error;
240
241 #ifdef  LOGGING
242                 if (check_log("@m6")) {
243                         register int i;
244                         
245                         for (i = 0; i < n; i++) {
246                                 LOG(("@m6 Read: char = '%c'", *(buf[0] + i)));
247                         }
248                 }
249 #endif  /* LOGGING */
250
251                 if (in_gda(dsp1) && !in_gda(dsp1 + (n-1))) {
252                         efault(WRGDAH);
253                         goto read_error;
254                 }
255
256                 if (!is_in_mem(dsp1, n)) {
257                         efault(WRUMEM);
258                         goto read_error;
259                 }
260
261                 for (   nr = n, cp = buf[0], addr = dsp1;
262                         nr;
263                         nr--, addr++, cp++
264                 ) {
265                         if (in_stack(addr)) {
266                                 ch_st_prot(addr);
267                                 stack_loc(addr) = *cp;
268                                 st_int(addr);
269                         }
270                         else {
271                                 ch_dt_prot(addr);
272                                 data_loc(addr) = *cp;
273                                 dt_int(addr);
274                         }
275                 }
276
277                 push_unsp(n);
278                 push_int(0);
279                 LOG(("@m9 Read: succeeded, n = %d", n));
280                 break;
281
282         read_error:
283                 push_err();
284                 LOG(("@m4 Read: failed, n = %d, errno = %d", n, errno));
285                 break;
286
287         case 4:                         /* Write */
288
289                 fd = pop_int();
290                 dsp1 = pop_ptr();
291                 nbytes = pop_intp();
292
293                 if (!good_fd(fd))
294                         goto write_error;
295                 if (nbytes < 0) {
296                         errno = 22;     /* EINVAL */
297                         goto read_error;
298                 }
299
300                 if (in_gda(dsp1) && !in_gda(dsp1 + (nbytes-1))) {
301                         efault(WWGDAH);
302                         goto write_error;
303                 }
304                 if (!is_in_mem(dsp1, nbytes)) {
305                         efault(WWUMEM);
306                         goto write_error;
307                 }
308
309 #ifdef  LOGGING
310                 for (addr = dsp1; addr < dsp1 + nbytes; addr++) {
311                         if (mem_sh(addr) == UNDEFINED) {
312                                 warning(in_stack(addr) ? WWLUNDEF : WWGUNDEF);
313                         }
314                 }
315 #endif  /* LOGGING */
316
317                 check_buf(0, (size)nbytes);
318                 for (   nr = nbytes, addr = dsp1, cp = buf[0];
319                         nr;
320                         nr--, addr++, cp++
321                 ) {
322                         *cp = mem_loc(addr);
323                 }
324
325 #ifdef  LOGGING
326                 if (check_log("@m6")) {
327                         register int i;
328                         
329                         for (i = 0; i < nbytes; i++) {
330                                 LOG(("@m6 write: char = '%c'", *(buf[0] + i)));
331                         }
332                 }
333 #endif  /* LOGGING */
334
335                 if ((n = write(fd, buf[0], nbytes)) == -1)
336                         goto write_error;
337
338                 push_unsp(n);
339                 push_int(0);
340                 LOG(("@m9 Write: succeeded, n = %d", n));
341                 break;
342
343         write_error:
344                 push_err();
345                 LOG(("@m4 Write: failed, n = %d, nbytes = %d, errno = %d",
346                         n, nbytes, errno));
347                 break;
348
349         case 5:                         /* Open */
350
351                 dsp1 = pop_ptr();
352                 flag = pop_int();
353                 if (!savestr(0, dsp1) || (fd = open(buf[0], flag)) == -1) {
354                         push_err();
355                         LOG(("@m4 Open: failed, file = %lu, flag = %d, fd = %d, errno = %d",
356                                         dsp1, flag, fd, errno));
357                 }
358                 else {
359                         push_int(fd);
360                         push_int(0);
361                         LOG(("@m9 Open: succeeded, file = %lu, flag = %d, fd = %d",
362                                         dsp1, flag, fd));
363                 }
364                 break;
365
366         case 6:                         /* Close */
367
368                 fd = pop_int();
369                 if (!good_fd(fd) || close(fd) == -1) {
370                         push_err();
371                         LOG(("@m4 Close: failed, fd = %d, errno = %d",
372                                 fd, errno));
373                 }
374                 else {
375                         push_int(0);
376                         LOG(("@m9 Close: succeeded"));
377                 }
378                 break;
379
380         case 7:                         /* Wait */
381
382                 if ((pid = wait(&status)) == -1) {
383                         push_err();
384                         LOG(("@m4 Wait: failed, status = %d, errno = %d",
385                                 status, errno));
386                 }
387                 else {
388                         push_i2(pid);
389                         push_i2(status);
390                         push_int(0);
391                         LOG(("@m9 Wait: succeeded, status = %d, pid = %d",
392                                         status, pid));
393                 }
394                 break;
395
396         case 8:                         /* Creat */
397
398                 dsp1 = pop_ptr();
399                 flag = pop_int();
400                 if (!savestr(0, dsp1) || (fd = creat(buf[0], flag)) == -1) {
401                         push_err();
402                         LOG(("@m4 Creat: failed, dsp1 = %lu, flag = %d, errno = %d",
403                                         dsp1, flag, errno));
404                 }
405                 else {
406                         push_int(fd);
407                         push_int(0);
408                         LOG(("@m9 Creat: succeeded, fd = %d", fd));
409                 }
410                 break;
411
412         case 9:                         /* Link */
413
414                 dsp1 = pop_ptr();
415                 dsp2 = pop_ptr();
416                 if (    !savestr(0, dsp1)
417                 ||      !savestr(1, dsp2)
418                 ||      link(buf[0], buf[1]) == -1
419                 ) {
420                         push_err();
421                         LOG(("@m4 Link: failed, dsp1 = %lu, dsp2 = %lu, errno = %d",
422                                         dsp1, dsp2, errno));
423                 }
424                 else {
425                         push_int(0);
426                         LOG(("@m9 Link: succeeded, dsp1 = %lu, dsp2 = %lu",
427                                         dsp1, dsp2));
428                 }
429                 break;
430
431         case 10:                        /* Unlink */
432
433                 dsp1 = pop_ptr();
434                 if (!savestr(0, dsp1) || unlink(buf[0]) == -1) {
435                         push_err();
436                         LOG(("@m4 Unlink: failed, dsp1 = %lu, errno = %d",
437                                         dsp1, errno));
438                 }
439                 else {
440                         push_int(0);
441                         LOG(("@m9 Unlink: succeeded, dsp1 = %lu", dsp1));
442                 }
443                 break;
444
445         case 12:                        /* Chdir */
446
447                 dsp1 = pop_ptr();
448                 if (!savestr(0, dsp1) || chdir(buf[0]) == -1) {
449                         push_err();
450                         LOG(("@m4 Chdir: failed, dsp1 = %lu, errno = %d",
451                                 dsp1, errno));
452                 }
453                 else {
454                         push_int(0);
455                         LOG(("@m9 Chdir: succeeded, dsp1 = %lu", dsp1));
456                 }
457                 break;
458
459         case 14:                        /* Mknod */
460
461                 dsp1 = pop_ptr();
462                 mode = pop_int();
463                 address = pop_int2();
464                 if (!savestr(0, dsp1) || mknod(buf[0], mode, address) == -1) {
465                         push_err();
466                         LOG(("@m4 Mknod: failed, dsp1 = %lu, mode = %d, address = %d, errno = %d",
467                                         dsp1, mode, address, errno));
468                 }
469                 else {
470                         push_int(0);
471                         LOG(("@m9 Mknod: succeeded, dsp1 = %lu", dsp1));
472                 }
473                 break;
474
475         case 15:                        /* Chmod */
476
477                 dsp1 = pop_ptr();
478                 mode = pop_int2();
479                 if (!savestr(0, dsp1) || chmod(buf[0], mode) == -1) {
480                         push_err();
481                         LOG(("@m4 Chmod: failed, dsp1 = %lu, mode = %d, errno = %d",
482                                 dsp1, mode, errno));
483                 }
484                 else {
485                         push_int(0);
486                         LOG(("@m9 Chmod: succeeded, dsp1 = %lu", dsp1));
487                 }
488                 break;
489
490         case 16:                        /* Chown */
491
492                 dsp1 = pop_ptr();
493                 owner = pop_int2();
494                 group = pop_int2();
495                 if (!savestr(0, dsp1) || chown(buf[0], owner, group) == -1) {
496                         push_err();
497                         LOG(("@m4 Chown: failed, dsp1 = %lu, owner = %d, group = %d, errno = %d",
498                                 dsp1, owner, group, errno));
499                 }
500                 else {
501                         push_int(0);
502                         LOG(("@m9 Chown: succeeded, dsp1 = %lu", dsp1));
503                 }
504                 break;
505
506         case 18:                        /* Stat */
507
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)
513                 ) {
514                         push_err();
515                         LOG(("@m4 Stat: failed, dsp1 = %lu, dsp2 = %lu, errno = %d",
516                                 dsp1, dsp2, errno));
517                 }
518                 else {
519                         push_int(0);
520                         LOG(("@m9 Stat: succeeded, dsp1 = %lu, dsp2 = %lu",
521                                 dsp1, dsp2));
522                 }
523                 break;
524
525         case 19:                        /* Lseek */
526
527                 fd = pop_int();
528                 off = pop_int4();
529                 whence = pop_int();
530                 LOG(("@m4 Lseek: fd = %d, off = %ld, whence = %d",
531                                 fd, off, whence));
532
533                 if (!good_fd(fd) || (off = lseek(fd, off, whence)) == -1) {
534                         push_err();
535                         LOG(("@m9 Lseek: failed, errno = %d", errno));
536                 }
537                 else {
538                         push_i4(off);
539                         push_int(0);
540                         LOG(("@m9 Lseek: succeeded, pushed %ld", off));
541                 }
542                 break;
543
544         case 20:                        /* Getpid */
545
546                 pid = getpid();
547                 push_i2(pid);
548                 LOG(("@m9 Getpid: succeeded, pid = %d", pid));
549                 break;
550
551         case 21:                        /* Mount */
552
553                 dsp1 = pop_ptr();
554                 dsp2 = pop_ptr();
555                 flag = pop_int();
556                 if (    !savestr(0, dsp1)
557                 ||      !savestr(1, dsp2)
558                 ||      mount(buf[0], buf[1], flag) == -1
559                 ) {
560                         push_err();
561                         LOG(("@m4 Mount: failed, dsp1 = %lu, dsp2 = %lu, flag = %d, errno = %d",
562                                 dsp1, dsp2, flag, errno));
563                 }
564                 else {
565                         push_int(0);
566                         LOG(("@m9 Mount: succeeded, dsp1 = %lu, dsp2 = %lu, flag = %d",
567                                 dsp1, dsp2, flag));
568                 }
569                 break;
570
571         case 22:                        /* Umount */
572
573                 dsp1 = pop_ptr();
574                 if (    !savestr(0, dsp1)
575 #ifndef BSD4_2                          /* from system.h */
576                 ||      umount(buf[0]) == -1
577 #else   /* BSD4_2 */
578                 ||      unmount(buf[0]) == -1
579 #endif  /* BSD4_2 */
580                 ) {
581                         push_err();
582                         LOG(("@m4 Umount: failed, dsp1 = %lu, errno = %d",
583                                 dsp1, errno));
584                 }
585                 else {
586                         push_int(0);
587                         LOG(("@m9 Mount: succeeded, dsp1 = %lu", dsp1));
588                 }
589                 break;
590
591         case 23:                        /* Setuid */
592
593                 userid = pop_int2();
594                 if (setuid(userid) == -1) {
595                         push_err();
596                         LOG(("@m4 Setuid: failed, userid = %d, errno = %d",
597                                 userid, errno));
598                 }
599                 else {
600                         push_int(0);
601                         LOG(("@m9 Setuid: succeeded, userid = %d", userid));
602                 }
603                 break;
604
605         case 24:                        /* Getuid */
606
607                 userid = getuid();
608                 push_i2(userid);
609                 LOG(("@m9 Getuid(part 1): real uid = %d", userid));
610                 userid = geteuid();
611                 push_i2(userid);
612                 LOG(("@m9 Getuid(part 2): eff uid = %d", userid));
613                 break;
614
615         case 25:                        /* Stime */
616
617                 tm = pop_int4();
618 #ifndef BSD4_2                          /* from system.h */
619                 rc = stime(&tm);
620 #else   /* BSD4_2 */
621                 tv.tv_sec = tm;
622                 tv.tv_usec = 0;         /* zero microseconds */
623                 rc = settimeofday(&tv, (struct timezone *)0);
624 #endif  /* BSD4_2 */
625                 if (rc == -1) {
626                         push_err();
627                         LOG(("@m4 Stime: failed, tm = %ld, errno = %d",
628                                 tm, errno));
629                 }
630                 else {
631                         push_int(0);
632                         LOG(("@m9 Stime: succeeded, tm = %ld", tm));
633                 }
634                 break;
635
636         case 26:                        /* Ptrace */
637
638                 request = pop_int();
639                 pid = pop_int2();
640                 dsp3 = pop_ptr();
641                 n = pop_int();          /* Data */
642                 einval(WPTRACEIMP);
643                 push_err();
644                 LOG(("@m4 Ptrace: failed, request = %d, pid = %d, addr = %lu, data = %d, errno = %d",
645                         request, pid, dsp3, n, errno));
646                 break;
647
648         case 27:                        /* Alarm */
649
650                 seconds = pop_uns2();
651                 LOG(("@m9 Alarm(part 1) seconds = %u", seconds));
652                 seconds = alarm(seconds);
653                 push_i2(seconds);
654                 LOG(("@m9 Alarm(part 2) seconds = %u", seconds));
655                 break;
656
657         case 28:                        /* Fstat */
658
659                 fd = pop_int();
660                 dsp2 = pop_ptr();
661                 if (    !good_fd(fd)
662                 ||      fstat(fd, &st_buf) == -1
663                 ||      !stat2mem(dsp2, &st_buf)
664                 ) {
665                         push_err();
666                         LOG(("@m4 Fstat: failed, fd = %d, dsp2 = %lu, errno = %d",
667                                 fd, dsp2, errno));
668                 }
669                 else {
670                         push_int(0);
671                         LOG(("@m9 Fstat: succeeded, fd = %d, dsp2 = %lu",
672                                 fd, dsp2));
673                 }
674                 break;
675
676         case 29:                        /* Pause */
677
678                 pause();
679                 LOG(("@m9 Pause: succeeded"));
680                 break;
681
682         case 30:                        /* Utime */
683
684                 dsp1 = pop_ptr();
685                 dsp2 = pop_ptr();
686                 if (memfault(dsp2, 2*INT4SIZE)) {
687                         push_err();
688                         LOG(("@m4 Utime: failed, dsp1 = %lu, dsp2 = %lu, errno = %d",
689                                         dsp1, dsp2, errno));
690                         break;
691                 }
692                 actime = mem_ldu(dsp2, INT4SIZE);
693                 modtime = mem_ldu(dsp2 + INT4SIZE, INT4SIZE);
694 #ifdef  SYS_V                           /* from system.h */
695                 utimbuf.x = actime;
696                 utimbuf.y = modtime;
697                 if (!savestr(0, dsp1) || utime(buf[0], &utimbuf) == -1) {
698 #else   /* SYS_V */
699                 utimbuf[0] = actime;
700                 utimbuf[1] = modtime;
701                 if (!savestr(0, dsp1) || utime(buf[0], utimbuf) == -1) {
702                         /* may require modification for POSIX ???!!! */
703 #endif  /* !SYS_V */
704                         push_err();
705                         LOG(("@m4 Utime: failed, dsp1 = %lu, dsp2 = %lu, errno = %d",
706                                         dsp1, dsp2, errno));
707                 }
708                 else {
709                         push_int(0);
710                         LOG(("@m9 Utime: succeeded, dsp1 = %lu, dsp2 = %lu",
711                                         dsp1, dsp2));
712                 }
713                 break;
714
715         case 33:                        /* Access */
716
717                 dsp1 = pop_ptr();
718                 mode = pop_int();
719                 if (!savestr(0, dsp1) || access(buf[0], mode) == -1) {
720                         push_err();
721                         LOG(("@m4 Access: failed, dsp1 = %lu, mode = %d, errno = %d",
722                                         dsp1, mode, errno));
723                 }
724                 else {
725                         push_int(0);
726                         LOG(("@m9 Access: succeeded, dsp1 = %lu, mode = %d",
727                                 dsp1, mode));
728                 }
729                 break;
730
731         case 34:                        /* Nice */
732
733                 incr = pop_int();
734                 nice(incr);
735                 LOG(("@m9 Nice: succeeded, incr = %d", incr));
736                 break;
737
738         case 35:                        /* Ftime */
739
740                 dsp2 = pop_ptr();
741 #ifdef  BSD_X                           /* from system.h */
742                 ftime(&tb_buf);
743 #endif  /* BSD_X */
744 #ifdef  SYS_V                           /* from system.h */
745                 tb_buf.time = time((time_t*)0);
746                 tb_buf.millitm = 0;
747                 tb_buf.timezone = timezone / 60;
748                 tb_buf.dstflag = daylight;
749 #endif  /* SYS_V */
750                 if (!timeb2mem(dsp2, &tb_buf)) {
751                         push_err();
752                         LOG(("@m4 Ftime: failed, dsp2 = %lu, errno = %d",
753                                 dsp2, errno));
754                 }
755                 else {
756                         push_int(0);
757                         LOG(("@m9 Ftime: succeeded, dsp2 = %lu", dsp2));
758                 }
759                 break;
760
761         case 36:                        /* Sync */
762
763                 sync();
764                 LOG(("@m9 Sync: succeeded"));
765                 break;
766
767         case 37:                        /* Kill */
768
769                 pid = pop_int2();
770                 sig = pop_int();
771                 if (kill(pid, sig) == -1) {
772                         push_err();
773                         LOG(("@m4 Kill: failed, pid = %d, sig = %d, errno = %d",
774                                         pid, sig, errno));
775                 }
776                 else {
777                         push_int(0);
778                         LOG(("@m9 Kill: succeeded, pid = %d, sig = %d",
779                                 pid, sig));
780                 }
781                 break;
782
783         case 41:                        /* Dup & Dup2 */
784
785                 fd = pop_int();
786                 fdnew = pop_int();
787                 if (fd & DUPMASK) {
788                         int fd1 = fd & ~DUPMASK;/* stripped */
789
790                         LOG(("@m4 Dup2: fd1 = %d, fdnew = %d", fd1, fdnew));
791                         if (!good_fd(fd1)) {
792                                 fdnew = -1;
793                                 goto dup2_error;
794                         }
795 #ifdef  BSD_X                           /* from system.h */
796                         fdnew = dup2(fd1, fdnew);
797 #endif  /* BSD_X */
798
799 #ifdef  SYS_V                           /* from system.h */
800                         {
801                                 /* simulating the semantics of dup2 on SYS_V */
802                                 int dupped = dup(fd1);
803
804                                 if (dupped < 0 && errno != EMFILE) {
805                                         /*      the dup failed, but not
806                                                 because of too many open
807                                                 file descriptors
808                                         */
809                                         fdnew = dupped;
810                                 }
811                                 else {
812                                         close(dupped);
813                                         close(fdnew);
814                                         fdnew = fcntl(fd1, F_DUPFD, fdnew);
815                                 }
816                         }
817 #endif  /* SYS_V */
818                 dup2_error:;
819                 }
820                 else {
821                         LOG(("@m4 Dup: fd = %d, fdnew = %d", fd, fdnew));
822                         fdnew = (!good_fd(fd) ? -1 : dup(fd));
823                 }
824
825                 if (fdnew == -1) {
826                         push_err();
827                         LOG(("@m4 Dup/Dup2: failed, fdnew = %d, errno = %d",
828                                 fdnew, errno));
829                 }
830                 else {
831                         push_int(fdnew);
832                         push_int(0);
833                         LOG(("@m9 Dup/Dup2: succeeded, fdnew = %d", fdnew));
834                 }
835                 break;
836
837         case 42:                        /* Pipe */
838
839                 if (pipe(pfds) == -1) {
840                         push_err();
841                         LOG(("@m4 Pipe: failed, errno = %d", errno));
842                 }
843                 else {
844                         push_int(pfds[0]);
845                         push_int(pfds[1]);
846                         push_int(0);
847                         LOG(("@m9 Pipe: succeeded, pfds[0] = %d, pfds[1] = %d",
848                                 pfds[0], pfds[1]));
849                 }
850                 break;
851
852         case 43:                        /* Times */
853
854                 dsp2 = pop_ptr();
855                 times(&tm_buf);
856                 if (!tms2mem(dsp2, &tm_buf)) {
857                         push_err();
858                         LOG(("@m4 Times: failed, dsp2 = %lu, errno = %d",
859                                 dsp2, errno));
860                 }
861                 else {
862                         LOG(("@m9 Times: succeeded, dsp2 = %lu", dsp2));
863                 }
864                 break;
865
866         case 44:                        /* Profil */
867
868                 dsp1 = pop_ptr();       /* Buffer */
869                 nbytes = pop_intp();    /* Buffer size */
870                 off = pop_intp();       /* Offset */
871                 n = pop_intp();         /* Scale */
872                 einval(WPROFILIMP);
873                 push_err();
874                 LOG(("@m4 Profil: failed, dsp1 = %lu, nbytes = %d, offset = %d, scale = %d, errno = %d",
875                         dsp1, nbytes, off, n, errno));
876                 break;
877
878         case 46:                        /* Setgid */
879
880                 groupid = pop_int2();
881                 if (setgid(groupid) == -1) {
882                         push_err();
883                         LOG(("@m4 Setgid: failed, groupid = %d, errno = %d",
884                                 groupid, errno));
885                 }
886                 else {
887                         push_int(0);
888                         LOG(("@m9 Setgid: succeeded, groupid = %d", groupid));
889                 }
890                 break;
891
892         case 47:                        /* Getgid */
893
894                 groupid = getgid();
895                 push_i2(groupid);
896                 LOG(("@m9 Getgid(part 1): succeeded, real groupid = %d",
897                                 groupid));
898                 groupid = getegid();
899                 push_i2(groupid);
900                 LOG(("@m9 Getgid(part 2): succeeded, eff groupid = %d",
901                                 groupid));
902                 break;
903
904         case 48:                        /* Sigtrp */
905
906                 trap_no = pop_int();
907                 sig_no = pop_int();
908                 
909                 if ((old_trap_no = do_sigtrp(trap_no, sig_no)) == -1) {
910                         push_err();
911                         LOG(("@m4 Sigtrp: failed, trap_no = %d, sig_no = %d, errno = %d",
912                                         trap_no, sig_no, errno));
913                 }
914                 else {
915                         push_int(old_trap_no);
916                         push_int(0);
917                         LOG(("@m9 Sigtrp: succeeded, trap_no = %d, sig_no = %d, old_trap_no = %d",
918                                         trap_no, sig_no, old_trap_no));
919                 }
920                 break;
921
922         case 51:                        /* Acct */
923
924                 dsp1 = pop_ptr();
925                 if (!savestr(0, dsp1) || acct(buf[0]) == -1) {
926                         push_err();
927                         LOG(("@m4 Acct: failed, dsp1 = %lu, errno = %d",
928                                 dsp1, errno));
929                 }
930                 else {
931                         push_int(0);
932                         LOG(("@m9 Acct: succeeded, dsp1 = %lu", dsp1));
933                 }
934                 break;
935
936         case 54:                        /* Ioctl */
937
938                 fd = pop_int();
939                 request = pop_int();
940                 dsp2 = pop_ptr();
941                 if (!good_fd(fd) || do_ioctl(fd, request, dsp2) != 0) {
942                         push_err();
943                         LOG(("@m4 Ioctl: failed, fd = %d, request = %d, dsp2 = %lu, errno = %d",
944                                 fd, request, dsp2, errno));
945                 }
946                 else {
947                         push_int(0);
948                         LOG(("@m9 Ioctl: succeeded, fd = %d, request = %d, dsp2 = %lu",
949                                 fd, request, dsp2));
950                 }
951                 break;
952
953         case 56:                        /* Mpxcall */
954
955                 request = pop_int();    /* Command */
956                 dsp1 = pop_ptr();       /* Vec */
957                 einval(WMPXIMP);
958                 push_err();
959                 LOG(("@m4 Mpxcall: failed, request = %d, dsp1 = %lu, errno = %d",
960                         request, dsp1, errno));
961                 break;
962
963         case 59:                        /* Exec */
964
965                 dsp1 = pop_ptr();
966                 dsp2 = pop_ptr();
967                 dsp3 = pop_ptr();
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)
973                 ) {
974                         push_err();
975                         LOG(("@m4 Exece: failed, dsp1 = %lu, dsp2 = %lu, dsp2 = %lu, errno = %d",
976                                 dsp1, dsp2, dsp3, errno));
977                 }
978                 break;
979
980         case 60:                        /* Umask */
981
982                 mode = pop_int2();
983                 oldmask = umask(mode);
984                 push_int(oldmask);
985                 LOG(("@m9 Umask: succeeded, mode = %d, oldmask = %d",
986                         mode, oldmask));
987                 break;
988
989         case 61:                        /* Chroot */
990
991                 dsp1 = pop_ptr();
992                 if (!savestr(0, dsp1) || chroot(buf[0]) == -1) {
993                         push_err();
994                         LOG(("@m4 Chroot: failed, dsp1 = %lu, errno = %d",
995                                 dsp1, errno));
996                 }
997                 else {
998                         push_int(0);
999                         LOG(("@m9 Chroot: succeeded, dsp1 = %lu", dsp1));
1000                 }
1001                 break;
1002
1003         default:
1004                 trap(EBADMON);
1005                 break;
1006         }
1007 }
1008
1009 /* Buffer administration */
1010
1011 PRIVATE check_buf(n, sz)
1012         int n;
1013         size sz;
1014 {
1015         if (buf_cnt[n] == 0) {
1016                 buf_cnt[n] = max(128, sz);
1017                 buf[n] = Malloc(buf_cnt[n], "moncall buffer");
1018         }
1019         else if (buf_cnt[n] < sz) {
1020                 buf_cnt[n] = allocfrac(sz);
1021                 buf[n] = Realloc(buf[n], buf_cnt[n], "moncall buffer");
1022         }
1023 }
1024
1025 PRIVATE int savestr(n, addr)
1026         int n;
1027         ptr addr;
1028 {
1029         register size len;
1030         register char *cp, ch;
1031
1032         /* determine the length, carefully */
1033         len = 0;
1034         do {
1035                 if (memfault(addr + len, 1L)) {
1036                         return 0;
1037                 }
1038                 ch = mem_loc(addr + len);
1039                 len++;
1040         } while (ch);
1041
1042         /* allocate enough buffer space */
1043         check_buf(n, len);
1044
1045         /* copy the string */
1046         cp = buf[n];
1047         do {
1048                 *cp++ = ch = mem_loc(addr);
1049                 addr++;
1050         } while (ch);
1051
1052         return 1;
1053 }
1054
1055 PRIVATE int vec(n1, n2, addr, vecvec)
1056         int n1, n2;
1057         ptr addr;
1058         char ***vecvec;
1059 {
1060         register char *cp1, *cp2;
1061         ptr p, ldp;
1062         register int n_ent = 0;         /* number of entries */
1063         register size str = 0;          /* total string length */
1064
1065         /* determine number of elements n_ent */
1066         p = addr;
1067         do {
1068                 if (memfault(addr, psize)) {
1069                         return 0;
1070                 }
1071                 ldp = mem_lddp(p);
1072                 if (!savestr(n2, ldp)) {
1073                         return 0;
1074                 }
1075                 str += strlen(buf[n2]) + 1;
1076                 n_ent++;
1077                 p += psize;
1078         } while (ldp);
1079         n_ent++;
1080
1081         *vecvec = (char **) Malloc((size)(n_ent * sizeof (char *)),
1082                                         "argvec or envvec in exec()");
1083         check_buf(n1, str);
1084
1085         /* copy the elements */
1086         for (   cp1 = buf[n1], n_ent = 0, p = addr;
1087                 ldp = mem_lddp(p);
1088                 p += psize, n_ent++
1089         ) {
1090                 if (!savestr(n2, ldp)) {
1091                         return 0;
1092                 }
1093                 (*vecvec)[n_ent] = cp1;
1094                 cp2 = buf[n2];
1095                 while (*cp1++ = *cp2++) {
1096                         /* nothing */
1097                 }
1098         }
1099         (*vecvec)[n_ent] = 0;
1100         return 1;
1101 }
1102
1103 int memfault(addr, length)
1104         ptr addr;
1105         size length;
1106 {
1107         /* centralizes (almost) all memory access tests in MON */
1108         if (!is_in_mem(addr, length)) {
1109                 efault(WMONFLT);
1110                 return 1;
1111         }
1112         return 0;
1113 }
1114
1115 efault(wrn)
1116         int wrn;                        /* warning number */
1117 {
1118         warning(wrn);
1119         errno = 14;                     /* EFAULT */
1120 }
1121
1122 einval(wrn)
1123         int wrn;                        /* warning number */
1124 {
1125         warning(wrn);
1126         errno = 22;                     /* EINVAL */
1127 }
1128