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