|
|
1.1 root 1: #ifndef lint
2: static char *rcsid = "$Header: xnftp.c,v 2.13 87/05/28 14:17:14 ed Exp $";
3: #endif lint
4:
5: /* $Log: xnftp.c,v $
6: * Revision 2.13 87/05/28 14:17:14 ed
7: * I botched the compiler bug fix...
8: *
9: * Revision 2.12 87/05/14 11:37:34 ed
10: * Raise error from hookup if connection not established.
11: * Better handling of truncated bulk data stream when it overflows buffer.
12: *
13: * Revision 2.11 87/05/11 14:40:12 ed
14: * Incorporated changes from JQ's 4.3e version.
15: *
16: * Revision 2.11 87/03/08 07:09:53 jqj
17: * work around "schain botch" 4.3BSD VAX compiler bug (from Scooter Morris).
18: *
19: * Revision 2.10 87/05/05 14:49:00 ed
20: * Move alarm setting/resetting closer to actual procedure calls.
21: *
22: * Revision 2.9 87/04/16 15:23:47 ed
23: * Fixed lingering bugs in Subset pathname usage.
24: *
25: * Revision 2.8 87/04/01 09:33:36 ed
26: * Changed for new MakeSecondaryCreds call.
27: * Reset connection on login failure.
28: *
29: * Revision 2.7 87/03/27 15:19:19 ed
30: * Don't assume secondary username is primary name.
31: * Additional check for underscore translation on text files.
32: *
33: * Revision 2.6 87/03/23 12:32:12 ed
34: * allow round-trip transfer of Viewpoint files, retain/specify uninterpreted
35: * attributes.
36: * Serialization/Deserialization of directories from server.
37: * Wildcard deletion.
38: * Compatibility with XDE MFileServer.
39: * New commands: Archive, Restore, Unify.
40: *
41: * Revision 2.5 87/01/14 15:59:29 ed
42: * Use FilingSubset, if rejected attempt Filing
43: * Allows user override with -F switch
44: * Maintain FilingSubset mandatory attributes
45: * User niceties: echo file name/type on transfer commands
46: * prompt on delete
47: * guess type which will determine file type implied by content
48: * New commands: (type related) Guess, Whatis
49: * (file transfer) Copy, Move, Rename
50: *
51: * Revision 2.4 86/12/15 11:41:16 jqj
52: * Added support for more ViewPoint file types (no other attributes, though)
53: *
54: * Revision 2.3 86/12/11 06:12:22 jqj
55: * Eliminated form, mode, and struct commands. Started adding support for
56: * more file types.
57: *
58: * Revision 2.2 86/09/07 07:43:40 jqj
59: * Cope with failure return from CourierOpen.
60: *
61: * Revision 2.1 86/06/30 12:19:39 jqj
62: * convert to Authentication v. 2 for compatibility with official spec.
63: *
64: * Revision 2.0 85/11/21 07:22:51 jqj
65: * 4.3BSD standard release
66: *
67: * Revision 1.5 85/09/24 14:45:10 jqj
68: * fix bug in alarm() handling that caused aborts during large file transfers.
69: *
70: * Revision 1.4 85/09/17 07:49:47 jqj
71: * 4.3 changes. Use more routines from CHlookup
72: *
73: * Revision 1.1 85/05/27 06:31:07 jqj
74: * Initial revision
75: *
76: */
77:
78: #include <stdio.h>
79: #include <ctype.h>
80: #include <sys/time.h>
81: #include <sys/param.h>
82: #include <sys/stat.h>
83: #include <netns/ns.h>
84: #include <netns/sp.h>
85: #include "ftp_var.h"
86: #include <xnscourier/Filing4.h>
87: #include <xnscourier/except.h>
88: #undef __Clearinghouse2 /* Filing4.h defs this */
89: #include <xnscourier/CH.h>
90:
91: #define XNS_TIME_DIFFERENCE 2177452800 /* [(1970-1901) years * 365 days/year + 17 leap days */
92: /* * 24 hours/day * 60 minutes/hour * 60 seconds/minute */
93: #define ROOT_DIRECTORY "/"
94: #define MAXNAMES 10
95:
96: CourierConnection *connected;
97: Clearinghouse3_ObjectName hostobjname;
98: Authentication3_Verifier verifier;
99:
100: /* the following 3 items make up the current session */
101: FilingSubset1_Session session; /* the current session */
102: Clearinghouse3_ObjectName username;
103: int continuetime;
104: int remoteprocpending;
105: FilingSubset1_Handle rootHandle;
106: char cur_dir[512]= 0;
107: char cur_pathname[512]= 0;
108: char cur_name[512]= 0;
109:
110: struct name_entry {
111: char *pathname;
112: LongCardinal type;
113: } ;
114:
115: static struct name_entry *name_list= 0;
116: static int name_count= 0;
117: static int name_size= 0;
118:
119: static FilingSubset1_ControlSequence nullControls = {0,0};
120: static FilingSubset1_ScopeSequence nullScope = {0,0};
121:
122: /* global data used to communicate with BDT procedures
123: */
124: extern GetAttributeSequences(),
125: GetAllAttributes(),
126: listproc(), nlistproc(),
127: storeproc(), retrieveproc(),
128: rlistproc(), mkdirproc(),
129: cdproc(), isdirproc(), deleteproc();
130:
131: char *malloc();
132: char *AttrToString();
133: Boolean AttrToBoolean();
134: LongCardinal AttrToLongCardinal();
135: Cardinal AttrToCardinal();
136: char *typetostring();
137:
138: static (*ProcEachSeq)();
139: static long bytessent;
140: static FILE *fout, *fin;
141:
142: LongCardinal filetypevalue; /* real transfer type */
143:
144: struct timeval timbuf[2];
145: Boolean is_a_directory= FALSE;
146: Boolean files_found= FALSE;
147: Boolean filing_subset= TRUE;
148: Boolean isdir= FALSE;
149:
150: copyhandle(dest,src)
151: FilingSubset1_Handle dest,src;
152: {
153: if (dest == (Unspecified *) 0) {
154: fprintf(stderr,"Oops. dest is null in copyhandle\n");
155: exit(1);
156: }
157: dest[0] = src[0];
158: dest[1] = src[1];
159: }
160:
161: getfilehandle(filename, handle)
162: char *filename;
163: FilingSubset1_Handle handle;
164: {
165: FilingSubset1_Attribute pathattr[1];
166: FilingSubset1_AttributeSequence attrseq;
167: FilingSubset1_OpenResults openresult;
168: Filing4_OpenResults openresult2;
169:
170: if (filename == (char *)0 || *filename == '\000' || (strcmp(filename, "/") == 0) ) {
171: if ( filing_subset )
172: copyhandle(handle,FilingSubset1_nullHandle);
173: else
174: copyhandle(handle,rootHandle);
175: return;
176: }
177:
178: attrseq.length = 1;
179: attrseq.sequence = pathattr;
180: pathattr[0].type = FilingSubset1_pathname;
181: copyhandle(handle, FilingSubset1_nullHandle);
182: #ifdef XEROXFSCOMPATIBILITY
183: if ( filename[0] == '/')
184: StringToAttr(filename+1, &pathattr[0]);
185: else
186: StringToAttr(filename, &pathattr[0]);
187: #else XEROXFSCOMPATIBILITY
188: StringToAttr(filename, &pathattr[0]);
189: #endif XEROXFSCOMPATIBILITY
190: alarm(0);
191: if ( filing_subset ) {
192: openresult = FilingSubset1_Open(connected, NULL, attrseq,
193: handle, nullControls,
194: session);
195: copyhandle(handle, openresult.file);
196: } else {
197: openresult2 = Filing4_Open(connected, NULL, attrseq,
198: handle, nullControls,
199: session);
200: copyhandle(handle, openresult2.file);
201: }
202: alarm(continuetime);
203: }
204:
205: getdirhandle(filename, handle)
206: char *filename;
207: FilingSubset1_Handle handle;
208: {
209: FilingSubset1_Attribute pathattr[1];
210: FilingSubset1_AttributeSequence attrseq;
211: FilingSubset1_OpenResults openresult;
212: Filing4_OpenResults openresult2;
213: char *rindex();
214: char *slash, *bang;
215:
216: if (filename == (char *)0 || *filename == '\000' || (strcmp(filename, "/") == 0) ) {
217: strcpy(cur_pathname, "/");
218: strcpy(cur_name, "/");
219: if ( filing_subset )
220: copyhandle(handle,FilingSubset1_nullHandle);
221: else
222: copyhandle(handle,rootHandle);
223: return;
224: } else if ( filename[0] == '/' ) {
225: strcpy(cur_pathname, filename);
226: } else {
227: strcpy(cur_pathname, cur_dir);
228: if ( strcmp(cur_pathname, "/") != 0 )
229: strcat(cur_pathname, "/");
230: strcat(cur_pathname, filename);
231: }
232:
233: if ( (slash= rindex(cur_pathname,'/')) == NULL )
234: strcpy(cur_name, cur_pathname);
235: else
236: strcpy(cur_name, slash+1);
237:
238: if ( (bang= rindex(cur_name, '!')) != NULL )
239: *bang= '\0';
240:
241: if ( filing_subset ) {
242: copyhandle(handle, FilingSubset1_nullHandle);
243: } else {
244: if ( slash == cur_pathname) {
245: copyhandle(handle, rootHandle);
246: return;
247: }
248:
249: attrseq.length = 1;
250: attrseq.sequence = pathattr;
251: pathattr[0].type = FilingSubset1_pathname;
252: copyhandle(handle, FilingSubset1_nullHandle);
253: *slash= '\0'; /* separate pathname from name */
254: #ifdef XEROXFSCOMPATIBILITY
255: if ( cur_pathname[0] == '/' )
256: StringToAttr(cur_pathname+1, &pathattr[0]);
257: else
258: StringToAttr(cur_pathname, &pathattr[0]);
259: #else XEROXFSCOMPATIBILITY
260: StringToAttr(cur_pathname, &pathattr[0]);
261: #endif XEROXFSCOMPATIBILITY
262: *slash= '/'; /* and put back */
263: alarm(0);
264: if ( filing_subset ) {
265: openresult = FilingSubset1_Open(connected, NULL, attrseq,
266: handle, nullControls,
267: session);
268: copyhandle(handle, openresult.file);
269: } else {
270: openresult2 = Filing4_Open(connected, NULL, attrseq,
271: handle, nullControls,
272: session);
273: copyhandle(handle, openresult2.file);
274: }
275: alarm(continuetime);
276: }
277: }
278:
279: freefilehandle(handle)
280: FilingSubset1_Handle handle;
281: {
282: if (handle[0] == FilingSubset1_nullHandle[0] &&
283: handle[1] == FilingSubset1_nullHandle[1])
284: return; /* don't free nullHandle */
285: if (handle[0] == rootHandle[0] &&
286: handle[1] == rootHandle[1])
287: return; /* don't free root directory */
288: alarm(0);
289: if ( filing_subset )
290: FilingSubset1_Close(connected, NULL, handle, session);
291: else
292: Filing4_Close(connected, NULL, handle, session);
293: alarm(continuetime);
294: }
295:
296: /*
297: * do a continue to make sure that the session doesn't time out.
298: * Note that this is usually called by an ALARM interrupt
299: */
300: probe()
301: {
302: FilingSubset1_ContinueResults cresult;
303: Filing4_ContinueResults cresult2;
304: alarm(0); /* cancel previous alarms */
305: if ( filing_subset ) {
306: cresult = FilingSubset1_Continue(connected, NULL, session);
307: continuetime = cresult.continuance / 5; /* seconds */
308: } else {
309: cresult2 = Filing4_Continue(connected, NULL, session);
310: continuetime = cresult2.continuance / 5; /* seconds */
311: }
312: alarm(continuetime); /* reset for another 2 min. or so */
313: }
314:
315: CourierConnection *
316: hookup(name)
317: char *name;
318: {
319: register struct ns_addr *hostaddr;
320: extern struct ns_addr *getXNSaddr();
321: Clearinghouse3_ObjectName defaultobjname;
322: static char hnamebuf[128];
323: CourierConnection *cconn;
324:
325: CH_NameDefault(&defaultobjname);
326: hostobjname = CH_StringToName(name, &defaultobjname);
327: if ((hostaddr = CH_LookupAddrDN( hostobjname, 0, hnamebuf, 128))) {
328: /* should check here to be sure host is a file service */
329: hostaddr->x_port = htons(5); /* ?? */
330: cconn = CourierOpen(hostaddr);
331: if ( cconn == (CourierConnection *) 0 ) {
332: Cardinal problem;
333: problem= FilingSubset1_noResponse;
334: raise(FilingSubset1_ConnectionError, &problem);
335: }
336: /* reset objname to flush wildcards */
337: /* clear_Clearinghouse3_ThreePartName(&hostobjname); */
338: hostobjname = CH_StringToName(hnamebuf, &defaultobjname);
339: hostname = hnamebuf;
340: if (verbose)
341: printf("Connected to %s\n", hnamebuf);
342: } else {
343: printf("%s: unknown host\n", name);
344: usefiling= 0;
345: cconn = (CourierConnection*)0;
346: }
347: return(cconn);
348: }
349:
350:
351: login(name,pwd)
352: char *pwd;
353: char *name;
354: {
355: FilingSubset1_Credentials credentials;
356: FilingSubset1_LogonResults logonresult;
357: FilingSubset1_LogonResults *resultptr= &logonresult;
358: Filing4_LogonResults logonresult2;
359: FilingSubset1_AttributeSequence attrseq;
360: FilingSubset1_OpenResults openresult;
361: Filing4_OpenResults openresult2;
362:
363:
364: if ( name != 0 )
365: username = CH_StringToName(name,&hostobjname);
366:
367: if ( usefiling ) {
368: usefiling= 0;
369: filing_subset= FALSE;
370: if ( name == 0 && pwd == 0 ) {
371: GetSimpleCredsAndVerifier(&username, 0,
372: &credentials.primary, &verifier);
373: } else {
374: MakeSimpleCredsAndVerifier(&username,pwd,
375: &credentials.primary, &verifier);
376: }
377: logonresult2= Filing4_Logon(connected, NULL, hostobjname,
378: credentials.primary, verifier);
379: resultptr= (FilingSubset1_LogonResults *) &logonresult2;
380:
381: } else {
382: usefiling= 0;
383: if ( name == 0 && pwd == 0 ) {
384: GetSimpleCredsAndVerifier(&username, 0, &credentials.primary, &verifier);
385: MakeSecondaryCreds(hostobjname.object, 0, 0, &credentials.secondary);
386: } else {
387: MakeSimpleCredsAndVerifier(0, pwd, &credentials.primary, &verifier);
388: MakeSecondaryCreds(hostobjname.object, name, pwd, &credentials.secondary);
389: }
390: filing_subset= TRUE;
391: DURING
392: logonresult = FilingSubset1_Logon(connected, NULL, hostobjname,
393: credentials, verifier);
394: HANDLER {
395: switch (Exception.Code) {
396: case REJECT_ERROR:
397: filing_subset= FALSE;
398: logonresult2= Filing4_Logon(connected, NULL, hostobjname,
399: credentials.primary, verifier);
400: resultptr= (FilingSubset1_LogonResults *) &logonresult2;
401: break;
402: default:
403: connected= (CourierConnection *)0; /* reset */
404: RERAISE;
405: }
406: } END_HANDLER;
407: }
408:
409: if ( filing_subset )
410: session = resultptr->session;
411: else
412: session = resultptr->session;
413: if (verbose)
414: printf("User %s:%s:%s logged on\n", username.object,
415: username.domain, username.organization);
416:
417: attrseq.length= 0;
418: attrseq.sequence= 0;
419: if ( filing_subset ) {
420: openresult= FilingSubset1_Open(connected, NULL, attrseq,
421: FilingSubset1_nullHandle, nullControls,
422: session);
423: copyhandle(rootHandle, openresult.file);
424: } else {
425: openresult2= Filing4_Open(connected, NULL, attrseq,
426: FilingSubset1_nullHandle, nullControls,
427: session);
428: copyhandle(rootHandle, openresult2.file);
429: }
430: strcpy(cur_dir, ROOT_DIRECTORY);
431: alarm(0);
432: signal(SIGALRM, probe);
433: probe();
434: }
435:
436: logout()
437: {
438: signal(SIGALRM, SIG_IGN);
439: if ( filing_subset )
440: FilingSubset1_Logoff(connected, NULL, session);
441: else
442: Filing4_Logoff(connected, NULL, session);
443: clear_FilingSubset1_Session(&session);
444: }
445:
446: domakedir(dest)
447: char *dest;
448: {
449: struct timeval start, stop, time;
450: FilingSubset1_StoreResults storeresults;
451: Filing4_StoreResults storeresults2;
452: FilingSubset1_Handle dirhandle;
453: FilingSubset1_AttributeSequence attrseq;
454: FilingSubset1_Attribute attrvals[5];
455:
456: gettimeofday(&time, (struct timezone *) 0);
457:
458: if (dest) {
459: getdirhandle(dest, dirhandle);
460: } else {
461: printf("No remote name specified\n");
462: return;
463: }
464:
465: bytessent= 0;
466: alarm(0);
467:
468: attrseq.length= 3;
469: attrseq.sequence= attrvals;
470:
471: if ( filing_subset ) {
472: attrvals[0].type= FilingSubset1_pathname;
473: StringToAttr(cur_pathname, &attrvals[0]);
474: } else {
475: attrvals[0].type= FilingSubset1_name;
476: StringToAttr(cur_name, &attrvals[0]);
477: }
478: attrvals[1].type = FilingSubset1_isDirectory;
479: BooleanToAttr(TRUE, &attrvals[1]);
480: attrvals[2].type = FilingSubset1_type;
481: LongCardinalToAttr(FilingSubset1_tDirectory, &attrvals[2]);
482: gettimeofday(&start, (struct timezone *)0);
483: if ( filing_subset )
484: storeresults = FilingSubset1_Store(connected, BDTclosewrite,
485: dirhandle, attrseq,
486: nullControls,
487: BulkData1_immediateSource, session);
488: else
489: storeresults2 = Filing4_Store(connected, BDTclosewrite,
490: dirhandle, attrseq,
491: nullControls,
492: BulkData1_immediateSource, session);
493: alarm(continuetime);
494: gettimeofday(&stop, (struct timezone *)0);
495: if ( filing_subset )
496: freefilehandle(storeresults.file);
497: else
498: freefilehandle(storeresults2.file);
499:
500: freefilehandle(dirhandle);
501: }
502:
503: doremovedir(src)
504: char *src;
505: {
506: dodelete(src);
507: }
508:
509: dostore(src, dest)
510: char *src, *dest;
511: {
512: sendrequest("STOR", src, dest);
513: }
514:
515: doappend(src, dest)
516: char *src, *dest;
517: {
518: NYI();
519: }
520:
521: dorename(src, dest)
522: char *src, *dest;
523: {
524: Filing4_Handle srchandle, dirhandle;
525: Filing4_AttributeSequence attrseq;
526: Filing4_Attribute attrvals[1];
527:
528: if ( filing_subset ) {
529: NotAvailableUnderSubset("Rename function not available");
530: return;
531: }
532:
533: if ( index(dest, '/') != 0 ) { /* rename across directory */
534: docopy("MOVE", src, dest); /* use move */
535: return;
536: }
537:
538: getdirhandle(src, dirhandle);
539: getfilehandle(cur_pathname, srchandle);
540:
541: attrseq.length= 1;
542: attrseq.sequence= attrvals;
543:
544: attrvals[0].type= Filing4_name;
545: StringToAttr(dest, &attrvals[0]);
546:
547: if (verbose) {
548: printf("renaming %s to %s...\n", src, dest);
549: }
550:
551: alarm(0);
552: Filing4_ChangeAttributes(connected, NULL, srchandle, attrseq, session);
553: alarm(continuetime);
554:
555: freefilehandle(srchandle);
556: freefilehandle(dirhandle);
557: }
558:
559: docopy(cmd, src, dest)
560: char *cmd, *src, *dest;
561: {
562: Filing4_Handle srchandle, srcdirhandle, dirhandle, newhandle;
563: Filing4_AttributeSequence attrseq;
564: Filing4_Attribute attrvals[1];
565: Filing4_AttributeTypeSequence typeseq;
566: Filing4_AttributeType attrs[2];
567: Filing4_ScopeSequence scopeseq;
568: Filing4_Scope scope;
569: Filing4_CopyResults copyresults;
570: Boolean copy= FALSE;
571:
572: if ( filing_subset ) {
573: NotAvailableUnderSubset("Copy/Move function not available");
574: return;
575: }
576:
577: if ( strcmp(cmd, "COPY") == 0 )
578: copy= TRUE;
579:
580: getdirhandle(src, srcdirhandle);
581: getfilehandle(cur_pathname, srchandle);
582: freefilehandle(srcdirhandle);
583:
584: getdirhandle(dest, dirhandle);
585:
586: typeseq.length= 2; typeseq.sequence= attrs;
587: attrs[0]= Filing4_isDirectory;
588: attrs[1]= Filing4_pathname;
589:
590: scopeseq.length= 1; scopeseq.sequence= &scope;
591: scope.designator= Filing4_filter;
592: scope.Filing4_filter_case.designator= Filing4_matches;
593: scope.Filing4_filter_case.Filing4_matches_case.attribute.type= Filing4_name;
594: StringToAttr(cur_name, &scope.Filing4_filter_case.Filing4_matches_case.attribute);
595: ProcEachSeq= isdirproc;
596: isdir= FALSE;
597:
598: alarm(0);
599: Filing4_List(connected, GetAttributeSequences, dirhandle, typeseq,
600: scopeseq, BulkData1_immediateSink, session);
601: alarm(continuetime);
602:
603: if ( isdir ) {
604: getfilehandle(cur_pathname, dirhandle); /* open directory as file */
605:
606: attrseq.length= 0;
607: attrseq.sequence= attrvals;
608: } else {
609: attrseq.length= 1;
610: attrseq.sequence= attrvals;
611:
612: attrvals[0].type= Filing4_name;
613: StringToAttr(cur_name, &attrvals[0]);
614: }
615:
616: if (verbose) {
617: if ( copy )
618: printf("copying ");
619: else
620: printf("moving ");
621: printf("%s to %s%s%s...\n", src, dest, (isdir ? "/" : ""),
622: (isdir ? src : ""));
623: }
624:
625: alarm(0);
626: if ( copy ) {
627: copyresults= Filing4_Copy(connected, NULL, srchandle, dirhandle,
628: attrseq, nullControls, session);
629:
630: freefilehandle(copyresults.newFile);
631: } else {
632: Filing4_Move(connected, NULL, srchandle, dirhandle,
633: attrseq, session);
634: }
635: alarm(continuetime);
636:
637: freefilehandle(srchandle);
638: freefilehandle(dirhandle);
639: }
640:
641: dounify(remote)
642: char *remote;
643: {
644: Filing4_Handle dirhandle, remotehandle;
645:
646: if ( filing_subset ) {
647: NotAvailableUnderSubset("Unify AccessLists");
648: return;
649: }
650:
651: getdirhandle(remote, dirhandle);
652: getfilehandle(cur_pathname, remotehandle);
653: freefilehandle(dirhandle);
654:
655: if ( verbose ) {
656: printf("unify access lists for %s\n", remote);
657: }
658:
659: alarm(0);
660: Filing4_UnifyAccessLists(connected, NULL, remotehandle, session);
661: alarm(continuetime);
662:
663: freefilehandle(remotehandle);
664:
665: }
666: recvrequest(cmd, local, remote, mode)
667: char *cmd, *local, *remote, *mode;
668: {
669: FILE *popen();
670: int (*closefunc)(), pclose(), fclose();
671: int do_unlink= FALSE;
672: int pos, i;
673: struct timeval start, stop;
674: FilingSubset1_Handle remotehandle; /* note: an array */
675: FilingSubset1_Handle dirhandle; /* note: an array */
676: FilingSubset1_AttributeTypeSequence typeseq;
677: FilingSubset1_AttributeType tsvals[10];
678: char *dir;
679: FilingSubset1_ScopeSequence scopeseq;
680: FilingSubset1_Scope scope;
681:
682: closefunc = NULL;
683:
684: fout = stdout;
685: typeseq.length = 0; typeseq.sequence = tsvals;
686: scopeseq.length= 1; scopeseq.sequence= &scope;
687: scope.designator= FilingSubset1_filter;
688: scope.FilingSubset1_filter_case.designator= FilingSubset1_matches;
689: if ( filing_subset )
690: scope.FilingSubset1_filter_case.FilingSubset1_matches_case.attribute.type= FilingSubset1_pathname;
691: else
692: scope.FilingSubset1_filter_case.FilingSubset1_matches_case.attribute.type= FilingSubset1_name;
693: timbuf[0].tv_sec= 0;
694:
695: copyhandle(remotehandle, FilingSubset1_nullHandle);
696:
697: if (strcmp(local, "-") && *local != '|')
698: if (access(local, 2) < 0) {
699: dir = rindex(local, '/');
700: /* get a good error message */
701: if (dir != NULL) *dir = '\0';
702: if (access(dir ? local : ".", 2) < 0) {
703: perror(local);
704: goto bad;
705: }
706: if (dir != NULL) *dir = '/';
707: }
708: if (strcmp(local, "-") == 0)
709: fout = stdout;
710: else if (*local == '|') {
711: char *ptr;
712: ptr= local+1;
713: while (isspace(*ptr)) ptr++;
714: fout = popen(ptr, "w");
715: if (fout == NULL) {
716: perror(ptr);
717: goto bad;
718: }
719: closefunc = pclose;
720: } else {
721: fout = fopen(local, mode);
722: if (fout == NULL) {
723: perror(local);
724: goto bad;
725: }
726: closefunc = fclose;
727: }
728:
729: if (remote) {
730: getdirhandle(remote, dirhandle);
731: }
732: bytessent= 0;
733: filetypevalue= typevalue;
734:
735: if ( filing_subset )
736: StringToAttr(cur_pathname+1,&scope.FilingSubset1_filter_case.FilingSubset1_matches_case.attribute);
737: else
738: StringToAttr(cur_name,&scope.FilingSubset1_filter_case.FilingSubset1_matches_case.attribute);
739:
740: if (strcmp(cmd,"NLST") == 0) {
741: typeseq.length = 1;
742: typeseq.sequence[0] = FilingSubset1_pathname;
743: ProcEachSeq = nlistproc;
744: alarm(0);
745: gettimeofday(&start, (struct timezone *)0);
746: if ( filing_subset )
747: FilingSubset1_List(connected, GetAttributeSequences, dirhandle,
748: typeseq, scopeseq,
749: BulkData1_immediateSink, session);
750: else
751: Filing4_List(connected, GetAttributeSequences, dirhandle,
752: typeseq, scopeseq,
753: BulkData1_immediateSink, session);
754: alarm(continuetime);
755: }
756: else if (strcmp(cmd,"LIST") == 0) {
757: typeseq.length = 7;
758: if ( filing_subset )
759: typeseq.sequence[0] = FilingSubset1_pathname;
760: else
761: typeseq.sequence[0] = FilingSubset1_name;
762: typeseq.sequence[1] = FilingSubset1_dataSize;
763: typeseq.sequence[2] = FilingSubset1_isDirectory;
764: typeseq.sequence[3] = FilingSubset1_isTemporary;
765: typeseq.sequence[4] = FilingSubset1_type;
766: typeseq.sequence[5] = FilingSubset1_createdOn;
767: typeseq.sequence[6] = FilingSubset1_version;
768: ProcEachSeq = listproc;
769: alarm(0);
770: gettimeofday(&start, (struct timezone *)0);
771: if ( filing_subset )
772: FilingSubset1_List(connected, GetAttributeSequences, dirhandle,
773: typeseq, scopeseq,
774: BulkData1_immediateSink, session);
775: else
776: Filing4_List(connected, GetAttributeSequences, dirhandle,
777: typeseq, scopeseq,
778: BulkData1_immediateSink, session);
779: alarm(continuetime);
780: }
781: else if (strcmp(cmd,"RETR") == 0) {
782: typeseq.length= 4;
783: typeseq.sequence[0]= FilingSubset1_createdOn;
784: typeseq.sequence[1]= FilingSubset1_pathname;
785: typeseq.sequence[2]= FilingSubset1_type;
786: typeseq.sequence[3]= FilingSubset1_isDirectory;
787:
788: is_a_directory= FALSE;
789: ProcEachSeq= rlistproc;
790:
791: alarm(0);
792: if ( filing_subset )
793: FilingSubset1_List(connected, GetAttributeSequences, dirhandle,
794: typeseq, scopeseq,
795: BulkData1_immediateSink, session);
796: else
797: Filing4_List(connected, GetAttributeSequences, dirhandle,
798: typeseq, scopeseq,
799: BulkData1_immediateSink, session);
800:
801: alarm(continuetime);
802:
803: if ( files_found ) {
804: if ( is_a_directory && (filetypevalue == FilingSubset1_tDirectory) ) {
805: if ( filing_subset ) {
806: NotAvailableUnderSubset("Cannot retrieve directory files");
807: do_unlink= TRUE;
808: goto error;
809: }
810: }
811:
812: if (verbose) {
813: printf("%s...(%s)...", local, typetostring(filetypevalue));
814: fflush(stdout);
815: }
816:
817: if ( (filetypevalue == FilingSubset1_tDirectory) ||
818: ((filetypevalue > LAST_FILING_TYPE) &&
819: (filetypevalue != TYPE_Interpress) &&
820: (filetypevalue != TYPE_VPCanvas)) ) {
821: if ( filing_subset ) {
822: NotAvailableUnderSubset("Cannot retrieve Viewpoint files");
823: do_unlink= TRUE;
824: goto error;
825: }
826:
827: alarm(0);
828: ProcEachSeq= GetAllAttributes;
829: Filing4_List(connected, GetAttributeSequences, dirhandle,
830: Filing4_allAttributeTypes, scopeseq,
831: BulkData1_immediateSink, session);
832: alarm(continuetime);
833: }
834:
835: bytessent= 0;
836: getfilehandle(cur_pathname, remotehandle); /* get file handle */
837: alarm(0);
838: gettimeofday(&start, (struct timezone *)0);
839: if ( filing_subset ) {
840: FilingSubset1_Retrieve(connected, retrieveproc, remotehandle,
841: BulkData1_immediateSink, session);
842: } else {
843: if ( is_a_directory )
844: Filing4_Serialize(connected, retrieveproc, remotehandle,
845: BulkData1_immediateSink, session);
846: else
847: Filing4_Retrieve(connected, retrieveproc, remotehandle,
848: BulkData1_immediateSink, session);
849: }
850: alarm(continuetime);
851: }
852: } else if (strcmp(cmd,"SER") == 0) {
853: ProcEachSeq= GetAllAttributes;
854:
855: alarm(0);
856: if ( filing_subset ) {
857: NotAvailableUnderSubset("Cannot serialize files");
858: do_unlink= TRUE;
859: goto error;
860: } else {
861: Filing4_List(connected, GetAttributeSequences, dirhandle,
862: Filing4_allAttributeTypes, scopeseq,
863: BulkData1_immediateSink, session);
864: }
865: alarm(continuetime);
866:
867: if ( files_found ) {
868: if (verbose) {
869: printf("%s to %s...(%s)...",cur_pathname, local, typetostring(filetypevalue));
870: fflush(stdout);
871: }
872:
873: bytessent= 0;
874: getfilehandle(cur_pathname, remotehandle); /* get file handle */
875: alarm(0);
876: gettimeofday(&start, (struct timezone *)0);
877: Filing4_Serialize(connected, retrieveproc, remotehandle,
878: BulkData1_immediateSink, session);
879: alarm(continuetime);
880: }
881: }
882: else printf("unrecognized command %s\n",cmd);
883: gettimeofday(&stop, (struct timezone *)0);
884: freefilehandle(remotehandle);
885:
886: if ( files_found ) {
887: if (bytessent > 0 && verbose)
888: ptransfer("received", bytessent, &start, &stop);
889: } else {
890: printf("%s not found\n",cur_pathname);
891: do_unlink= TRUE;
892: }
893:
894: error:
895: freefilehandle(dirhandle);
896:
897: bad:
898: if (closefunc != NULL && fout != NULL) {
899: (*closefunc)(fout);
900: if ( closefunc == fclose ) {
901: if (timbuf[0].tv_sec != 0 )
902: utimes(local,&timbuf[0]);
903: }
904: }
905: if ( do_unlink )
906: unlink(local);
907:
908: fout = NULL;
909: }
910:
911:
912: sendrequest(cmd, local, remote)
913: char *cmd, *local, *remote;
914: {
915: FILE *popen();
916: int (*closefunc)(), pclose(), fclose();
917: struct stat st;
918: struct timeval start, stop;
919: FilingSubset1_StoreResults storeresults;
920: Filing4_DeserializeResults deserializeresults;
921: Filing4_StoreResults storeresults2;
922: FilingSubset1_Handle dirhandle;
923: FilingSubset1_AttributeSequence attrseq;
924: FilingSubset1_Attribute attrvals[50];
925: Boolean GetDirectoryAttribute();
926: struct timeval time;
927: long createdate;
928: long datasize;
929:
930: gettimeofday(&time,(struct timezone *) 0);
931: createdate= time.tv_sec + XNS_TIME_DIFFERENCE;
932: filetypevalue= typevalue;
933:
934: closefunc = NULL;
935: if (strcmp(local, "-") == 0) {
936: fin = stdin;
937: closefunc = NULL;
938: } else if (*local == '|') {
939: char *ptr;
940: ptr= local+1;
941: while (isspace(*ptr)) ptr++;
942: fin = popen(ptr, "r");
943: if (fin == NULL) {
944: perror(ptr);
945: return;
946: }
947: closefunc = pclose;
948: } else {
949: if (typevalue == TYPE_Guess) {
950: filetypevalue= get_type(local); /* guess file type */
951: }
952: fin = fopen(local, "r");
953: if (fin == NULL) {
954: perror(local);
955: return;
956: }
957: closefunc = fclose;
958: if (fstat(fileno(fin), &st) < 0 ||
959: (st.st_mode&S_IFMT) != S_IFREG) {
960: fprintf(stderr, "%s: not a plain file.", local);
961: fclose(fin);
962: fin= NULL;
963: return;
964: }
965: createdate= st.st_mtime + XNS_TIME_DIFFERENCE;
966: datasize= st.st_size;
967: }
968:
969: if (filetypevalue == TYPE_Guess) /* if input from file, TYPE_G should already be replaced */
970: filetypevalue= TYPE_A; /* assume ascii for pipes/stdin... */
971:
972: if (remote) {
973: getdirhandle(remote, dirhandle);
974: } else {
975: printf("No remote name specified\n");
976: return;
977: }
978: bytessent = 0;
979: if (strcmp(cmd,"STOR") == 0) {
980: if (verbose) {
981: printf("%s to %s...",local,remote);
982: fflush(stdout);
983: }
984: attrseq.length = 1;
985: attrseq.sequence = attrvals;
986: if ( filing_subset ) {
987: attrvals[0].type = FilingSubset1_pathname;
988: StringToAttr(cur_pathname, &attrvals[0]);
989: } else {
990: attrvals[0].type = FilingSubset1_name;
991: StringToAttr(cur_name, &attrvals[0]);
992: }
993:
994: if ( (filetypevalue == TYPE_Directory) ||
995: ((filetypevalue > LAST_FILING_TYPE) &&
996: (filetypevalue != TYPE_Interpress) &&
997: (filetypevalue != TYPE_VPCanvas)) ) {
998: isdir= GetDirectoryAttribute(fin);
999: } else {
1000: isdir= FALSE;
1001: }
1002:
1003: if ( !isdir ) {
1004: attrseq.length += 4;
1005: attrvals[1].type = FilingSubset1_type;
1006: LongCardinalToAttr(filetypevalue, &attrvals[1]);
1007: attrvals[2].type = FilingSubset1_createdOn;
1008: LongCardinalToAttr(createdate,&attrvals[2]);
1009: attrvals[3].type= FilingSubset1_isDirectory;
1010: BooleanToAttr(FALSE, &attrvals[3]);
1011: attrvals[4].type= FilingSubset1_dataSize;
1012: LongCardinalToAttr(datasize, &attrvals[4]);
1013: }
1014:
1015: if (verbose) {
1016: printf("(%s)...", typetostring(filetypevalue));
1017: fflush(stdout);
1018: }
1019:
1020: if ( (filetypevalue == TYPE_Directory) ||
1021: ((filetypevalue > LAST_FILING_TYPE) &&
1022: (filetypevalue != TYPE_Interpress) &&
1023: (filetypevalue != TYPE_VPCanvas)) ) {
1024: if ( filing_subset ) {
1025: NotAvailableUnderSubset("Cannot store Viewpoint files");
1026: goto error;
1027: }
1028: if ( isdir ) {
1029: if ( AddExtendedDeserializeAttributes(fin, &attrseq) == 0 ) {
1030: goto error;
1031: }
1032: } else {
1033: if ( AddExtendedStoreAttributes(fin, &attrseq) == 0 ) {
1034: goto error;
1035: }
1036: }
1037: }
1038:
1039: alarm(0);
1040: gettimeofday(&start, (struct timezone *)0);
1041: if ( filing_subset ) {
1042: storeresults = FilingSubset1_Store(connected, storeproc,
1043: dirhandle, attrseq,
1044: nullControls,
1045: BulkData1_immediateSource,
1046: session);
1047: } else {
1048: if ( isdir )
1049: deserializeresults = Filing4_Deserialize(connected, storeproc,
1050: dirhandle, attrseq,
1051: nullControls,
1052: BulkData1_immediateSource,
1053: session);
1054: else
1055: storeresults2 = Filing4_Store(connected, storeproc,
1056: dirhandle, attrseq,
1057: nullControls,
1058: BulkData1_immediateSource,
1059: session);
1060: }
1061: alarm(continuetime);
1062: gettimeofday(&stop, (struct timezone *)0);
1063: if ( filing_subset ) {
1064: freefilehandle(storeresults.file);
1065: } else {
1066: if ( isdir )
1067: freefilehandle(deserializeresults.file);
1068: else
1069: freefilehandle(storeresults2.file);
1070: }
1071: } else if (strcmp(cmd,"DSER") == 0) {
1072: if ( filing_subset ) {
1073: NotAvailableUnderSubset("Cannot Deserialize files");
1074: goto error;
1075: }
1076: if (verbose) {
1077: printf("%s to %s...",local,remote);
1078: fflush(stdout);
1079: }
1080: attrseq.length = 1;
1081: attrseq.sequence = attrvals;
1082: attrvals[0].type = FilingSubset1_name;
1083: StringToAttr(cur_name, &attrvals[0]);
1084:
1085: if (verbose) {
1086: printf("(%s)...", typetostring(filetypevalue));
1087: fflush(stdout);
1088: }
1089:
1090: if ( AddExtendedDeserializeAttributes(fin, &attrseq) == 0 ) {
1091: goto error;
1092: }
1093:
1094: alarm(0);
1095: gettimeofday(&start, (struct timezone *)0);
1096: deserializeresults = Filing4_Deserialize(connected, storeproc,
1097: dirhandle, attrseq, nullControls,
1098: BulkData1_immediateSource, session);
1099: alarm(continuetime);
1100: gettimeofday(&stop, (struct timezone *)0);
1101: freefilehandle(deserializeresults.file);
1102: }
1103: else {
1104: printf("unrecognized command %s\n",cmd);
1105: alarm(continuetime);
1106: }
1107: if (bytessent > 0 && verbose)
1108: ptransfer("sent", bytessent, &start, &stop);
1109: error:
1110: freefilehandle(dirhandle);
1111: if (closefunc != NULL && fin != NULL)
1112: (*closefunc)(fin);
1113: fin = NULL;
1114: }
1115:
1116:
1117:
1118: docd(dest)
1119: char *dest;
1120: {
1121: FilingSubset1_AttributeSequence attrseq;
1122: FilingSubset1_AttributeTypeSequence typeseq;
1123: Boolean current= FALSE;
1124: FilingSubset1_AttributeType cdattrs[2];
1125: FilingSubset1_ScopeSequence scopeseq;
1126: FilingSubset1_Scope scope;
1127: FilingSubset1_Handle remotehandle;
1128:
1129: if (dest == (char*)NULL || *dest == '\0' || (strcmp(dest, "/") == 0) ) {
1130: getdirhandle("/", remotehandle);
1131: strcpy(cur_dir, "/");
1132: dopwd();
1133: return;
1134: } else {
1135: getdirhandle(dest, remotehandle);
1136: }
1137:
1138: isdir= FALSE;
1139:
1140: if ( filing_subset ) {
1141: StringToAttr(cur_pathname+1,&scope.FilingSubset1_filter_case.FilingSubset1_matches_case.attribute);
1142: scope.FilingSubset1_filter_case.FilingSubset1_matches_case.attribute.type= FilingSubset1_pathname;
1143: } else {
1144: StringToAttr(cur_name,&scope.FilingSubset1_filter_case.FilingSubset1_matches_case.attribute);
1145: scope.FilingSubset1_filter_case.FilingSubset1_matches_case.attribute.type= FilingSubset1_name;
1146: }
1147: typeseq.length = 2; typeseq.sequence = cdattrs;
1148: cdattrs[0] = FilingSubset1_isDirectory;
1149: cdattrs[1] = FilingSubset1_pathname;
1150: scopeseq.length= 1; scopeseq.sequence= &scope;
1151: scope.designator= FilingSubset1_filter;
1152: scope.FilingSubset1_filter_case.designator= FilingSubset1_matches;
1153: ProcEachSeq= cdproc;
1154: alarm(0);
1155: if ( filing_subset )
1156: FilingSubset1_List(connected, GetAttributeSequences, remotehandle, typeseq,
1157: scopeseq, BulkData1_immediateSink, session);
1158: else
1159: Filing4_List(connected, GetAttributeSequences, remotehandle, typeseq,
1160: scopeseq, BulkData1_immediateSink, session);
1161:
1162: alarm(continuetime);
1163: freefilehandle(remotehandle);
1164:
1165: if ( files_found == FALSE ) {
1166: printf("%s not found\n", dest);
1167: } else if ( !isdir ) {
1168: printf("%s not a directory\n", dest);
1169: } else {
1170: if ( dest[0] != '/' ) {
1171: if ( strcmp(cur_dir, "/") != 0 )
1172: strcat(cur_dir, "/");
1173: strcat(cur_dir, dest);
1174: } else {
1175: strcpy(cur_dir, dest);
1176: }
1177: if (verbose) dopwd();
1178: }
1179:
1180: }
1181:
1182: dopwd()
1183: {
1184: printf("Remote working directory: %s\n",cur_dir);
1185: }
1186:
1187: dodelete(src)
1188: char *src;
1189: {
1190: int i;
1191: FilingSubset1_Handle remotehandle;
1192: FilingSubset1_Handle dirhandle;
1193: FilingSubset1_AttributeSequence attrseq;
1194: FilingSubset1_AttributeTypeSequence typeseq;
1195: FilingSubset1_AttributeType delattrs[2];
1196: FilingSubset1_ScopeSequence scopeseq;
1197: FilingSubset1_Scope scope;
1198:
1199: typeseq.length = 2; typeseq.sequence= delattrs;
1200: delattrs[0] = FilingSubset1_type;
1201: delattrs[1]= FilingSubset1_pathname;
1202:
1203: scopeseq.length= 1; scopeseq.sequence= &scope;
1204: scope.designator= FilingSubset1_filter;
1205: scope.FilingSubset1_filter_case.designator= FilingSubset1_matches;
1206:
1207: name_count= 0;
1208: name_size= MAXNAMES;
1209: if ( (name_list= (struct name_entry *)malloc(sizeof(struct name_entry) * name_size)) == 0 ) {
1210: perror("dodelete");
1211: return;
1212: }
1213:
1214: getdirhandle(src, dirhandle);
1215:
1216: if ( filing_subset ) {
1217: scope.FilingSubset1_filter_case.FilingSubset1_matches_case.attribute.type= FilingSubset1_pathname;
1218: StringToAttr(cur_pathname+1,&scope.FilingSubset1_filter_case.FilingSubset1_matches_case.attribute);
1219: } else {
1220: scope.FilingSubset1_filter_case.FilingSubset1_matches_case.attribute.type= FilingSubset1_name;
1221: StringToAttr(cur_name,&scope.FilingSubset1_filter_case.FilingSubset1_matches_case.attribute);
1222: }
1223:
1224: ProcEachSeq= deleteproc;
1225: alarm(0);
1226: if ( filing_subset )
1227: FilingSubset1_List(connected, GetAttributeSequences, dirhandle, typeseq,
1228: scopeseq, BulkData1_immediateSink, session);
1229: else
1230: Filing4_List(connected, GetAttributeSequences, dirhandle, typeseq,
1231: scopeseq, BulkData1_immediateSink, session);
1232:
1233: alarm(continuetime);
1234: freefilehandle(dirhandle);
1235:
1236: for ( i= 0 ; i < name_count ; i++ ) {
1237: struct name_entry *entry;
1238:
1239: entry= &name_list[i];
1240: if ( verbose ) {
1241: if ( entry->type == TYPE_Directory ) {
1242: if (!confirm("Delete directory", entry->pathname) ) {
1243: clear_String(&entry->pathname);
1244: continue;
1245: }
1246: } else if ( entry->type == TYPE_VPDrawer ) {
1247: if (!confirm("Delete file drawer", entry->pathname) ) {
1248: clear_String(&entry->pathname);
1249: continue;
1250: }
1251: } else {
1252: if (!confirm("Delete file",entry->pathname) ) {
1253: clear_String(&entry->pathname);
1254: continue;
1255: }
1256: }
1257: }
1258:
1259: getfilehandle(entry->pathname,remotehandle);
1260: alarm(0);
1261: if ( filing_subset )
1262: FilingSubset1_Delete(connected, NULL, remotehandle, session);
1263: else
1264: Filing4_Delete(connected, NULL, remotehandle, session);
1265: alarm(continuetime);
1266:
1267: clear_String(&entry->pathname);
1268: }
1269: }
1270:
1271: NYI()
1272: {
1273: printf("Not yet implemented\n");
1274: }
1275:
1276: NotAvailableUnderSubset(message)
1277: char *message;
1278: {
1279: printf("%s under Subset,\n Reopen connection with -F switch and retry\n", message);
1280: }
1281:
1282: ptransfer(direction, bytes, t0, t1)
1283: char *direction;
1284: long bytes;
1285: struct timeval *t0, *t1;
1286: {
1287: struct timeval td;
1288: long ms;
1289: float bs;
1290:
1291: tvsub(&td, t1, t0);
1292: ms = (td.tv_sec * 1000) + (td.tv_usec / 1000);
1293: #define nz(x) ((x) == 0 ? 1 : (x))
1294: bs = ((1000. * (float) bytes) / (float) nz(ms));
1295: printf("\n%ld bytes %s in %d.%02d seconds (%.2g Kbytes/s)\n",
1296: bytes, direction, td.tv_sec, td.tv_usec / 10000, bs / 1024.);
1297: }
1298:
1299: tvadd(tsum, t0)
1300: struct timeval *tsum, *t0;
1301: {
1302:
1303: tsum->tv_sec += t0->tv_sec;
1304: tsum->tv_usec += t0->tv_usec;
1305: if (tsum->tv_usec > 1000000)
1306: tsum->tv_sec++, tsum->tv_usec -= 1000000;
1307: }
1308:
1309: tvsub(tdiff, t1, t0)
1310: struct timeval *tdiff, *t1, *t0;
1311: {
1312:
1313: tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
1314: tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
1315: if (tdiff->tv_usec < 0)
1316: tdiff->tv_sec--, tdiff->tv_usec += 1000000;
1317: }
1318:
1319: nlistproc(attr)
1320: FilingSubset1_AttributeSequence attr;
1321: {
1322: int i;
1323: char *thisname;
1324: FilingSubset1_AttributeType t;
1325:
1326: files_found= TRUE;
1327:
1328: for (i = 0; i < attr.length; i++) {
1329: t = attr.sequence[i].type;
1330: if (t == FilingSubset1_pathname) {
1331: thisname = AttrToString(&attr.sequence[i]);
1332: #ifdef XEROXFSCOMPATIBILITY
1333: /*
1334: * Xerox File servers don't include beginning /
1335: */
1336: if ( *thisname != '/' )
1337: fputc('/', fout);
1338: #endif XEROXFSCOMPATIIBLITY
1339: fputs(thisname, fout);
1340: fputc('\n', fout);
1341: clear_String(&thisname);
1342: return;
1343: }
1344: }
1345: }
1346:
1347:
1348: listproc(attr)
1349: FilingSubset1_AttributeSequence attr;
1350: {
1351: int i;
1352: char *thisname;
1353: char *slash;
1354: Boolean istemp = 0;
1355: Boolean isdir = 0;
1356: LongCardinal thistype = 0;
1357: LongCardinal thissize = 0;
1358: LongCardinal thisdate = 0;
1359: FilingSubset1_AttributeType t;
1360: char filetypestr[25];
1361: char filetypebuf[20];
1362: Cardinal thisversion = 0;
1363: char *filedatestr;
1364: char *ctime();
1365: char *rindex();
1366:
1367: files_found= TRUE;
1368:
1369: for (i = 0; i < attr.length; i++) {
1370: t = attr.sequence[i].type;
1371: if (t == FilingSubset1_name || t == FilingSubset1_pathname)
1372: thisname = AttrToString(&attr.sequence[i]);
1373: else if (t == FilingSubset1_isDirectory)
1374: isdir = AttrToBoolean(&attr.sequence[i]);
1375: else if (t == FilingSubset1_isTemporary)
1376: istemp = AttrToBoolean(&attr.sequence[i]);
1377: else if (t == FilingSubset1_type)
1378: thistype = AttrToLongCardinal(&attr.sequence[i]);
1379: else if (t == FilingSubset1_dataSize)
1380: thissize = AttrToLongCardinal(&attr.sequence[i]);
1381: else if (t == FilingSubset1_version)
1382: thisversion = AttrToCardinal(&attr.sequence[i]);
1383: else if (t == FilingSubset1_createdOn) {
1384: thisdate = AttrToLongCardinal(&attr.sequence[i]);
1385: thisdate = thisdate - XNS_TIME_DIFFERENCE;
1386: filedatestr= ctime(&thisdate);
1387: filedatestr[24]= '\0';
1388: filedatestr += 4;
1389: }
1390: }
1391:
1392: strcpy(filetypestr, "(");
1393: strcat(filetypestr, typetostring(thistype));
1394: strcat(filetypestr, ")");
1395:
1396: if ( (slash= rindex(thisname, '/')) == NULL )
1397: slash= thisname;
1398: else
1399: slash++;
1400:
1401: fprintf(fout, "%c%c%-16s%7ld %s %s",
1402: isdir?'D':' ', istemp?'T':' ',
1403: filetypestr, thissize, filedatestr, slash);
1404: if ( thisversion != 0)
1405: fprintf(fout,"!%d",thisversion);
1406: fprintf(fout,"\n");
1407: clear_String(&thisname);
1408: }
1409:
1410: /*
1411: * process used by retrieve to get file type, createdOn and pathname
1412: */
1413: rlistproc(attr)
1414: FilingSubset1_AttributeSequence attr;
1415: {
1416: int i;
1417: char *thisname;
1418: FilingSubset1_AttributeType t;
1419: char *AttrToString();
1420:
1421: files_found= TRUE;
1422:
1423: /*
1424: * Xerox file servers will return all versions of the requested file in
1425: * ascending version order. We assume that the last version will be the
1426: * highest and remember that name so that the retrieve will pull the
1427: * highest version of the file. If we request just the file with no
1428: * version, the server will return the oldest version (not what I would
1429: * expect...)
1430: */
1431:
1432: for (i= 0; i < attr.length; i++) {
1433: t= attr.sequence[i].type;
1434: if (t == FilingSubset1_createdOn) {
1435: gettimeofday(&timbuf[0],(struct timezone *)0);
1436: timbuf[1].tv_sec= AttrToLongCardinal(&attr.sequence[i]) - XNS_TIME_DIFFERENCE;
1437: timbuf[1].tv_usec= 0;
1438: } else if (t == FilingSubset1_type) {
1439: if (typevalue == TYPE_Guess) {
1440: filetypevalue= AttrToLongCardinal(&attr.sequence[i]);
1441: }
1442: } else if (t == FilingSubset1_pathname) {
1443: thisname= AttrToString(&attr.sequence[i]);
1444: if (verbose) {
1445: printf("%s to ", thisname);
1446: fflush(stdout);
1447: }
1448: clear_String(&thisname);
1449: } else if (t == FilingSubset1_isDirectory) {
1450: is_a_directory= AttrToBoolean(&attr.sequence[i]);
1451: }
1452: }
1453:
1454: }
1455:
1456: cdproc(attr)
1457: FilingSubset1_AttributeSequence attr;
1458: {
1459: char *AttrtoString();
1460: char *dest;
1461: int i;
1462:
1463: files_found= TRUE;
1464:
1465: dest= 0;
1466: for (i= 0; i < attr.length; i++) {
1467: if (attr.sequence[i].type == FilingSubset1_isDirectory
1468: && AttrToBoolean(&attr.sequence[i])) {
1469: isdir= TRUE; /* if directory, change handles */
1470: }
1471: if (attr.sequence[i].type == FilingSubset1_pathname)
1472: dest= AttrToString(&attr.sequence[i]);
1473: }
1474:
1475: if (!isdir || dest == 0) { /* if no directory or pathname */
1476: isdir= FALSE; /* assume failure */
1477: }
1478: }
1479:
1480: #define MAXPACKS 20
1481: static
1482: GetAttributeSequences(conn)
1483: CourierConnection *conn;
1484: {
1485: int count, i;
1486: Unspecified buffer[MAXWORDS*MAXPACKS], *bp, *bufend;
1487: FilingSubset1_StreamOfAttributeSequence attrs;
1488: Boolean overflow= FALSE;
1489:
1490: files_found= FALSE;
1491:
1492: bufend = buffer;
1493: bp = buffer+((MAXWORDS-1)*MAXPACKS); /* end of available space */
1494: while ((count = BDTread(conn, (char*)bufend,
1495: MAXWORDS*sizeof(Unspecified))) > 0) {
1496: bufend += count/sizeof(Unspecified);
1497: bytessent += count;
1498: if (bufend > bp) {
1499: fprintf(stderr,"BDT read too big to fit\n");
1500: BDTabort(conn);
1501: /* should clear out stuff here if we knew how much
1502: * fall back to previous block on the assumption
1503: * we can give a truncated list
1504: */
1505: bufend -= count/sizeof(Unspecified);
1506: overflow=TRUE;
1507: }
1508: }
1509: bp = buffer;
1510: while (bp < bufend) {
1511: bp += internalize_FilingSubset1_StreamOfAttributeSequence(&attrs,bp);
1512: if (0 == (int) attrs.designator) {
1513: for (i=0; i < attrs.nextSegment_case.segment.length; i++) {
1514: (*ProcEachSeq)(
1515: attrs.nextSegment_case.segment.sequence[i]);
1516: }
1517: free(attrs.nextSegment_case.segment.sequence);
1518: } else {
1519: for (i = 0; i < attrs.lastSegment_case.length; i++) {
1520: (*ProcEachSeq)(
1521: attrs.lastSegment_case.sequence[i]);
1522: }
1523: free(attrs.lastSegment_case.sequence);
1524: return;
1525: }
1526: }
1527: if ( overflow ) {
1528: fprintf(stderr, "\nListing was truncated due to internal bulk data buffer size\n");
1529: overflow= FALSE;
1530: }
1531: }
1532:
1533: int
1534: getBDTch(conn,bpp)
1535: CourierConnection *conn;
1536: u_char **bpp;
1537: {
1538: static u_char buffer[SPPMAXDATA];
1539: static int count;
1540:
1541: if (*bpp == NULL) {*bpp = buffer; count = 0;}
1542: if (*bpp >= buffer+count) {
1543: count=BDTread(conn,buffer,sizeof(buffer));
1544: *bpp = buffer;
1545: }
1546: if (count <= 0) return(EOF);
1547: else return(*((*bpp)++));
1548:
1549: }
1550:
1551: retrieveproc(conn)
1552: CourierConnection *conn;
1553: {
1554: int count, ocount, ch, hashbytes;
1555: char buffer[SPPMAXDATA];
1556: int charset, charset16;
1557: char *bp;
1558:
1559: switch (filetypevalue) {
1560: default :
1561: errno = ocount = 0;
1562: fflush(fout);
1563: while ((count = BDTread(conn, buffer, sizeof(buffer))) > 0) {
1564: if ((ocount = write(fileno(fout),buffer,count)) < 0) {
1565: perror("write");
1566: BDTabort(conn);
1567: break;
1568: }
1569: bytessent += count;
1570: if (hash) {
1571: putchar('#');
1572: fflush(stdout);
1573: }
1574: }
1575: if (count < 0) perror("netin");
1576: break;
1577:
1578: case TYPE_VPMailNote :
1579: case TYPE_A :
1580: charset = 0; charset16 = 0; bp = NULL;
1581: hashbytes = 0;
1582: while ((ch = getBDTch(conn,&bp)) != EOF) {
1583: if (ch == '\377') {
1584: ch = getBDTch(conn,&bp);
1585: if (ch == '\377') charset16 = 1;
1586: else charset = ch;
1587: continue;
1588: }
1589: if (charset16) {
1590: charset = ch;
1591: ch = getBDTch(conn,&bp);
1592: }
1593: switch (charset) {
1594: case 0: /* normal character set -- minimal xlation */
1595: if (ch == '\r') {
1596: int nextch;
1597:
1598: putc('\n',fout);
1599: bytessent++;
1600: if ( (nextch = getBDTch(conn,&bp)) != '\n'){
1601: if (nextch == '\r')
1602: putc('\n',fout);
1603: else if ( nextch == ','+0200 )
1604: putc('_',fout);
1605: else if ( nextch != EOF )
1606: putc(nextch,fout);
1607: else
1608: continue;
1609: }
1610: bytessent= bytessent++;
1611:
1612: while (hash && bytessent >= hashbytes){
1613: putchar('#');
1614: fflush(stdout);
1615: hashbytes += sizeof(buffer);
1616: }
1617: break;
1618: }
1619: else if (ch == ','+0200) ch = '_';
1620: /* more mapping here */
1621: putc(ch,fout);
1622: bytessent++;
1623: break;
1624: default:
1625: break; /* ignore */
1626: }
1627: }
1628: if (hash) {
1629: while (bytessent >= hashbytes) {
1630: putchar('#');
1631: hashbytes += sizeof(buffer);
1632: }
1633: putchar('\n');
1634: fflush(stdout);
1635: }
1636: /* if (count < 0) perror("netin"); */
1637: break;
1638: }
1639: }
1640:
1641: storeproc(conn)
1642: CourierConnection *conn;
1643: {
1644: int count, ocount;
1645: u_char buffer[SPPMAXDATA];
1646: u_char *bp;
1647:
1648: errno = ocount = 0;
1649: clearerr(fin);
1650: switch (filetypevalue) {
1651:
1652: default :
1653: while ((count = fread(buffer, sizeof(char), SPPMAXDATA, fin)) > 0
1654: && (ocount = BDTwrite(conn, buffer, count)) > 0) {
1655: bytessent += count;
1656: if (hash) {
1657: putchar('#');
1658: fflush(stdout);
1659: }
1660: }
1661: break;
1662: case TYPE_VPMailNote :
1663: case TYPE_A :
1664: while ((count = fread(buffer, sizeof(char), SPPMAXDATA, fin))
1665: > 0) {
1666: ocount = count;
1667: for (bp = buffer; count > 0; count--, bp++) {
1668: if (*bp == '\n') *bp = '\r';
1669: else if (*bp == '_') *bp = ','+0200;
1670: /* more translations here */
1671: }
1672: if ((ocount = BDTwrite(conn, buffer, ocount)) <= 0)
1673: break;
1674: bytessent += ocount;
1675: if (hash) {
1676: putchar('#');
1677: fflush(stdout);
1678: }
1679: }
1680: break;
1681: }
1682: if (ocount < 0) {
1683: BDTabort(conn);
1684: perror("netout");
1685: }
1686: else if (ferror(fin)) {
1687: BDTabort(conn);
1688: perror("fread");
1689: }
1690: else
1691: BDTclosewrite(conn);
1692: }
1693:
1694: isdirproc(attr)
1695: FilingSubset1_AttributeSequence attr;
1696: {
1697: int i;
1698: char *name;
1699: FilingSubset1_AttributeType t;
1700:
1701: for ( i= 0; i < attr.length; i++ ) {
1702: t= attr.sequence[i].type;
1703: if ( t == FilingSubset1_isDirectory ) {
1704: isdir= AttrToBoolean(&attr.sequence[i]);
1705: } else if ( t == FilingSubset1_pathname ) {
1706: name= AttrToString(&attr.sequence[1]);
1707: strcpy(cur_pathname, name);
1708: clear_String(&name);
1709: }
1710: }
1711: }
1712:
1713: deleteproc(attr)
1714: FilingSubset1_AttributeSequence attr;
1715: {
1716: int i;
1717: char *name;
1718: struct name_entry *entry;
1719: FilingSubset1_AttributeType t;
1720:
1721: if ( name_count > name_size ) {
1722: name_size += MAXNAMES;
1723: name_list= (struct name_entry *) realloc(name_list,
1724: sizeof(struct name_entry) * name_size);
1725: }
1726:
1727: entry= &name_list[name_count];
1728: for ( i= 0; i < attr.length; i++ ) {
1729: t= attr.sequence[i].type;
1730: if ( t == FilingSubset1_type ) {
1731: entry->type= AttrToLongCardinal(&attr.sequence[i]);
1732: } else if ( t == FilingSubset1_pathname ) {
1733: entry->pathname= AttrToString(&attr.sequence[1]);
1734: }
1735: }
1736: name_count++;
1737: }
1738:
1739: GetAllAttributes(attr)
1740: FilingSubset1_AttributeSequence attr;
1741: {
1742: int i;
1743: char *thisname;
1744: FilingSubset1_AttributeType t;
1745: int got_createdon, got_type, got_pathname;
1746:
1747: files_found= TRUE;
1748: got_createdon= got_pathname= got_type= 0;
1749:
1750: /*
1751: * Xerox file servers will return all versions of the requested file in
1752: * ascending version order. We assume that the last version will be the
1753: * highest and remember that name so that the retrieve will pull the
1754: * highest version of the file. If we request just the file with no
1755: * version, the server will return the oldest version (not what I would
1756: * expect...)
1757: */
1758: for (i= 0; i < attr.length; i++) {
1759: t= attr.sequence[i].type;
1760: if (t == FilingSubset1_createdOn) {
1761: gettimeofday(&timbuf[0],(struct timezone *)0);
1762: timbuf[1].tv_sec= AttrToLongCardinal(&attr.sequence[i]) - XNS_TIME_DIFFERENCE;
1763: timbuf[1].tv_usec= 0;
1764: got_createdon++;
1765: } else if (t == FilingSubset1_type) {
1766: if (typevalue == TYPE_Guess) {
1767: filetypevalue= AttrToLongCardinal(&attr.sequence[i]);
1768: }
1769: got_type++;
1770: } else if (t == FilingSubset1_pathname) {
1771: thisname= AttrToString(&attr.sequence[i]);
1772: strcpy(cur_pathname, thisname);
1773: clear_String(&thisname);
1774: got_pathname++;
1775: }
1776:
1777: if ( got_createdon && got_type && got_pathname )
1778: break;
1779: }
1780:
1781: SaveExtendedAttributes(fout, attr);
1782:
1783: return;
1784: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.