1219b2ee8SDavid du Colombier /* posix */ 2219b2ee8SDavid du Colombier #include <sys/types.h> 3219b2ee8SDavid du Colombier #include <unistd.h> 4219b2ee8SDavid du Colombier #include <stdlib.h> 5219b2ee8SDavid du Colombier #include <stdio.h> 6219b2ee8SDavid du Colombier #include <string.h> 7219b2ee8SDavid du Colombier #include <errno.h> 8219b2ee8SDavid du Colombier #include <signal.h> 9219b2ee8SDavid du Colombier 10219b2ee8SDavid du Colombier /* socket extensions */ 11219b2ee8SDavid du Colombier #include <sys/socket.h> 12219b2ee8SDavid du Colombier #include <netinet/in.h> 13219b2ee8SDavid du Colombier #include <sys/un.h> 14219b2ee8SDavid du Colombier #include <netdb.h> 15219b2ee8SDavid du Colombier 16219b2ee8SDavid du Colombier #include "priv.h" 17219b2ee8SDavid du Colombier 18*7e125112SDavid du Colombier static char pbotch[] = "rcmd: protocol botch\n"; 19*7e125112SDavid du Colombier static char lbotch[] = "rcmd: botch starting error stream\n"; 20219b2ee8SDavid du Colombier 21219b2ee8SDavid du Colombier static void 22219b2ee8SDavid du Colombier ding(int x) 23219b2ee8SDavid du Colombier { 24219b2ee8SDavid du Colombier } 25219b2ee8SDavid du Colombier 26219b2ee8SDavid du Colombier int 27219b2ee8SDavid du Colombier rcmd(char **dst, int port, char *luser, char *ruser, char *cmd, int *fd2p) 28219b2ee8SDavid du Colombier { 29219b2ee8SDavid du Colombier char c; 30219b2ee8SDavid du Colombier int i, fd, lfd, fd2, port2; 31219b2ee8SDavid du Colombier struct hostent *h; 32219b2ee8SDavid du Colombier Rock *r; 33219b2ee8SDavid du Colombier struct sockaddr_in in; 34219b2ee8SDavid du Colombier char buf[128]; 35219b2ee8SDavid du Colombier void (*x)(int); 36219b2ee8SDavid du Colombier 37219b2ee8SDavid du Colombier h = gethostbyname(*dst); 38219b2ee8SDavid du Colombier if(h == 0) 39219b2ee8SDavid du Colombier return -1; 40219b2ee8SDavid du Colombier *dst = h->h_name; 41219b2ee8SDavid du Colombier 42219b2ee8SDavid du Colombier /* connect using a reserved tcp port */ 43219b2ee8SDavid du Colombier fd = socket(PF_INET, SOCK_STREAM, 0); 44219b2ee8SDavid du Colombier if(fd < 0) 45219b2ee8SDavid du Colombier return -1; 46219b2ee8SDavid du Colombier r = _sock_findrock(fd, 0); 47219b2ee8SDavid du Colombier if(r == 0){ 48219b2ee8SDavid du Colombier errno = ENOTSOCK; 49219b2ee8SDavid du Colombier return -1; 50219b2ee8SDavid du Colombier } 51219b2ee8SDavid du Colombier r->reserved = 1; 52219b2ee8SDavid du Colombier in.sin_family = AF_INET; 53219b2ee8SDavid du Colombier in.sin_port = htons(port); 54219b2ee8SDavid du Colombier memmove(&in.sin_addr, h->h_addr_list[0], sizeof(in.sin_addr)); 55219b2ee8SDavid du Colombier if(connect(fd, &in, sizeof(in)) < 0){ 56219b2ee8SDavid du Colombier close(fd); 57219b2ee8SDavid du Colombier return -1; 58219b2ee8SDavid du Colombier } 59219b2ee8SDavid du Colombier 60219b2ee8SDavid du Colombier /* error stream */ 61219b2ee8SDavid du Colombier if(fd2p){ 62219b2ee8SDavid du Colombier /* create an error stream and wait for a call in */ 63219b2ee8SDavid du Colombier for(i = 0; i < 10; i++){ 64219b2ee8SDavid du Colombier lfd = rresvport(&port2); 65219b2ee8SDavid du Colombier if(lfd < 0) 66219b2ee8SDavid du Colombier continue; 67219b2ee8SDavid du Colombier if(listen(lfd, 1) == 0) 68219b2ee8SDavid du Colombier break; 69219b2ee8SDavid du Colombier close(lfd); 70219b2ee8SDavid du Colombier } 71219b2ee8SDavid du Colombier if(i >= 10){ 72219b2ee8SDavid du Colombier fprintf(stderr, pbotch); 73219b2ee8SDavid du Colombier return -1; 74219b2ee8SDavid du Colombier } 75219b2ee8SDavid du Colombier 76*7e125112SDavid du Colombier snprintf(buf, sizeof buf, "%d", port2); 77219b2ee8SDavid du Colombier if(write(fd, buf, strlen(buf)+1) < 0){ 78219b2ee8SDavid du Colombier close(fd); 79219b2ee8SDavid du Colombier close(lfd); 80219b2ee8SDavid du Colombier fprintf(stderr, lbotch); 81219b2ee8SDavid du Colombier return -1; 82219b2ee8SDavid du Colombier } 83219b2ee8SDavid du Colombier } else { 84219b2ee8SDavid du Colombier if(write(fd, "", 1) < 0){ 85219b2ee8SDavid du Colombier fprintf(stderr, pbotch); 86219b2ee8SDavid du Colombier return -1; 87219b2ee8SDavid du Colombier } 88219b2ee8SDavid du Colombier } 89219b2ee8SDavid du Colombier 90219b2ee8SDavid du Colombier /* pass id's and command */ 91219b2ee8SDavid du Colombier if(write(fd, luser, strlen(luser)+1) < 0 92219b2ee8SDavid du Colombier || write(fd, ruser, strlen(ruser)+1) < 0 93219b2ee8SDavid du Colombier || write(fd, cmd, strlen(cmd)+1) < 0){ 94219b2ee8SDavid du Colombier if(fd2p) 95219b2ee8SDavid du Colombier close(fd2); 96219b2ee8SDavid du Colombier fprintf(stderr, pbotch); 97219b2ee8SDavid du Colombier return -1; 98219b2ee8SDavid du Colombier } 99219b2ee8SDavid du Colombier 100219b2ee8SDavid du Colombier if(fd2p){ 101219b2ee8SDavid du Colombier x = signal(SIGALRM, ding); 102219b2ee8SDavid du Colombier alarm(15); 103219b2ee8SDavid du Colombier fd2 = accept(lfd, &in, &i); 104219b2ee8SDavid du Colombier alarm(0); 105219b2ee8SDavid du Colombier close(lfd); 106219b2ee8SDavid du Colombier signal(SIGALRM, x); 107219b2ee8SDavid du Colombier 108219b2ee8SDavid du Colombier if(fd2 < 0){ 109219b2ee8SDavid du Colombier close(fd); 110219b2ee8SDavid du Colombier close(lfd); 111219b2ee8SDavid du Colombier fprintf(stderr, lbotch); 112219b2ee8SDavid du Colombier return -1; 113219b2ee8SDavid du Colombier } 114219b2ee8SDavid du Colombier *fd2p = fd2; 115219b2ee8SDavid du Colombier } 116219b2ee8SDavid du Colombier 117219b2ee8SDavid du Colombier /* get reply */ 118219b2ee8SDavid du Colombier if(read(fd, &c, 1) != 1){ 119219b2ee8SDavid du Colombier if(fd2p) 120219b2ee8SDavid du Colombier close(fd2); 121219b2ee8SDavid du Colombier fprintf(stderr, pbotch); 122219b2ee8SDavid du Colombier return -1; 123219b2ee8SDavid du Colombier } 124219b2ee8SDavid du Colombier if(c == 0) 125219b2ee8SDavid du Colombier return fd; 126219b2ee8SDavid du Colombier i = 0; 127219b2ee8SDavid du Colombier while(c){ 128219b2ee8SDavid du Colombier buf[i++] = c; 129219b2ee8SDavid du Colombier if(read(fd, &c, 1) != 1) 130219b2ee8SDavid du Colombier break; 131219b2ee8SDavid du Colombier if(i >= sizeof(buf)-1) 132219b2ee8SDavid du Colombier break; 133219b2ee8SDavid du Colombier } 134219b2ee8SDavid du Colombier buf[i] = 0; 135219b2ee8SDavid du Colombier fprintf(stderr, "rcmd: %s\n", buf); 136219b2ee8SDavid du Colombier close(fd); 137219b2ee8SDavid du Colombier return -1; 138219b2ee8SDavid du Colombier } 139