|
|
1.1 root 1:
2: static char SCCSID[] = "@(#)pull.c 2.1 DKHOST 85/01/15";
3:
4: #include <sys/types.h>
5: #include "sysexits.h"
6: #include <signal.h>
7: #include "tdefs.h"
8: #include "udefs.h"
9: #include <stdio.h>
10: #include <errno.h>
11: #include <string.h>
12: #include <varargs.h>
13: #include "pupu.h"
14: #include <ndir.h>
15:
16: Efn takefile, fetchrequest, setdirectory, terminate;
17: Efn takelink, confirmed, remoteerror, alldone;
18:
19: Sexp pulltable[] = {
20: 'F', takefile,
21: 'L', takelink,
22: 'S', fetchrequest,
23: 'D', setdirectory,
24: 'X', terminate,
25: 0, 0
26: };
27:
28: Sexp fetchtable[] = {
29: 'F', takefile,
30: 'L', takelink,
31: 'c', confirmed,
32: 'e', remoteerror,
33: 'X', alldone,
34: 0, 0
35: };
36:
37: Eexp justquit[];
38:
39: Sint dochown;
40:
41: EcharP below();
42: EpwP getpwnam();
43:
44: pull(fd, names, directory, errfcn, options)
45: PfnP errfcn;
46: PcharP *names, directory, options;
47: {
48: begin(fd, errfcn, "local", ".");
49:
50: dochown = (geteuid() == 0);
51:
52: if(setjmp(giveup))
53: return(lasterror);
54:
55: sendinit(options);
56:
57: setbase(directory);
58:
59: while(*names)
60: fetchfile(*names++);
61:
62: msginit('X');
63: msgsend();
64: msgwait(justquit);
65:
66: signal(SIGALRM, alarmwas);
67: return(lasterror);
68: }
69:
70: fetchfile(name)
71: PcharP name;
72: {
73: msginit('S');
74:
75: msgfmt("%s", name);
76:
77: msgconf(fetchtable);
78: }
79:
80: fetchrequest()
81: {
82: Achar name[NAMELEN];
83:
84: msgtake("%s", name);
85:
86: sendfile(name);
87:
88: reply('c');
89:
90: return(0);
91: }
92:
93: ppremote(fd)
94: {
95: begin(fd, (TfnP) 0, "remote", ".");
96:
97: dochown = (geteuid() == 0);
98:
99: if(setjmp(giveup))
100: return(lasterror);
101:
102: msgwait(inittable);
103:
104: msgwait(pulltable);
105:
106: signal(SIGALRM, alarmwas);
107: return(lasterror);
108: }
109:
110: setdirectory()
111: {
112: setbase(&buf[H_DATA]);
113:
114: reply('c');
115:
116: return(0);
117: }
118:
119: setbase(p)
120: RcharP p;
121: {
122: RcharP q;
123: RpwP pw;
124:
125: if(*p == '/')
126: strcpy(basedir, p);
127: else if(*p == '~'){
128: if(q = strchr(++p, '/'))
129: *q++ = '\0';
130:
131: if(*p){
132: if(pw = getpwnam(p))
133: strcpy(basedir, pw->pw_dir);
134: else
135: err("No passwd entry for", p, -EX_NOUSER);
136: }else{
137: curdir(basedir);
138: strcpy(wdir, basedir);
139: }
140:
141: if(q){
142: strcat(basedir, "/");
143: strcat(basedir, q);
144: }
145: }else{
146: curdir(basedir);
147: strcpy(wdir, basedir);
148:
149: if(strcmp(p, ".") != 0){
150: strcat(basedir, "/");
151: strcat(basedir, p);
152: }
153: }
154:
155: db(stderr, "setdirectory %s\n", basedir);
156: changedir(basedir);
157:
158: return(0);
159: }
160:
161: changedir(newdir)
162: PcharP newdir;
163: {
164: RcharP p;
165:
166: if(!(p = below(wdir, newdir)))
167: p = newdir;
168:
169: if(*p){
170: if(chdir(p) < 0 && (makedirectory(p), chdir(p) < 0))
171: err("Can't chdir to", p, EX_NOINPUT);
172:
173: strcpy(wdir, newdir);
174: }
175: db(stderr, "changedir newdir %s p %s wdir %s\n", newdir, p, wdir);
176: }
177:
178: PcharP
179: below(ref, check)
180: RcharP ref, check;
181: {
182: Rint len;
183:
184: len = strlen(ref);
185:
186: if(strncmp(ref, check, len) != 0)
187: return(NIL);
188:
189: check += len;
190:
191: if(*check == '/')
192: return(check+1);
193: if(*check)
194: return(NIL);
195: return(check);
196: }
197:
198: takefile()
199: {
200: RcharP p;
201: Rint haderr;
202: Achar type;
203: Achar name[NAMELEN];
204: Aint mode, uid, gid;
205: Along mtime;
206: time_t timea[2];
207:
208: msgtake("%c", &type);
209: msgtake("%s", name);
210: msgtake("%o", &mode);
211: msgtake("%d", &uid);
212: msgtake("%d", &gid);
213: msgtake("%ld", &mtime);
214:
215: sprintf(wholename, "%s/%s", basedir, name);
216:
217: p = strrchr(wholename, '/');
218: *p = '\0';
219:
220: changedir(wholename);
221:
222: *p++ = '/';
223:
224: switch(type){
225: case 'r':
226: haderr = pluckregular(p);
227: break;
228:
229: case 'd':
230: makedirectory(p);
231: haderr = 0;
232: break;
233:
234: case 'c':
235: haderr = pluckspecial(p, S_IFCHR);
236: break;
237:
238: case 'b':
239: haderr = pluckspecial(p, S_IFBLK);
240: break;
241:
242: case 'p':
243: haderr = pluckspecial(p, S_IFIFO);
244: }
245:
246: reply('c');
247:
248: if(haderr)
249: return(0);
250:
251: chmod(p, mode);
252:
253: timea[0] = time((TlongP) 0);
254: timea[1] = mtime;
255:
256: if(timea[1] >= timea[0])
257: timea[1] = timea[0] - 1;
258:
259: utime(p, timea);
260:
261: if(dochown)
262: chown(p, uid, gid);
263:
264: return(0);
265: }
266:
267: pluckregular(p)
268: PcharP p;
269: {
270: Rint ffd, len;
271:
272: if((ffd = creatn(p, 0200)) < 0
273: && (chmod(p, 0200), (ffd = creatn(p, 0200)) < 0)){
274:
275: warn("Can't create", wholename, EX_CANTCREAT);
276:
277: while(msgread(cfd, buf, sizeof(buf)) > 0);
278:
279: return(BAD);
280: }
281:
282: currentfile = wholename;
283: timeoutmsg = "File reception timed out";
284:
285: alarm(RTIMEOUT);
286:
287: while((len = msgread(cfd, buf, sizeof(buf))) > 0){
288: db(stderr, "len %d\n", len);
289: if(write(ffd, buf, len) != len){
290: warn("Write failed on", wholename, EX_IOERR);
291: while((len = msgread(cfd, buf, sizeof(buf))) > 0);
292: }
293: alarm(RTIMEOUT);
294: }
295:
296: alarm(0);
297:
298: if(len < 0)
299: stopnow(EX_IOERR);
300:
301: closen(ffd);
302:
303: return(GOOD);
304: }
305:
306: pluckspecial(name, mode)
307: PcharP name;
308: {
309: Rint dev;
310: Aint maj, min;
311:
312: unlink(name);
313:
314: if(mode == S_IFIFO)
315: dev = 0;
316: else{
317: msgtake("%d", &maj);
318: msgtake("%d", &min);
319:
320: dev = makedev(maj, min);
321: }
322:
323: if(mknod(name, mode, dev) < 0){
324: warn("Can't mknod", wholename, EX_CANTCREAT);
325: return(BAD);
326: }
327:
328: return(GOOD);
329: }
330:
331: takelink()
332: {
333: RcharP p;
334: Achar name[NAMELEN], prev[NAMELEN];
335:
336: msgtake("%s", name);
337: msgtake("%s", prev);
338:
339: sprintf(wholename, "%s/%s", basedir, name);
340:
341: p = strrchr(wholename, '/');
342: *p = '\0';
343: changedir(wholename);
344: *p++ = '/';
345:
346: sprintf(buf, "%s/%s", basedir, prev);
347:
348: if((link(buf, p) < 0) && (unlink(p), (link(buf, p) < 0)))
349: warn("Can't link to", wholename, EX_CANTCREAT);
350:
351: reply('c');
352:
353: return(0);
354: }
355:
356: makedirectory(p)
357: PcharP p;
358: {
359: RcharP q;
360: Aint pid, n, result;
361: Achar temp[NAMELEN];
362:
363: db(stderr, "makedirectory %s\n", p);
364: sprintf(temp, "%s/", p);
365:
366: q = temp;
367: if(*q == '/')
368: q++;
369:
370: while(q = strchr(q, '/')){
371: *q = '\0';
372:
373: if(access(temp, 1) < 0){
374: db(stderr, "mkdir %s\n", temp);
375: if((pid = fork()) == 0){
376: freopen("/dev/null", "w", stderr);
377: execl("/bin/mkdir", "mkdir", temp, 0);
378: err("No mkdir", NIL, EX_UNAVAILABLE);
379: /* NOTREACHED */
380: }
381: while((n = wait(&result)) > 0 && n != pid);
382:
383: if(result != 0)
384: warn("Can't make directory", temp, -EX_CANTCREAT);
385: }
386:
387: *q++ = '/';
388: }
389: }
390:
391: terminate()
392: {
393: msginit('x');
394: msgfmt("%d", lasterror);
395: msgsend();
396:
397: return(1);
398: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.