Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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)
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
	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
}