User libraries depend on their dependencies .a's
[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 static int isdigit(int c) {return ((c >= '0' && c <= '9'));}
20
21 static int
22 call(char *clone, char *dest, int *cfdp, char *dir, char *local)
23 {
24         int fd, cfd;
25         int n;
26         char name[3*NAMELEN+5];
27         char data[3*NAMELEN+10];
28         char *p;
29
30         cfd = open(clone, O_RDWR);
31         if(cfd < 0)
32                 return -1;
33
34         /* get directory name */
35         n = read(cfd, name, sizeof(name)-1);
36         if(n < 0){
37                 close(cfd);
38                 return -1;
39         }
40         name[n] = 0;
41         p = strrchr(clone, '/');
42         *p = 0;
43         if(dir)
44                 sprintf(dir, "%.*s/%.*s", 2*NAMELEN+1, clone, NAMELEN, name);
45         sprintf(data, "%.*s/%.*s/data", 2*NAMELEN+1, clone, NAMELEN, name);
46
47         /* set local side (port number, for example) if we need to */
48         if(local)
49                 sprintf(name, "connect %.*s %.*s", 2*NAMELEN, dest, NAMELEN, local);
50         else
51                 sprintf(name, "connect %.*s", 2*NAMELEN, dest);
52         /* connect */
53         if(write(cfd, name, strlen(name)) < 0){
54                 close(cfd);
55                 return -1;
56         }
57
58         /* open data connection */
59         fd = open(data, O_RDWR);
60         if(fd < 0){
61                 close(cfd);
62                 return -1;
63         }
64         if(cfdp)
65                 *cfdp = cfd;
66         else
67                 close(cfd);
68         return fd;
69 }
70
71 int
72 dial(char *dest, char *local, char *dir, int *cfdp)
73 {
74         char net[128];
75         char netdir[128], csname[NETPATHLEN], *slp;
76         char clone[NAMELEN+12];
77         char *p;
78         int n;
79         int fd;
80         int rv;
81
82         /* go for a standard form net!... */
83         p = strchr(dest, '!');
84         if(p == 0){
85                 sprintf(net, "net!%.*s", sizeof(net)-5, dest);
86         } else {
87                 strncpy(net, dest, sizeof(net)-1);
88                 net[sizeof(net)-1] = 0;
89         }
90
91         slp = strrchr(net, '/');
92         if (slp != 0) {
93                 *slp++ = '\0';
94                 strcpy(netdir, net);
95                 memmove(net, slp, strlen(slp)+1);
96         } else
97                 strcpy(netdir, "/net");
98  
99
100         // special case because we are so special.
101         // if the first char of the address is a digit,
102         // and the first char of the port is a digit,
103         // skip all this cs stuff.
104         p = strchr(net, '!');
105         if (p && isdigit(p[1])) {
106                 char *q = strchr(&p[1], '!');
107                 if (q && isdigit(q[1])) {
108                         *p++ = 0;
109                         sprintf(clone, "%s/%s/clone", netdir, net);
110                         return call(clone, p, cfdp, dir, local);
111                 }
112         }
113         /* call the connection server */
114         sprintf(csname, "%s/cs", netdir);
115         fd = open(csname, O_RDWR);
116         if(fd < 0){
117                 /* no connection server, don't translate */
118                 p = strchr(net, '!');
119                 *p++ = 0;
120                 sprintf(clone, "%s/%s/clone", netdir, net);
121                 return call(clone, p, cfdp, dir, local);
122         }
123
124         /*
125          *  send dest to connection to translate
126          */
127         if(write(fd, net, strlen(net)) < 0){
128                 close(fd);
129                 return -1;
130         }
131
132         /*
133          *  loop through each address from the connection server till
134          *  we get one that works.
135          */
136         rv = -1;
137         lseek(fd, 0, 0);
138         while((n = read(fd, net, sizeof(net) - 1)) > 0){
139                 net[n] = 0;
140                 p = strchr(net, ' ');
141                 if(p == 0)
142                         continue;
143                 *p++ = 0;
144                 rv = call(net, p, cfdp, dir, local);
145                 if(rv >= 0)
146                         break;
147         }
148         close(fd);
149         return rv;
150 }