/* udclient.c * VERSION: 0.5 * AUTHOR: miura@da-cha.org * DATE: 2005.01.15 * * repeater to communicate with unix domain socket */ #include #include #include #include #include #include #include #include #include "udclient.h" #include #define BFSZ (4096) /* buffer size */ #define COMMAND "udclient" #define VERSION "0.5" /* * data transport routin */ static ssize_t ud_transport(int in, int out) { char* buf = NULL; /* data buffer */ ssize_t len = BFSZ; /* data length */ int count = -1; /* read count */ char *debug = NULL; /* debug buffer */ int i=0; /* read input */ debug = (char*)malloc(BFSZ*3+1); while (len == BFSZ) { count++; /* allocate data buffer */ if ((buf = (char*)realloc(buf, (count + 1) * BFSZ)) == NULL) { perror("realloc"); exit(1); } /* read input to data buffer */ if ((len = read(in, buf + count * BFSZ, BFSZ)) < 0) { perror("read"); exit(1); } /* for debug */ for (i=0; i 0 && write(out, buf, len) < 0) { perror("write"); exit(1); } //syslog(LOG_LOCAL0|LOG_NOTICE, "udclient wrote %d bytes", len); /* destroy data buffer */ free(buf); return len; } /* unix domain client routine for SOCK_STREAM */ int ud_cli(FILE *in, FILE *out, int sockfd) { int maxfd, in_eof; fd_set rset; in_eof = 0; FD_ZERO(&rset); for ( ; ; ) { if (in_eof == 0) { FD_SET(fileno(in), &rset); } FD_SET(sockfd, &rset); maxfd = max(fileno(in), sockfd) + 1; select(maxfd, &rset, NULL, NULL, NULL); if (FD_ISSET(sockfd, &rset)) { /*socket is readable */ syslog(LOG_LOCAL0|LOG_NOTICE, "socket is readable"); if (ud_transport(sockfd, fileno(out)) == 0) { if (in_eof == 1) { /* normal termination */ return 0; } else { perror("ud_cli: server terminated prematurely"); exit(1); } } } if (FD_ISSET(fileno(in), &rset)) { /* stdin is readable */ syslog(LOG_LOCAL0|LOG_NOTICE, "stdin is readable"); if (ud_transport(fileno(in), sockfd) == 0) { in_eof = 1; shutdown(sockfd, SHUT_WR); /* send FIN */ FD_CLR(fileno(in), &rset); } } } /* NOREACH */ return 1; } static void print_help(void) { fprintf(stderr, "usage: " COMMAND " [-v|-h] path\n" "\n" "-h\t show this message.\n" "-v\t print version.\n" "\n" "Communication with server through unix domain socket\n" "specified by path argument.\n" "Writtend by Hiroshi Miura , Jan. 2005\n" ); } static int proc_opt(int argc, char *argv[]) { int i = 1; char c; if (argc < 2) return 0; while (1) { if ((c = getopt(argc, argv, "hv")) == -1) break; switch (c) { case 'h': return 0; case 'v': fprintf(stderr, COMMAND ": Version " VERSION "\n"); return -1; default: fprintf(stderr, "Error: unknown option(s).\n\n"); return 0; } } if ( argc == i + 1 ) return i; if ( argc > i + 1 ) { fprintf(stderr, "Error: too many argument(s).\n\n"); } else { fprintf(stderr, "Error: socket pathname is needed.\n\n"); } return 0; } /* 引数はUnix Socket に用いるファイル名 */ int main(int argc, char *argv[]) { int sockfd; int pathname_i; struct sockaddr_un svaddr; FILE *in, *out; int proto = SOCK_STREAM; if ((pathname_i = proc_opt(argc, argv)) <= 0) { if (pathname_i == 0) print_help(); exit(1); } in = stdin; out = stdout; /* create unix domain socket and connect server*/ bzero(&svaddr, sizeof(svaddr)); svaddr.sun_family = AF_LOCAL; strncpy(svaddr.sun_path, argv[pathname_i], sizeof(svaddr.sun_path) - 1); if ((sockfd = socket(PF_LOCAL, proto, 0)) < 0) { perror("socket"); exit(1); } if (connect(sockfd, (struct sockaddr*)&svaddr, SUN_LEN(&svaddr)) < 0) { perror("connect"); close(sockfd); exit(1); } /* transport data */ if (!ud_cli(in, out, sockfd)){ close(sockfd); exit(1); } close(sockfd); exit(0); }