1 /* posix */ 2 #include <sys/types.h> 3 #include <unistd.h> 4 #include <stdlib.h> 5 #include <stdio.h> 6 #include <string.h> 7 #include <errno.h> 8 #include <signal.h> 9 10 /* socket extensions */ 11 #include <sys/socket.h> 12 #include <netinet/in.h> 13 #include <sys/un.h> 14 #include <netdb.h> 15 16 #include "priv.h" 17 18 static char *pbotch = "rcmd: protocol botch\n"; 19 static char *lbotch = "rcmd: botch starting error stream\n"; 20 21 static void 22 ding(int x) 23 { 24 } 25 26 int 27 rcmd(char **dst, int port, char *luser, char *ruser, char *cmd, int *fd2p) 28 { 29 char c; 30 int i, fd, lfd, fd2, port2; 31 struct hostent *h; 32 Rock *r; 33 struct sockaddr_in in; 34 char buf[128]; 35 void (*x)(int); 36 37 h = gethostbyname(*dst); 38 if(h == 0) 39 return -1; 40 *dst = h->h_name; 41 42 /* connect using a reserved tcp port */ 43 fd = socket(PF_INET, SOCK_STREAM, 0); 44 if(fd < 0) 45 return -1; 46 r = _sock_findrock(fd, 0); 47 if(r == 0){ 48 errno = ENOTSOCK; 49 return -1; 50 } 51 r->reserved = 1; 52 in.sin_family = AF_INET; 53 in.sin_port = htons(port); 54 memmove(&in.sin_addr, h->h_addr_list[0], sizeof(in.sin_addr)); 55 if(connect(fd, &in, sizeof(in)) < 0){ 56 close(fd); 57 return -1; 58 } 59 60 /* error stream */ 61 if(fd2p){ 62 /* create an error stream and wait for a call in */ 63 for(i = 0; i < 10; i++){ 64 lfd = rresvport(&port2); 65 if(lfd < 0) 66 continue; 67 if(listen(lfd, 1) == 0) 68 break; 69 close(lfd); 70 } 71 if(i >= 10){ 72 fprintf(stderr, pbotch); 73 return -1; 74 } 75 76 sprintf(buf, "%d", port2); 77 if(write(fd, buf, strlen(buf)+1) < 0){ 78 close(fd); 79 close(lfd); 80 fprintf(stderr, lbotch); 81 return -1; 82 } 83 } else { 84 if(write(fd, "", 1) < 0){ 85 fprintf(stderr, pbotch); 86 return -1; 87 } 88 } 89 90 /* pass id's and command */ 91 if(write(fd, luser, strlen(luser)+1) < 0 92 || write(fd, ruser, strlen(ruser)+1) < 0 93 || write(fd, cmd, strlen(cmd)+1) < 0){ 94 if(fd2p) 95 close(fd2); 96 fprintf(stderr, pbotch); 97 return -1; 98 } 99 100 if(fd2p){ 101 x = signal(SIGALRM, ding); 102 alarm(15); 103 fd2 = accept(lfd, &in, &i); 104 alarm(0); 105 close(lfd); 106 signal(SIGALRM, x); 107 108 if(fd2 < 0){ 109 close(fd); 110 close(lfd); 111 fprintf(stderr, lbotch); 112 return -1; 113 } 114 *fd2p = fd2; 115 } 116 117 /* get reply */ 118 if(read(fd, &c, 1) != 1){ 119 if(fd2p) 120 close(fd2); 121 fprintf(stderr, pbotch); 122 return -1; 123 } 124 if(c == 0) 125 return fd; 126 i = 0; 127 while(c){ 128 buf[i++] = c; 129 if(read(fd, &c, 1) != 1) 130 break; 131 if(i >= sizeof(buf)-1) 132 break; 133 } 134 buf[i] = 0; 135 fprintf(stderr, "rcmd: %s\n", buf); 136 close(fd); 137 return -1; 138 } 139