Back to index

im-sdk  12.3.91
udclient.c
Go to the documentation of this file.
00001 /* 
00002  * AUTHOR: miura@da-cha.org
00003  * DATE: 2005.04.15
00004  *
00005  *  repeater to communicate with unix domain socket
00006  */
00007 
00008 #include <sys/types.h>
00009 #include <sys/socket.h>
00010 #include <sys/select.h>
00011 #include <stdio.h>
00012 #include <sys/un.h>
00013 #include <string.h>
00014 #include <unistd.h>
00015 #include <stdlib.h>
00016 #include <errno.h>
00017 
00018 #ifdef USE_POLL
00019 #include <poll.h>
00020 #endif
00021 
00022 #include "udclient.h"
00023 
00024 #define BUFSIZE (4096)
00025 
00026 #define COMMAND "udclient"
00027 #define VERSION "0.6"
00028 
00029 /*
00030  * data transport routine
00031  */
00032 static ssize_t ud_transport(int in, int out, char *buf, size_t bufsize)
00033 {
00034        ssize_t len, wlen, llen;
00035        char *ptr = buf;
00036 
00037        if ((len = read(in, buf, bufsize)) < 0) {
00038               if (errno == EINTR)
00039                      return 0;
00040               else
00041                      return -1;
00042        }
00043        llen = len;
00044        while (llen > 0) {
00045               if ((wlen = write(out, ptr, llen)) < 0) {
00046                      if (errno == EINTR)
00047                             wlen = 0;
00048                      else
00049                             return -1;
00050               }
00051               llen -= wlen;
00052               ptr += wlen;
00053        }
00054        return len;
00055 }
00056 
00057 /* unix domain client routine for SOCK_STREAM */
00058 #ifdef USE_POLL
00059 
00060 int ud_cli(FILE *in, FILE *out, int sockfd)
00061 {
00062        struct pollfd pollfd[2];
00063        int in_eof;
00064        char *buf;
00065 
00066        if ((buf = (char *)malloc(sizeof(char)*BUFSIZE)) == NULL)
00067               exit (1);
00068 
00069        pollfd[0].fd = 0; /* stdin */
00070        pollfd[0].events = POLLIN;
00071        pollfd[1].fd = sockfd;
00072        pollfd[1].events = POLLIN;
00073 
00074        in_eof = 0;
00075        /* transport request & response, until stdin or socket is closed */
00076        while (1) {
00077               int ret = poll(pollfd, 2, INFTIM);
00078               if (ret == -1) break;
00079               if (pollfd[0].revents == POLLIN) {
00080                      /* transport request from stdin to iiim server */
00081                      if (ud_transport(fileno(in), pollfd[1].fd, buf, BUFSIZE) == 0) {
00082                             in_eof = 1;
00083                             shutdown(sockfd, SHUT_WR); /* send FIN */
00084                             break;
00085                      }
00086               }
00087               if (pollfd[1].revents == POLLIN) {
00088                      /* transport response from iiim server to stdout */
00089                      if (ud_transport(pollfd[1].fd, fileno(out), buf, BUFSIZE) <= 0) {
00090                             if (in_eof == 1) {
00091                                    break;
00092                             }
00093                             free(buf);
00094                             return 1;
00095                      }
00096               } 
00097               /* error check */
00098               if ((pollfd[1].revents & (POLLNVAL | POLLHUP | POLLERR))) {
00099                      free(buf);
00100                      return 1;
00101               }
00102        }
00103        free(buf);
00104        return 0;
00105 }
00106 #else /* USE_POLL */
00107 int ud_cli(FILE *in, FILE *out, int sockfd)
00108 {
00109        int maxfd, in_eof;
00110        fd_set rset;
00111        char *buf;
00112 
00113        if ((buf = (char *)malloc(sizeof(char)*BUFSIZE)) == NULL)
00114               exit (1);
00115 
00116        in_eof = 0;
00117        FD_ZERO(&rset);
00118        while (1) {
00119               if (in_eof == 0) {
00120                      FD_SET(fileno(in), &rset);
00121               }
00122               FD_SET(sockfd, &rset);
00123               maxfd = max(fileno(in), sockfd) + 1;
00124               select(maxfd, &rset, NULL, NULL, NULL);
00125 
00126               if (FD_ISSET(sockfd, &rset)) { /*socket is readable */
00127                      if (ud_transport(sockfd, fileno(out), buf, BUFSIZE) == 0) {
00128                             if (in_eof == 1) { /* normal termination */
00129                                    break;
00130                             } else {
00131                                    perror("ud_cli: server terminated prematurely"); 
00132                                    free(buf);
00133                                    return 1;
00134                             }
00135                      }
00136               }
00137               if (FD_ISSET(fileno(in), &rset)) { /* stdin  is readable */
00138                      if (ud_transport(fileno(in), sockfd, buf, BUFSIZE) == 0) {
00139                             in_eof = 1;
00140                             shutdown(sockfd, SHUT_WR); /* send FIN */
00141                             FD_CLR(fileno(in), &rset);
00142                      }
00143               }
00144        }
00145        free(buf);
00146        return 0;
00147 }
00148 #endif /* USE_POLL */
00149 
00150 static void print_help(void)
00151 {
00152        fprintf(stderr, "usage: " COMMAND " [-v|-h] path\n"
00153               "\n"
00154               "-h\t show this message.\n"
00155               "-v\t print version.\n"
00156               "\n"
00157               "Communicate with server through unix domain socket\n"
00158               "specified by path argument.\n"
00159               "Written by Hiroshi Miura <miura@da-cha.org>, Jan. 2005\n"
00160               );
00161 }
00162 
00163 static int proc_opt(int argc, char *argv[])
00164 {
00165        int i = 1;
00166        char c;
00167 
00168        if (argc < 2) {
00169               fprintf(stderr, "Error: socket pathname is needed.\n\n");
00170               return 0;
00171        }
00172 
00173        while (1) {
00174               if ((c = getopt(argc, argv, "hv")) == -1) 
00175                      break;
00176 
00177               switch (c) {
00178               case 'h':
00179                      print_help();
00180                      return 0;
00181               case 'v':
00182                      fprintf(stderr, COMMAND ": Version " VERSION "\n");
00183                      return 0;
00184               default:
00185                      fprintf(stderr, "Error: unknown option(s).\n\n");
00186                      print_help();
00187                      return 0;
00188               }
00189        }
00190 
00191        if ( argc == i + 1 )
00192               return i;
00193        
00194        if ( argc > i + 1 ) {
00195               fprintf(stderr, "Error: too many argument(s).\n\n");
00196        } else {
00197               fprintf(stderr, "Error: socket pathname is needed.\n\n");
00198        }
00199        print_help();
00200        return 0;
00201 }
00202 
00203 int main(int argc, char *argv[])
00204 {
00205        int sockfd;
00206        int pathname_i;
00207        struct sockaddr_un svaddr;
00208        FILE *in, *out;
00209        int proto = SOCK_STREAM;
00210 
00211        if ((pathname_i = proc_opt(argc, argv)) <= 0) {
00212               exit(1);
00213        }
00214 
00215        in = stdin; out      = stdout; 
00216 
00217        /* create unix domain socket and connect server*/
00218        bzero(&svaddr, sizeof(svaddr));
00219        svaddr.sun_family = AF_LOCAL;
00220        strncpy(svaddr.sun_path, argv[pathname_i], sizeof(svaddr.sun_path) - 1);
00221 
00222        if ((sockfd = socket(PF_LOCAL, proto, 0)) < 0) {
00223               perror("socket");
00224               exit(1);
00225        }
00226        if (connect(sockfd, (struct sockaddr*)&svaddr, SUN_LEN(&svaddr)) < 0) {
00227               perror("connect");
00228               close(sockfd);
00229               exit(1);
00230        }
00231 
00232        /* transport data */
00233        if (!ud_cli(in, out, sockfd)){
00234               close(sockfd);       
00235               exit(1);
00236        }
00237 
00238        close(sockfd);
00239        exit(0);
00240 }