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