|
|
1.1 root 1: #ifndef lint
2: static char *rcsid = "$Header: xnsremote.c,v 1.3 87/04/01 08:23:53 ed Exp $";
3: #endif lint
4:
5: /*
6: * Copyright (c) 1986, 1987 Xerox Corporation.
7: */
8:
9: /* $Log: xnsremote.c,v $
10: * Revision 1.3 87/04/01 08:23:53 ed
11: * Changed for new MakeSecondaryCreds call.
12: *
13: * Revision 1.2 87/03/25 10:55:53 ed
14: * Don't reset usefiling in login.
15: *
16: * Revision 1.1 87/03/17 16:29:19 ed
17: * Initial revision
18: *
19: *
20: */
21:
22: #include <stdio.h>
23: #include <sys/time.h>
24: #include <sys/param.h>
25: #include <sys/stat.h>
26: #include <netns/ns.h>
27: #include <netns/sp.h>
28: #include <xnscourier/FilingSubset1.h>
29: #include <xnscourier/Filing4.h>
30: #include <xnscourier/except.h>
31: #undef __Clearinghouse2 /* Filing4.h defs this */
32: #include <xnscourier/CH.h>
33: #include <xnscourier/filetypes.h>
34:
35: #ifdef PRINTOPTION
36: #ifndef XNSPRINT
37: #define XNSPRINT "/usr/new/xnsprint"
38: #endif XNSPRINT
39:
40: #ifndef MAHA
41: #define MAHA "/usr/new/maha"
42: #endif MAHA
43: #endif PRINTOPTION
44:
45: #define ROOT_DIRECTORY "/"
46:
47: CourierConnection *connected;
48: Clearinghouse3_ObjectName hostobjname;
49: Authentication3_Verifier verifier;
50:
51: /* the following 3 items make up the current session */
52: FilingSubset1_Session session; /* the current session */
53: Clearinghouse3_ObjectName username;
54: FilingSubset1_Handle rootHandle;
55: char cur_dir[512]= 0;
56: char cur_pathname[512]= 0;
57: char cur_name[512]= 0;
58:
59: static FilingSubset1_ControlSequence nullControls = {0,0};
60: static FilingSubset1_ScopeSequence nullScope = {0,0};
61:
62: /* global data used to communicate with BDT procedures
63: */
64: extern GetAttributeSequences(),
65: listproc(), retrieveproc();
66:
67: char *AttrToString();
68: Boolean AttrToBoolean();
69: LongCardinal AttrToLongCardinal();
70: Cardinal AttrToCardinal();
71:
72: static (*ProcEachSeq)();
73: static FILE *fout= stdout;
74:
75: Boolean files_found= FALSE;
76: Boolean filing_subset= TRUE;
77: Boolean usefiling= TRUE;
78: Boolean verbose= FALSE;
79:
80: LongCardinal typevalue= 0;
81: char *service, *pager;
82: extern int errno;
83: char thru_options[512];
84:
85: struct name_entry {
86: char *pathname;
87: LongCardinal type;
88: } ;
89:
90: static struct name_entry *name_list= 0;
91: static int name_count= 0;
92: static int name_size= 0;
93: #define MAX_NAMES 10
94:
95: main(argc, argv)
96: int argc;
97: char *argv[];
98: {
99: char *file, *rightbrkt;
100: char oldservice[100];
101: char *index(), *getenv();
102: int i;
103: CourierConnection *hookup();
104: int opt;
105: extern int optind;
106: extern char *optarg;
107:
108: #ifdef PRINTOPTION
109: static char *options= "fvP:";
110: static char *usage= "Usage: %s [-f] [-v] [-P printer] file1 ... filen\n";
111: #else PRINTOPTION
112: static char *options= "fvs";
113: static char *usage= "Usage: %s [-f] [-v] [-s] file1 ... filen\n";
114: #endif PRINTOPTION
115:
116: if ( argc < 1 ) {
117: fprintf(stderr, usage, argv[0]);
118: exit(1);
119: }
120:
121: #ifndef PRINTOPTION
122: pager= getenv("PAGER");
123: #endif PRINTOPTION
124:
125: strcpy(thru_options, "");
126:
127: while ((opt= getopt(argc, argv, options)) != EOF)
128: switch (opt) {
129: case 'v':
130: verbose++;
131: break;
132:
133: case 'f':
134: usefiling= 0;
135: break;
136:
137: #ifdef PRINTOPTION
138: case 'P' :
139: strcat(thru_options, " -P ");
140: strcat(thru_options, optarg);
141: break;
142: #else PRINTOPTION
143: case 's' :
144: pager= '\0'; /* override pager */
145: break;
146: #endif PRINTOPTION
147: default:
148: fprintf(stderr, "Invalid command option -%c\n", opt);
149: exit(1);
150: }
151:
152: for ( ; optind < argc ; optind++ ) {
153: if ( getserviceandfile(argv[optind], &service, &file) == 0 ) {
154: fprintf(stderr, "Invalid name %s\n", argv[optind]);
155: exit(1);
156: }
157: DURING {
158: if ( strcmp(oldservice, service) != 0 ) {
159: if ( (connected= hookup(service)) == (CourierConnection *)0 ) {
160: fprintf(stderr, "\nCan't connect to %s\n", service);
161: continue;
162: }
163: login(0,0);
164: strcpy(oldservice, service);
165: }
166:
167: getfile(file);
168:
169: } HANDLER {
170: FilingErrMsg(Exception.Code, Exception.Message);
171: #ifndef PRINTOPTION
172: if ( fout != stdout )
173: pclose(fout);
174: #endif PRINTOPTION
175: } END_HANDLER;
176:
177: }
178:
179: return(0);
180: }
181:
182: getserviceandfile(name, srvcptr, fileptr)
183: char *name;
184: char **srvcptr, **fileptr;
185: {
186: char *sptr, *fptr;
187: char *index(), *rindex();
188:
189: /*
190: * look for Xerox forms first:
191: * [host]filename
192: */
193:
194: if ( (sptr= index(name, '[')) != 0 ) {
195: if ( (fptr= index(sptr, ']')) != 0 ) {
196: *fptr= '\0';
197: *srvcptr= sptr + 1;
198: *fileptr= fptr + 1;
199: return(1);
200: } else
201: return(0);
202: }
203:
204: /*
205: * (host)filename
206: */
207:
208: if ( (sptr= index(name, '(')) != 0 ) {
209: if ( (fptr= index(sptr, ')')) != 0 ) {
210: *fptr= '\0';
211: *srvcptr= sptr + 1;
212: *fileptr= fptr + 1;
213: return(1);
214: } else
215: return(0);
216: }
217:
218: /*
219: * look for XNS style with trailing : delimiter
220: * (assumes no : in file name, use alternate spec instead)
221: * object:domain:organization:filename
222: * domain & organization are optional
223: */
224:
225: if ( (fptr= rindex(name, ':')) != 0 ) {
226: *fptr= '\0';
227: *srvcptr= name;
228: *fileptr= fptr + 1;
229: return(1);
230: } else
231: return(0);
232: }
233:
234: copyhandle(dest,src)
235: FilingSubset1_Handle dest,src;
236: {
237: if (dest == (Unspecified *) 0) {
238: fprintf(stderr,"Oops. dest is null in copyhandle\n");
239: exit(1);
240: }
241: dest[0] = src[0];
242: dest[1] = src[1];
243: }
244:
245: getfilehandle(filename, handle)
246: char *filename;
247: FilingSubset1_Handle handle;
248: {
249: FilingSubset1_Attribute pathattr[1];
250: FilingSubset1_AttributeSequence attrseq;
251: FilingSubset1_OpenResults openresult;
252: Filing4_OpenResults openresult2;
253:
254: if (filename == (char *)0 || *filename == '\000' || (strcmp(filename, "/") == 0) ) {
255: if ( filing_subset )
256: copyhandle(handle,FilingSubset1_nullHandle);
257: else
258: copyhandle(handle,rootHandle);
259: return;
260: }
261:
262: attrseq.length = 1;
263: attrseq.sequence = pathattr;
264: pathattr[0].type = FilingSubset1_pathname;
265: copyhandle(handle, FilingSubset1_nullHandle);
266: #ifdef XEROXFSCOMPATIBILITY
267: if ( filename[0] == '/')
268: StringToAttr(filename+1, &pathattr[0]);
269: else
270: StringToAttr(filename, &pathattr[0]);
271: #else XEROXFSCOMPATIBILITY
272: StringToAttr(filename, &pathattr[0]);
273: #endif XEROXFSCOMPATIBILITY
274: alarm(0);
275: if ( filing_subset ) {
276: openresult = FilingSubset1_Open(connected, NULL, attrseq,
277: handle, nullControls,
278: session);
279: copyhandle(handle, openresult.file);
280: } else {
281: openresult2 = Filing4_Open(connected, NULL, attrseq,
282: handle, nullControls,
283: session);
284: copyhandle(handle, openresult2.file);
285: }
286: }
287:
288: getdirhandle(filename, handle)
289: char *filename;
290: FilingSubset1_Handle handle;
291: {
292: FilingSubset1_Attribute pathattr[1];
293: FilingSubset1_AttributeSequence attrseq;
294: FilingSubset1_OpenResults openresult;
295: Filing4_OpenResults openresult2;
296: char *rindex();
297: char *slash;
298:
299: if (filename == (char *)0 || *filename == '\000' || (strcmp(filename, "/") == 0) ) {
300: strcpy(cur_pathname, "/");
301: strcpy(cur_name, "/");
302: if ( filing_subset )
303: copyhandle(handle,FilingSubset1_nullHandle);
304: else
305: copyhandle(handle,rootHandle);
306: return;
307: } else if ( filename[0] == '/' ) {
308: strcpy(cur_pathname, filename);
309: } else {
310: strcpy(cur_pathname, cur_dir);
311: if ( strcmp(cur_pathname, "/") != 0 )
312: strcat(cur_pathname, "/");
313: strcat(cur_pathname, filename);
314: }
315:
316: if ( (slash= rindex(cur_pathname,'/')) == NULL )
317: strcpy(cur_name, cur_pathname);
318: else
319: strcpy(cur_name, slash+1);
320:
321: if ( filing_subset ) {
322: copyhandle(handle, FilingSubset1_nullHandle);
323: } else {
324: if ( slash == cur_pathname) {
325: copyhandle(handle, rootHandle);
326: return;
327: }
328:
329: attrseq.length = 1;
330: attrseq.sequence = pathattr;
331: pathattr[0].type = FilingSubset1_pathname;
332: copyhandle(handle, FilingSubset1_nullHandle);
333: *slash= '\0'; /* separate pathname from name */
334: #ifdef XEROXFSCOMPATIBILITY
335: if ( cur_pathname[0] == '/' )
336: StringToAttr(cur_pathname+1, &pathattr[0]);
337: else
338: StringToAttr(cur_pathname, &pathattr[0]);
339: #else XEROXFSCOMPATIBILITY
340: StringToAttr(cur_pathname, &pathattr[0]);
341: #endif XEROXFSCOMPATIBILITY
342: *slash= '/'; /* and put back */
343: alarm(0);
344: if ( filing_subset ) {
345: openresult = FilingSubset1_Open(connected, NULL, attrseq,
346: handle, nullControls,
347: session);
348: copyhandle(handle, openresult.file);
349: } else {
350: openresult2 = Filing4_Open(connected, NULL, attrseq,
351: handle, nullControls,
352: session);
353: copyhandle(handle, openresult2.file);
354: }
355: }
356: }
357:
358: freefilehandle(handle)
359: FilingSubset1_Handle handle;
360: {
361: if (handle[0] == FilingSubset1_nullHandle[0] &&
362: handle[1] == FilingSubset1_nullHandle[1])
363: return; /* don't free nullHandle */
364: if (handle[0] == rootHandle[0] &&
365: handle[1] == rootHandle[1])
366: return; /* don't free root directory */
367: alarm(0);
368: if ( filing_subset )
369: FilingSubset1_Close(connected, NULL, handle, session);
370: else
371: Filing4_Close(connected, NULL, handle, session);
372: }
373:
374: CourierConnection *
375: hookup(name)
376: char *name;
377: {
378: register struct ns_addr *hostaddr;
379: extern struct ns_addr *getXNSaddr();
380: Clearinghouse3_ObjectName defaultobjname;
381: static char hnamebuf[128];
382: CourierConnection *cconn;
383:
384: CH_NameDefault(&defaultobjname);
385: hostobjname = CH_StringToName(name, &defaultobjname);
386: if ((hostaddr = CH_LookupAddrDN( hostobjname, 0, hnamebuf, 128))) {
387: /* should check here to be sure host is a file service */
388: hostaddr->x_port = htons(5); /* ?? */
389: cconn = CourierOpen(hostaddr);
390: /* reset objname to flush wildcards */
391: /* clear_Clearinghouse3_ThreePartName(&hostobjname); */
392: hostobjname = CH_StringToName(hnamebuf, &defaultobjname);
393: }
394: return(cconn);
395: }
396:
397:
398: login(name,pwd)
399: char *pwd;
400: char *name;
401: {
402: FilingSubset1_Credentials credentials;
403: FilingSubset1_LogonResults logonresult;
404: FilingSubset1_LogonResults *resultptr= &logonresult;
405: Filing4_LogonResults logonresult2;
406: FilingSubset1_AttributeSequence attrseq;
407: FilingSubset1_OpenResults openresult;
408: Filing4_OpenResults openresult2;
409:
410:
411: if ( name != 0 )
412: username = CH_StringToName(name,&hostobjname);
413:
414: if ( usefiling ) {
415: filing_subset= FALSE;
416: if ( name == 0 && pwd == 0 ) {
417: GetSimpleCredsAndVerifier(&username, 0,
418: &credentials.primary, &verifier);
419: } else {
420: MakeSimpleCredsAndVerifier(&username,pwd,
421: &credentials.primary, &verifier);
422: }
423: logonresult2= Filing4_Logon(connected, NULL, hostobjname,
424: credentials.primary, verifier);
425: resultptr= (FilingSubset1_LogonResults *) &logonresult2;
426:
427: } else {
428: if ( name == 0 && pwd == 0 ) {
429: GetSimpleCredsAndVerifier(&username, 0, &credentials.primary, &verifier);
430: MakeSecondaryCreds(hostobjname.object, 0, 0, &credentials.secondary);
431: } else {
432: MakeSimpleCredsAndVerifier(0, pwd, &credentials.primary, &verifier);
433: MakeSecondaryCreds(hostobjname.object, name, pwd, &credentials.secondary);
434: }
435: filing_subset= TRUE;
436: DURING
437: logonresult = FilingSubset1_Logon(connected, NULL, hostobjname,
438: credentials, verifier);
439: HANDLER {
440: switch (Exception.Code) {
441: case REJECT_ERROR:
442: filing_subset= FALSE;
443: logonresult2= Filing4_Logon(connected, NULL, hostobjname,
444: credentials.primary, verifier);
445: resultptr= (FilingSubset1_LogonResults *) &logonresult2;
446: break;
447: default:
448: RERAISE;
449: }
450: } END_HANDLER;
451: }
452:
453: if ( filing_subset )
454: session = resultptr->session;
455: else
456: session = resultptr->session;
457:
458: attrseq.length= 0;
459: attrseq.sequence= 0;
460: if ( filing_subset ) {
461: openresult= FilingSubset1_Open(connected, NULL, attrseq,
462: FilingSubset1_nullHandle, nullControls,
463: session);
464: copyhandle(rootHandle, openresult.file);
465: } else {
466: openresult2= Filing4_Open(connected, NULL, attrseq,
467: FilingSubset1_nullHandle, nullControls,
468: session);
469: copyhandle(rootHandle, openresult2.file);
470: }
471: strcpy(cur_dir, ROOT_DIRECTORY);
472: }
473:
474: logout()
475: {
476: if ( filing_subset )
477: FilingSubset1_Logoff(connected, NULL, session);
478: else
479: Filing4_Logoff(connected, NULL, session);
480: clear_FilingSubset1_Session(&session);
481: }
482:
483:
484: getfile(remote)
485: char *remote;
486: {
487: FILE *popen();
488: FilingSubset1_Handle remotehandle; /* note: an array */
489: FilingSubset1_Handle dirhandle; /* note: an array */
490: FilingSubset1_AttributeTypeSequence typeseq;
491: FilingSubset1_AttributeType tsvals[10];
492: FilingSubset1_ScopeSequence scopeseq;
493: FilingSubset1_Scope scope;
494: char pcmd[500];
495: int i;
496: register struct name_entry *entry;
497:
498: name_count= 0;
499: name_size= MAX_NAMES;
500: if ( (name_list= (struct name_entry *) malloc(sizeof(struct name_entry) * name_size)) == 0 ) {
501: perror("getfile: ");
502: return;
503: }
504:
505: typeseq.length = 0; typeseq.sequence = tsvals;
506: scopeseq.length= 1; scopeseq.sequence= &scope;
507: scope.designator= FilingSubset1_filter;
508: scope.FilingSubset1_filter_case.designator= FilingSubset1_matches;
509: if ( filing_subset )
510: scope.FilingSubset1_filter_case.FilingSubset1_matches_case.attribute.type= FilingSubset1_pathname;
511: else
512: scope.FilingSubset1_filter_case.FilingSubset1_matches_case.attribute.type= FilingSubset1_name;
513:
514: copyhandle(remotehandle, FilingSubset1_nullHandle);
515: getdirhandle(remote, dirhandle);
516:
517: if ( filing_subset )
518: StringToAttr(cur_pathname,&scope.FilingSubset1_filter_case.FilingSubset1_matches_case.attribute);
519: else
520: StringToAttr(cur_name,&scope.FilingSubset1_filter_case.FilingSubset1_matches_case.attribute);
521:
522: typeseq.length = 2;
523: typeseq.sequence[0] = FilingSubset1_pathname;
524: typeseq.sequence[1] = FilingSubset1_type;
525:
526: ProcEachSeq = listproc;
527: if ( filing_subset )
528: FilingSubset1_List(connected, GetAttributeSequences, dirhandle,
529: typeseq, scopeseq,
530: BulkData1_immediateSink, session);
531: else
532: Filing4_List(connected, GetAttributeSequences, dirhandle,
533: typeseq, scopeseq,
534: BulkData1_immediateSink, session);
535:
536:
537: if ( !files_found ) {
538: fprintf(stderr, "\n(%s)%s not found\n", service, remote);
539: } else {
540: for ( i= 0 ; i < name_count ; i++ ) {
541: entry= &name_list[i];
542: #ifdef PRINTOPTION
543: if ( (entry->type != FilingSubset1_tText) && (entry->type != TYPE_VPMailNote) &&
544: (entry->type != TYPE_Interpress) ) {
545: fprintf(stderr, "\n\n\n\nInvalid file type (%d)\n\n\n\n", entry->type);
546: clear_String(&entry->pathname);
547: continue;
548: }
549:
550: if ( entry->type == TYPE_Interpress ) {
551: sprintf(pcmd, "%s -q -b \"(%s)%s\"%s -", XNSPRINT, service, entry->pathname, thru_options);
552: } else {
553: sprintf(pcmd, "%s -b \"(%s)%s\"%s", MAHA, service, entry->pathname, thru_options);
554: }
555:
556: if ( (fout= popen(pcmd, "w")) == NULL ) {
557: perror("popen: ");
558: exit(1);
559: }
560:
561: if (verbose) {
562: fprintf(stderr, "\n\printing (%s)%s...\n\n",service,entry->pathname);
563: }
564: #else PRINTOPTION
565: if ( entry->type != FilingSubset1_tText ) {
566: fprintf(stderr, "\n\n\nCan only view text files.\n\n\n");
567: clear_String(&entry->pathname);
568: continue;
569: }
570:
571: if ( pager == NULL || *pager == '\0' ) {
572: fout= stdout;
573: } else {
574: sprintf(pcmd, "%s%s", pager, thru_options);
575: if ( (fout= popen(pcmd, "w")) == NULL )
576: fout= stdout;
577: }
578:
579: if (verbose) {
580: fprintf(stderr, "\n\n\n\nretrieving (%s)%s...\n\n\n\n",service,entry->pathname);
581: }
582: #endif PRINTOPTION
583:
584: typevalue= entry->type;
585:
586: getfilehandle(entry->pathname, remotehandle); /* get file handle */
587: if ( filing_subset ) {
588: FilingSubset1_Retrieve(connected, retrieveproc, remotehandle,
589: BulkData1_immediateSink, session);
590: } else {
591: Filing4_Retrieve(connected, retrieveproc, remotehandle,
592: BulkData1_immediateSink, session);
593: }
594:
595: freefilehandle(remotehandle);
596: #ifdef PRINTOPTION
597: pclose(fout);
598: #else PRINTOPTION
599: if ( fout != stdout )
600: pclose(fout);
601: #endif PRINTOPTION
602:
603: clear_String(&entry->pathname);
604: }
605: }
606:
607: free(name_list);
608: freefilehandle(dirhandle);
609:
610: }
611:
612: listproc(attr)
613: FilingSubset1_AttributeSequence attr;
614: {
615: int i;
616: FilingSubset1_AttributeType t;
617: struct name_entry *entry;
618:
619: files_found= TRUE;
620:
621: /*
622: * Xerox file servers will return all versions of the requested file in
623: * ascending version order. We assume that the last version will be the
624: * highest and remember that name so that the retrieve will pull the
625: * highest version of the file. If we request just the file with no
626: * version, the server will return the oldest version (not what I would
627: * expect...)
628: */
629:
630: if ( name_count > name_size ) {
631: name_size += MAX_NAMES;
632: name_list= (struct name_entry *) realloc(name_list,
633: sizeof(struct name_entry) * name_size);
634: }
635:
636: entry= &name_list[name_count];
637: for (i = 0; i < attr.length; i++) {
638: t = attr.sequence[i].type;
639: if (t == FilingSubset1_name || t == FilingSubset1_pathname) {
640: entry->pathname = AttrToString(&attr.sequence[i]);
641: } else if (t == FilingSubset1_type) {
642: entry->type = AttrToLongCardinal(&attr.sequence[i]);
643: }
644: }
645: name_count++;
646: }
647:
648:
649: #define MAXPACKS 20
650: static
651: GetAttributeSequences(conn)
652: CourierConnection *conn;
653: {
654: int count, i;
655: Unspecified buffer[MAXWORDS*MAXPACKS], *bp, *bufend;
656: FilingSubset1_StreamOfAttributeSequence attrs;
657:
658: files_found= FALSE;
659:
660: bufend = buffer;
661: bp = buffer+((MAXWORDS-1)*MAXPACKS); /* end of available space */
662: while ((count = BDTread(conn, (char*)bufend,
663: MAXWORDS*sizeof(Unspecified))) > 0) {
664: bufend += count/sizeof(Unspecified);
665: if (bufend > bp) {
666: fprintf(stderr,"BDT read too big to fit\n");
667: BDTabort(conn);
668: /* should clear out stuff here if we knew how much */
669: }
670: }
671: bp = buffer;
672: while (bp < bufend) {
673: bp += internalize_FilingSubset1_StreamOfAttributeSequence(&attrs,bp);
674: if (0 == (int) attrs.designator) {
675: for (i=0; i < attrs.nextSegment_case.segment.length; i++) {
676: (*ProcEachSeq)(
677: attrs.nextSegment_case.segment.sequence[i]);
678: }
679: free(attrs.nextSegment_case.segment.sequence);
680: } else {
681: for (i = 0; i < attrs.lastSegment_case.length; i++) {
682: (*ProcEachSeq)(
683: attrs.lastSegment_case.sequence[i]);
684: }
685: free(attrs.lastSegment_case.sequence);
686: return;
687: }
688: }
689: }
690:
691: int
692: getBDTch(conn,bpp)
693: CourierConnection *conn;
694: u_char **bpp;
695: {
696: static u_char buffer[SPPMAXDATA];
697: static int count;
698:
699: if (*bpp == NULL) {*bpp = buffer; count = 0;}
700: if (*bpp >= buffer+count) {
701: count=BDTread(conn,buffer,sizeof(buffer));
702: *bpp = buffer;
703: }
704: if (count <= 0) return(EOF);
705: else return(*((*bpp)++));
706:
707: }
708:
709: retrieveproc(conn)
710: CourierConnection *conn;
711: {
712: int count, ocount, ch;
713: char buffer[SPPMAXDATA];
714: int charset, charset16;
715: char *bp;
716:
717: errno = ocount = 0;
718: fflush(fout);
719:
720: switch (typevalue) {
721: default :
722: fprintf(stderr, "Unsupported file type\n");
723: BDTabort(conn);
724: break;
725:
726: case TYPE_Interpress :
727: while ((count = BDTread(conn, buffer, sizeof(buffer))) > 0) {
728: if ((ocount = write (fileno(fout), buffer, count)) < 0) {
729: perror("write");
730: BDTabort(conn);
731: break;
732: }
733: }
734: if (count < 0) perror("netin");
735: break;
736:
737: case TYPE_VPMailNote :
738: case TYPE_A :
739: charset = 0; charset16 = 0; bp = NULL;
740: while ((ch = getBDTch(conn,&bp)) != EOF) {
741: if (ch == '\377') {
742: ch = getBDTch(conn,&bp);
743: if (ch == '\377') charset16 = 1;
744: else charset = ch;
745: continue;
746: }
747: if (charset16) {
748: charset = ch;
749: ch = getBDTch(conn,&bp);
750: }
751: switch (charset) {
752: case 0: /* normal character set -- minimal xlation */
753: if (ch == '\r') {
754: int nextch;
755:
756: putc('\n',fout);
757: if ( (nextch = getBDTch(conn,&bp)) != '\n'){
758: if (nextch == '\r')
759: putc('\n',fout);
760: else if ( nextch != EOF )
761: putc(nextch,fout);
762: else
763: continue;
764: }
765: break;
766: }
767: else if (ch == ','+0200) ch = '_';
768: /* more mapping here */
769: putc(ch,fout);
770: break;
771: default:
772: break; /* ignore */
773: }
774: }
775: /* if (count < 0) perror("netin"); */
776: break;
777: }
778: }
779:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.