home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1998 September / PCO_0998.ISO / filesbbs / dos / sbbs_src.exe / SBBS / XFER_HI.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-02  |  52.1 KB  |  1,517 lines

  1. #line 1 "XFER_HI.C"
  2.  
  3. /* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
  4.  
  5. #include "sbbs.h"
  6.  
  7. uint temp_dirnum;
  8.  
  9. /****************************************************************************/
  10. /* Uploads files                                                            */
  11. /****************************************************************************/
  12. void upload(uint dirnum)
  13. {
  14.     static char lastdesc[59];
  15.     uchar str[256],src[256]={""},descbeg[25]={""},descend[25]={""},path[256]
  16.         ,fname[13],keys[256],ch,*p;
  17.     time_t start,end;
  18.     int i,j,file,destuser[MAX_USERXFER],destusers=0;
  19.     uint k;
  20.     file_t f;
  21.     struct dfree d;
  22.     user_t user;
  23.     node_t node;
  24.  
  25. if(sys_status&SS_EVENT && online==ON_REMOTE && !dir_op(dirnum))
  26.     bprintf(text[UploadBeforeEvent],timeleft/60);
  27. if(altul)
  28.     strcpy(path,altpath[altul-1]);
  29. else
  30.     strcpy(path,dir[dirnum]->path);
  31. if(path[1]==':')
  32.     i=path[0]-'A'+1;
  33. else i=0;
  34. getdfree(i,&d);
  35. if(d.df_sclus==0xffff)
  36.     errormsg(WHERE,ERR_CHK,path,0);
  37. if((ulong)d.df_bsec*(ulong)d.df_sclus
  38.     *(ulong)d.df_avail<(ulong)min_dspace*1024L) {
  39.     bputs(text[LowDiskSpace]);
  40.     sprintf(str,"Diskspace is low: %s",path);
  41.     errorlog(str);
  42.     if(!dir_op(dirnum))
  43.         return; }
  44. bprintf(text[DiskNBytesFree],ultoac((ulong)d.df_bsec
  45.     *(ulong)d.df_sclus*(ulong)d.df_avail,tmp));
  46. f.dir=curdirnum=dirnum;
  47. f.misc=0;
  48. f.altpath=altul;
  49. bputs(text[Filename]);
  50. if(!getstr(fname,12,K_UPPER) || strchr(fname,'?') || strchr(fname,'*')
  51.     || !checkfname(fname) || (trashcan(fname,"FILE") && !dir_op(dirnum))) {
  52.     if(fname[0])
  53.         bputs(text[BadFilename]);
  54.     return; }
  55. if(dirnum==sysop_dir)
  56.     sprintf(str,text[UploadToSysopDirQ],fname);
  57. else if(dirnum==user_dir)
  58.     sprintf(str,text[UploadToUserDirQ],fname);
  59. else
  60.     sprintf(str,text[UploadToCurDirQ],fname,lib[dir[dirnum]->lib]->sname
  61.         ,dir[dirnum]->sname);
  62. if(!yesno(str)) return;
  63. action=NODE_ULNG;
  64. padfname(fname,f.name);
  65. sprintf(str,"%s%s",path,fname);
  66. if(fexist(str)) {   /* File is on disk */
  67.     if(!dir_op(dirnum) && online!=ON_LOCAL) {         /* local users or sysops */
  68.         bprintf(text[FileAlreadyThere],fname);
  69.         return; }
  70.     if(!yesno(text[FileOnDiskAddQ]))
  71.         return; }
  72. else if(online==ON_LOCAL) {
  73.     bputs(text[FileNotOnDisk]);
  74.     bputs(text[EnterPath]);
  75.     if(!getstr(tmp,60,K_LINE|K_UPPER))
  76.         return;
  77.     backslash(tmp);
  78.     sprintf(src,"%s%s",tmp,fname); }
  79. strcpy(str,dir[dirnum]->exts);
  80. strcpy(tmp,f.name);
  81. truncsp(tmp);
  82. j=strlen(str);
  83. for(i=0;i<j;i+=ch+1) { /* Check extension of upload with allowable exts */
  84.     p=strchr(str+i,',');
  85.     if(p!=NULL)
  86.         *p=0;
  87.     ch=strlen(str+i);
  88.     if(!strcmp(tmp+9,str+i))
  89.         break; }
  90. if(j && i>=j) {
  91.     bputs(text[TheseFileExtsOnly]);
  92.     bputs(dir[dirnum]->exts);
  93.     CRLF;
  94.     if(!dir_op(dirnum)) return; }
  95. bputs(text[SearchingForDupes]);
  96. for(i=k=0;i<usrlibs;i++)
  97.     for(j=0;j<usrdirs[i];j++,k++) {
  98.         outchar('.');
  99.         if(k && !(k%5))
  100.             bputs("\b\b\b\b\b     \b\b\b\b\b");
  101.         if((usrdir[i][j]==dirnum || dir[usrdir[i][j]]->misc&DIR_DUPES)
  102.             && findfile(usrdir[i][j],f.name)) {
  103.             bputs(text[SearchedForDupes]);
  104.             bprintf(text[FileAlreadyOnline],f.name);
  105.             if(!dir_op(dirnum))
  106.                 return;      /* File is in database for another dir */
  107.             if(usrdir[i][j]==dirnum)
  108.                 return; } } /* don't allow duplicates */
  109. bputs(text[SearchedForDupes]);
  110. if(dirnum==user_dir) {  /* User to User transfer */
  111.     bputs(text[EnterAfterLastDestUser]);
  112.     while((!dir_op(dirnum) && destusers<max_userxfer) || destusers<MAX_USERXFER) {
  113.         bputs(text[SendFileToUser]);
  114.         if(!getstr(str,LEN_ALIAS,K_UPRLWR))
  115.             break;
  116.         if((user.number=finduser(str))!=0) {
  117.             if(!dir_op(dirnum) && user.number==useron.number) {
  118.                 bputs(text[CantSendYourselfFiles]);
  119.                 continue; }
  120.             for(i=0;i<destusers;i++)
  121.                 if(user.number==destuser[i])
  122.                     break;
  123.             if(i<destusers) {
  124.                 bputs(text[DuplicateUser]);
  125.                 continue; }
  126.             getuserdat(&user);
  127.             if((user.rest&(FLAG('T')|FLAG('D')))
  128.                 || !chk_ar(lib[dir[user_dir]->lib]->ar,user)
  129.                 || !chk_ar(dir[user_dir]->dl_ar,user)) {
  130.                 bprintf(text[UserWontBeAbleToDl],user.alias); }
  131.             else {
  132.                 bprintf(text[UserAddedToDestList],user.alias);
  133.                 destuser[destusers++]=user.number; } }
  134.         else {
  135.             CRLF; } }
  136.     if(!destusers)
  137.         return; }
  138. if(dir[dirnum]->misc&DIR_RATE) {
  139.     SYNC;
  140.     bputs(text[RateThisFile]);
  141.     ch=getkey(K_ALPHA);
  142.     if(!isalpha(ch) || sys_status&SS_ABORT)
  143.         return;
  144.     CRLF;
  145.     sprintf(descbeg,text[Rated],toupper(ch)); }
  146. if(dir[dirnum]->misc&DIR_ULDATE) {
  147.     now=time(NULL);
  148.     if(descbeg[0])
  149.         strcat(descbeg," ");
  150.     sprintf(str,"%s  ",unixtodstr(now,tmp));
  151.     strcat(descbeg,str); }
  152. if(dir[dirnum]->misc&DIR_MULT) {
  153.     SYNC;
  154.     if(!noyes(text[MultipleDiskQ])) {
  155.         bputs(text[HowManyDisksTotal]);
  156.         if((i=getnum(99))<2)
  157.             return;
  158.         bputs(text[NumberOfFile]);
  159.         if((j=getnum(i))<1)
  160.             return;
  161.         if(j==1)
  162.             lastdesc[0]=0;
  163.         if(i>9)
  164.             sprintf(descend,text[FileOneOfTen],j,i);
  165.         else
  166.             sprintf(descend,text[FileOneOfTwo],j,i); }
  167.     else
  168.         lastdesc[0]=0; }
  169. else
  170.     lastdesc[0]=0;
  171. bputs(text[EnterDescNow]);
  172. i=LEN_FDESC-(strlen(descbeg)+strlen(descend));
  173. getstr(lastdesc,i,K_LINE|K_EDIT|K_AUTODEL);
  174. if(sys_status&SS_ABORT)
  175.     return;
  176. if(descend[0])      /* end of desc specified, so pad desc with spaces */
  177.     sprintf(f.desc,"%s%-*s%s",descbeg,i,lastdesc,descend);
  178. else                /* no end specified, so string ends at desc end */
  179.     sprintf(f.desc,"%s%s",descbeg,lastdesc);
  180.  
  181. if(dir[dirnum]->misc&DIR_ANON && !(dir[dirnum]->misc&DIR_AONLY)
  182.     && (dir_op(dirnum) || useron.exempt&FLAG('A'))) {
  183.     if(!noyes(text[AnonymousQ]))
  184.         f.misc|=FM_ANON; }
  185. sprintf(str,"%s%s",path,fname);
  186. if(src[0]) {    /* being copied from another local dir */
  187.     bprintf(text[RetrievingFile],fname);
  188.     if(mv(src,str,1))
  189.         return;
  190.     CRLF; }
  191. if(fexist(str)) {   /* File is on disk */
  192.     if(!uploadfile(&f))
  193.         return; }
  194. else {
  195.     menu("ULPROT");
  196.     SYNC;
  197.     strcpy(keys,"Q");
  198.     if(dirnum==user_dir || !max_batup)  /* no batch user to user xfers */
  199.         mnemonics(text[ProtocolOrQuit]);
  200.     else {
  201.         mnemonics(text[ProtocolBatchOrQuit]);
  202.         strcat(keys,"B"); }
  203.     for(i=0;i<total_prots;i++)
  204.         if(prot[i]->ulcmd[0] && chk_ar(prot[i]->ar,useron)) {
  205.             sprintf(tmp,"%c",prot[i]->mnemonic);
  206.             strcat(keys,tmp); }
  207.     ch=getkeys(keys,0);
  208.     if(ch=='Q')
  209.         return;
  210.     if(ch=='B') {
  211.         if(batup_total>=max_batup)
  212.             bputs(text[BatchUlQueueIsFull]);
  213.         else {
  214.             for(i=0;i<batup_total;i++)
  215.                 if(!strcmp(batup_name[i],f.name)) {
  216.                     bprintf(text[FileAlreadyInQueue],f.name);
  217.                     return; }
  218.             strcpy(batup_name[batup_total],f.name);
  219.             strcpy(batup_desc[batup_total],f.desc);
  220.             batup_dir[batup_total]=dirnum;
  221.             batup_misc[batup_total]=f.misc;
  222.             batup_alt[batup_total]=altul;
  223.             batup_total++;
  224.             bprintf(text[FileAddedToUlQueue]
  225.                 ,f.name,batup_total,max_batup); } }
  226.     else {
  227.         for(i=0;i<total_prots;i++)
  228.             if(prot[i]->ulcmd[0] && prot[i]->mnemonic==ch
  229.                 && chk_ar(prot[i]->ar,useron))
  230.                 break;
  231.         if(i<total_prots) {
  232.             start=time(NULL);
  233.             protocol(cmdstr(prot[i]->ulcmd,str,nulstr,NULL),0);
  234.             end=time(NULL);
  235.             if(!(dir[dirnum]->misc&DIR_ULTIME)) /* Don't deduct upload time */
  236.                 starttime+=end-start;
  237.             ch=uploadfile(&f);
  238.             autohangup();
  239.             if(!ch)  /* upload failed, don't process user to user xfer */
  240.                 return; } } }
  241. if(dirnum==user_dir) {  /* Add files to XFER.IXT in INDX dir */
  242.     sprintf(str,"%sXFER.IXT",data_dir);
  243.     if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) {
  244.         errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_APPEND);
  245.         return; }
  246.     for(j=0;j<destusers;j++) {
  247.         for(i=1;i<=sys_nodes;i++) { /* Tell user, if online */
  248.             getnodedat(i,&node,0);
  249.             if(node.useron==destuser[j] && !(node.misc&NODE_POFF)
  250.                 && (node.status==NODE_INUSE || node.status==NODE_QUIET)) {
  251.                 sprintf(str,text[UserToUserXferNodeMsg],node_num,useron.alias);
  252.                 putnmsg(i,str);
  253.                 break; } }
  254.         if(i>sys_nodes) {   /* User not online */
  255.             sprintf(str,text[UserSentYouFile],useron.alias);
  256.             putsmsg(destuser[j],str); }
  257.         sprintf(str,"%4.4u %12.12s %4.4u\r\n"
  258.             ,destuser[j],f.name,useron.number);
  259.         write(file,str,strlen(str)); }
  260.     close(file); }
  261. }
  262.  
  263. /****************************************************************************/
  264. /* Checks directory for 'dir' and prompts user to enter description for     */
  265. /* the files that aren't in the database.                                   */
  266. /* Returns 1 if the user aborted, 0 if not.                                 */
  267. /****************************************************************************/
  268. char bulkupload(uint dirnum)
  269. {
  270.     char done,str[256];
  271.     struct ffblk ff;
  272.     file_t f;
  273.  
  274. memset(&f,0,sizeof(file_t));
  275. f.dir=dirnum;
  276. f.altpath=altul;
  277. bprintf(text[BulkUpload],lib[dir[dirnum]->lib]->sname,dir[dirnum]->sname);
  278. sprintf(str,"%s*.*",altul>0 && altul<=altpaths ? altpath[altul-1]
  279.     : dir[dirnum]->path);
  280. done=findfirst(str,&ff,0);
  281. action=NODE_ULNG;
  282. SYNC;
  283. while(!done && !msgabort()) {
  284.     if(gettotalfiles(dirnum)>dir[dirnum]->maxfiles) {
  285.         bputs(text[DirFull]);
  286.         return(0); }
  287.     strupr(ff.ff_name);
  288.     padfname(ff.ff_name,str);
  289.     if(findfile(f.dir,str)==0) {
  290.         strcpy(f.name,str);
  291.         f.cdt=ff.ff_fsize;
  292.         bprintf(text[BulkUploadDescPrompt],f.name,f.cdt);
  293.         getstr(f.desc,LEN_FDESC,K_LINE);
  294.         if(sys_status&SS_ABORT)
  295.             return(1);
  296.         uploadfile(&f); }    /* used to abort here if the file failed upload */
  297.     done=findnext(&ff); }
  298. return(0);
  299. }
  300.  
  301.  
  302.  
  303. /****************************************************************************/
  304. /* This is the batch menu section                                           */
  305. /****************************************************************************/
  306. void batchmenu()
  307. {
  308.     char str[129],tmp2[250],done=0,ch;
  309.     uint i,j,xfrprot,xfrdir;
  310.     ulong totalcdt,totalsize,totaltime;
  311.     time_t start,end;
  312.     int file,n;
  313.     file_t f;
  314.  
  315. if(!batdn_total && !batup_total && upload_dir==INVALID_DIR) {
  316.     bputs(text[NoFilesInBatchQueue]);
  317.     return; }
  318. if(useron.misc&(RIP|WIP) && !(useron.misc&EXPERT))
  319.     menu("BATCHXFR");
  320. lncntr=0;
  321. while(online && !done && (batdn_total || batup_total
  322.     || upload_dir!=INVALID_DIR)) {
  323.     if(!(useron.misc&(EXPERT|RIP|WIP))) {
  324.         sys_status&=~SS_ABORT;
  325.         if(lncntr) {
  326.             SYNC;
  327.             CRLF;
  328.             if(lncntr)          /* CRLF or SYNC can cause pause */
  329.                 pause(); }
  330.         menu("BATCHXFR"); }
  331.     ASYNC;
  332.     bputs(text[BatchMenuPrompt]);
  333.     ch=getkeys("BCDLQRU?\r",0);
  334.     if(ch>SP)
  335.         logch(ch,0);
  336.     switch(ch) {
  337.         case '?':
  338.             if(useron.misc&(EXPERT|RIP|WIP))
  339.                 menu("BATCHXFR");
  340.             break;
  341.         case CR:
  342.         case 'Q':
  343.             lncntr=0;
  344.             done=1;
  345.             break;
  346.         case 'B':   /* Bi-directional transfers */
  347.             if(useron.rest&FLAG('D')) {
  348.                 bputs(text[R_Download]);
  349.                 break; }
  350.             if(useron.rest&FLAG('U')) {
  351.                 bputs(text[R_Upload]);
  352.                 break; }
  353.             if(!batdn_total) {
  354.                 bputs(text[DownloadQueueIsEmpty]);
  355.                 break; }
  356.             if(!batup_total && upload_dir==INVALID_DIR) {
  357.                 bputs(text[UploadQueueIsEmpty]);
  358.                 break; }
  359.             for(i=0,totalcdt=0;i<batdn_total;i++)
  360.                     totalcdt+=batdn_cdt[i];
  361.             if(!(useron.exempt&FLAG('D'))
  362.                 && totalcdt>useron.cdt+useron.freecdt) {
  363.                 bprintf(text[YouOnlyHaveNCredits]
  364.                     ,ultoac(useron.cdt+useron.freecdt,tmp));
  365.                 break; }
  366.             for(i=0,totalsize=totaltime=0;i<batdn_total;i++) {
  367.                 totalsize+=batdn_size[i];
  368.                 if(!(dir[batdn_dir[i]]->misc&DIR_TFREE) && cur_cps)
  369.                     totaltime+=batdn_size[i]/(ulong)cur_cps; }
  370.             if(!(useron.exempt&FLAG('T')) && !SYSOP && totaltime>timeleft) {
  371.                 bputs(text[NotEnoughTimeToDl]);
  372.                 break; }
  373.             menu("BIPROT");
  374.             if(!create_batchdn_lst())
  375.                 break;
  376.             if(!create_batchup_lst())
  377.                 break;
  378.             if(!create_bimodem_pth())
  379.                 break;
  380.             SYNC;
  381.             mnemonics(text[ProtocolOrQuit]);
  382.             strcpy(tmp2,"Q");
  383.             for(i=0;i<total_prots;i++)
  384.                 if(prot[i]->bicmd[0] && chk_ar(prot[i]->ar,useron)) {
  385.                     sprintf(tmp,"%c",prot[i]->mnemonic);
  386.                     strcat(tmp2,tmp); }
  387.             ungetkey(useron.prot);
  388.             ch=getkeys(tmp2,0);
  389.             if(ch=='Q')
  390.                 break;
  391.             for(i=0;i<total_prots;i++)
  392.                 if(prot[i]->bicmd[0] && prot[i]->mnemonic==ch
  393.                     && chk_ar(prot[i]->ar,useron))
  394.                     break;
  395.             if(i<total_prots) {
  396.                 xfrprot=i;
  397.                 action=NODE_BXFR;
  398.                 SYNC;
  399.                 for(i=0;i<batdn_total;i++)
  400.                     if(dir[batdn_dir[i]]->seqdev) {
  401.                         lncntr=0;
  402.                         unpadfname(batdn_name[i],tmp);
  403.                         sprintf(tmp2,"%s%s",temp_dir,tmp);
  404.                         if(!fexist(tmp2)) {
  405.                             seqwait(dir[batdn_dir[i]]->seqdev);
  406.                             bprintf(text[RetrievingFile],tmp);
  407.                             sprintf(str,"%s%s"
  408.                                 ,batdn_alt[i]>0 && batdn_alt[i]<=altpaths
  409.                                 ? altpath[batdn_alt[i]-1]
  410.                                 : dir[batdn_dir[i]]->path
  411.                                 ,tmp);
  412.                             mv(str,tmp2,1); /* copy the file to temp dir */
  413.                             getnodedat(node_num,&thisnode,1);
  414.                             thisnode.aux=0xff;
  415.                             putnodedat(node_num,thisnode);
  416.                             CRLF; } }
  417.                 sprintf(str,"%sBATCHDN.LST",node_dir);
  418.                 sprintf(tmp2,"%sBATCHUP.LST",node_dir);
  419.                 start=time(NULL);
  420.                 protocol(cmdstr(prot[xfrprot]->bicmd,str,tmp2,NULL),0);
  421.                 end=time(NULL);
  422.                 for(i=0;i<batdn_total;i++)
  423.                     if(dir[batdn_dir[i]]->seqdev) {
  424.                         unpadfname(batdn_name[i],tmp);
  425.                         sprintf(tmp2,"%s%s",temp_dir,tmp);
  426.                         remove(tmp2); }
  427.                 batch_upload();
  428.                 batch_download(xfrprot);
  429.                 if(batdn_total)     /* files still in queue, not xfered */
  430.                     notdownloaded(totalsize,start,end);
  431.                 autohangup(); }
  432.             break;
  433.         case 'C':
  434.             if(batup_total) {
  435.                 if(!noyes(text[ClearUploadQueueQ])) {
  436.                     batup_total=0;
  437.                     bputs(text[UploadQueueCleared]); } }
  438.             if(batdn_total) {
  439.                 if(!noyes(text[ClearDownloadQueueQ])) {
  440.                     for(i=0;i<batdn_total;i++) {
  441.                         f.dir=batdn_dir[i];
  442.                         f.datoffset=batdn_offset[i];
  443.                         f.size=batdn_size[i];
  444.                         strcpy(f.name,batdn_name[i]);
  445.                         closefile(f); }
  446.                     batdn_total=0;
  447.                     bputs(text[DownloadQueueCleared]); } }
  448.             break;
  449.         case 'D':
  450.             if(useron.rest&FLAG('D')) {
  451.                 bputs(text[R_Download]);
  452.                 break; }
  453.             if(!batdn_total) {
  454.                 bputs(text[DownloadQueueIsEmpty]);
  455.                 break; }
  456.             start_batch_download();
  457.             break;
  458.         case 'L':
  459.             if(batup_total) {
  460.                 bputs(text[UploadQueueLstHdr]);
  461.                 for(i=0;i<batup_total;i++)
  462.                     bprintf(text[UploadQueueLstFmt],i+1,batup_name[i]
  463.                         ,batup_desc[i]); }
  464.             if(batdn_total) {
  465.                 bputs(text[DownloadQueueLstHdr]);
  466.                 for(i=0,totalcdt=0,totalsize=0;i<batdn_total;i++) {
  467.                     bprintf(text[DownloadQueueLstFmt],i+1
  468.                         ,batdn_name[i],ultoac(batdn_cdt[i],tmp)
  469.                         ,ultoac(batdn_size[i],str)
  470.                         ,cur_cps
  471.                         ? sectostr(batdn_size[i]/(ulong)cur_cps,tmp2)
  472.                         : "??:??:??");
  473.                     totalsize+=batdn_size[i];
  474.                     totalcdt+=batdn_cdt[i]; }
  475.                 bprintf(text[DownloadQueueTotals]
  476.                     ,ultoac(totalcdt,tmp),ultoac(totalsize,str),cur_cps
  477.                     ? sectostr(totalsize/(ulong)cur_cps,tmp2)
  478.                     : "??:??:??"); }
  479.             break;  /* Questionable line ^^^, see note above function */
  480.         case 'R':
  481.             if(batup_total) {
  482.                 bprintf(text[RemoveWhichFromUlQueue],batup_total);
  483.                 n=getnum(batup_total);
  484.                 if(n>=1) {
  485.                     n--;
  486.                     batup_total--;
  487.                     while(n<batup_total) {
  488.                         batup_dir[n]=batup_dir[n+1];
  489.                         batup_misc[n]=batup_misc[n+1];
  490.                         batup_alt[n]=batup_alt[n+1];
  491.                         strcpy(batup_name[n],batup_name[n+1]);
  492.                         strcpy(batup_desc[n],batup_desc[n+1]);
  493.                         n++; }
  494.                     if(!batup_total)
  495.                         bputs(text[UploadQueueCleared]); } }
  496.              if(batdn_total) {
  497.                 bprintf(text[RemoveWhichFromDlQueue],batdn_total);
  498.                 n=getnum(batdn_total);
  499.                 if(n>=1) {
  500.                     n--;
  501.                     f.dir=batdn_dir[n];
  502.                     strcpy(f.name,batdn_name[n]);
  503.                     f.datoffset=batdn_offset[n];
  504.                     f.size=batdn_size[n];
  505.                     closefile(f);
  506.                     batdn_total--;
  507.                     while(n<batdn_total) {
  508.                         strcpy(batdn_name[n],batdn_name[n+1]);
  509.                         batdn_dir[n]=batdn_dir[n+1];
  510.                         batdn_cdt[n]=batdn_cdt[n+1];
  511.                         batdn_alt[n]=batdn_alt[n+1];
  512.                         batdn_size[n]=batdn_size[n+1];
  513.                         batdn_offset[n]=batdn_offset[n+1];
  514.                         n++; }
  515.                     if(!batdn_total)
  516.                         bputs(text[DownloadQueueCleared]); } }
  517.             break;
  518.        case 'U':
  519.             if(useron.rest&FLAG('U')) {
  520.                 bputs(text[R_Upload]);
  521.                 break; }
  522.             if(!batup_total && upload_dir==INVALID_DIR) {
  523.                 bputs(text[UploadQueueIsEmpty]);
  524.                 break; }
  525.             menu("BATUPROT");
  526.             if(!create_batchup_lst())
  527.                 break;
  528.             if(!create_bimodem_pth())
  529.                 break;
  530.             ASYNC;
  531.             mnemonics(text[ProtocolOrQuit]);
  532.             strcpy(str,"Q");
  533.             for(i=0;i<total_prots;i++)
  534.                 if(prot[i]->batulcmd[0] && chk_ar(prot[i]->ar,useron)) {
  535.                     sprintf(tmp,"%c",prot[i]->mnemonic);
  536.                     strcat(str,tmp); }
  537.             ch=getkeys(str,0);
  538.             if(ch=='Q')
  539.                 break;
  540.             for(i=0;i<total_prots;i++)
  541.                 if(prot[i]->batulcmd[0] && prot[i]->mnemonic==ch
  542.                     && chk_ar(prot[i]->ar,useron))
  543.                     break;
  544.             if(i<total_prots) {
  545.                 sprintf(str,"%sBATCHUP.LST",node_dir);
  546.                 xfrprot=i;
  547.                 if(batup_total)
  548.                     xfrdir=batup_dir[0];
  549.                 else
  550.                     xfrdir=upload_dir;
  551.                 action=NODE_ULNG;
  552.                 SYNC;
  553.                 if(online==ON_REMOTE) {
  554.                     delfiles(temp_dir,"*.*");
  555.                     start=time(NULL);
  556.                     protocol(cmdstr(prot[xfrprot]->batulcmd,str,nulstr,NULL),1);
  557.                     end=time(NULL);
  558.                     if(!(dir[xfrdir]->misc&DIR_ULTIME))
  559.                         starttime+=end-start; }
  560.                 batch_upload();
  561.                 delfiles(temp_dir,"*.*");
  562.                 autohangup(); }
  563.             break; } }
  564. delfiles(temp_dir,"*.*");
  565. }
  566.  
  567. /****************************************************************************/
  568. /* Download files from batch queue                                          */
  569. /****************************************************************************/
  570. void start_batch_download()
  571. {
  572.     char ch,str[256],tmp2[256],tmp3[128],fname[64];
  573.     int j;
  574.     uint i,xfrprot;
  575.     ulong totalcdt,totalsize,totaltime;
  576.     time_t start,end;
  577.     file_t f;
  578.  
  579. if(useron.rest&FLAG('D')) {     /* Download restriction */
  580.     bputs(text[R_Download]);
  581.     return; }
  582. for(i=0,totalcdt=0;i<batdn_total;i++)
  583.     totalcdt+=batdn_cdt[i];
  584. if(!(useron.exempt&FLAG('D'))
  585.     && totalcdt>useron.cdt+useron.freecdt) {
  586.     bprintf(text[YouOnlyHaveNCredits]
  587.         ,ultoac(useron.cdt+useron.freecdt,tmp));
  588.     return; }
  589.  
  590. if(online==ON_LOCAL) {          /* Local download */
  591.     bputs(text[EnterPath]);
  592.     if(!getstr(str,60,K_LINE|K_UPPER))
  593.         return;
  594.     backslash(str);
  595.     for(i=0;i<batdn_total;i++) {
  596.         curdirnum=batdn_dir[i];         /* for ARS */
  597.         lncntr=0;
  598.         unpadfname(batdn_name[i],tmp);
  599.         sprintf(tmp2,"%s%s",str,tmp);
  600.         seqwait(dir[batdn_dir[i]]->seqdev);
  601.         bprintf(text[RetrievingFile],tmp);
  602.         sprintf(tmp3,"%s%s"
  603.             ,batdn_alt[i]>0 && batdn_alt[i]<=altpaths
  604.             ? altpath[batdn_alt[i]-1]
  605.             : dir[batdn_dir[i]]->path
  606.             ,tmp);
  607.         j=mv(tmp3,tmp2,1);
  608.         getnodedat(node_num,&thisnode,1);
  609.         thisnode.aux=30; /* clear the seq dev # */
  610.         putnodedat(node_num,thisnode);
  611.         CRLF;
  612.         if(j)   /* copy unsuccessful */
  613.             return;
  614.         for(j=0;j<total_dlevents;j++)
  615.             if(!stricmp(dlevent[j]->ext,batdn_name[i]+9)
  616.                 && chk_ar(dlevent[j]->ar,useron)) {
  617.                 bputs(dlevent[j]->workstr);
  618.                 external(cmdstr(dlevent[j]->cmd,tmp2,nulstr,NULL),EX_OUTL);
  619.                 CRLF; }
  620.         }
  621.     for(i=0;i<batdn_total;i++) {
  622.         curdirnum=batdn_dir[i];         /* for ARS */
  623.         f.dir=batdn_dir[i];
  624.         strcpy(f.name,batdn_name[i]);
  625.         f.datoffset=batdn_offset[i];
  626.         f.size=batdn_size[i];
  627.         f.altpath=batdn_alt[i];
  628.         downloadfile(f);
  629.         closefile(f); }
  630.     batdn_total=0;
  631.     return; }
  632.  
  633. for(i=0,totalsize=totaltime=0;i<batdn_total;i++) {
  634.     totalsize+=batdn_size[i];
  635.     if(!(dir[batdn_dir[i]]->misc&DIR_TFREE) && cur_cps)
  636.         totaltime+=batdn_size[i]/(ulong)cur_cps; }
  637. if(!(useron.exempt&FLAG('T')) && !SYSOP && totaltime>timeleft) {
  638.     bputs(text[NotEnoughTimeToDl]);
  639.     return; }
  640. menu("BATDPROT");
  641. if(!create_batchdn_lst())
  642.     return;
  643. if(!create_bimodem_pth())
  644.     return;
  645. ASYNC;
  646. mnemonics(text[ProtocolOrQuit]);
  647. strcpy(tmp2,"Q");
  648. for(i=0;i<total_prots;i++)
  649.     if(prot[i]->batdlcmd[0] && chk_ar(prot[i]->ar,useron)) {
  650.         sprintf(tmp,"%c",prot[i]->mnemonic);
  651.         strcat(tmp2,tmp); }
  652. ungetkey(useron.prot);
  653. ch=getkeys(tmp2,0);
  654. if(ch=='Q' || sys_status&SS_ABORT)
  655.     return;
  656. for(i=0;i<total_prots;i++)
  657.     if(prot[i]->batdlcmd[0] && prot[i]->mnemonic==ch
  658.         && chk_ar(prot[i]->ar,useron))
  659.         break;
  660. if(i<total_prots) {
  661.     xfrprot=i;
  662.     /* delfiles(temp_dir,"*.*"); fix for CD-ROM */
  663.     for(i=0;i<batdn_total;i++) {
  664.         curdirnum=batdn_dir[i];         /* for ARS */
  665.         unpadfname(batdn_name[i],fname);
  666.         if(dir[batdn_dir[i]]->seqdev) {
  667.             lncntr=0;
  668.             sprintf(tmp2,"%s%s",temp_dir,fname);
  669.             if(!fexist(tmp2)) {
  670.                 seqwait(dir[batdn_dir[i]]->seqdev);
  671.                 bprintf(text[RetrievingFile],fname);
  672.                 sprintf(str,"%s%s"
  673.                     ,batdn_alt[i]>0 && batdn_alt[i]<=altpaths
  674.                     ? altpath[batdn_alt[i]-1]
  675.                     : dir[batdn_dir[i]]->path
  676.                     ,fname);
  677.                 mv(str,tmp2,1); /* copy the file to temp dir */
  678.                 getnodedat(node_num,&thisnode,1);
  679.                 thisnode.aux=40; /* clear the seq dev # */
  680.                 putnodedat(node_num,thisnode);
  681.                 CRLF; } }
  682.         else
  683.             sprintf(tmp2,"%s%s"
  684.                 ,batdn_alt[i]>0 && batdn_alt[i]<=altpaths
  685.                 ? altpath[batdn_alt[i]-1]
  686.                 : dir[batdn_dir[i]]->path
  687.                 ,fname);
  688.         sprintf(str,"total_dlevents=%d",total_dlevents);
  689. //          logline("dl",str);
  690.         for(j=0;j<total_dlevents;j++) {
  691. //              logline("dl",dlevent[j]->ext);
  692.   //          logline("dl",dlevent[j]->cmd);
  693.     //          logline("dl",tmp2);
  694.             if(stricmp(dlevent[j]->ext,batdn_name[i]+9))
  695.                 continue;
  696. //              logline("dl","chkar");
  697.             if(!chk_ar(dlevent[j]->ar,useron))
  698.                 continue;
  699. //              logline("dl","bputs");
  700.             bputs(dlevent[j]->workstr);
  701. //              logline("dl","external");
  702.             external(cmdstr(dlevent[j]->cmd,tmp2,nulstr,NULL),EX_OUTL);
  703. //              logline("dl","crlf");
  704.             CRLF; }
  705. //          logline("dl","after dlevents");
  706.         }
  707.  
  708.     sprintf(str,"%sBATCHDN.LST",node_dir);
  709.     getnodedat(node_num,&thisnode,1);
  710.     action=NODE_DLNG;
  711.     if(cur_cps)
  712.         unixtodos(now+(totalsize/(ulong)cur_cps)
  713.             ,&date,&curtime);
  714.     thisnode.aux=(curtime.ti_hour*60)+curtime.ti_min;
  715.     thisnode.action=action;
  716.     putnodedat(node_num,thisnode); /* calculate ETA */
  717.     start=time(NULL);
  718.     protocol(cmdstr(prot[xfrprot]->batdlcmd,str,nulstr,NULL),0);
  719.     end=time(NULL);
  720.     batch_download(xfrprot);
  721.     if(batdn_total)
  722.         notdownloaded(totalsize,start,end);
  723.     /* delfiles(temp_dir,"*.*"); fix for CD-ROM */
  724.     autohangup(); }
  725. }
  726.  
  727. /*****************************************************************************/
  728. /* Temp directory section. Files must be extracted here and both temp_uler   */
  729. /* and temp_uler fields should be filled before entrance.                    */
  730. /*****************************************************************************/
  731. void temp_xfer()
  732. {
  733.     char str[256],tmp2[256],done=0,ch;
  734.     uint i,dirnum=total_dirs,j,files;
  735.     ulong bytes;
  736.     time_t start,end;
  737.     struct ffblk ff;
  738.     struct dfree d;
  739.     file_t f;
  740.  
  741. if(!usrlibs)
  742.     return;
  743. if(useron.rest&FLAG('D')) {
  744.     bputs(text[R_Download]);
  745.     return; }
  746. /*************************************/
  747. /* Create TEMP directory information */
  748. /*************************************/
  749. if((dir[dirnum]=(dir_t *)MALLOC(sizeof(dir_t)))==0) {
  750.     errormsg(WHERE,ERR_ALLOC,"temp_dir",sizeof(dir_t));
  751.     return; }
  752. memset(dir[dirnum],0,sizeof(dir_t));
  753. dir[dirnum]->lname="Temporary";
  754. dir[dirnum]->sname="Temp";
  755. strcpy(dir[dirnum]->code,"TEMP");
  756. dir[dirnum]->path=temp_dir;
  757. dir[dirnum]->maxfiles=MAX_FILES;
  758. dir[dirnum]->data_dir=dir[0]->data_dir;
  759. dir[dirnum]->op_ar=nulstr;
  760. temp_dirnum=curdirnum=usrdir[curlib][curdir[curlib]];
  761. total_dirs++;
  762.  
  763. /****************************/
  764. /* Fill filedat information */
  765. /****************************/
  766. sprintf(f.name,"TEMP_%3.3d.%s",node_num,useron.tmpext);
  767. strcpy(f.desc,"Temp File");
  768. f.dir=dirnum;
  769. f.misc=f.timesdled=f.dateuled=f.datedled=0L;
  770.  
  771. if(useron.misc&(RIP|WIP) && !(useron.misc&EXPERT))
  772.     menu("TEMPXFER");
  773. lncntr=0;
  774. while(online && !done) {
  775.     if(!(useron.misc&(EXPERT|RIP|WIP))) {
  776.         sys_status&=~SS_ABORT;
  777.         if(lncntr) {
  778.             SYNC;
  779.             CRLF;
  780.             if(lncntr)          /* CRLF or SYNC can cause pause */
  781.                 pause(); }
  782.         menu("TEMPXFER"); }
  783.     ASYNC;
  784.     bputs(text[TempDirPrompt]);
  785.     strcpy(f.uler,temp_uler);
  786.     ch=getkeys("ADEFNILQRVX?\r",0);
  787.     if(ch>SP)
  788.         logch(ch,0);
  789.     switch(ch) {
  790.         case 'A':   /* add to temp file */
  791.             if(temp_dir[1]==':')
  792.                 i=temp_dir[0]-'A'+1;
  793.             else i=0;
  794.             getdfree(i,&d);
  795.             if(d.df_sclus==0xffff)
  796.                 errormsg(WHERE,ERR_CHK,temp_dir,0);
  797.             if((ulong)d.df_bsec*(ulong)d.df_sclus
  798.                 *(ulong)d.df_avail<(ulong)min_dspace*1024L) {
  799.                 bputs(text[LowDiskSpace]);
  800.                 sprintf(str,"Diskspace is low: %s",temp_dir);
  801.                 errorlog(str);
  802.                 if(!dir_op(dirnum))
  803.                     break; }
  804.             bprintf(text[DiskNBytesFree],ultoac((ulong)d.df_bsec
  805.                 *(ulong)d.df_sclus*(ulong)d.df_avail,tmp));
  806.             if(!getfilespec(str))
  807.                 break;
  808.             if(!checkfname(str))
  809.                 break;
  810.             sprintf(tmp2,"Added %s to %s",str,f.name);
  811.             logline(nulstr,tmp2);
  812.             sprintf(tmp2,"%s%s",temp_dir,str);
  813.             sprintf(str,"%s%s",temp_dir,f.name);
  814.             external(cmdstr(temp_cmd(),str,tmp2,NULL),EX_CC|EX_OUTL|EX_OUTR);
  815.             break;
  816.         case 'D':   /* download from temp dir */
  817.             sprintf(str,"%s%s",temp_dir,f.name);
  818.             if(!fexist(str)) {
  819.                 bprintf(text[TempFileNotCreatedYet],f.name);
  820.                 break; }
  821.             f.size=f.cdt=flength(str);
  822.             f.opencount=0;
  823.             if(temp_cdt)    /* if file was not free */
  824.                 f.cdt=f.size;
  825.             else
  826.                 f.cdt=0;
  827.             if(!(useron.exempt&FLAG('D'))
  828.                 && f.cdt>useron.cdt+useron.freecdt) {
  829.                 bprintf(text[YouOnlyHaveNCredits]
  830.                     ,ultoac(useron.cdt+useron.freecdt,tmp));
  831.                 break; }    /* f.cdt must equal size here */
  832.             if(!(useron.exempt&FLAG('T')) && !dir_op(dirnum)
  833.                 && !(dir[temp_dirnum]->misc&DIR_TFREE) && cur_cps
  834.                 && f.size/(ulong)cur_cps>timeleft) {
  835.                 bputs(text[NotEnoughTimeToDl]);
  836.                 break; }
  837.             if(!chk_ar(dir[temp_dirnum]->dl_ar,useron)) {
  838.                 bputs(text[CantDownloadFromDir]);
  839.                 break; }
  840.             addfiledat(&f);
  841.             menu("DLPROT");
  842.             SYNC;
  843.             mnemonics(text[ProtocolOrQuit]);
  844.             strcpy(tmp2,"Q");
  845.             for(i=0;i<total_prots;i++)
  846.                 if(prot[i]->dlcmd[0] && chk_ar(prot[i]->ar,useron)) {
  847.                     sprintf(tmp,"%c",prot[i]->mnemonic);
  848.                     strcat(tmp2,tmp); }
  849.             ungetkey(useron.prot);
  850.             ch=getkeys(tmp2,0);
  851.             for(i=0;i<total_prots;i++)
  852.                 if(prot[i]->dlcmd[0] && prot[i]->mnemonic==ch
  853.                     && chk_ar(prot[i]->ar,useron))
  854.                     break;
  855.             if(i<total_prots) {
  856.                 getnodedat(node_num,&thisnode,1);
  857.                 action=NODE_DLNG;
  858.                 if(cur_cps)
  859.                     unixtodos(now+(f.size/(ulong)cur_cps)
  860.                         ,&date,&curtime);
  861.                 thisnode.aux=(curtime.ti_hour*60)+curtime.ti_min;
  862.                 putnodedat(node_num,thisnode); /* calculate ETA */
  863.                 start=time(NULL);
  864.                 j=protocol(cmdstr(prot[i]->dlcmd,str,nulstr,NULL),0);
  865.                 end=time(NULL);
  866.                 if(dir[temp_dirnum]->misc&DIR_TFREE)
  867.                     starttime+=end-start;
  868.                 if(prot[i]->misc&PROT_DSZLOG) {
  869.                     if(checkprotlog(f))
  870.                         downloadfile(f);
  871.                     else
  872.                         notdownloaded(f.size,start,end); }
  873.                 else {
  874.                     if(!j)
  875.                         downloadfile(f);
  876.                     else {
  877.                         bprintf(text[FileNotSent],f.name);
  878.                         notdownloaded(f.size,start,end); } }
  879.                 autohangup(); }
  880.             removefiledat(f);
  881.             break;
  882.         case 'E':
  883.             extract(usrdir[curlib][curdir[curlib]]);
  884.             sys_status&=~SS_ABORT;
  885.             break;
  886.         case 'F':   /* Create a file list */
  887.             delfiles(temp_dir,"*.*");
  888.             create_filelist("FILELIST.TXT",0);
  889.             if(!(sys_status&SS_ABORT))
  890.                 logline(nulstr,"Created list of all files");
  891.             CRLF;
  892.             sys_status&=~SS_ABORT;
  893.             break;
  894.         case 'I':   /* information on what's here */
  895.             bprintf(text[TempFileInfo],f.uler,temp_file);
  896.             break;
  897.         case 'L':   /* list files in dir */
  898.             if(!getfilespec(str))
  899.                 break;
  900.             if(!checkfname(str))
  901.                 break;
  902.             bytes=files=0L;
  903.             CRLF;
  904.             sprintf(tmp2,"%s%s",temp_dir,str);
  905.             i=findfirst(tmp2,&ff,0);
  906.             while(!i && !msgabort()) {
  907.                 bprintf("%s %10s\r\n",padfname(ff.ff_name,str)
  908.                     ,ultoac(ff.ff_fsize,tmp));
  909.                 files++;
  910.                 bytes+=ff.ff_fsize;
  911.                 i=findnext(&ff); }
  912.             if(!files)
  913.                 bputs(text[EmptyDir]);
  914.             else if(files>1)
  915.                 bprintf(text[TempDirTotal],ultoac(bytes,tmp),files);
  916.             break;
  917.         case 'N':   /* Create a list of new files */
  918.             delfiles(temp_dir,"*.*");
  919.             create_filelist("NEWFILES.TXT",FL_ULTIME);
  920.             if(!(sys_status&SS_ABORT))
  921.                 logline(nulstr,"Created list of new files");
  922.             CRLF;
  923.             sys_status&=~SS_ABORT;
  924.             break;
  925.         case 'R':   /* Remove files from dir */
  926.             if(!getfilespec(str))
  927.                 break;
  928.             // padfname(str,tmp);  Removed 04/14/96
  929.             bprintf(text[NFilesRemoved],delfiles(temp_dir,tmp));
  930.             break;
  931.         case 'V':   /* view files in dir */
  932.             bputs(text[FileSpec]);
  933.             if(!getstr(str,12,K_UPPER) || !checkfname(str))
  934.                 break;
  935.             viewfiles(dirnum,str);
  936.             break;
  937.         case CR:
  938.         case 'Q':   /* quit */
  939.             done=1;
  940.             break;
  941.         case 'X':   /* extract from archive in temp dir */
  942.             extract(dirnum);
  943.             sys_status&=~SS_ABORT;
  944.             break;
  945.         case '?':   /* menu */
  946.             if(useron.misc&(EXPERT|RIP|WIP))
  947.                 menu("TEMPXFER");
  948.             break; }
  949.     if(sys_status&SS_ABORT)
  950.         break; }
  951. FREE(dir[dirnum]);
  952. total_dirs--;
  953. }
  954.  
  955.  
  956. /****************************************************************************/
  957. /* Re-sorts file directory 'dirnum' according to dir[dirnum]->sort type     */
  958. /****************************************************************************/
  959. void resort(uint dirnum)
  960. {
  961.     char str[25],ixbfname[128],datfname[128],exbfname[128],txbfname[128]
  962.         ,ext[512],nulbuf[512];
  963.     uchar HUGE16 *ixbbuf, HUGE16 *datbuf;
  964.     uchar HUGE16 *ixbptr[MAX_FILES];
  965.     int ixbfile,datfile,exbfile,txbfile,i,j;
  966.     ulong ixblen,datlen,offset,newoffset,l;
  967.  
  968. memset(nulbuf,0,512);
  969. bprintf(text[ResortLineFmt],lib[dir[dirnum]->lib]->sname,dir[dirnum]->sname);
  970. sprintf(ixbfname,"%s%s.IXB",dir[dirnum]->data_dir,dir[dirnum]->code);
  971. sprintf(datfname,"%s%s.DAT",dir[dirnum]->data_dir,dir[dirnum]->code);
  972. sprintf(exbfname,"%s%s.EXB",dir[dirnum]->data_dir,dir[dirnum]->code);
  973. sprintf(txbfname,"%s%s.TXB",dir[dirnum]->data_dir,dir[dirnum]->code);
  974.  
  975. if(flength(ixbfname)<1L || flength(datfname)<1L) {
  976.     remove(exbfname);
  977.     remove(txbfname);
  978.     remove(ixbfname);
  979.     remove(datfname);
  980.     bputs(text[ResortEmptyDir]);
  981.     return; }
  982. bputs(text[Sorting]);
  983. if((ixbfile=nopen(ixbfname,O_RDONLY))==-1) {
  984.     errormsg(WHERE,ERR_OPEN,ixbfname,O_RDONLY);
  985.     return; }
  986. if((datfile=nopen(datfname,O_RDONLY))==-1) {
  987.     close(ixbfile);
  988.     errormsg(WHERE,ERR_OPEN,datfname,O_RDONLY);
  989.     return; }
  990. ixblen=filelength(ixbfile);
  991. datlen=filelength(datfile);
  992. if((ixbbuf=MALLOC(ixblen))==NULL) {
  993.     close(ixbfile);
  994.     close(datfile);
  995.     errormsg(WHERE,ERR_ALLOC,ixbfname,ixblen);
  996.     return; }
  997. if((datbuf=MALLOC(datlen))==NULL) {
  998.     close(ixbfile);
  999.     close(datfile);
  1000.     FREE((char *)ixbbuf);
  1001.     errormsg(WHERE,ERR_ALLOC,datfname,datlen);
  1002.     return; }
  1003. if(lread(ixbfile,ixbbuf,ixblen)!=ixblen) {
  1004.     close(ixbfile);
  1005.     close(datfile);
  1006.     FREE((char *)ixbbuf);
  1007.     FREE((char *)datbuf);
  1008.     errormsg(WHERE,ERR_READ,ixbfname,ixblen);
  1009.     return; }
  1010. if(lread(datfile,datbuf,datlen)!=datlen) {
  1011.     close(ixbfile);
  1012.     close(datfile);
  1013.     FREE((char *)ixbbuf);
  1014.     FREE((char *)datbuf);
  1015.     errormsg(WHERE,ERR_READ,datfname,datlen);
  1016.     return; }
  1017. close(ixbfile);
  1018. close(datfile);
  1019. if((ixbfile=nopen(ixbfname,O_WRONLY|O_TRUNC))==-1) {
  1020.     FREE((char *)ixbbuf);
  1021.     FREE((char *)datbuf);
  1022.     errormsg(WHERE,ERR_OPEN,ixbfname,O_WRONLY|O_TRUNC);
  1023.     return; }
  1024. if((datfile=nopen(datfname,O_WRONLY|O_TRUNC))==-1) {
  1025.     close(ixbfile);
  1026.     FREE((char *)ixbbuf);
  1027.     FREE((char *)datbuf);
  1028.     errormsg(WHERE,ERR_OPEN,datfname,O_WRONLY|O_TRUNC);
  1029.     return; }
  1030. for(l=0,i=0;l<ixblen && i<MAX_FILES;l+=F_IXBSIZE,i++)
  1031.     ixbptr[i]=ixbbuf+l;
  1032. switch(dir[dirnum]->sort) {
  1033.     case SORT_NAME_A:
  1034.         qsort((void *)ixbptr,ixblen/F_IXBSIZE,sizeof(ixbptr[0])
  1035.             ,(int(*)(const void*, const void*))fnamecmp_a);
  1036.         break;
  1037.     case SORT_NAME_D:
  1038.         qsort((void *)ixbptr,ixblen/F_IXBSIZE,sizeof(ixbptr[0])
  1039.             ,(int(*)(const void*, const void*))fnamecmp_d);
  1040.         break;
  1041.     case SORT_DATE_A:
  1042.         qsort((void *)ixbptr,ixblen/F_IXBSIZE,sizeof(ixbptr[0])
  1043.             ,(int(*)(const void*, const void*))fdatecmp_a);
  1044.         break;
  1045.     case SORT_DATE_D:
  1046.         qsort((void *)ixbptr,ixblen/F_IXBSIZE,sizeof(ixbptr[0])
  1047.             ,(int(*)(const void*, const void*))fdatecmp_d);
  1048.         break; }
  1049.  
  1050. if((exbfile=nopen(exbfname,O_RDWR|O_CREAT))==-1) {
  1051.     close(ixbfile);
  1052.     close(datfile);
  1053.     FREE((char *)ixbbuf);
  1054.     FREE((char *)datbuf);
  1055.     errormsg(WHERE,ERR_OPEN,exbfname,O_RDWR|O_CREAT);
  1056.     return; }
  1057. if((txbfile=nopen(txbfname,O_RDWR|O_CREAT))==-1) {
  1058.     close(exbfile);
  1059.     close(datfile);
  1060.     close(exbfile);
  1061.     FREE((char *)ixbbuf);
  1062.     FREE((char *)datbuf);
  1063.     errormsg(WHERE,ERR_OPEN,txbfname,O_RDWR|O_CREAT);
  1064.     return; }
  1065.  
  1066. for(i=0;i<ixblen/F_IXBSIZE;i++) {
  1067.     offset=ixbptr[i][11]|((long)ixbptr[i][12]<<8)|((long)ixbptr[i][13]<<16);
  1068.     lwrite(datfile,&datbuf[offset],F_LEN);
  1069.  
  1070.     newoffset=(ulong)i*(ulong)F_LEN;
  1071.  
  1072.     j=datbuf[offset+F_MISC];  /* misc bits */
  1073.     if(j!=ETX) j-=SP;
  1074.     if(j&FM_EXTDESC) { /* extended description */
  1075.         lseek(exbfile,(offset/F_LEN)*512L,SEEK_SET);
  1076.         memset(ext,0,512);
  1077.         read(exbfile,ext,512);
  1078.         while(filelength(txbfile)<(newoffset/F_LEN)*512L) {
  1079. //              lseek(txbfile,0L,SEEK_END);
  1080.             write(txbfile,nulbuf,512); }
  1081.         lseek(txbfile,(newoffset/F_LEN)*512L,SEEK_SET);
  1082.         write(txbfile,ext,512); }
  1083.  
  1084.     str[0]=newoffset&0xff;       /* Get offset within DAT file for IXB file */
  1085.     str[1]=(newoffset>>8)&0xff;
  1086.     str[2]=(newoffset>>16)&0xff;
  1087.     lwrite(ixbfile,ixbptr[i],11);       /* filename */
  1088.     lwrite(ixbfile,str,3);              /* offset */
  1089.     lwrite(ixbfile,ixbptr[i]+14,8); }   /* upload and download times */
  1090. close(exbfile);
  1091. close(txbfile);
  1092. close(ixbfile);
  1093. close(datfile);
  1094. remove(exbfname);
  1095. rename(txbfname,exbfname);
  1096. if(!flength(exbfname))
  1097.     remove(exbfname);
  1098. FREE((char *)ixbbuf);
  1099. FREE((char *)datbuf);
  1100. if(ixblen/F_IXBSIZE==datlen/F_LEN)
  1101.     bputs(text[Sorted]);
  1102. else
  1103.     bprintf(text[Compressed]
  1104.         ,(uint)((datlen/F_LEN)-(ixblen/F_IXBSIZE))
  1105.         ,ultoac(((datlen/F_LEN)-(ixblen/F_IXBSIZE))*F_LEN,tmp));
  1106. }
  1107.  
  1108. /*****************************************************************************/
  1109. /* Handles extraction from a normal transfer file to the temp directory      */
  1110. /*****************************************************************************/
  1111. void extract(uint dirnum)
  1112. {
  1113.     char fname[13],str[256],excmd[256],path[256],done
  1114.         ,files[256],tmp[256],intmp=0;
  1115.     int i,j;
  1116.     struct ffblk ff;
  1117.     file_t f;
  1118.     struct dfree d;
  1119.  
  1120. temp_dirnum=curdirnum=dirnum;
  1121. if(!strcmp(dir[dirnum]->code,"TEMP"))
  1122.     intmp=1;
  1123. if(temp_dir[1]==':')
  1124.     i=temp_dir[0]-'A'+1;
  1125. else i=0;
  1126. getdfree(i,&d);
  1127. if(d.df_sclus==0xffff)
  1128.     errormsg(WHERE,ERR_CHK,temp_dir,0);
  1129. if((ulong)d.df_bsec*(ulong)d.df_sclus
  1130.     *(ulong)d.df_avail<(ulong)min_dspace*1024L) {
  1131.     bputs(text[LowDiskSpace]);
  1132.     sprintf(str,"Diskspace is low: %s",temp_dir);
  1133.     errorlog(str);
  1134.     if(!dir_op(dirnum))
  1135.         return; }
  1136. else if(!intmp) {   /* not in temp dir */
  1137.     CRLF; }
  1138. bprintf(text[DiskNBytesFree],ultoac((ulong)d.df_bsec
  1139.     *(ulong)d.df_sclus*(ulong)d.df_avail,tmp));
  1140. if(!intmp) {    /* not extracting FROM temp directory */
  1141.     sprintf(str,"%s*.*",temp_dir);
  1142.     if(fexist(str)) {
  1143.         bputs(text[RemovingTempFiles]);
  1144.         done=findfirst(str,&ff,0);
  1145.         while(!done) {
  1146.             sprintf(str,"%s%s",temp_dir,ff.ff_name);
  1147.             remove(str);
  1148.             done=findnext(&ff); }
  1149.         CRLF; } }
  1150. bputs(text[ExtractFrom]);
  1151. if(!getstr(fname,12,K_UPPER) || !checkfname(fname) || strchr(fname,'*')
  1152.     || strchr(fname,'?'))
  1153.     return;
  1154. padfname(fname,f.name);
  1155. strcpy(str,f.name);
  1156. truncsp(str);
  1157. for(i=0;i<total_fextrs;i++)
  1158.     if(!strcmp(str+9,fextr[i]->ext) && chk_ar(fextr[i]->ar,useron)) {
  1159.         strcpy(excmd,fextr[i]->cmd);
  1160.         break; }
  1161. if(i==total_fextrs) {
  1162.     bputs(text[UnextractableFile]);
  1163.     return; }
  1164. if(!intmp && !findfile(dirnum,f.name)) {    /* not temp dir */
  1165.     bputs(text[SearchingAllDirs]);
  1166.     for(i=0;i<usrdirs[curlib] && !msgabort();i++) {
  1167.         if(i==dirnum) continue;
  1168.         if(findfile(usrdir[curlib][i],f.name))
  1169.             break; }
  1170.     if(i==usrdirs[curlib]) { /* not found in cur lib */
  1171.         bputs(text[SearchingAllLibs]);
  1172.         for(i=0;i<usrlibs;i++) {
  1173.             if(i==curlib) continue;
  1174.             for(j=0;j<usrdirs[i] && !msgabort();j++)
  1175.                 if(findfile(usrdir[i][j],f.name))
  1176.                     break;
  1177.             if(j<usrdirs[i])
  1178.                 break; }
  1179.         if(i==usrlibs) {
  1180.             bputs(text[FileNotFound]);  /* not in database */
  1181.             return; }
  1182.         dirnum=usrdir[i][j]; }
  1183.     else
  1184.         dirnum=usrdir[curlib][i]; }
  1185. if(sys_status&SS_ABORT)
  1186.     return;
  1187. sprintf(path,"%s%s",dir[dirnum]->path,fname);
  1188. if(!intmp) {    /* not temp dir, so get temp_file info */
  1189.     f.datoffset=f.dateuled=f.datedled=0L;
  1190.     f.dir=dirnum;
  1191.     getfileixb(&f);
  1192.     if(!f.datoffset && !f.dateuled && !f.datedled)  /* error reading ixb */
  1193.         return;
  1194.     f.size=0;
  1195.     getfiledat(&f);
  1196.     fileinfo(f);
  1197.     if(f.altpath>0 && f.altpath<=altpaths)
  1198.         sprintf(path,"%s%s",altpath[f.altpath-1],fname);
  1199.     temp_dirnum=dirnum;
  1200.     if(dir[f.dir]->misc&DIR_FREE)
  1201.         temp_cdt=0L;
  1202.     else
  1203.         temp_cdt=f.cdt;
  1204.     strcpy(temp_uler,f.uler);
  1205.     strcpy(temp_file,f.name); }     /* padded filename */
  1206. if(!fexist(path)) {
  1207.     bputs(text[FileNotThere]);  /* not on disk */
  1208.     return; }
  1209. done=0;
  1210. while(online && !done) {
  1211.     mnemonics(text[ExtractFilesPrompt]);
  1212.     switch(getkeys("EVQ",0)) {
  1213.         case 'E':
  1214.             if(!getfilespec(str))
  1215.                 break;
  1216.             if(!checkfname(str))
  1217.                 break;
  1218.             if((i=external(cmdstr(excmd,path,str,NULL)
  1219.                 ,EX_INR|EX_OUTL|EX_OUTR|EX_CC))!=0) {
  1220.                 errormsg(WHERE,ERR_EXEC,cmdstr(excmd,path,str,NULL),i);
  1221.                 return; }
  1222.             sprintf(tmp,"Extracted %s from %s",str,path);
  1223.             logline(nulstr,tmp);
  1224.             CRLF;
  1225.             break;
  1226.         case 'V':
  1227.             viewfiles(dirnum,fname);
  1228.             break;
  1229.         default:
  1230.             done=1;
  1231.             break; } }
  1232. }
  1233.  
  1234. /****************************************************************************/
  1235. /* Creates the file BATCHDN.LST in the node directory. Returns 1 if         */
  1236. /* everything goes okay. 0 if not.                                          */
  1237. /****************************************************************************/
  1238. int create_batchdn_lst()
  1239. {
  1240.     char str[256];
  1241.     int i,file;
  1242.  
  1243. sprintf(str,"%sBATCHDN.LST",node_dir);
  1244. if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
  1245.     errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
  1246.     return(0); }
  1247. for(i=0;i<batdn_total;i++) {
  1248.     if(batdn_dir[i]>=total_dirs || dir[batdn_dir[i]]->seqdev)
  1249.         strcpy(str,temp_dir);
  1250.     else
  1251.         strcpy(str,batdn_alt[i]>0 && batdn_alt[i]<=altpaths
  1252.             ? altpath[batdn_alt[i]-1] : dir[batdn_dir[i]]->path);
  1253.     write(file,str,strlen(str));
  1254.     unpadfname(batdn_name[i],str);
  1255.     strcat(str,crlf);
  1256.     write(file,str,strlen(str)); }
  1257. close(file);
  1258. return(1);
  1259. }
  1260.  
  1261. /****************************************************************************/
  1262. /* Creates the file BATCHUP.LST in the node directory. Returns 1 if         */
  1263. /* everything goes okay. 0 if not.                                          */
  1264. /* This list is not used by any protocols to date.                          */
  1265. /****************************************************************************/
  1266. int create_batchup_lst()
  1267. {
  1268.     char str[256];
  1269.     int i,file;
  1270.  
  1271. sprintf(str,"%sBATCHUP.LST",node_dir);
  1272. if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
  1273.     errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
  1274.     return(0); }
  1275. for(i=0;i<batup_total;i++) {
  1276.     if(batup_dir[i]>=total_dirs)
  1277.         strcpy(str,temp_dir);
  1278.     else
  1279.         strcpy(str,batup_alt[i]>0 && batup_alt[i]<=altpaths
  1280.             ? altpath[batup_alt[i]-1] : dir[batup_dir[i]]->path);
  1281.     write(file,str,strlen(str));
  1282.     unpadfname(batup_name[i],str);
  1283.     strcat(str,crlf);
  1284.     write(file,str,strlen(str)); }
  1285. close(file);
  1286. return(1);
  1287. }
  1288.  
  1289. /****************************************************************************/
  1290. /* Creates the file BIMODEM.PTH in the node directory. Returns 1 if         */
  1291. /* everything goes okay. 0 if not.                                          */
  1292. /****************************************************************************/
  1293. int create_bimodem_pth()
  1294. {
  1295.     char str[256],tmp2[512];
  1296.     int i,file;
  1297.  
  1298. sprintf(str,"%sBIMODEM.PTH",node_dir);  /* Create bimodem file */
  1299. if((file=nopen(str,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
  1300.     errormsg(WHERE,ERR_OPEN,str,O_WRONLY|O_CREAT|O_TRUNC);
  1301.     return(0); }
  1302. for(i=0;i<batup_total;i++) {
  1303.     sprintf(str,"%s%s",batup_dir[i]>=total_dirs ? temp_dir
  1304.         : batup_alt[i]>0 && batup_alt[i]<=altpaths
  1305.         ? altpath[batup_alt[i]-1] : dir[batup_dir[i]]->path
  1306.         ,unpadfname(batup_name[i],tmp));
  1307.     sprintf(tmp2,"D       %-80.80s%-160.160s"
  1308.         ,unpadfname(batup_name[i],tmp),str);
  1309.     write(file,tmp2,248); }
  1310. for(i=0;i<batdn_total;i++) {
  1311.     sprintf(str,"%s%s"
  1312.         ,(batdn_dir[i]>=total_dirs || dir[batdn_dir[i]]->seqdev)
  1313.         ? temp_dir : batdn_alt[i]>0 && batdn_alt[i]<=altpaths
  1314.             ? altpath[batdn_alt[i]-1] : dir[batdn_dir[i]]->path
  1315.             ,unpadfname(batdn_name[i],tmp));
  1316.     sprintf(tmp2,"U       %-240.240s",str);
  1317.     write(file,tmp2,248); }
  1318. close(file);
  1319. return(1);
  1320. }
  1321.  
  1322. /****************************************************************************/
  1323. /* Processes files that were supposed to be received in the batch queue     */
  1324. /****************************************************************************/
  1325. void batch_upload()
  1326. {
  1327.     char str1[256],str2[256];
  1328.     int i,j,x,y;
  1329.     file_t f;
  1330.     struct ffblk ff;
  1331.  
  1332. for(i=0;i<batup_total;) {
  1333.     curdirnum=batup_dir[i];             /* for ARS */
  1334.     lncntr=0;                               /* defeat pause */
  1335.     unpadfname(batup_name[i],tmp);
  1336.     sprintf(str1,"%s%s",temp_dir,tmp);
  1337.     sprintf(str2,"%s%s",dir[batup_dir[i]]->path,tmp);
  1338.     if(fexist(str1) && fexist(str2)) { /* file's in two places */
  1339.         bprintf(text[FileAlreadyThere],batup_name[i]);
  1340.         remove(str1);    /* this is the one received */
  1341.         i++;
  1342.         continue; }
  1343.     if(fexist(str1))
  1344.         mv(str1,str2,0);
  1345.     strcpy(f.name,batup_name[i]);
  1346.     strcpy(f.desc,batup_desc[i]);
  1347.     f.dir=batup_dir[i];
  1348.     f.misc=batup_misc[i];
  1349.     f.altpath=batup_alt[i];
  1350.     if(uploadfile(&f)) {
  1351.         batup_total--;
  1352.         for(j=i;j<batup_total;j++) {
  1353.             batup_dir[j]=batup_dir[j+1];
  1354.             batup_alt[j]=batup_alt[j+1];
  1355.             batup_misc[j]=batup_misc[j+1];
  1356.             strcpy(batup_name[j],batup_name[j+1]);
  1357.             strcpy(batup_desc[j],batup_desc[j+1]); } }
  1358.     else i++; }
  1359. if(upload_dir==INVALID_DIR)
  1360.     return;
  1361. sprintf(str1,"%s*.*",temp_dir);
  1362. i=findfirst(str1,&ff,0);
  1363. while(!i) {
  1364.     memset(&f,0,sizeof(file_t));
  1365.     f.dir=upload_dir;
  1366.     padfname(ff.ff_name,f.name);
  1367.     strupr(f.name);
  1368.     sprintf(str1,"%s%s",temp_dir,ff.ff_name);
  1369.     for(x=0;x<usrlibs;x++) {
  1370.         for(y=0;y<usrdirs[x];y++)
  1371.             if(dir[usrdir[x][y]]->misc&DIR_DUPES
  1372.                 && findfile(usrdir[x][y],f.name))
  1373.                 break;
  1374.         if(y<usrdirs[x])
  1375.             break; }
  1376.     sprintf(str2,"%s%s",dir[f.dir]->path,ff.ff_name);
  1377.     if(x<usrlibs || fexist(str2)) {
  1378.         bprintf(text[FileAlreadyOnline],f.name);
  1379.         remove(str1); }
  1380.     else {
  1381.         mv(str1,str2,0);
  1382.         uploadfile(&f); }
  1383.     i=findnext(&ff); }
  1384. }
  1385.  
  1386. /****************************************************************************/
  1387. /* Processes files that were supposed to be sent from the batch queue       */
  1388. /* xfrprot is -1 if downloading files from within QWK (no DSZLOG)           */
  1389. /****************************************************************************/
  1390. void batch_download(int xfrprot)
  1391. {
  1392.     int i,j;
  1393.     file_t f;
  1394.  
  1395. for(i=0;i<batdn_total;) {
  1396.     lncntr=0;                               /* defeat pause */
  1397.     f.dir=curdirnum=batdn_dir[i];
  1398.     strcpy(f.name,batdn_name[i]);
  1399.     f.datoffset=batdn_offset[i];
  1400.     f.size=batdn_size[i];
  1401. /*                                               Removed 05/18/95
  1402.     if(dir[f.dir]->misc&DIR_TFREE && cur_cps)  Looks like it gave back double
  1403.         starttime+=f.size/(ulong)cur_cps;
  1404. */
  1405.     f.altpath=batdn_alt[i];
  1406.     if(xfrprot==-1 || (prot[xfrprot]->misc&PROT_DSZLOG && checkprotlog(f))
  1407.         || !(prot[xfrprot]->misc&PROT_DSZLOG)) {
  1408.         if(dir[f.dir]->misc&DIR_TFREE && cur_cps)
  1409.             starttime+=f.size/(ulong)cur_cps;
  1410.         downloadfile(f);
  1411.         closefile(f);
  1412.         batdn_total--;
  1413.         for(j=i;j<batdn_total;j++) {
  1414.             strcpy(batdn_name[j],batdn_name[j+1]);
  1415.             batdn_dir[j]=batdn_dir[j+1];
  1416.             batdn_cdt[j]=batdn_cdt[j+1];
  1417.             batdn_alt[j]=batdn_alt[j+1];
  1418.             batdn_size[j]=batdn_size[j+1];
  1419.             batdn_offset[j]=batdn_offset[j+1]; } }
  1420.     else i++; }
  1421. }
  1422.  
  1423. /****************************************************************************/
  1424. /* Adds a list of files to the batch download queue                         */
  1425. /****************************************************************************/
  1426. void batch_add_list(char *list)
  1427. {
  1428.     char str[128];
  1429.     int file,i,j,k;
  1430.     FILE *stream;
  1431.     file_t    f;
  1432.  
  1433. if((stream=fnopen(&file,list,O_RDONLY))!=NULL) {
  1434.     bputs(text[SearchingAllLibs]);
  1435.     while(!feof(stream)) {
  1436.         checkline();
  1437.         if(!online)
  1438.             break;
  1439.         if(!fgets(str,127,stream))
  1440.             break;
  1441.         truncsp(str);
  1442.         sprintf(f.name,"%.12s",str);
  1443.         strupr(f.name);
  1444.         lncntr=0;
  1445.         for(i=k=0;i<usrlibs;i++) {
  1446.             for(j=0;j<usrdirs[i];j++,k++) {
  1447.                 outchar('.');
  1448.                 if(k && !(k%5))
  1449.                     bputs("\b\b\b\b\b     \b\b\b\b\b");
  1450.                 if(findfile(usrdir[i][j],f.name))
  1451.                     break; }
  1452.             if(j<usrdirs[i])
  1453.                 break; }
  1454.         if(i<usrlibs) {
  1455.             f.dir=usrdir[i][j];
  1456.             getfileixb(&f);
  1457.             f.size=0;
  1458.             getfiledat(&f);
  1459.             if(f.size==-1L)
  1460.                 bprintf(text[FileIsNotOnline],f.name);
  1461.             else
  1462.                 addtobatdl(f); } }
  1463.     fclose(stream);
  1464.     remove(list);
  1465.     CRLF; }
  1466. }
  1467.  
  1468. /****************************************************************************/
  1469. /* Creates a text file named NEWFILES.DAT in the temp directory that        */
  1470. /* all new files since p-date. Returns number of files in list.             */
  1471. /****************************************************************************/
  1472. ulong create_filelist(char *name, char mode)
  1473. {
  1474.     char str[256];
  1475.     int i,j,d,file;
  1476.     ulong    l,k;
  1477.  
  1478. bprintf(text[CreatingFileList],name);
  1479. sprintf(str,"%s%s",temp_dir,name);
  1480. if((file=nopen(str,O_CREAT|O_WRONLY|O_APPEND))==-1) {
  1481.     errormsg(WHERE,ERR_OPEN,str,O_CREAT|O_WRONLY|O_APPEND);
  1482.     return(0); }
  1483. k=0;
  1484. if(mode&FL_ULTIME) {
  1485.     sprintf(str,"New files since: %s\r\n",timestr(&ns_time));
  1486.     write(file,str,strlen(str)); }
  1487. for(i=d=0;i<usrlibs;i++) {
  1488.     for(j=0;j<usrdirs[i];j++,d++) {
  1489.         outchar('.');
  1490.         if(d && !(d%5))
  1491.             bputs("\b\b\b\b\b     \b\b\b\b\b");
  1492.         if(mode&FL_ULTIME /* New-scan */
  1493.             && (lib[usrlib[i]]->offline_dir==usrdir[i][j]
  1494.             || dir[usrdir[i][j]]->misc&DIR_NOSCAN))
  1495.             continue;
  1496.         l=listfiles(usrdir[i][j],nulstr,file,mode);
  1497.         if((long)l==-1)
  1498.             break;
  1499.         k+=l; }
  1500.     if(j<usrdirs[i])
  1501.         break; }
  1502. if(k>1) {
  1503.     sprintf(str,"\r\n%d Files Listed.\r\n",k);
  1504.     write(file,str,strlen(str)); }
  1505. close(file);
  1506. if(k)
  1507.     bprintf(text[CreatedFileList],name);
  1508. else {
  1509.     bputs(text[NoFiles]);
  1510.     sprintf(str,"%s%s",temp_dir,name);
  1511.     remove(str); }
  1512. strcpy(temp_file,name);
  1513. strcpy(temp_uler,"File List");
  1514. return(k);
  1515. }
  1516.  
  1517.