Minimal changes to get m6502 to compile (won't work)
[Apout.git] / bsdtrap.c
1 /* bsdtrap.c - Deal with 2.11BSD trap instructions.
2  *
3  * $Revision: 1.66 $
4  * $Date: 2008/05/19 13:26:42 $
5  */
6 #ifdef EMU211
7
8 /* NOTE NOTE NOTE NOTE
9  * Grep for the word DONE in this file to see the implemented syscalls.
10  */
11
12 #define BSDTRAP_NAME
13 #include "defines.h"
14 #include <sys/stat.h>
15 #include <sys/time.h>
16 #include <stdlib.h>
17 #include <unistd.h>
18 #include <fcntl.h>
19 #include <dirent.h>
20 #include <sys/wait.h>
21 #include <signal.h>
22 #include <utime.h>
23 #include <sys/file.h>
24 #include <sys/resource.h>
25 #include <sys/socket.h>
26 #include <sys/uio.h>
27 #include "bsdtrap.h"
28 #ifdef __linux__
29 #include <grp.h>                /* setgroups() */
30 #endif
31
32 #define MAX_BLKSIZE     1024    /* Maximum block size from stat/fstat */
33
34 #undef STREAM_BUFFERING         /* This works, but doesn't seem to give */
35 /* any speed improvement */
36
37 arglist *A;                     /* Pointer to various arguments on stack */
38
39
40 /* Forward prototypes */
41 #ifdef __STDC__
42 #define P(s) s
43 #else
44 #define P(s) ()
45 #endif
46 static int trap_execve P((int));
47 static int bsdopen_dir P((char *name));
48 #ifdef NEED_MAP_FCNTL
49 static int16_t map_fcntl P((int16_t f));
50 #endif
51 #undef P
52
53 void bsdtrap()
54 {
55     int i, j, len, pid, pfd[2];
56     char *buf, *buf2;
57     int16_t *shortptr;
58     long larg1;
59     char *fmode;                /* used with fdopen only */
60     struct stat stbuf;          /* used in STAT */
61     struct tr_stat *tr_stbuf;   /* used in STAT */
62     struct tr_timeval *tr_del, *tr_oldel;       /* used in ADJTIME */
63     struct timeval del, oldel;  /* used in ADJTIME */
64     struct timeval utv[2];      /* used in UTIMES */
65     struct tr_timezone *tr_zone;        /* used in GETTIMEOFDAY */
66     struct timezone zone;       /* used in GETTIMEOFDAY */
67     struct tr_itimerval *tr_tval, *tr_oltval;   /* used in itimer calls */
68     struct itimerval tval, oltval;      /* used in itimer calls */
69     struct tr_sockaddr *tr_sock;        /* used in socket calls */
70     struct sockaddr sock;       /* used in socket calls */
71     gid_t *gidset;              /* used in GETGROUPS */
72     struct tr_rlimit *tr_rlp;   /* used in rlimit calls */
73     struct rlimit rlp;          /* used in rlimit calls */
74     struct tr_rusage *tr_use;   /* used in getrusage */
75     struct rusage use;          /* used in getrusage */
76     struct iovec *ivec;         /* used in writev, readv */
77     struct tr_iovec *trivec;    /* used in writev, readv */
78
79     TrapDebug((dbg_file, "pid %d %s: ", (int) getpid(),
80                bsdtrap_name[ir & 0xff]));
81
82     A = (arglist *) & dspace[(regs[SP] + 2)];
83
84     i = errno = 0;
85     switch (ir & 0xff) {
86     case S_INDIR:
87         (void) printf("Does 2.11BSD use INDIR? I don't think so\n");
88         exit(EXIT_FAILURE);
89
90     case S_QUOTA:               /* DONE - for now */
91     case S_SETQUOTA:    /* DONE - for now */
92         i = -1;
93         errno = EINVAL;
94         break;
95
96     /* These syscalls are not implemented, and */
97     /* always return EPERM to the caller */
98     case S_PTRACE:              /* DONE - bad syscall */
99     case S_MOUNT:               /* DONE - bad syscall */
100     case S_UMOUNT:              /* DONE - bad syscall */
101     case S_PROFIL:              /* DONE - bad syscall */
102     case S_NOSYS147:    /* DONE - bad syscall */
103     case S_SYSCTL:
104         i = -1;
105         errno = EPERM;
106         break;
107     /* These syscalls are ignored, and */
108     /* always return C=0 to the caller */
109     case S_OLDLOCK:     /* DONE - ok syscall */
110     case S_OLDPHYS:     /* DONE - ok syscall */
111     case S_FSTATFS:     /* DONE - ok syscall */
112     case S_SIGPROCMASK: /* DONE - ok syscall */
113     case S_SIGRETURN:   /* DONE - ok syscall */
114     case S_SIGALTSTACK: /* DONE - ok syscall */
115     case S_VHANGUP:     /* DONE - ok syscall */
116         i = 0;
117         break;
118     case S_SIGACTION:   /* DONE */
119 #define NO_SIGNALS_YET
120 #ifdef NO_SIGNALS_YET
121         i = 0;
122 #else
123         i = do_sigaction(uarg1, uarg2, uarg3);
124 #endif
125         break;
126     case S_IOCTL:               /* DONE a bit */
127         i = trap_ioctl();
128         break;
129     case S_SBRK:                /* DONE */
130         if (uarg1 < regs[SP]) {
131             i = 0;
132             TrapDebug((dbg_file, "set break to %d ", uarg1));
133         } else {
134             i = -1;
135             errno = ENOMEM;
136             TrapDebug((dbg_file, "break %d > SP %d", uarg1, regs[SP]));
137         }
138         break;
139     case S_SYNC:                /* DONE */
140         sync();
141         i = 0;
142         break;
143     case S_FSYNC:               /* DONE */
144         i = fsync(sarg1);
145         break;
146     case S_GETDTABLESIZE:       /* DONE */
147         i = getdtablesize();
148         break;
149     case S_EXIT:                /* DONE */
150 #ifdef DEBUG
151         TrapDebug((dbg_file, "val %d\n", sarg1));
152         fflush(dbg_file);
153 #endif
154         exit(sarg1);
155     case S_DUP:         /* DONE */
156         TrapDebug((dbg_file, "on %d ", sarg1));
157         i = dup(sarg1);
158 #ifdef STREAM_BUFFERING
159         if ((i != -1) && ValidFD(sarg1) && stream[sarg1]) {
160             fmode = streammode[sarg1];
161             stream[i] = fdopen(i, fmode);
162             streammode[i] = fmode;
163         }
164 #endif
165         break;
166     case S_DUP2:                /* DONE */
167         TrapDebug((dbg_file, "on %d %d ", sarg1, sarg2));
168         i = dup2(sarg1, sarg2);
169 #ifdef STREAM_BUFFERING
170         if ((i != -1) && ValidFD(sarg2) && ValidFD(sarg1)
171                 && stream[sarg1]) {
172             fmode = streammode[sarg1];
173             stream[sarg2] = fdopen(sarg2, fmode);
174             streammode[sarg2] = fmode;
175         }
176 #endif
177         break;
178     case S_REBOOT:              /* DONE */
179         (void) Reboot(sarg1);
180         break;
181     case S_UMASK:               /* DONE */
182         i = umask((mode_t) sarg1);
183         break;
184     case S_GETPAGESIZE: /* DONE */
185         i = getpagesize();
186         break;
187     case S_GETHOSTNAME: /* DONE */
188         buf = (char *) &dspace[uarg1];
189         i = gethostname(buf, sarg2);
190         break;
191     case S_SETHOSTNAME: /* DONE */
192         buf = (char *) &dspace[uarg1];
193         sethostname(buf, sarg2);
194         break;
195     case S_LSEEK:               /* DONE */
196         larg1 = (sarg2 << 16) | uarg3;
197 #ifdef STREAM_BUFFERING
198         if (ValidFD(sarg1) && stream[sarg1]) {
199             i = fseek(stream[sarg1], larg1, sarg4);
200             if (i == 0)
201                 i = ftell(stream[sarg1]);
202         } else
203 #endif
204             i = lseek(sarg1, larg1, sarg4);
205         if (i == -1)
206             break;
207         else {
208             regs[1] = i & 0xffff;
209             i = (i >> 16) & 0xffff;
210             break;
211         }
212     case S_READ:                /* DONE */
213         TrapDebug((dbg_file, "%d bytes on %d ", uarg3, sarg1));
214         buf = (char *) &dspace[uarg2];
215 #ifdef STREAM_BUFFERING
216         if (ValidFD(sarg1) && stream[sarg1])
217             i = fread(buf, 1, uarg3, stream[sarg1]);
218         else
219 #endif
220             i = read(sarg1, buf, uarg3);
221         break;
222     case S_LINK:                /* DONE */
223         buf = xlate_filename((char *) &dspace[uarg1]);
224         buf2 = xlate_filename((char *) &dspace[uarg2]);
225         i = link(buf, buf2);
226         break;
227     case S_SYMLINK:     /* DONE */
228         buf = xlate_filename((char *) &dspace[uarg1]);
229         buf2 = xlate_filename((char *) &dspace[uarg2]);
230         i = symlink(buf, buf2);
231         break;
232     case S_RENAME:              /* DONE */
233         buf = xlate_filename((char *) &dspace[uarg1]);
234         buf2 = xlate_filename((char *) &dspace[uarg2]);
235         i = rename(buf, buf2);
236         break;
237     case S_READLINK:    /* DONE */
238         buf = xlate_filename((char *) &dspace[uarg1]);
239         i = readlink(buf, (char *) &dspace[uarg2], sarg3);
240         break;
241     case S_ACCESS:              /* DONE */
242         buf = xlate_filename((char *) &dspace[uarg1]);
243         i = access(buf, sarg2);
244         break;
245     case S_MKDIR:               /* DONE */
246         buf = xlate_filename((char *) &dspace[uarg1]);
247         i = mkdir(buf, sarg2);
248         break;
249     case S_RMDIR:               /* DONE */
250         buf = xlate_filename((char *) &dspace[uarg1]);
251         i = rmdir(buf);
252         break;
253     case S_ACCT:                /* DONE */
254         buf = xlate_filename((char *) &dspace[uarg1]);
255         i = acct(buf);
256         break;
257     case S_WRITEV:              /* DONE */
258     case S_READV:               /* DONE */
259         ivec = (struct iovec *) malloc(uarg3 * sizeof(struct iovec));
260         if (ivec == NULL) {
261             i = -1;
262             errno = EINVAL;
263             break;
264         }
265         trivec = (struct tr_iovec *) &dspace[uarg2];
266
267         for (j = 0; j < uarg3; j++) {
268             ivec[j].iov_len = trivec[j].iov_len;
269             ivec[j].iov_base = (char *) &dspace[trivec[j].iov_base];
270         }
271         if ((ir & 0xff) == S_READV)
272             i = readv(sarg1, ivec, uarg3);
273         else
274             i = writev(sarg1, ivec, uarg3);
275         free(ivec);
276         break;
277     case S_WRITE:               /* DONE */
278         buf = (char *) &dspace[uarg2];
279         TrapDebug((dbg_file, "%d bytes on %d ", uarg3, sarg1));
280 #ifdef STREAM_BUFFERING
281         if (ValidFD(sarg1) && stream[sarg1])
282             i = fwrite(buf, 1, uarg3, stream[sarg1]);
283         else
284 #endif
285             i = write(sarg1, buf, uarg3);
286         break;
287     case S_CLOSE:               /* DONE */
288 #ifdef DEBUG
289         TrapDebug((dbg_file, "on %d ", sarg1));
290         if ((dbg_file != NULL) && (sarg1 == fileno(dbg_file))) {
291             i = 0;
292             break;              /* Don't close our debug file! */
293         }
294 #endif
295 #ifdef STREAM_BUFFERING
296         if (ValidFD(sarg1) && stream[sarg1]) {
297             i = fclose(stream[sarg1]);
298             stream[sarg1] = NULL;
299         } else
300 #endif
301             i = close(sarg1);
302         break;
303     case S_FCNTL:
304         TrapDebug((dbg_file, "on %d %d %d ", sarg1, sarg2, sarg3));
305         i = fcntl(sarg1, sarg2, sarg3);
306         break;
307     case S_FLOCK:
308         i = flock(sarg1, sarg2);
309         break;
310     case S_LSTAT:               /* DONE */
311         buf = xlate_filename((char *) &dspace[uarg1]);
312         tr_stbuf = (struct tr_stat *) &dspace[uarg2];
313         i = lstat(buf, &stbuf);
314         TrapDebug((dbg_file, "on %s ", buf));
315         goto dostat;
316     case S_STAT:                /* DONE */
317         buf = xlate_filename((char *) &dspace[uarg1]);
318         tr_stbuf = (struct tr_stat *) &dspace[uarg2];
319         i = stat(buf, &stbuf);
320         TrapDebug((dbg_file, "on %s ", buf));
321         goto dostat;
322     case S_FSTAT:               /* DONE */
323         tr_stbuf = (struct tr_stat *) &dspace[uarg2];
324         i = fstat(uarg1, &stbuf);
325         TrapDebug((dbg_file, "on fd %d ", uarg1));
326
327 dostat:
328         if (i == -1)
329             break;
330         else {
331             /* The following stops blksize equalling 64K,
332              * which becomes 0 in a 16-bit int. This then
333              * causes 2.11BSD flsbuf() to malloc(0), which
334              * then causes malloc to go crazy - wkt.
335              */
336             if (stbuf.st_blksize > MAX_BLKSIZE)
337                 stbuf.st_blksize = MAX_BLKSIZE;
338
339             tr_stbuf->st_dev = stbuf.st_dev;
340             tr_stbuf->st_ino = stbuf.st_ino;
341             tr_stbuf->st_mode = stbuf.st_mode;
342             tr_stbuf->st_nlink = stbuf.st_nlink;
343             tr_stbuf->st_uid = stbuf.st_uid;
344             tr_stbuf->st_gid = stbuf.st_gid;
345             tr_stbuf->st_rdev = stbuf.st_rdev;
346 #ifndef NO_STFLAGS
347             tr_stbuf->st_flags = stbuf.st_flags;
348 #endif
349             copylong(tr_stbuf->st_size, stbuf.st_size);
350             copylong(tr_stbuf->st_atim, stbuf.st_atime);
351             copylong(tr_stbuf->st_mtim, stbuf.st_mtime);
352             copylong(tr_stbuf->st_ctim, stbuf.st_ctime);
353             copylong(tr_stbuf->st_blksize, stbuf.st_blksize);
354             larg1 = stbuf.st_blocks;
355             copylong(tr_stbuf->st_blocks, larg1);
356         }
357         break;
358     case S_UTIMES:              /* DONE */
359         buf = xlate_filename((char *) &dspace[uarg1]);
360         tr_del = (struct tr_timeval *) &dspace[uarg2];
361         tr_oldel = (struct tr_timeval *) &dspace[uarg4];
362         i = utimes(buf, utv);
363         if (i == -1)
364             break;
365         copylong(tr_del->tv_sec, utv[0].tv_sec);
366         copylong(tr_del->tv_usec, utv[0].tv_usec);
367         copylong(tr_oldel->tv_sec, utv[1].tv_sec);
368         copylong(tr_oldel->tv_usec, utv[1].tv_usec);
369         break;
370     case S_ADJTIME:     /* DONE */
371         tr_del = (struct tr_timeval *) &dspace[uarg1];
372         /* Convert tr_del to del */
373         copylong(del.tv_sec, tr_del->tv_sec);
374         copylong(del.tv_usec, tr_del->tv_usec);
375         i = adjtime(&del, &oldel);
376
377         if (uarg2) {
378             tr_oldel = (struct tr_timeval *) &dspace[uarg2];
379             copylong(tr_oldel->tv_sec, oldel.tv_sec);
380             copylong(tr_oldel->tv_usec, oldel.tv_usec);
381         }
382         break;
383     case S_GETTIMEOFDAY:        /* DONE */
384         tr_del = (struct tr_timeval *) &dspace[uarg1];
385         tr_zone = (struct tr_timezone *) &dspace[uarg2];
386         i = gettimeofday(&del, &zone);
387         copylong(tr_del->tv_sec, del.tv_sec);
388         copylong(tr_del->tv_usec, del.tv_usec);
389         tr_zone->tz_minuteswest = zone.tz_minuteswest;
390         tr_zone->tz_dsttime = zone.tz_dsttime;
391         break;
392     case S_SETTIMEOFDAY:        /* DONE */
393         tr_del = (struct tr_timeval *) &dspace[uarg1];
394         tr_zone = (struct tr_timezone *) &dspace[uarg2];
395         copylong(del.tv_sec, tr_del->tv_sec);
396         copylong(del.tv_usec, tr_del->tv_usec);
397         zone.tz_minuteswest = tr_zone->tz_minuteswest;
398         zone.tz_dsttime = tr_zone->tz_dsttime;
399         i = settimeofday(&del, &zone);
400         break;
401     case S_GETITIMER:   /* DONE */
402         tr_tval = (struct tr_itimerval *) &dspace[uarg2];
403         i = getitimer(sarg1, &tval);
404         copylong(tr_tval->it_interval.tv_sec, tval.it_interval.tv_sec);
405         copylong(tr_tval->it_interval.tv_usec,
406                  tval.it_interval.tv_usec);
407         copylong(tr_tval->it_value.tv_sec, tval.it_value.tv_sec);
408         copylong(tr_tval->it_value.tv_usec, tval.it_value.tv_usec);
409         break;
410     case S_SETITIMER:   /* DONE */
411         tr_tval = (struct tr_itimerval *) &dspace[uarg2];
412         tr_oltval = (struct tr_itimerval *) &dspace[uarg2];
413         copylong(tval.it_interval.tv_sec, tr_tval->it_interval.tv_sec);
414         copylong(tval.it_interval.tv_usec,
415                  tr_tval->it_interval.tv_usec);
416         copylong(tval.it_value.tv_sec, tr_tval->it_value.tv_sec);
417         copylong(tval.it_value.tv_usec, tr_tval->it_value.tv_usec);
418         i = setitimer(sarg1, &tval, &oltval);
419         if (i == -1)
420             break;
421         copylong(tr_oltval->it_interval.tv_sec,
422                  oltval.it_interval.tv_sec);
423         copylong(tr_oltval->it_interval.tv_usec,
424                  oltval.it_interval.tv_usec);
425         copylong(tr_oltval->it_value.tv_sec, oltval.it_value.tv_sec);
426         copylong(tr_oltval->it_value.tv_usec, oltval.it_value.tv_usec);
427         break;
428     case S_UNLINK:              /* DONE */
429         buf = xlate_filename((char *) &dspace[uarg1]);
430         i = unlink(buf);
431         break;
432     case S_OPEN:                /* DONE */
433         buf = xlate_filename((char *) &dspace[uarg1]);
434
435         i = stat(buf, &stbuf);  /* If file is a directory */
436         if (i == 0 && (stbuf.st_mode & S_IFDIR)) {
437             i = bsdopen_dir(buf);
438             fmode = "w+";
439             TrapDebug((dbg_file, "(dir) on %s ", buf));
440         } else {
441 #ifdef NEED_MAP_FCNTL
442             sarg2 = map_fcntl(sarg2);
443 #endif
444             switch (sarg2 & O_ACCMODE) {
445             case O_RDONLY:
446                 fmode = "r";
447                 break;
448             case O_WRONLY:
449                 fmode = "w";
450                 break;
451             default:
452                 fmode = "w+";
453                 break;
454             }
455             i = open(buf, sarg2, sarg3);
456             TrapDebug((dbg_file, "on %s ", buf));
457             TrapDebug((dbg_file, "sarg2 is %d, sarg3 is 0x%x ", sarg2,
458                        sarg3));
459         }
460 #ifdef STREAM_BUFFERING
461         if (i == -1)
462             break;
463         /* Now get its stream pointer if possible */
464         /* Can someone explain why fdopen doesn't work for O_RDWR? */
465 #if 0
466         if (ValidFD(i) && !isatty(i) && (sarg2 != O_RDWR)) {
467             stream[i] = fdopen(i, fmode);
468             streammode[i] = fmode;
469         }
470 #endif
471         stream[i] = fdopen(i, fmode);
472         streammode[i] = fmode;
473 #endif
474         break;
475     case S_MKNOD:               /* DONE */
476         buf = xlate_filename((char *) &dspace[uarg1]);
477         i = mknod(buf, sarg2, sarg3);
478         break;
479     case S_CHMOD:               /* DONE */
480         buf = xlate_filename((char *) &dspace[uarg1]);
481         i = chmod(buf, sarg2);
482         break;
483     case S_FCHMOD:              /* DONE */
484         i = fchmod(sarg1, sarg2);
485         break;
486     case S_TRUNCATE:    /* DONE */
487         buf = xlate_filename((char *) &dspace[uarg1]);
488         larg1 = (sarg2 << 16) | uarg3;
489         i = truncate(buf, larg1);
490         break;
491     case S_FTRUNCATE:   /* DONE */
492         larg1 = (sarg2 << 16) | uarg3;
493         i = ftruncate(sarg1, larg1);
494         break;
495     case S_KILL:                /* DONE */
496         i = kill(sarg1, sarg2);
497         break;
498     case S_KILLPG:              /* DONE */
499         i = killpg(sarg1, sarg2);
500         break;
501     case S_CHOWN:               /* DONE */
502         buf = xlate_filename((char *) &dspace[uarg1]);
503         i = chown(buf, sarg2, sarg3);
504         break;
505     case S_PIPE:                /* DONE */
506         i = pipe(pfd);
507 #ifdef STREAM_BUFFERING
508         if (ValidFD(pfd[0])) {
509             stream[pfd[0]] = fdopen(pfd[0], "r");
510             streammode[pfd[0]] = "r";
511         }
512         if (ValidFD(pfd[1])) {
513             stream[pfd[1]] = fdopen(pfd[1], "w");
514             streammode[pfd[1]] = "w";
515         }
516 #endif
517         if (i == -1)
518             break;
519         i = pfd[0];
520         regs[1] = pfd[1];
521         break;
522     case S_CHROOT:              /* DONE */
523         buf = xlate_filename((char *) &dspace[uarg1]);
524         if (buf == NULL) {
525             errno = ENOENT;
526             i = -1;
527             break;
528         }
529         set_apout_root(buf);
530         i = 0;
531         break;
532     case S_CHDIR:               /* DONE */
533         buf = xlate_filename((char *) &dspace[uarg1]);
534         i = chdir(buf);
535         break;
536     case S_FCHDIR:              /* DONE */
537         i = fchdir(sarg1);
538         break;
539
540 #ifndef NO_CHFLAGS
541     case S_CHFLAGS:     /* DONE */
542         buf = xlate_filename((char *) &dspace[uarg1]);
543         i = chflags(buf, uarg2);
544         break;
545     case S_FCHFLAGS:    /* DONE */
546         i = fchflags(sarg1, uarg2);
547         break;
548 #endif
549
550     case S_CREAT:               /* DONE */
551         buf = xlate_filename((char *) &dspace[uarg1]);
552         i = creat(buf, sarg2);
553 #ifdef STREAM_BUFFERING
554         if (ValidFD(i)) {
555             stream[i] = fdopen(i, "w");
556             streammode[i] = "w";
557         }
558 #endif
559         break;
560     case S_EXECVE:              /* DONE, I think */
561         i = trap_execve(1);
562         break;
563     case S_EXECV:               /* Not sure here */
564         i = trap_execve(0);
565         break;
566     case S_WAIT:                /* Not sure here */
567         i = wait(&pid);
568         if (i == -1)
569             break;
570         regs[1] = pid;
571         break;
572     case S_WAIT4:               /* Definitely incomplete */
573         TrapDebug((dbg_file, "on pid %d options %d ", sarg1, uarg3));
574         if (uarg4)
575             TrapDebug((dbg_file, " rusage on!!! "));
576         shortptr = (int16_t *) & dspace[uarg2];
577         i = wait4(sarg1, &j, uarg3, 0);
578         *shortptr = j;
579         break;
580     case S_FORK:                /* DONE */
581     case S_VFORK:               /* DONE */
582         i = fork();
583         if (i != 0) {
584             regs[PC] += 2;
585         } /* Took ages to find this! */
586         else
587             ov_changes = 0;
588         break;
589     case S_GETHOSTID:   /* DONE */
590         i = gethostid();
591         regs[1] = i & 0xffff;
592         i = (i >> 16) & 0xffff;
593         break;
594     case S_SETHOSTID:   /* DONE */
595         larg1 = (sarg2 << 16) | uarg3;
596         sethostid(larg1);
597         i = 0;
598         break;
599     case S_GETUID:              /* DONE */
600         i = getuid();
601         break;
602     case S_SETUID:              /* DONE */
603         i = setuid(uarg1);
604         break;
605     case S_GETEUID:     /* DONE */
606         i = geteuid();
607         break;
608     case S_GETPID:              /* DONE */
609         i = getpid();
610         break;
611     case S_GETPPID:     /* DONE */
612         i = getppid();
613         break;
614     case S_GETGID:              /* DONE */
615         i = getgid();
616         break;
617     case S_GETEGID:     /* DONE */
618         i = getegid();
619         break;
620 #ifndef NO_GETPGID
621     case S_GETPGRP:     /* DONE */
622         i = getpgid(sarg1);
623         break;
624 #endif
625     case S_SETPGRP:     /* DONE */
626         i = setpgid(sarg1, sarg2);
627         break;
628     case S_SETREGID:    /* DONE */
629         i = setregid(sarg1, sarg2);
630         break;
631     case S_SETREUID:    /* DONE */
632         i = setreuid(sarg1, sarg2);
633         break;
634     case S_GETPRIORITY: /* DONE */
635         i = getpriority(sarg1, sarg2);
636         break;
637     case S_SETPRIORITY: /* DONE */
638         i = setpriority(sarg1, sarg2, sarg3);
639         break;
640     case S_LISTEN:              /* DONE */
641         i = listen(sarg1, sarg2);
642         break;
643     case S_SHUTDOWN:    /* DONE */
644         i = shutdown(sarg1, sarg2);
645         break;
646     case S_SOCKET:              /* DONE */
647         i = socket(sarg1, sarg2, sarg3);
648         break;
649     case S_SOCKETPAIR:  /* DONE */
650         i = socketpair(sarg1, sarg2, sarg3, pfd);
651         break;
652         shortptr = (int16_t *) & dspace[uarg4];
653         *shortptr = pfd[0];
654         shortptr += 2;
655         *shortptr = pfd[1];
656         break;
657     case S_RECV:                /* DONE */
658         buf = (char *) &dspace[uarg2];
659         i = recv(sarg1, buf, sarg3, sarg4);
660         break;
661     case S_SEND:                /* DONE */
662         buf = (char *) &dspace[uarg2];
663         i = send(sarg1, buf, sarg3, sarg4);
664         break;
665     case S_ACCEPT:              /* DONE */
666         tr_sock = (struct tr_sockaddr *) &dspace[uarg2];
667         sock.sa_family = tr_sock->sa_family;
668         ll_word(uarg3, len);
669 #ifndef __linux__
670         sock.sa_len = len;
671 #endif
672         memcpy(sock.sa_data, tr_sock->sa_data, len);
673         i = accept(sarg1, &sock, (socklen_t *) & len);
674         if (i != -1) {
675             sl_word(uarg3, len);
676             memcpy(tr_sock->sa_data, sock.sa_data, len);
677         }
678         break;
679     case S_GETPEERNAME: /* DONE */
680         tr_sock = (struct tr_sockaddr *) &dspace[uarg2];
681         sock.sa_family = tr_sock->sa_family;
682         ll_word(uarg3, len);
683 #ifndef __linux__
684         sock.sa_len = len;
685 #endif
686         memcpy(sock.sa_data, tr_sock->sa_data, len);
687         i = getpeername(sarg1, &sock, (socklen_t *) & len);
688         if (i != -1) {
689             sl_word(uarg3, len);
690             memcpy(tr_sock->sa_data, sock.sa_data, len);
691         }
692         break;
693     case S_GETSOCKNAME: /* DONE */
694         tr_sock = (struct tr_sockaddr *) &dspace[uarg2];
695         sock.sa_family = tr_sock->sa_family;
696         ll_word(uarg3, len);
697 #ifndef __linux__
698         sock.sa_len = len;
699 #endif
700         memcpy(sock.sa_data, tr_sock->sa_data, len);
701         i = getsockname(sarg1, &sock, (socklen_t *) & len);
702         if (i != -1) {
703             sl_word(uarg3, len);
704             memcpy(tr_sock->sa_data, sock.sa_data, len);
705         }
706         break;
707     case S_BIND:                /* DONE */
708         tr_sock = (struct tr_sockaddr *) &dspace[uarg2];
709         sock.sa_family = tr_sock->sa_family;
710         len = sarg3;
711 #ifndef __linux__
712         sock.sa_len = sarg3;
713 #endif
714         memcpy(sock.sa_data, tr_sock->sa_data, len);
715         i = bind(sarg1, &sock, len);
716         break;
717     case S_CONNECT:     /* DONE */
718         tr_sock = (struct tr_sockaddr *) &dspace[uarg2];
719         sock.sa_family = tr_sock->sa_family;
720         len = sarg3;
721 #ifndef __linux__
722         sock.sa_len = sarg3;
723 #endif
724         memcpy(sock.sa_data, tr_sock->sa_data, len);
725         i = connect(sarg1, &sock, len);
726         break;
727     case S_RECVFROM:    /* DONE I think */
728         tr_sock = (struct tr_sockaddr *) &dspace[uarg5];
729         sock.sa_family = tr_sock->sa_family;
730         ll_word(uarg6, len);
731 #ifndef __linux__
732         sock.sa_len = len;
733 #endif
734         memcpy(sock.sa_data, tr_sock->sa_data, len);
735         buf = (char *) &dspace[uarg2];
736         i = recvfrom(sarg1, buf, sarg3, sarg4, &sock,
737                      (socklen_t *) & len);
738         if (i != -1) {
739             sl_word(uarg6, len);
740             memcpy(tr_sock->sa_data, sock.sa_data, len);
741         }
742         break;
743     case S_GETGROUPS:
744         len = sarg1;
745         gidset = (gid_t *) malloc(len * sizeof(gid_t));
746         if (gidset == NULL) {
747             i = -1;
748             errno = EINVAL;
749             break;
750         }
751         i = getgroups(len, gidset);
752         shortptr = (int16_t *) & dspace[uarg2];
753         for (j = 0; j < i; j++)
754             shortptr[j] = gidset[j];
755         free(gidset);
756         break;
757     case S_SETGROUPS:
758         len = sarg1;
759         if (len > 16) {
760             i = -1;
761             errno = EFAULT;
762             break;
763         }
764         gidset = (gid_t *) malloc(len * sizeof(gid_t));
765         if (gidset == NULL) {
766             i = -1;
767             errno = EINVAL;
768             break;
769         }
770         shortptr = (int16_t *) & dspace[uarg2];
771         for (j = 0; j < len; j++)
772             gidset[j] = shortptr[j];
773         i = setgroups(len, gidset);
774         free(gidset);
775         break;
776     case S_GETRLIMIT:   /* DONE */
777         tr_rlp = (struct tr_rlimit *) &dspace[uarg2];
778         i = getrlimit(sarg1, &rlp);
779         if (i == -1)
780             break;
781         copylong(tr_rlp->rlim_cur, rlp.rlim_cur);
782         copylong(tr_rlp->rlim_max, rlp.rlim_max);
783         break;
784     case S_SETRLIMIT:   /* DONE */
785         tr_rlp = (struct tr_rlimit *) &dspace[uarg2];
786         copylong(rlp.rlim_cur, tr_rlp->rlim_cur);
787         copylong(rlp.rlim_max, tr_rlp->rlim_max);
788         i = setrlimit(sarg1, &rlp);
789         break;
790     case S_GETRUSAGE:
791         TrapDebug((dbg_file, "arg1 %d pointer 0%o ", sarg1, uarg2));
792         tr_use = (struct tr_rusage *) &dspace[uarg2];
793         i = getrusage(sarg1, &use);
794         if (i == -1)
795             break;
796
797         /* Should do tr_use->ru_utime;        user time used */
798         /* Should do tr_use->ru_stime;        system time used */
799         copylong(tr_use->ru_maxrss, use.ru_maxrss);
800         copylong(tr_use->ru_ixrss, use.ru_ixrss);
801         copylong(tr_use->ru_idrss, use.ru_idrss);
802         copylong(tr_use->ru_isrss, use.ru_isrss);
803         copylong(tr_use->ru_minflt, use.ru_minflt);
804         copylong(tr_use->ru_majflt, use.ru_majflt);
805         copylong(tr_use->ru_ovly, ov_changes);
806         copylong(tr_use->ru_nswap, use.ru_nswap);
807         copylong(tr_use->ru_inblock, use.ru_inblock);
808         copylong(tr_use->ru_oublock, use.ru_oublock);
809         copylong(tr_use->ru_msgsnd, use.ru_msgsnd);
810         copylong(tr_use->ru_msgrcv, use.ru_msgrcv);
811         copylong(tr_use->ru_nsignals, use.ru_nsignals);
812         copylong(tr_use->ru_nvcsw, use.ru_nvcsw);
813         copylong(tr_use->ru_nivcsw, use.ru_nivcsw);
814         break;
815     default:
816         if ((ir & 0xff) > S_GETSOCKNAME) {
817             TrapDebug((stderr,
818                        "Apout - unknown syscall %d at PC 0%o\n",
819                        ir & 0xff, regs[PC]));
820         } else {
821             (void) fprintf(stderr,
822                            "Apout - the 2.11BSD %s syscall is not yet implemented\n",
823                            bsdtrap_name[ir & 0xff]);
824         }
825         exit(EXIT_FAILURE);
826     }
827
828     /* Set r0 to either errno or i, */
829     /* and clear/set C bit */
830
831     if (i == -1) {
832         SET_CC_C();
833         regs[0] = errno;
834         TrapDebug((dbg_file, "errno is %s\n", strerror(errno)));
835     } else {
836         CLR_CC_C();
837         regs[0] = i;
838         TrapDebug((dbg_file, "return %d\n", i));
839     }
840     return;
841 }
842
843
844
845 static int trap_execve(int want_env)
846 {
847     u_int16_t cptr, cptr2;
848     char *buf, *name, *origpath;
849
850     origpath = strdup((char *) &dspace[uarg1]);
851     name = xlate_filename(origpath);
852     TrapDebug((dbg_file, "%s Execing %s (%s) ", progname, name, origpath));
853
854     set_bsdsig_dfl();           /* Set signals to default values */
855
856     cptr = uarg2;
857     Argc = 0;
858     Envc = 0;
859     while (Argc < MAX_ARGS) {
860         ll_word(cptr, cptr2);
861         if (cptr2 == 0)
862             break;
863         buf = (char *) &dspace[cptr2];
864         Argv[Argc++] = strdup(buf);
865         cptr += 2;
866         TrapDebug((dbg_file, "%s ", buf));
867     }
868     Argv[Argc] = NULL;
869     TrapDebug((dbg_file, "\n"));
870
871     if (want_env) {
872         cptr = uarg3;
873         while (Envc < MAX_ARGS) {
874             ll_word(cptr, cptr2);
875             if (cptr2 == 0)
876                 break;
877             buf = (char *) &dspace[cptr2];
878             Envp[Envc++] = strdup(buf);
879             cptr += 2;
880         }
881         Envp[Envc] = NULL;
882     }
883
884     if (load_a_out(name, origpath, want_env) == -1) {
885         for (Argc--; Argc >= 0; Argc--)
886             free(Argv[Argc]);
887         if (want_env)
888             for (Envc--; Envc >= 0; Envc--)
889                 free(Envp[Envc]);
890         errno = ENOENT;
891         return (-1);
892     }
893     run();                      /* Ok, so it's recursive, I dislike setjmp */
894     return (0);                 /* Just to shut the compiler up */
895 }
896
897 /* 2.11BSD reads directories as if they were ordinary files.
898  * The solution is to read the directory entries, and build a
899  * real file, which is passed back to the open call.
900  *
901  * A directory consists of some number of blocks of DIRBLKSIZ
902  * bytes, where DIRBLKSIZ is chosen such that it can be transferred
903  * to disk in a single atomic operation (e.g. 512 bytes on most machines).
904  *
905  * Each DIRBLKSIZ byte block contains some number of directory entry
906  * structures, which are of variable length.  Each directory entry has
907  * a struct direct at the front of it, containing its inode number,
908  * the length of the entry, and the length of the name contained in
909  * the entry.  These are followed by the name padded to a 4 byte boundary
910  * with null bytes.  All names are guaranteed null terminated.
911  * The maximum length of a name in a directory is MAXNAMLEN.
912  *
913  * The macro DIRSIZ(dp) gives the amount of space required to represent
914  * a directory entry.  Free space in a directory is represented by
915  * entries which have dp->d_reclen > DIRSIZ(dp).  All DIRBLKSIZ bytes
916  * in a directory block are claimed by the directory entries.  This
917  * usually results in the last entry in a directory having a large
918  * dp->d_reclen.  When entries are deleted from a directory, the
919  * space is returned to the previous entry in the same directory
920  * block by increasing its dp->d_reclen.  If the first entry of
921  * a directory block is free, then its dp->d_ino is set to 0.
922  * Entries other than the first in a directory do not normally have
923  * dp->d_ino set to 0.
924  */
925
926 static int bsdopen_dir(char *name)
927 {
928     DIR *d;
929     char *tmpname;
930     int i, nlen, total_left;
931     struct dirent *dent;
932     struct tr_direct odent, empty;
933
934     d = opendir(name);
935     if (d == NULL)
936         return (-1);
937     tmpname = strdup(TMP_PLATE);
938     i = mkstemp(tmpname);
939     if (i == -1) {
940         (void) fprintf(stderr, "Apout - open_dir couldn't open %s\n",
941                        tmpname);
942         exit(EXIT_FAILURE);
943     }
944     unlink(tmpname);
945     free(tmpname);
946
947     total_left = TR_DIRBLKSIZ;
948     empty.d_ino = 0;
949     empty.d_namlen = 0;
950     empty.d_name[0] = '\0';
951     empty.d_name[1] = '\0';
952     empty.d_name[2] = '\0';
953     empty.d_name[3] = '\0';
954
955     while ((dent = readdir(d)) != NULL) {
956         memset(odent.d_name, 0, TR_MAXNAMLEN + 1);      /* Null name */
957         nlen = strlen(dent->d_name) + 1;        /* Name length */
958         if (nlen > TR_MAXNAMLEN + 1)
959             nlen = TR_MAXNAMLEN + 1;
960         strncpy(odent.d_name, dent->d_name, nlen);
961         odent.d_ino = dent->d_fileno;
962         /* Nasty hack: ensure inode */
963         /* is never 0 */
964         if (odent.d_ino == 0)
965             odent.d_ino = 1;
966         odent.d_namlen = nlen;
967         nlen += (nlen & 3);     /* Round up to mult of 4 */
968         odent.d_reclen = nlen + 6;      /* Name + 3 u_int16_ts */
969
970         /* Not enough room, write */
971         /* a blank entry */
972         if ((total_left - odent.d_reclen) < 10) {
973             empty.d_reclen = total_left;
974             write(i, &empty, empty.d_reclen);
975             total_left = TR_DIRBLKSIZ;
976         }
977         write(i, &odent, odent.d_reclen);
978         total_left -= odent.d_reclen;
979     }
980     closedir(d);
981
982     if (total_left) {
983         empty.d_reclen = total_left;
984         write(i, &empty, empty.d_reclen);
985     }
986     lseek(i, 0, SEEK_SET);
987     return (i);
988 }
989
990 #ifdef NEED_MAP_FCNTL
991 /* Map the 2.11BSD fcntl mode bits to the underlying
992  * system's bits. We have to do this for Linux
993  */
994 static int16_t map_fcntl(int16_t f)
995 {
996     int16_t out = 0;
997
998     if (f & BSD_RDONLY)
999         out |= O_RDONLY;
1000     if (f & BSD_WRONLY)
1001         out |= O_WRONLY;
1002     if (f & BSD_RDWR)
1003         out |= O_RDWR;
1004     if (f & BSD_NONBLOCK)
1005         out |= O_NONBLOCK;
1006     if (f & BSD_APPEND)
1007         out |= O_APPEND;
1008     if (f & BSD_SHLOCK)
1009         out |= O_SHLOCK;
1010     if (f & BSD_EXLOCK)
1011         out |= O_EXLOCK;
1012     if (f & BSD_ASYNC)
1013         out |= O_ASYNC;
1014     if (f & BSD_FSYNC)
1015         out |= O_FSYNC;
1016     if (f & BSD_CREAT)
1017         out |= O_CREAT;
1018     if (f & BSD_TRUNC)
1019         out |= O_TRUNC;
1020     if (f & BSD_EXCL)
1021         out |= O_EXCL;
1022
1023     TrapDebug((dbg_file, "map_fcntl: 0x%x -> 0x%x, ", f, out));
1024     return (out);
1025 }
1026 #endif
1027 #endif                          /* EMU211 */