Fixes stat() #include
[akaros.git] / user / iplib / dial.c
1 /* 
2  * This file is part of the UCB release of Plan 9. It is subject to the license
3  * terms in the LICENSE file found in the top-level directory of this
4  * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
5  * part of the UCB release of Plan 9, including this file, may be copied,
6  * modified, propagated, or distributed except according to the terms contained
7  * in the LICENSE file.
8  */
9 #include <stdlib.h>
10
11 #include <sys/types.h>
12 #include <string.h>
13 #include <fcntl.h>
14 #include <stdio.h>
15 #include <unistd.h>
16
17 #define NAMELEN 28
18 #define NETPATHLEN 40
19
20 static int
21 call(char *clone, char *dest, int *cfdp, char *dir, char *local)
22 {
23         int fd, cfd;
24         int n;
25         char name[3*NAMELEN+5];
26         char data[3*NAMELEN+10];
27         char *p;
28
29         cfd = open(clone, O_RDWR);
30         if(cfd < 0)
31                 return -1;
32
33         /* get directory name */
34         n = read(cfd, name, sizeof(name)-1);
35         if(n < 0){
36                 close(cfd);
37                 return -1;
38         }
39         name[n] = 0;
40         p = strrchr(clone, '/');
41         *p = 0;
42         if(dir)
43                 sprintf(dir, "%.*s/%.*s", 2*NAMELEN+1, clone, NAMELEN, name);
44         sprintf(data, "%.*s/%.*s/data", 2*NAMELEN+1, clone, NAMELEN, name);
45
46         /* set local side (port number, for example) if we need to */
47         if(local)
48                 sprintf(name, "connect %.*s %.*s", 2*NAMELEN, dest, NAMELEN, local);
49         else
50                 sprintf(name, "connect %.*s", 2*NAMELEN, dest);
51         /* connect */
52         if(write(cfd, name, strlen(name)) < 0){
53                 close(cfd);
54                 return -1;
55         }
56
57         /* open data connection */
58         fd = open(data, O_RDWR);
59         if(fd < 0){
60                 close(cfd);
61                 return -1;
62         }
63         if(cfdp)
64                 *cfdp = cfd;
65         else
66                 close(cfd);
67         return fd;
68 }
69
70 int
71 dial(char *dest, char *local, char *dir, int *cfdp)
72 {
73         char net[128];
74         char netdir[128], csname[NETPATHLEN], *slp;
75         char clone[NAMELEN+12];
76         char *p;
77         int n;
78         int fd;
79         int rv;
80
81         /* go for a standard form net!... */
82         p = strchr(dest, '!');
83         if(p == 0){
84                 sprintf(net, "net!%.*s", sizeof(net)-5, dest);
85         } else {
86                 strncpy(net, dest, sizeof(net)-1);
87                 net[sizeof(net)-1] = 0;
88         }
89
90         slp = strrchr(net, '/');
91         if (slp != 0) {
92                 *slp++ = '\0';
93                 strcpy(netdir, net);
94                 memmove(net, slp, strlen(slp)+1);
95         } else
96                 strcpy(netdir, "/net");
97  
98
99         /* call the connection server */
100         sprintf(csname, "%s/cs", netdir);
101         fd = open(csname, O_RDWR);
102         if(fd < 0){
103                 /* no connection server, don't translate */
104                 p = strchr(net, '!');
105                 *p++ = 0;
106                 sprintf(clone, "%s/%s/clone", netdir, net);
107                 return call(clone, p, cfdp, dir, local);
108         }
109
110         /*
111          *  send dest to connection to translate
112          */
113         if(write(fd, net, strlen(net)) < 0){
114                 close(fd);
115                 return -1;
116         }
117
118         /*
119          *  loop through each address from the connection server till
120          *  we get one that works.
121          */
122         rv = -1;
123         lseek(fd, 0, 0);
124         while((n = read(fd, net, sizeof(net) - 1)) > 0){
125                 net[n] = 0;
126                 p = strchr(net, ' ');
127                 if(p == 0)
128                         continue;
129                 *p++ = 0;
130                 rv = call(net, p, cfdp, dir, local);
131                 if(rv >= 0)
132                         break;
133         }
134         close(fd);
135         return rv;
136 }