1 #include "lib.h"
2 #include <unistd.h>
3 #include <errno.h>
4 #include <stdarg.h>
5 #include "sys9.h"
6
7 /*
8 * BUG: advisory locking not implemented
9 */
10
11 #define OFL (O_ACCMODE|O_NONBLOCK|O_APPEND)
12
13 int
fcntl(int fd,int cmd,...)14 fcntl(int fd, int cmd, ...)
15 {
16 int arg, i, ans, err;
17 Fdinfo *fi, *fans;
18 va_list va;
19 unsigned long oflags;
20
21 err = 0;
22 ans = 0;
23 va_start(va, cmd);
24 arg = va_arg(va, int);
25 va_end(va);
26 fi = &_fdinfo[fd];
27 if(fd<0 || fd>=OPEN_MAX || !(fi->flags&FD_ISOPEN))
28 err = EBADF;
29 else switch(cmd){
30 case F_DUPFD:
31 if(fi->flags&(FD_BUFFERED|FD_BUFFEREDX)){
32 err = EGREG; /* dup of buffered fd not implemented */
33 break;
34 }
35 oflags = fi->oflags;
36 for(i = (arg>0)? arg : 0; i<OPEN_MAX; i++)
37 if(!(_fdinfo[i].flags&FD_ISOPEN))
38 break;
39 if(i == OPEN_MAX)
40 err = EMFILE;
41 else {
42 ans = _DUP(fd, i);
43 if(ans != i){
44 if(ans < 0){
45 _syserrno();
46 err = errno;
47 }else
48 err = EBADF;
49 }else{
50 fans = &_fdinfo[ans];
51 fans->flags = fi->flags&~FD_CLOEXEC;
52 fans->oflags = oflags;
53 fans->uid = fi->uid;
54 fans->gid = fi->gid;
55 }
56 }
57 break;
58 case F_GETFD:
59 ans = fi->flags&FD_CLOEXEC;
60 break;
61 case F_SETFD:
62 fi->flags = (fi->flags&~FD_CLOEXEC)|(arg&FD_CLOEXEC);
63 break;
64 case F_GETFL:
65 ans = fi->oflags&OFL;
66 break;
67 case F_SETFL:
68 fi->oflags = (fi->oflags&~OFL)|(arg&OFL);
69 break;
70 case F_GETLK:
71 case F_SETLK:
72 case F_SETLKW:
73 err = EINVAL;
74 break;
75 }
76 if(err){
77 errno = err;
78 ans = -1;
79 }
80 return ans;
81 }
82