"Fossies" - the Fresh Open Source Software Archive

Member "links-1.04/af_unix.c" (2 Jun 2016, 5796 Bytes) of package /linux/www/links-1.04.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "af_unix.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.03_vs_1.04.

    1 /* af_unix.c
    2  * (c) 2002 Mikulas Patocka
    3  * This file is a part of the Links program, released under GPL
    4  */
    5 
    6 #include "links.h"
    7 
    8 #ifdef DONT_USE_AF_UNIX
    9 
   10 int bind_to_af_unix(void)
   11 {
   12     return -1;
   13 }
   14 
   15 void af_unix_close(void)
   16 {
   17 }
   18 
   19 #else
   20 
   21 #ifdef USE_AF_UNIX
   22 #include <sys/un.h>
   23 #endif
   24 
   25 #if defined(__GNU__)
   26 #define SOCKET_TIMEOUT_HACK
   27 #endif
   28 
   29 static void af_unix_connection(void *);
   30 
   31 #define ADDR_SIZE   4096
   32 
   33 union address {
   34     struct sockaddr s;
   35 #ifdef USE_AF_UNIX
   36     struct sockaddr_un suni;
   37 #endif
   38     struct sockaddr_in sin;
   39     unsigned char buffer[ADDR_SIZE];
   40 };
   41 
   42 static union address s_unix;
   43 static union address s_unix_acc;
   44 
   45 static socklen_t s_unix_l;
   46 static int s_unix_fd = -1;
   47 static int s_unix_master = 0;
   48 
   49 
   50 #define S2C1_HANDSHAKE_LENGTH   6
   51 #define C2S2_HANDSHAKE_LENGTH   sizeof(struct links_handshake)
   52 #define S2C3_HANDSHAKE_LENGTH   sizeof(struct links_handshake)
   53 
   54 static struct links_handshake {
   55     unsigned char version[30];
   56     unsigned char system_name[32];
   57     unsigned char system_id;
   58     unsigned char sizeof_long;
   59 } links_handshake;
   60 
   61 #define HANDSHAKE_WRITE(hndl, sz)                   \
   62     if ((r = hard_write(hndl, (unsigned char *)&links_handshake, sz)) != (sz))
   63 #define HANDSHAKE_READ(hndl, sz)                    \
   64     if ((r = hard_read(hndl, (unsigned char *)&received_handshake, sz)) != (sz) || memcmp(&received_handshake, &links_handshake, sz))
   65 
   66 
   67 #ifdef USE_AF_UNIX
   68 
   69 static int get_address(void)
   70 {
   71     unsigned char *path;
   72     if (!links_home) return -1;
   73     path = stracpy(links_home);
   74     add_to_strn(&path, LINKS_SOCK_NAME);
   75     if (anonymous) {
   76         add_to_strn(&path, cast_uchar LINKS_ANONYMOUS_SOCK_SUFFIX);
   77     }
   78     s_unix_l = (unsigned char *)&s_unix.suni.sun_path - (unsigned char *)&s_unix.suni + strlen(path) + 1;
   79     if (strlen(path) > sizeof(union address) || (size_t)s_unix_l > sizeof(union address)) {
   80         mem_free(path);
   81         return -1;
   82     }
   83     memset(&s_unix, 0, sizeof s_unix);
   84     s_unix.suni.sun_family = AF_UNIX;
   85     strcpy(s_unix.suni.sun_path, path);
   86     mem_free(path);
   87     return PF_UNIX;
   88 }
   89 
   90 static void unlink_unix(void)
   91 {
   92     int rs;
   93     /*debug("unlink: %s", s_unix.suni.sun_path);*/
   94     EINTRLOOP(rs, unlink(s_unix.suni.sun_path));
   95     if (rs) {
   96         /*perror("unlink");*/
   97     }
   98 }
   99 
  100 #else
  101 
  102 static int get_address(void)
  103 {
  104     memset(&s_unix, 0, sizeof s_unix);
  105     s_unix.sin.sin_family = AF_INET;
  106     s_unix.sin.sin_port = htons(LINKS_PORT + !!anonymous);
  107     s_unix.sin.sin_addr.s_addr = htonl(0x7f000001);
  108     s_unix_l = sizeof(struct sockaddr_in);
  109     return PF_INET;
  110 }
  111 
  112 static void unlink_unix(void)
  113 {
  114 }
  115 
  116 #endif
  117 
  118 int bind_to_af_unix(void)
  119 {
  120     int u = 0;
  121     int a1 = 1;
  122     int cnt = 0;
  123     int af;
  124     int r;
  125     int rs;
  126     struct links_handshake received_handshake;
  127     memset(&links_handshake, 0, sizeof links_handshake);
  128     safe_strncpy(links_handshake.version, "Links " VERSION_STRING, sizeof links_handshake.version);
  129     safe_strncpy(links_handshake.system_name, system_name, sizeof links_handshake.system_name);
  130     links_handshake.system_id = SYSTEM_ID;
  131     links_handshake.sizeof_long = sizeof(long);
  132     if ((af = get_address()) == -1) return -1;
  133     again:
  134     EINTRLOOP(s_unix_fd, socket(af, SOCK_STREAM, 0));
  135     if (s_unix_fd == -1) return -1;
  136 #if defined(SOL_SOCKET) && defined(SO_REUSEADDR)
  137     EINTRLOOP(rs, setsockopt(s_unix_fd, SOL_SOCKET, SO_REUSEADDR, (void *)&a1, sizeof a1));
  138 #endif
  139     EINTRLOOP(rs, bind(s_unix_fd, &s_unix.s, s_unix_l));
  140     if (rs) {
  141         /*perror("");
  142         debug("bind: %d", errno);*/
  143         if (af == PF_INET && errno == EADDRNOTAVAIL) {
  144             /* do not try to connect if the user has not configured loopback interface */
  145             EINTRLOOP(rs, close(s_unix_fd));
  146             return -1;
  147         }
  148         EINTRLOOP(rs, close(s_unix_fd));
  149         EINTRLOOP(s_unix_fd, socket(af, SOCK_STREAM, 0));
  150         if (s_unix_fd == -1) return -1;
  151 #if defined(SOL_SOCKET) && defined(SO_REUSEADDR)
  152         EINTRLOOP(rs, setsockopt(s_unix_fd, SOL_SOCKET, SO_REUSEADDR, (void *)&a1, sizeof a1));
  153 #endif
  154         EINTRLOOP(rs, connect(s_unix_fd, &s_unix.s, s_unix_l));
  155         if (rs) {
  156 retry:
  157             /*perror("");
  158             debug("connect: %d", errno);*/
  159             if (++cnt < MAX_BIND_TRIES) {
  160                 portable_sleep(100);
  161                 EINTRLOOP(rs, close(s_unix_fd));
  162                 s_unix_fd = -1;
  163                 goto again;
  164             }
  165 #ifdef SOCKET_TIMEOUT_HACK
  166 retry_unlink:
  167 #endif
  168             EINTRLOOP(rs, close(s_unix_fd));
  169             s_unix_fd = -1;
  170             if (!u) {
  171                 unlink_unix();
  172                 u = 1;
  173                 goto again;
  174             }
  175             return -1;
  176         }
  177 #ifdef SOCKET_TIMEOUT_HACK
  178         if (!can_read_timeout(s_unix_fd, AF_UNIX_SOCKET_TIMEOUT))
  179             goto retry_unlink;
  180 #endif
  181         HANDSHAKE_READ(s_unix_fd, S2C1_HANDSHAKE_LENGTH) {
  182             if (r != S2C1_HANDSHAKE_LENGTH) goto retry;
  183             goto close_and_fail;
  184         }
  185         HANDSHAKE_WRITE(s_unix_fd, C2S2_HANDSHAKE_LENGTH)
  186             goto close_and_fail;
  187         HANDSHAKE_READ(s_unix_fd, S2C3_HANDSHAKE_LENGTH)
  188             goto close_and_fail;
  189         return s_unix_fd;
  190     }
  191     EINTRLOOP(rs, listen(s_unix_fd, 100));
  192     if (rs) {
  193         error("ERROR: listen failed: %d", errno);
  194         close_and_fail:
  195         EINTRLOOP(rs, close(s_unix_fd));
  196         s_unix_fd = -1;
  197         return -1;
  198     }
  199     s_unix_master = 1;
  200     set_handlers(s_unix_fd, af_unix_connection, NULL, NULL, NULL);
  201     return -1;
  202 }
  203 
  204 static void af_unix_connection(void *xxx)
  205 {
  206     socklen_t l = s_unix_l;
  207     int ns;
  208     int r;
  209     int rs;
  210     struct links_handshake received_handshake;
  211     memset(&s_unix_acc, 0, sizeof s_unix_acc);
  212     EINTRLOOP(ns, accept(s_unix_fd, &s_unix_acc.s, &l));
  213     if (ns == -1) return;
  214     HANDSHAKE_WRITE(ns, S2C1_HANDSHAKE_LENGTH) {
  215         EINTRLOOP(rs, close(ns));
  216         return;
  217     }
  218     HANDSHAKE_READ(ns, C2S2_HANDSHAKE_LENGTH) {
  219         portable_sleep(100);    /* workaround for a race in previous Links version */
  220         EINTRLOOP(rs, close(ns));
  221         return;
  222     }
  223     HANDSHAKE_WRITE(ns, S2C3_HANDSHAKE_LENGTH) {
  224         EINTRLOOP(rs, close(ns));
  225         return;
  226     }
  227     init_term(ns, ns, win_func);
  228     set_highpri();
  229 }
  230 
  231 void af_unix_close(void)
  232 {
  233     int rs;
  234     if (s_unix_master) {
  235         set_handlers(s_unix_fd, NULL, NULL, NULL, NULL);
  236     }
  237     if (s_unix_fd != -1) {
  238         EINTRLOOP(rs, close(s_unix_fd));
  239         s_unix_fd = -1;
  240     }
  241     if (s_unix_master) {
  242         unlink_unix();
  243         s_unix_master = 0;
  244     }
  245 }
  246 
  247 #endif