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) 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 lfd = -1; 62 if(fd2p){ 63 /* create an error stream and wait for a call in */ 64 for(i = 0; i < 10; i++){ 65 lfd = rresvport(&port2); 66 if(lfd < 0) 67 continue; 68 if(listen(lfd, 1) == 0) 69 break; 70 close(lfd); 71 } 72 if(i >= 10){ 73 fprintf(stderr, pbotch); 74 return -1; 75 } 76 77 snprintf(buf, sizeof buf, "%d", port2); 78 if(write(fd, buf, strlen(buf)+1) < 0){ 79 close(fd); 80 close(lfd); 81 fprintf(stderr, lbotch); 82 return -1; 83 } 84 } else { 85 if(write(fd, "", 1) < 0){ 86 fprintf(stderr, pbotch); 87 return -1; 88 } 89 } 90 91 /* pass id's and command */ 92 if(write(fd, luser, strlen(luser)+1) < 0 93 || write(fd, ruser, strlen(ruser)+1) < 0 94 || write(fd, cmd, strlen(cmd)+1) < 0){ 95 fprintf(stderr, pbotch); 96 return -1; 97 } 98 99 fd2 = -1; 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 *fd2p = -1; 122 } 123 fprintf(stderr, pbotch); 124 return -1; 125 } 126 if(c == 0) 127 return fd; 128 i = 0; 129 while(c){ 130 buf[i++] = c; 131 if(read(fd, &c, 1) != 1) 132 break; 133 if(i >= sizeof(buf)-1) 134 break; 135 } 136 buf[i] = 0; 137 fprintf(stderr, "rcmd: %s\n", buf); 138 close(fd); 139 return -1; 140 } 141