kconfig: use pkg-config for ncurses detection
[akaros.git] / tools / compilers / gcc-glibc / glibc-2.19-akaros / sysdeps / akaros / getsockopt.c
1 /* Copyright (c) 2015 Google, Inc.
2  * Barret Rhoden <brho@cs.berkeley.edu>
3  * See LICENSE for details. */
4
5 #include <errno.h>
6 #include <sys/socket.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <fcntl.h>
10
11 #include <sys/plan9_helpers.h>
12
13 static int sol_socket_error_gso(Rock *r, void *optval, socklen_t *optlen)
14 {
15         char buf[Ctlsize];
16         int fd, ret;
17         char *p;
18
19         _sock_get_conv_filename(r, "status", buf);
20         fd = open(buf, O_RDONLY);
21         if (fd < 0)
22                 return -1;
23         ret = read(fd, buf, sizeof(buf));
24         close(fd);
25         if (ret < 0)
26                 return -1;
27         p = strchr(buf, ' ');
28         if (!p)
29                 return -1;
30         *p = 0;
31         /* The first word in a connected TCP conv status file is 'Established'.
32          * For UDP it is 'Open'.
33          *
34          * For now, we'll default to no socket error, and only set the error if
35          * we know we aren't Established/Open.  If we want, we can parse the
36          * different string values, like Established, Syn_sent, and return
37          * custom error messages.  But just ECONNREFUSED is fine for now. */
38         ret = 0;
39         switch (r->stype) {
40         case SOCK_DGRAM:
41                 if (strcmp(buf, "Open"))
42                         ret = ECONNREFUSED;
43                 break;
44         case SOCK_STREAM:
45                 if (strcmp(buf, "Established"))
46                         ret = ECONNREFUSED;
47                 break;
48         }
49         *(int*)optval = ret;
50         *optlen = 4;
51         return 0;
52 }
53
54 static int sol_socket_gso(Rock *r, int optname, void *optval, socklen_t *optlen)
55 {
56         switch (optname) {
57         case (SO_TYPE):
58                 if (*optlen < 4) {
59                         __set_errno(EINVAL);
60                         return -1;
61                 }
62                 *(int*)optval = r->stype;
63                 *optlen = 4;
64                 break;
65         case (SO_ERROR):
66                 return sol_socket_error_gso(r, optval, optlen);
67         default:
68                 __set_errno(ENOPROTOOPT);
69                 return -1;
70         };
71         return 0;
72 }
73
74 int __getsockopt(int sockfd, int level, int optname, void *optval,
75                  socklen_t *optlen)
76 {
77         Rock *r = _sock_findrock(sockfd, 0);
78
79         if (!r) {
80                 /* could be EBADF too, we can't tell */
81                 __set_errno(ENOTSOCK);
82                 return -1;
83         }
84         switch (level) {
85         case (SOL_SOCKET):
86                 return sol_socket_gso(r, optname, optval, optlen);
87         default:
88                 __set_errno(ENOPROTOOPT);
89                 return -1;
90         };
91 }
92 weak_alias(__getsockopt, getsockopt)