xref: /plan9/sys/src/ape/lib/bsd/rcmd.c (revision 781103c4074deb8af160e8a0da2742ba6b29dc2b)
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 
187e125112SDavid du Colombier static char pbotch[] = "rcmd: protocol botch\n";
197e125112SDavid du Colombier static char lbotch[] = "rcmd: botch starting error stream\n";
20219b2ee8SDavid du Colombier 
21219b2ee8SDavid du Colombier static void
ding(int)22*781103c4SDavid du Colombier ding(int)
23219b2ee8SDavid du Colombier {
24219b2ee8SDavid du Colombier }
25219b2ee8SDavid du Colombier 
26219b2ee8SDavid du Colombier int
rcmd(char ** dst,int port,char * luser,char * ruser,char * cmd,int * fd2p)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 */
61*781103c4SDavid du Colombier 	lfd = -1;
62219b2ee8SDavid du Colombier 	if(fd2p){
63219b2ee8SDavid du Colombier 		/* create an error stream and wait for a call in */
64219b2ee8SDavid du Colombier 		for(i = 0; i < 10; i++){
65219b2ee8SDavid du Colombier 			lfd = rresvport(&port2);
66219b2ee8SDavid du Colombier 			if(lfd < 0)
67219b2ee8SDavid du Colombier 				continue;
68219b2ee8SDavid du Colombier 			if(listen(lfd, 1) == 0)
69219b2ee8SDavid du Colombier 				break;
70219b2ee8SDavid du Colombier 			close(lfd);
71219b2ee8SDavid du Colombier 		}
72219b2ee8SDavid du Colombier 		if(i >= 10){
73219b2ee8SDavid du Colombier 			fprintf(stderr, pbotch);
74219b2ee8SDavid du Colombier 			return -1;
75219b2ee8SDavid du Colombier 		}
76219b2ee8SDavid du Colombier 
777e125112SDavid du Colombier 		snprintf(buf, sizeof buf, "%d", port2);
78219b2ee8SDavid du Colombier 		if(write(fd, buf, strlen(buf)+1) < 0){
79219b2ee8SDavid du Colombier 			close(fd);
80219b2ee8SDavid du Colombier 			close(lfd);
81219b2ee8SDavid du Colombier 			fprintf(stderr, lbotch);
82219b2ee8SDavid du Colombier 			return -1;
83219b2ee8SDavid du Colombier 		}
84219b2ee8SDavid du Colombier 	} else {
85219b2ee8SDavid du Colombier 		if(write(fd, "", 1) < 0){
86219b2ee8SDavid du Colombier 			fprintf(stderr, pbotch);
87219b2ee8SDavid du Colombier 			return -1;
88219b2ee8SDavid du Colombier 		}
89219b2ee8SDavid du Colombier 	}
90219b2ee8SDavid du Colombier 
91219b2ee8SDavid du Colombier 	/* pass id's and command */
92219b2ee8SDavid du Colombier 	if(write(fd, luser, strlen(luser)+1) < 0
93219b2ee8SDavid du Colombier 	|| write(fd, ruser, strlen(ruser)+1) < 0
94219b2ee8SDavid du Colombier 	|| write(fd, cmd, strlen(cmd)+1) < 0){
95219b2ee8SDavid du Colombier 		fprintf(stderr, pbotch);
96219b2ee8SDavid du Colombier 		return -1;
97219b2ee8SDavid du Colombier 	}
98219b2ee8SDavid du Colombier 
99*781103c4SDavid du Colombier 	fd2 = -1;
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){
119*781103c4SDavid du Colombier 		if(fd2p){
120219b2ee8SDavid du Colombier 			close(fd2);
121*781103c4SDavid du Colombier 			*fd2p = -1;
122*781103c4SDavid du Colombier 		}
123219b2ee8SDavid du Colombier 		fprintf(stderr, pbotch);
124219b2ee8SDavid du Colombier 		return -1;
125219b2ee8SDavid du Colombier 	}
126219b2ee8SDavid du Colombier 	if(c == 0)
127219b2ee8SDavid du Colombier 		return fd;
128219b2ee8SDavid du Colombier 	i = 0;
129219b2ee8SDavid du Colombier 	while(c){
130219b2ee8SDavid du Colombier 		buf[i++] = c;
131219b2ee8SDavid du Colombier 		if(read(fd, &c, 1) != 1)
132219b2ee8SDavid du Colombier 			break;
133219b2ee8SDavid du Colombier 		if(i >= sizeof(buf)-1)
134219b2ee8SDavid du Colombier 			break;
135219b2ee8SDavid du Colombier 	}
136219b2ee8SDavid du Colombier 	buf[i] = 0;
137219b2ee8SDavid du Colombier 	fprintf(stderr, "rcmd: %s\n", buf);
138219b2ee8SDavid du Colombier 	close(fd);
139219b2ee8SDavid du Colombier 	return -1;
140219b2ee8SDavid du Colombier }
141