1: #ifndef lint 2: static char *rcsid = "$Header: xnftp.c,v 2.0 85/11/21 07:22:51 jqj Exp $"; 3: #endif lint 4: 5: /* $Log: xnftp.c,v $ 6: * Revision 2.0 85/11/21 07:22:51 jqj 7: * 4.3BSD standard release 8: * 9: * Revision 1.5 85/09/24 14:45:10 jqj 10: * fix bug in alarm() handling that caused aborts during large file transfers. 11: * 12: * Revision 1.4 85/09/17 07:49:47 jqj 13: * 4.3 changes. Use more routines from CHlookup 14: * 15: * Revision 1.1 85/05/27 06:31:07 jqj 16: * Initial revision 17: * 18: */ 19: 20: #include <stdio.h> 21: #include <sys/time.h> 22: #include <sys/param.h> 23: #include <sys/stat.h> 24: #include <netns/ns.h> 25: #include <netns/sp.h> 26: #include "ftp_var.h" 27: #include <xnscourier/CH.h> 28: 29: CourierConnection *connected; 30: Clearinghouse2_ObjectName hostobjname; 31: Authentication1_Verifier verifier; 32: 33: /* the following 3 items make up the current session */ 34: Filing4_Session session; /* the current session */ 35: Clearinghouse2_ObjectName username; 36: int continuetime; 37: int remoteprocpending; 38: Filing4_Handle wdHandle; /* the current remote working dir */ 39: 40: static Filing4_ControlSequence nullControls = {0,0}; 41: static Filing4_ScopeSequence nullScope = {0,0}; 42: 43: /* global data used to communicate with BDT procedures 44: */ 45: extern GetAttributeSequences(), 46: listproc(), nlistproc(), 47: storeproc(), retrieveproc(); 48: static (*ProcEachSeq)(); 49: static long bytessent; 50: static FILE *fout, *fin; 51: 52: copyhandle(dest,src) 53: Filing4_Handle dest,src; 54: { 55: if (dest == (Unspecified *) 0) { 56: fprintf(stderr,"Oops. dest is null in copyhandle\n"); 57: exit(1); 58: } 59: dest[0] = src[0]; 60: dest[1] = src[1]; 61: } 62: 63: StringToAttr(str, attr) 64: char *str; 65: Filing4_Attribute *attr; 66: { 67: Unspecified buf[2049], *bp; 68: Cardinal len; 69: 70: bp = buf + sizeof_Cardinal(len); 71: len = externalize_String(&str, bp); 72: (void) externalize_Cardinal(&len, buf); 73: internalize_Clearinghouse2_Item(&(attr->value), buf); 74: return; 75: } 76: 77: char * 78: AttrToString(attr) 79: Filing4_Attribute *attr; 80: { 81: Unspecified buf[2049], *bp; 82: Cardinal len; 83: char *strval; 84: 85: externalize_Clearinghouse2_Item(&(attr->value), buf); 86: bp = buf; 87: bp += internalize_Cardinal(&len, bp); 88: bp += internalize_String(&strval, bp); 89: return(strval); 90: } 91: 92: UserToAttr(id, attr) 93: Clearinghouse2_Name id; 94: Filing4_Attribute *attr; 95: { 96: Unspecified buf[2049], *bp; 97: Cardinal len; 98: 99: bp = buf + sizeof_Cardinal(len); 100: len = externalize_Clearinghouse2_Name(&id, bp); 101: (void) externalize_Cardinal(&len, buf); 102: internalize_Clearinghouse2_Item(&(attr->value), buf); 103: return; 104: } 105: 106: LongCardinalToAttr(val, attr) 107: LongCardinal val; 108: Filing4_Attribute *attr; 109: { 110: Unspecified buf[3], *bp; 111: Cardinal len; 112: 113: bp = buf + sizeof_Cardinal(len); 114: len = externalize_LongCardinal(&val, bp); 115: (void) externalize_Cardinal(&len, buf); 116: internalize_Clearinghouse2_Item(&(attr->value), buf); 117: return; 118: } 119: 120: BooleanToAttr(val, attr) 121: int val; 122: Filing4_Attribute *attr; 123: { 124: Boolean boolval; 125: Unspecified buf[3], *bp; 126: Cardinal len; 127: 128: boolval = (Boolean) val; 129: bp = buf + sizeof_Cardinal(len); 130: len = externalize_Boolean(&boolval, bp); 131: (void) externalize_Cardinal(&len, buf); 132: internalize_Clearinghouse2_Item(&(attr->value), buf); 133: return; 134: } 135: 136: int 137: AttrToBoolean(attr) 138: Filing4_Attribute *attr; 139: { 140: Unspecified buf[1]; 141: Boolean result; 142: 143: (void) externalize_Unspecified(attr->value.sequence, buf); 144: (void) internalize_Boolean(&result, buf); 145: return(result); 146: } 147: 148: LongCardinal 149: AttrToLongCardinal(attr) 150: Filing4_Attribute *attr; 151: { 152: Unspecified buf[2]; 153: LongCardinal result; 154: 155: (void) externalize_Unspecified(attr->value.sequence, buf); 156: (void) externalize_Unspecified((attr->value.sequence)+1, buf+1); 157: (void) internalize_LongCardinal(&result, buf); 158: return(result); 159: } 160: 161: 162: getfilehandle(filename, handle) 163: char *filename; 164: Filing4_Handle handle; 165: { 166: Filing4_Attribute pathattr[1]; 167: Filing4_AttributeSequence attrseq; 168: Filing4_OpenResults openresult; 169: 170: if (filename == (char *)0 || *filename == '\000') { 171: copyhandle(handle,wdHandle); 172: return; 173: } 174: attrseq.length = 1; 175: attrseq.sequence = pathattr; 176: pathattr[0].type = Filing4_pathname; 177: copyhandle(handle, Filing4_nullHandle); 178: if (*filename != '/') { /* relative pathname specified */ 179: StringToAttr(filename, &pathattr[0]); 180: copyhandle(handle, wdHandle); 181: } else if (filename[1] == '\000') { 182: /* root specified */ 183: attrseq.length = 0; 184: } else { /* absolute pathname specified */ 185: StringToAttr(filename+1, &pathattr[0]); 186: } 187: alarm(0); 188: openresult = Filing4_Open(connected, NULL, attrseq, 189: handle, nullControls, 190: session); 191: alarm(continuetime); 192: copyhandle(handle, openresult.file); 193: } 194: 195: freefilehandle(handle) 196: Filing4_Handle handle; 197: { 198: if (handle[0] == Filing4_nullHandle[0] && 199: handle[1] == Filing4_nullHandle[1]) 200: return; /* don't free nullHandle */ 201: if (handle[0] == wdHandle[0] && 202: handle[1] == wdHandle[1]) 203: return; /* don't free working directory */ 204: alarm(0); 205: Filing4_Close(connected, NULL, handle, session); 206: alarm(continuetime); 207: } 208: 209: /* 210: * do a continue to make sure that the session doesn't time out. 211: * Note that this is usually called by an ALARM interrupt 212: */ 213: probe() 214: { 215: Filing4_ContinueResults cresult; 216: 217: alarm(0); /* cancel previous alarms */ 218: cresult = Filing4_Continue(connected, NULL, session); 219: continuetime = cresult.continuance / 5; /* seconds */ 220: alarm(continuetime); /* reset for another 2 min. or so */ 221: } 222: 223: CourierConnection * 224: hookup(name) 225: char *name; 226: { 227: register struct ns_addr *hostaddr; 228: extern struct ns_addr *getXNSaddr(); 229: Clearinghouse2_ObjectName defaultobjname; 230: static char hnamebuf[128]; 231: CourierConnection *cconn; 232: 233: CH_NameDefault(&defaultobjname); 234: hostobjname = CH_StringToName(name, &defaultobjname); 235: if ((hostaddr = CH_LookupAddrDN( hostobjname, 0, hnamebuf, 128))) { 236: /* should check here to be sure host is a file service */ 237: hostaddr->x_port = htons(IDPPORT_COURIER); /* ?? */ 238: cconn = CourierOpen(hostaddr); 239: /* reset objname to flush wildcards */ 240: /* clear_Clearinghouse2_ThreePartName(&hostobjname); */ 241: hostobjname = CH_StringToName(hnamebuf, &defaultobjname); 242: hostname = hnamebuf; 243: if (verbose) 244: printf("Connected to %s\n", hnamebuf); 245: } else { 246: printf("%s: unknown host\n", name); 247: cconn = (CourierConnection*)0; 248: } 249: return(cconn); 250: } 251: 252: 253: login(name,pwd) 254: char *pwd; 255: char *name; 256: { 257: Authentication1_Credentials credentials; 258: Filing4_LogonResults logonresult; 259: 260: username = CH_StringToName(name,&hostobjname); 261: MakeSimpleCredsAndVerifier(&username,pwd, 262: &credentials, &verifier); 263: logonresult = Filing4_Logon(connected, NULL, hostobjname, 264: credentials, verifier); 265: session = logonresult.session; 266: copyhandle(wdHandle, Filing4_nullHandle); 267: if (verbose) 268: printf("User %s:%s:%s logged on\n", username.object, 269: username.domain, username.organization); 270: alarm(0); 271: signal(SIGALRM, probe); 272: probe(); 273: } 274: 275: logout() 276: { 277: signal(SIGALRM, SIG_IGN); 278: Filing4_Logoff(connected, NULL, session); 279: clear_Filing4_Session(&session); 280: copyhandle(wdHandle, Filing4_nullHandle); 281: } 282: 283: domakedir(dest) 284: char *dest; 285: { 286: sendrequest("MKDIR", "-", dest); 287: } 288: 289: doremovedir(src) 290: char *src; 291: { 292: dodelete(src); 293: } 294: 295: dostore(src, dest) 296: char *src, *dest; 297: { 298: sendrequest("STOR", src, dest); 299: } 300: 301: doappend(src, dest) 302: char *src, *dest; 303: { 304: NYI(); 305: } 306: 307: dorename(src, dest) 308: char *src, *dest; 309: { 310: NYI(); 311: } 312: 313: recvrequest(cmd, local, remote, mode) 314: char *cmd, *local, *remote, *mode; 315: { 316: FILE *popen(); 317: int (*closefunc)(), pclose(), fclose(); 318: struct timeval start, stop; 319: Filing4_Handle remotehandle; /* note: an array */ 320: Filing4_AttributeTypeSequence typeseq; 321: Filing4_AttributeType tsvals[10]; 322: 323: closefunc = NULL; 324: fout = stdout; 325: typeseq.length = 0; typeseq.sequence = tsvals; 326: if (strcmp(local, "-") && *local != '|') 327: if (access(local, 2) < 0) { 328: char *dir = rindex(local, '/'); 329: /* get a good error message */ 330: if (dir != NULL) *dir = '\0'; 331: if (access(dir ? local : ".", 2) < 0) { 332: perror(local); 333: goto bad; 334: } 335: if (dir != NULL) *dir = '/'; 336: } 337: if (strcmp(local, "-") == 0) 338: fout = stdout; 339: else if (*local == '|') { 340: fout = popen(local + 1, "w"); 341: if (fout == NULL) { 342: perror(local + 1); 343: goto bad; 344: } 345: closefunc = pclose; 346: } else { 347: fout = fopen(local, mode); 348: if (fout == NULL) { 349: perror(local); 350: goto bad; 351: } 352: closefunc = fclose; 353: } 354: bytessent = 0; 355: gettimeofday(&start, (struct timezone *)0); 356: getfilehandle(remote, remotehandle); 357: alarm(0); 358: if (strcmp(cmd,"NLST") == 0) { 359: typeseq.length = 1; 360: typeseq.sequence[0] = Filing4_pathname; 361: ProcEachSeq = nlistproc; 362: Filing4_List(connected, GetAttributeSequences, remotehandle, 363: typeseq, nullScope, 364: BulkData1_immediateSink, session); 365: } 366: else if (strcmp(cmd,"LIST") == 0) { 367: typeseq.length = 5; 368: typeseq.sequence[0] = Filing4_name; 369: typeseq.sequence[1] = Filing4_dataSize; 370: typeseq.sequence[2] = Filing4_isDirectory; 371: typeseq.sequence[3] = Filing4_isTemporary; 372: typeseq.sequence[4] = Filing4_type; 373: ProcEachSeq = listproc; 374: Filing4_List(connected, GetAttributeSequences, remotehandle, 375: typeseq, nullScope, 376: BulkData1_immediateSink, session); 377: } 378: else if (strcmp(cmd,"RETR") == 0) { 379: Filing4_Retrieve(connected, retrieveproc, remotehandle, 380: BulkData1_immediateSink, session); 381: } 382: else printf("unrecognized command %s\n",cmd); 383: alarm(continuetime); 384: gettimeofday(&stop, (struct timezone *)0); 385: freefilehandle(remotehandle); 386: if (bytessent > 0 && verbose) 387: ptransfer("received", bytessent, &start, &stop); 388: bad: 389: if (closefunc != NULL && fout != NULL) 390: (*closefunc)(fout); 391: fout = NULL; 392: } 393: 394: 395: sendrequest(cmd, local, remote) 396: char *cmd, *local, *remote; 397: { 398: FILE *popen(); 399: int (*closefunc)(), pclose(), fclose(); 400: struct stat st; 401: struct timeval start, stop; 402: Filing4_StoreResults storeresults; 403: Filing4_CreateResults createresults; 404: Filing4_Handle remotehandle; 405: Filing4_AttributeSequence attrseq; 406: Filing4_Attribute attrvals[5]; 407: 408: closefunc = NULL; 409: if (strcmp(local, "-") == 0) { 410: fin = stdin; 411: closefunc = NULL; 412: } else if (*local == '|') { 413: fin = popen(local + 1, "r"); 414: if (fin == NULL) { 415: perror(local + 1); 416: goto bad; 417: } 418: closefunc = pclose; 419: } else { 420: fin = fopen(local, "r"); 421: if (fin == NULL) { 422: perror(local); 423: goto bad; 424: } 425: closefunc = fclose; 426: if (fstat(fileno(fin), &st) < 0 || 427: (st.st_mode&S_IFMT) != S_IFREG) { 428: fprintf(stderr, "%s: not a plain file.", local); 429: goto bad; 430: } 431: } 432: if (remote) { 433: char *dir = rindex(remote,'/'); 434: if (dir != NULL) { 435: *dir = '\000'; 436: getfilehandle(remote, remotehandle); 437: *dir = '/'; 438: remote = dir+1; 439: } else { 440: getfilehandle("", remotehandle); 441: } 442: } else { 443: printf("No remote name specified\n"); 444: return; 445: } 446: bytessent = 0; 447: gettimeofday(&start, (struct timezone *)0); 448: alarm(0); 449: if (strcmp(cmd,"STOR") == 0) { 450: attrseq.length = 2; 451: attrseq.sequence = attrvals; 452: attrvals[0].type = Filing4_name; 453: StringToAttr(remote, &attrvals[0]); 454: attrvals[1].type = Filing4_type; 455: if (typevalue == TYPE_A) 456: LongCardinalToAttr(Filing4_tText, &attrvals[1]); 457: else 458: LongCardinalToAttr(Filing4_tUnspecified, &attrvals[1]); 459: storeresults = Filing4_Store(connected, storeproc, 460: remotehandle, attrseq, 461: nullControls, 462: BulkData1_immediateSource, 463: session); 464: alarm(continuetime); 465: freefilehandle(storeresults.file); 466: } 467: else if (strcmp(cmd,"MKDIR") == 0) { 468: attrseq.length = 3; 469: attrseq.sequence = attrvals; 470: attrvals[0].type = Filing4_name; 471: StringToAttr(remote, &attrvals[0]); 472: attrvals[1].type = Filing4_isDirectory; 473: BooleanToAttr(1, &attrvals[1]); 474: attrvals[2].type = Filing4_type; 475: LongCardinalToAttr(Filing4_tDirectory, &attrvals[2]); 476: createresults = Filing4_Create(connected, NULL, 477: remotehandle, attrseq, 478: nullControls, session); 479: alarm(continuetime); 480: freefilehandle(createresults.file); 481: } 482: else { 483: printf("unrecognized command %s\n",cmd); 484: alarm(continuetime); 485: } 486: gettimeofday(&stop, (struct timezone *)0); 487: freefilehandle(remotehandle); 488: if (bytessent > 0 && verbose) 489: ptransfer("sent", bytessent, &start, &stop); 490: bad: 491: if (closefunc != NULL && fin != NULL) 492: (*closefunc)(fin); 493: fin = NULL; 494: } 495: 496: 497: 498: docd(dest) 499: char *dest; 500: { 501: Filing4_AttributeSequence attrseq; 502: Filing4_AttributeTypeSequence typeseq; 503: Filing4_AttributeType cdattrs[1]; 504: Filing4_GetAttributesResults garesult; 505: Filing4_Handle remotehandle, temphandle; 506: char trydest[100]; 507: int i; 508: 509: if (dest == (char*)NULL || *dest == '\0') { 510: trydest[0] = '/'; /* assume absolute pathname */ 511: strcpy(trydest+1,username.object); 512: getfilehandle(trydest, remotehandle); 513: } 514: else 515: getfilehandle(dest, remotehandle); 516: typeseq.length = 1; typeseq.sequence = cdattrs; 517: cdattrs[0] = Filing4_isDirectory; 518: alarm(0); 519: garesult = Filing4_GetAttributes(connected, NULL, remotehandle, 520: typeseq, session); 521: alarm(continuetime); 522: for (i = 0; i < garesult.attributes.length; i++) { 523: if (garesult.attributes.sequence[i].type == Filing4_isDirectory 524: && AttrToBoolean(&(garesult.attributes.sequence[i]))) { 525: copyhandle(temphandle, wdHandle); 526: copyhandle(wdHandle, remotehandle); /* change dir */ 527: if (verbose) dopwd(); 528: freefilehandle(temphandle); /* free old wdHandle */ 529: return; 530: } 531: } 532: printf("%s is not a directory\n", dest); 533: freefilehandle(remotehandle); 534: } 535: 536: dopwd() 537: { 538: Filing4_AttributeSequence attrseq; 539: Filing4_AttributeTypeSequence typeseq; 540: Filing4_AttributeType pwdattrs[1]; 541: Filing4_GetAttributesResults garesult; 542: 543: if (wdHandle[0] == 0 && wdHandle[1] == 0) { 544: printf("Remote working directory: /\n"); 545: return; 546: } 547: typeseq.length = 1; typeseq.sequence = pwdattrs; 548: pwdattrs[0] = Filing4_pathname; 549: alarm(0); 550: garesult = Filing4_GetAttributes(connected, NULL, wdHandle, typeseq, 551: session); 552: alarm(continuetime); 553: if (garesult.attributes.length > 0 && 554: garesult.attributes.sequence[0].type == Filing4_pathname) 555: printf("Remote working directory: /%s\n", 556: AttrToString(&(garesult.attributes.sequence[0]))); 557: else printf("Remote working directory not set\n"); 558: clear_Filing4_GetAttributesResults(&garesult); 559: } 560: 561: dodelete(src) 562: char *src; 563: { 564: Filing4_Handle remotehandle; 565: Filing4_AttributeSequence attrseq; 566: Filing4_AttributeTypeSequence typeseq; 567: Filing4_AttributeType delattrs[1]; 568: Filing4_GetAttributesResults garesult; 569: 570: typeseq.length = 1; typeseq.sequence = delattrs; 571: delattrs[0] = Filing4_isDirectory; 572: getfilehandle(src, remotehandle); 573: garesult = Filing4_GetAttributes(connected, NULL, remotehandle, 574: typeseq, session); 575: if (garesult.attributes.length > 0 && 576: garesult.attributes.sequence[0].type == Filing4_isDirectory && 577: AttrToBoolean(&(garesult.attributes.sequence[0]))) { 578: if (!confirm("Delete directory", src)) return; 579: } 580: 581: clear_Filing4_GetAttributesResults(&garesult); 582: alarm(0); 583: Filing4_Delete(connected, NULL, remotehandle, session); 584: alarm(continuetime); 585: } 586: 587: NYI() 588: { 589: printf("Not yet implemented\n"); 590: } 591: 592: 593: ptransfer(direction, bytes, t0, t1) 594: char *direction; 595: long bytes; 596: struct timeval *t0, *t1; 597: { 598: struct timeval td; 599: long ms; 600: float bs; 601: 602: tvsub(&td, t1, t0); 603: ms = (td.tv_sec * 1000) + (td.tv_usec / 1000); 604: #define nz(x) ((x) == 0 ? 1 : (x)) 605: bs = ((1000. * (float) bytes) / (float) nz(ms)); 606: printf("\n%ld bytes %s in %d.%02d seconds (%.2g Kbytes/s)\n", 607: bytes, direction, td.tv_sec, td.tv_usec / 10000, bs / 1024.); 608: } 609: 610: tvadd(tsum, t0) 611: struct timeval *tsum, *t0; 612: { 613: 614: tsum->tv_sec += t0->tv_sec; 615: tsum->tv_usec += t0->tv_usec; 616: if (tsum->tv_usec > 1000000) 617: tsum->tv_sec++, tsum->tv_usec -= 1000000; 618: } 619: 620: tvsub(tdiff, t1, t0) 621: struct timeval *tdiff, *t1, *t0; 622: { 623: 624: tdiff->tv_sec = t1->tv_sec - t0->tv_sec; 625: tdiff->tv_usec = t1->tv_usec - t0->tv_usec; 626: if (tdiff->tv_usec < 0) 627: tdiff->tv_sec--, tdiff->tv_usec += 1000000; 628: } 629: 630: nlistproc(attr) 631: Filing4_AttributeSequence attr; 632: { 633: int i; 634: char *thisname; 635: Filing4_AttributeType t; 636: 637: for (i = 0; i < attr.length; i++) { 638: t = attr.sequence[i].type; 639: if (t == Filing4_pathname) fputc('/', fout); 640: if (t == Filing4_name || 641: t == Filing4_pathname) { 642: thisname = AttrToString(&attr.sequence[i]); 643: fputs(thisname, fout); 644: fputc('\n', fout); 645: clear_String(&thisname); 646: return; 647: } 648: } 649: } 650: 651: 652: listproc(attr) 653: Filing4_AttributeSequence attr; 654: { 655: int i; 656: char *thisname = ""; 657: Boolean istemp = 0; 658: Boolean isdir = 0; 659: LongCardinal thistype = 0; 660: LongCardinal thissize = 0; 661: Filing4_AttributeType t; 662: char *filetypestr; 663: char filetypebuf[20]; 664: 665: for (i = 0; i < attr.length; i++) { 666: t = attr.sequence[i].type; 667: if (t == Filing4_name || 668: t == Filing4_pathname) 669: thisname = AttrToString(&attr.sequence[i]); 670: else if (t == Filing4_isDirectory) 671: isdir = AttrToBoolean(&attr.sequence[i]); 672: else if (t == Filing4_isTemporary) 673: istemp = AttrToBoolean(&attr.sequence[i]); 674: else if (t == Filing4_type) 675: thistype = AttrToLongCardinal(&attr.sequence[i]); 676: else if (t == Filing4_dataSize) 677: thissize = AttrToLongCardinal(&attr.sequence[i]); 678: } 679: 680: if (thistype == Filing4_tDirectory) 681: filetypestr = "(dir.)"; 682: else if (thistype == Filing4_tText) 683: filetypestr = "(text)"; 684: else if (thistype == Filing4_tSerialized) 685: filetypestr = "(ser.)"; 686: else if (thistype == 4353) 687: filetypestr = "(Star)"; 688: else if (thistype != Filing4_tUnspecified) { 689: sprintf(filetypebuf, "(%ld)", thistype); 690: filetypestr = filetypebuf; 691: } 692: else filetypestr = ""; 693: fprintf(fout, "%c%c%-6s%7ld %s\n", 694: isdir?'D':' ', istemp?'T':' ', 695: filetypestr, thissize, thisname); 696: clear_String(&thisname); 697: } 698: 699: #define MAXPACKS 20 700: static 701: GetAttributeSequences(conn) 702: CourierConnection *conn; 703: { 704: int count, i; 705: Unspecified buffer[MAXWORDS*MAXPACKS], *bp, *bufend; 706: Filing4_StreamOfAttributeSequence attrs; 707: 708: bufend = buffer; 709: bp = buffer+((MAXWORDS-1)*MAXPACKS); /* end of available space */ 710: while ((count = BDTread(conn, (char*)bufend, 711: MAXWORDS*sizeof(Unspecified))) > 0) { 712: bufend += count/sizeof(Unspecified); 713: bytessent += count; 714: if (bufend > bp) { 715: fprintf(stderr,"BDT read too big to fit\n"); 716: BDTabort(conn); 717: /* should clear out stuff here if we knew how much */ 718: } 719: } 720: bp = buffer; 721: while (bp < bufend) { 722: bp += internalize_Filing4_StreamOfAttributeSequence(&attrs,bp); 723: if (0 == (int) attrs.designator) { 724: for (i=0; i < attrs.nextSegment_case.segment.length; i++) { 725: (*ProcEachSeq)( 726: attrs.nextSegment_case.segment.sequence[i]); 727: } 728: free(attrs.nextSegment_case.segment.sequence); 729: } else { 730: for (i = 0; i < attrs.lastSegment_case.length; i++) { 731: (*ProcEachSeq)( 732: attrs.lastSegment_case.sequence[i]); 733: } 734: free(attrs.lastSegment_case.sequence); 735: return; 736: } 737: } 738: } 739: 740: int 741: getBDTch(conn,bpp) 742: CourierConnection *conn; 743: u_char **bpp; 744: { 745: static u_char buffer[SPPMAXDATA]; 746: static int count; 747: 748: if (*bpp == NULL) {*bpp = buffer; count = 0;} 749: if (*bpp >= buffer+count) { 750: count=BDTread(conn,buffer,sizeof(buffer)); 751: *bpp = buffer; 752: } 753: if (count <= 0) return(EOF); 754: else return(*((*bpp)++)); 755: 756: } 757: 758: retrieveproc(conn) 759: CourierConnection *conn; 760: { 761: int count, ocount, ch, hashbytes; 762: char buffer[SPPMAXDATA]; 763: int charset, charset16; 764: char *bp; 765: 766: switch (typevalue) { 767: default: 768: fprintf(stderr,"We don't support type %s. Using binary\n", 769: typename); 770: case TYPE_I: 771: case TYPE_L: 772: errno = ocount = 0; 773: fflush(fout); 774: while ((count = BDTread(conn, buffer, sizeof(buffer))) > 0) { 775: if ((ocount = write(fileno(fout),buffer,count)) < 0) { 776: perror("write"); 777: BDTabort(conn); 778: break; 779: } 780: bytessent += count; 781: if (hash) { 782: putchar('#'); 783: fflush(stdout); 784: } 785: } 786: if (count < 0) perror("netin"); 787: break; 788: 789: case TYPE_A: 790: charset = 0; charset16 = 0; bp = NULL; 791: hashbytes = 0; 792: while ((ch = getBDTch(conn,&bp)) != EOF) { 793: if (ch == '\377') { 794: ch = getBDTch(conn,&bp); 795: if (ch == '\377') charset16 = 1; 796: else charset = ch; 797: continue; 798: } 799: if (charset16) { 800: charset = ch; 801: ch = getBDTch(conn,&bp); 802: } 803: switch (charset) { 804: case 0: /* normal character set -- minimal xlation */ 805: if (ch == '\r') { 806: ch = '\n'; 807: while (hash && bytessent >= hashbytes){ 808: putchar('#'); 809: fflush(stdout); 810: hashbytes += sizeof(buffer); 811: } 812: } 813: else if (ch == ','+0200) ch = '_'; 814: /* more mapping here */ 815: putc(ch,fout); 816: bytessent++; 817: break; 818: default: 819: break; /* ignore */ 820: } 821: } 822: if (hash) { 823: while (bytessent < hashbytes) { 824: putchar('#'); 825: hashbytes += sizeof(buffer); 826: } 827: putchar('\n'); 828: fflush(stdout); 829: } 830: /* if (count < 0) perror("netin"); */ 831: break; 832: } 833: } 834: 835: storeproc(conn) 836: CourierConnection *conn; 837: { 838: int count, ocount; 839: u_char buffer[SPPMAXDATA]; 840: u_char *bp; 841: 842: errno = ocount = 0; 843: clearerr(fin); 844: switch (typevalue) { 845: default: 846: fprintf(stderr,"We don't support type %s. Using binary\n", 847: typename); 848: case TYPE_I: 849: case TYPE_L: 850: while ((count = fread(buffer,sizeof(char),SPPMAXDATA,fin)) > 0 851: && (ocount = BDTwrite(conn, buffer, count)) > 0) { 852: bytessent += count; 853: if (hash) { 854: putchar('#'); 855: fflush(stdout); 856: } 857: } 858: break; 859: case TYPE_A: 860: while ((count = fread(buffer,sizeof(char),SPPMAXDATA,fin)) 861: > 0) { 862: ocount = count; 863: for (bp = buffer; count > 0; count--, bp++) { 864: if (*bp == '\n') *bp = '\r'; 865: else if (*bp == '_') *bp = ','+0200; 866: /* more translations here */ 867: } 868: if ((ocount = BDTwrite(conn, buffer, ocount)) <= 0) 869: break; 870: bytessent += ocount; 871: if (hash) { 872: putchar('#'); 873: fflush(stdout); 874: } 875: } 876: break; 877: } 878: if (ocount < 0) { 879: BDTabort(conn); 880: perror("netout"); 881: } 882: else if (ferror(fin)) { 883: BDTabort(conn); 884: perror("fread"); 885: } 886: else 887: BDTclosewrite(conn); 888: }