Blame


1 e9612918 2005-03-21 devnull /*
2 e9612918 2005-03-21 devnull * Multiplexor for sftp sessions.
3 e9612918 2005-03-21 devnull * Assumes can parse session with sftp> prompts.
4 e9612918 2005-03-21 devnull * Assumes clients are well-behaved and don't hang up the system.
5 e9612918 2005-03-21 devnull *
6 e9612918 2005-03-21 devnull * Stupid sftp bug: sftp invokes ssh, which always set O_NONBLOCK
7 e9612918 2005-03-21 devnull * on 0, 1, and 2. Ssh inherits sftp's 2, so we can't use the output pipe
8 fa325e9b 2020-01-10 cross * on fd 2, since it will get set O_NONBLOCK, sftp won't notice, and
9 e9612918 2005-03-21 devnull * writes will be lost. So instead we use a separate pipe for errors
10 fa325e9b 2020-01-10 cross * and consult it after each command. Assume the pipe buffer is
11 e9612918 2005-03-21 devnull * big enough to hold the error output.
12 e9612918 2005-03-21 devnull */
13 e9612918 2005-03-21 devnull #include <u.h>
14 e9612918 2005-03-21 devnull #include <fcntl.h>
15 e9612918 2005-03-21 devnull #include <libc.h>
16 e9612918 2005-03-21 devnull #include <bio.h>
17 e9612918 2005-03-21 devnull
18 e9612918 2005-03-21 devnull #undef pipe
19 e9612918 2005-03-21 devnull
20 e9612918 2005-03-21 devnull int debug;
21 e9612918 2005-03-21 devnull #define dprint if(debug)print
22 e9612918 2005-03-21 devnull int sftpfd;
23 e9612918 2005-03-21 devnull int sftperr;
24 e9612918 2005-03-21 devnull Biobuf bin;
25 e9612918 2005-03-21 devnull
26 e9612918 2005-03-21 devnull void
27 e9612918 2005-03-21 devnull usage(void)
28 e9612918 2005-03-21 devnull {
29 e9612918 2005-03-21 devnull fprint(2, "usage: sftpcache system\n");
30 e9612918 2005-03-21 devnull exits("usage");
31 e9612918 2005-03-21 devnull }
32 e9612918 2005-03-21 devnull
33 e9612918 2005-03-21 devnull char*
34 e9612918 2005-03-21 devnull Brd(Biobuf *bin)
35 e9612918 2005-03-21 devnull {
36 e9612918 2005-03-21 devnull static char buf[1000];
37 e9612918 2005-03-21 devnull int c, tot;
38 fa325e9b 2020-01-10 cross
39 e9612918 2005-03-21 devnull tot = 0;
40 e9612918 2005-03-21 devnull while((c = Bgetc(bin)) >= 0 && tot<sizeof buf){
41 e9612918 2005-03-21 devnull buf[tot++] = c;
42 e9612918 2005-03-21 devnull if(c == '\n'){
43 e9612918 2005-03-21 devnull buf[tot] = 0;
44 3ae1a866 2005-03-24 devnull dprint("OUT %s", buf);
45 e9612918 2005-03-21 devnull return buf;
46 e9612918 2005-03-21 devnull }
47 e9612918 2005-03-21 devnull if(c == ' ' && tot == 6 && memcmp(buf, "sftp> ", 5) == 0){
48 e9612918 2005-03-21 devnull buf[tot] = 0;
49 3ae1a866 2005-03-24 devnull dprint("OUT %s\n", buf);
50 e9612918 2005-03-21 devnull return buf;
51 e9612918 2005-03-21 devnull }
52 e9612918 2005-03-21 devnull }
53 e9612918 2005-03-21 devnull if(tot == sizeof buf)
54 e9612918 2005-03-21 devnull sysfatal("response too long");
55 e9612918 2005-03-21 devnull return nil;
56 e9612918 2005-03-21 devnull }
57 e9612918 2005-03-21 devnull
58 e9612918 2005-03-21 devnull int
59 e9612918 2005-03-21 devnull readstr(int fd, char *a, int n)
60 e9612918 2005-03-21 devnull {
61 e9612918 2005-03-21 devnull int i;
62 fa325e9b 2020-01-10 cross
63 e9612918 2005-03-21 devnull for(i=0; i<n; i++){
64 e9612918 2005-03-21 devnull if(read(fd, a+i, 1) != 1)
65 e9612918 2005-03-21 devnull return -1;
66 e9612918 2005-03-21 devnull if(a[i] == '\n'){
67 e9612918 2005-03-21 devnull a[i] = 0;
68 e9612918 2005-03-21 devnull return i;
69 e9612918 2005-03-21 devnull }
70 e9612918 2005-03-21 devnull }
71 e9612918 2005-03-21 devnull return n;
72 e9612918 2005-03-21 devnull }
73 e9612918 2005-03-21 devnull
74 e9612918 2005-03-21 devnull void
75 e9612918 2005-03-21 devnull doerrors(int fd)
76 e9612918 2005-03-21 devnull {
77 e9612918 2005-03-21 devnull char buf[100];
78 3ae1a866 2005-03-24 devnull int n, first;
79 fa325e9b 2020-01-10 cross
80 3ae1a866 2005-03-24 devnull first = 1;
81 e9612918 2005-03-21 devnull while((n = read(sftperr, buf, sizeof buf)) > 0){
82 3ae1a866 2005-03-24 devnull if(debug){
83 3ae1a866 2005-03-24 devnull if(first){
84 3ae1a866 2005-03-24 devnull first = 0;
85 3ae1a866 2005-03-24 devnull fprint(2, "OUT errors:\n");
86 3ae1a866 2005-03-24 devnull }
87 e9612918 2005-03-21 devnull write(1, buf, n);
88 3ae1a866 2005-03-24 devnull }
89 e9612918 2005-03-21 devnull write(fd, buf, n);
90 e9612918 2005-03-21 devnull }
91 e9612918 2005-03-21 devnull }
92 e9612918 2005-03-21 devnull
93 e9612918 2005-03-21 devnull void
94 e9612918 2005-03-21 devnull bell(void *x, char *msg)
95 e9612918 2005-03-21 devnull {
96 e9612918 2005-03-21 devnull if(strcmp(msg, "sys: child") == 0 || strcmp(msg, "sys: write on closed pipe") == 0)
97 e9612918 2005-03-21 devnull sysfatal("sftp exited");
98 e9612918 2005-03-21 devnull if(strcmp(msg, "alarm") == 0)
99 e9612918 2005-03-21 devnull noted(NCONT);
100 e9612918 2005-03-21 devnull noted(NDFLT);
101 e9612918 2005-03-21 devnull }
102 e9612918 2005-03-21 devnull
103 e9612918 2005-03-21 devnull void
104 e9612918 2005-03-21 devnull main(int argc, char **argv)
105 e9612918 2005-03-21 devnull {
106 e9612918 2005-03-21 devnull char buf[200], cmd[1000], *q, *s;
107 e9612918 2005-03-21 devnull char dir[100], ndir[100];
108 e9612918 2005-03-21 devnull int p[2], px[2], pe[2], pid, ctl, nctl, fd, n;
109 fa325e9b 2020-01-10 cross
110 e9612918 2005-03-21 devnull notify(bell);
111 e9612918 2005-03-21 devnull fmtinstall('H', encodefmt);
112 e9612918 2005-03-21 devnull
113 e9612918 2005-03-21 devnull ARGBEGIN{
114 e9612918 2005-03-21 devnull case 'D':
115 e9612918 2005-03-21 devnull debug = 1;
116 e9612918 2005-03-21 devnull break;
117 e9612918 2005-03-21 devnull default:
118 e9612918 2005-03-21 devnull usage();
119 e9612918 2005-03-21 devnull }ARGEND
120 fa325e9b 2020-01-10 cross
121 e9612918 2005-03-21 devnull if(argc != 1)
122 e9612918 2005-03-21 devnull usage();
123 fa325e9b 2020-01-10 cross
124 e9612918 2005-03-21 devnull if(pipe(p) < 0 || pipe(px) < 0 || pipe(pe) < 0)
125 e9612918 2005-03-21 devnull sysfatal("pipe: %r");
126 e9612918 2005-03-21 devnull pid = fork();
127 e9612918 2005-03-21 devnull if(pid < 0)
128 e9612918 2005-03-21 devnull sysfatal("fork: %r");
129 e9612918 2005-03-21 devnull if(pid == 0){
130 e9612918 2005-03-21 devnull close(p[1]);
131 e9612918 2005-03-21 devnull close(px[0]);
132 e9612918 2005-03-21 devnull close(pe[0]);
133 e9612918 2005-03-21 devnull dup(p[0], 0);
134 e9612918 2005-03-21 devnull dup(px[1], 1);
135 e9612918 2005-03-21 devnull dup(pe[1], 2);
136 e9612918 2005-03-21 devnull if(p[0] > 2)
137 e9612918 2005-03-21 devnull close(p[0]);
138 e9612918 2005-03-21 devnull if(px[1] > 2)
139 e9612918 2005-03-21 devnull close(px[1]);
140 e9612918 2005-03-21 devnull if(pe[1] > 2)
141 e9612918 2005-03-21 devnull close(pe[1]);
142 e9612918 2005-03-21 devnull execl("sftp", "sftp", "-b", "/dev/stdin", argv[0], nil);
143 e9612918 2005-03-21 devnull sysfatal("exec sftp: %r");
144 e9612918 2005-03-21 devnull }
145 e9612918 2005-03-21 devnull
146 e9612918 2005-03-21 devnull close(p[0]);
147 e9612918 2005-03-21 devnull close(px[1]);
148 e9612918 2005-03-21 devnull close(pe[1]);
149 e9612918 2005-03-21 devnull
150 e9612918 2005-03-21 devnull sftpfd = p[1];
151 e9612918 2005-03-21 devnull sftperr = pe[0];
152 e9612918 2005-03-21 devnull Binit(&bin, px[0], OREAD);
153 e9612918 2005-03-21 devnull
154 e9612918 2005-03-21 devnull fcntl(sftperr, F_SETFL, fcntl(sftperr, F_GETFL, 0)|O_NONBLOCK);
155 e9612918 2005-03-21 devnull
156 e9612918 2005-03-21 devnull do
157 e9612918 2005-03-21 devnull q = Brd(&bin);
158 e9612918 2005-03-21 devnull while(q && strcmp(q, "sftp> ") != 0);
159 e9612918 2005-03-21 devnull if(q == nil)
160 e9612918 2005-03-21 devnull sysfatal("unexpected eof");
161 e9612918 2005-03-21 devnull
162 e9612918 2005-03-21 devnull snprint(buf, sizeof buf, "unix!%s/%s.sftp", getns(), argv[0]);
163 e9612918 2005-03-21 devnull ctl = announce(buf, dir);
164 e9612918 2005-03-21 devnull if(ctl < 0)
165 e9612918 2005-03-21 devnull sysfatal("announce %s: %r", buf);
166 e9612918 2005-03-21 devnull
167 e9612918 2005-03-21 devnull pid = fork();
168 e9612918 2005-03-21 devnull if(pid < 0)
169 e9612918 2005-03-21 devnull sysfatal("fork");
170 e9612918 2005-03-21 devnull if(pid != 0)
171 e9612918 2005-03-21 devnull exits(nil);
172 fa325e9b 2020-01-10 cross
173 e9612918 2005-03-21 devnull for(;;){
174 e9612918 2005-03-21 devnull nctl = listen(dir, ndir);
175 e9612918 2005-03-21 devnull if(nctl < 0)
176 e9612918 2005-03-21 devnull sysfatal("listen %s: %r", buf);
177 e9612918 2005-03-21 devnull fd = accept(ctl, ndir);
178 e9612918 2005-03-21 devnull close(nctl);
179 e9612918 2005-03-21 devnull if(fd < 0)
180 e9612918 2005-03-21 devnull continue;
181 e9612918 2005-03-21 devnull for(;;){
182 cbeb0b26 2006-04-01 devnull /* alarm(1000); */
183 e9612918 2005-03-21 devnull n = readstr(fd, cmd, sizeof cmd);
184 cbeb0b26 2006-04-01 devnull /* alarm(0); */
185 e9612918 2005-03-21 devnull if(n <= 0)
186 e9612918 2005-03-21 devnull break;
187 e9612918 2005-03-21 devnull dprint("CMD %s\n", cmd);
188 3ae1a866 2005-03-24 devnull if(strcmp(cmd, "DONE") == 0){
189 3ae1a866 2005-03-24 devnull fprint(fd, "DONE\n");
190 e9612918 2005-03-21 devnull break;
191 3ae1a866 2005-03-24 devnull }
192 3ae1a866 2005-03-24 devnull fprint(sftpfd, "-%s\n", cmd);
193 e9612918 2005-03-21 devnull q = Brd(&bin);
194 e9612918 2005-03-21 devnull if(*q==0 || q[strlen(q)-1] != '\n')
195 e9612918 2005-03-21 devnull sysfatal("unexpected response");
196 e9612918 2005-03-21 devnull q[strlen(q)-1] = 0;
197 3ae1a866 2005-03-24 devnull if(q[0] != '-' || strcmp(q+1, cmd) != 0)
198 e9612918 2005-03-21 devnull sysfatal("unexpected response");
199 e9612918 2005-03-21 devnull while((q = Brd(&bin)) != nil){
200 e9612918 2005-03-21 devnull if(strcmp(q, "sftp> ") == 0){
201 e9612918 2005-03-21 devnull doerrors(fd);
202 e9612918 2005-03-21 devnull break;
203 e9612918 2005-03-21 devnull }
204 e9612918 2005-03-21 devnull s = q+strlen(q);
205 e9612918 2005-03-21 devnull while(s > q && (s[-1] == ' ' || s[-1] == '\n' || s[-1] == '\t' || s[-1] == '\r'))
206 e9612918 2005-03-21 devnull s--;
207 e9612918 2005-03-21 devnull *s = 0;
208 e9612918 2005-03-21 devnull fprint(fd, "%s\n", q);
209 e9612918 2005-03-21 devnull }
210 e9612918 2005-03-21 devnull if(q == nil){
211 e9612918 2005-03-21 devnull fprint(fd, "!!! unexpected eof\n");
212 e9612918 2005-03-21 devnull sysfatal("unexpected eof");
213 e9612918 2005-03-21 devnull }
214 e9612918 2005-03-21 devnull }
215 e9612918 2005-03-21 devnull close(fd);
216 e9612918 2005-03-21 devnull }
217 e9612918 2005-03-21 devnull }