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