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
ding(int)22 ding(int)
23 {
24 }
25
26 int
rcmd(char ** dst,int port,char * luser,char * ruser,char * cmd,int * fd2p)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