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