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