home *** CD-ROM | disk | FTP | other *** search
/ Aminet 10 / aminetcdnumber101996.iso / Aminet / misc / unix / adt_c next >
Text File  |  1995-12-07  |  80KB  |  4,157 lines

  1. #if 0
  2.  ############################################################################
  3.  ##                                                                        ##
  4.  ## This is ADT 2.2, a user friendly frontend for all Aminet FTP sites. It ##
  5.  ## can be compiled easily on any UNIX flavor and AmigaDOS. Under UNIX,    ##
  6.  ## compile it using the command                                           ##
  7.  ##                                                                        ##
  8.  ##   sh adt.c            (you may append flags, e.g. sh adt.c -DNO_FTP)   ##
  9.  ##                                                                        ##
  10.  ## or use simply type make (your current dir should be where adt.c is)    ##
  11.  ##                                       ##
  12.  ## Improvements of adt.c version 2.2:                       ##
  13.  ##  - fixed size display bug (files >1MB and <10MB                        ##
  14.  ##  - updated builtin site list                                           ##
  15.  ##                                        ##
  16.  ##         Matthias Scheler <mscheler@aminet.org>               ##
  17.  ##                                        ##
  18.  ## Improvements of adt.c version 2.1:                       ##
  19.  ##  - if used with internal/external ftp, adt now passes the username to  ##
  20.  ##    the ftp server. This is neccessary at sites using the identd !      ##
  21.  ##  - if transfer-method is NFS, downloads don't mean a copy from one     ##
  22.  ##    filesystem to another (temporary) one. A softlink is created        ##
  23.  ##    instead of, and the user can sz or mcopy or whatever all files      ##
  24.  ##    manually out of his private download dir.                           ##
  25.  ##                                        ##
  26.  ##        Manfred Bathelt <mdbathel@cip.informatik.uni-erlangen.de>  ##
  27.  ##                                       ##
  28.  ## See adt.c.readme for further notes                                     ##
  29.  ##                                                                        ##
  30.  ############################################################################
  31.  
  32.  libs="-lcurses -ltermcap"
  33.  for i in /usr/lib/libsocket* ; do if [ -r $i ] ; then  # Kludge for systems
  34.   libs="$libs -lsocket -lnsl" ; break                   # with bash as /bin/sh
  35.  fi ; done                                              # like NetBSD or Linux
  36.  
  37.  echo cc -O -s -o adt $* $0 $libs
  38.  exec cc -O -s -o adt $* $0 $libs
  39.  exit
  40. #endif
  41.  
  42. #include <stdio.h>
  43.  
  44. #ifdef AMIGA
  45. # define getchr getch
  46. # define makedir(x,y) mkdir(x)
  47. # define popen(x,y) stdout
  48. # define pclose(x)
  49. # define sleep(x)
  50. # define COPYCMD "copy"
  51. # define CURDIR "\"\""
  52. # define TEMPPATH "t:"
  53. # define NO_FTP
  54. # define NO_FIND_CLIENT
  55. # define _system(x) puts(x)
  56. #else
  57. # define getchr getchar
  58. # define makedir(x,y) mkdir(x,y)
  59. /*  # define COPYCMD "cp"            DO NOT USE COPY FOR DOWNLOAD VIA NFS */
  60. # define COPYCMD "ln -s"          /* use softlink instead of, and cp manually */
  61. # define CURDIR "."
  62. # define TEMPPATH "/tmp/"
  63. #endif
  64.  
  65. #ifdef NO_FTP
  66. # define NO_BUILTIN_FTP
  67. # define NO_EXTERNAL_FTP
  68. #endif
  69.  
  70. #ifdef NO_BUILTIN_FTP
  71. # ifdef NO_FIND_CLIENT
  72. #  define NO_TCP_UTILITY
  73. # endif
  74. #else /* !NO_BUILTIN_FTP */
  75. # define NO_EXTERNAL_FTP
  76. #endif
  77.  
  78. /*---------------------------------INCLUDES---------------------------------*/
  79. #define _INCLUDE_POSIX_SOURCE
  80.  
  81. #ifndef AMIGA
  82. # include <sys/types.h>
  83.  
  84. # ifdef DEBUG
  85. #  include <stdlib.h>
  86. #  include <unistd.h>
  87. #  include <string.h>
  88. #  include <sys/param.h>
  89. #  include <sys/stat.h>
  90. # endif
  91.  
  92. # ifndef NO_EXTERNAL_FTP
  93. #  include <sys/stat.h>
  94. # endif
  95.  
  96. # ifndef NO_TCP_UTILITY
  97. #  include <sys/file.h>
  98. #  include <stdio.h>
  99. #  include <netdb.h>
  100. #  include <sys/socket.h>
  101. #  include <netinet/in.h>
  102. #  include <arpa/inet.h>
  103. # endif
  104. #endif
  105.  
  106. #ifndef NO_CURSES
  107. # include <curses.h>
  108. #endif
  109.  
  110. #include <signal.h>
  111. /*---------------------------------GLOBALS-----------------------------------*/
  112.  
  113. #define E_FILE 20
  114. #define E_DIR  10
  115. #define E_DESC 44
  116.  
  117. #define K_CTRL -'@'
  118.  
  119. struct adt_entry {
  120.   long time;
  121.   long size;
  122.   long readmesize;
  123.   short version;
  124.   char readmelen;
  125.   char tagged;
  126.   char osversion;
  127.   char status;
  128.   char file[E_FILE + 1];
  129.   char dir[E_DIR + 1];
  130.   char desc[E_DESC + 1];
  131. };
  132. #define ENTRY struct adt_entry
  133.  
  134. #define STATUS_LOCAL  0
  135. #define STATUS_REMOTE 1
  136.  
  137.  
  138. struct adt_list {
  139.   ENTRY **list;
  140.   char *(*disp) ();
  141.   int mem;
  142.   int num;
  143.   int offset;
  144.   int current;
  145.   char type;
  146.   char top;
  147.   char *sel;
  148.   char *sort;
  149.   char *cmds;
  150. };
  151. #define LIST struct adt_list
  152.  
  153.  
  154. struct adt_transfer {
  155.   char *name;
  156.   char *text;
  157.   int (*init) ();
  158. };
  159. #define TRANSFER struct adt_transfer
  160.  
  161. extern TRANSFER TransferTypes[];
  162.  
  163.  
  164. LIST AllFiles, VisibleFiles, Marked, Alternate;
  165. LIST *File = &AllFiles, *Vis = &VisibleFiles, *Mark = &Marked, *Alt = &Alternate;
  166.  
  167. int Dispmode;
  168. int Width = 80, Height = 25;
  169. int LastCall;
  170. char *NoFilesString = "No files available";
  171. char HomeDir[250];
  172. char UserName[50] = "user";
  173. char ConfigFile[200] = ".adtrc";
  174. char *FindDesc = "Performing local case insensitive substring search";
  175. char GotComplete, GotLocal, GotRecent;
  176. char Flat, Readme, Silent, Path[250], Action;
  177. char InitialSetup;
  178. char Connected;
  179. char MaskSIGINT, GotSIGINT;
  180.  
  181. int (*disp_init) ();
  182. int (*disp_cleanup) ();
  183. int (*disp_choice) ();
  184. int (*disp_mainloop) ();
  185. int (*disp_report) ();
  186. int (*disp_status) ();
  187. int (*disp_confirm) ();
  188. int (*disp_more) ();
  189. int (*disp_getchar) ();
  190. int (*disp_refresh) ();
  191. int (*disp_clear) ();
  192. char *(*disp_inputstr) ();
  193.  
  194. int (*trans_options) ();
  195. int (*trans_connect) ();
  196. int (*trans_remopen) ();
  197. int (*trans_download) ();
  198. int (*trans_disconnect) ();
  199. int (*trans_close) ();
  200.  
  201. /*----------------------------main exit point--------------------------------*/
  202. int exit_adt(err)
  203.   char *err;
  204. {
  205.   if (disp_cleanup)
  206.     disp_cleanup();
  207.  
  208.   if (trans_close)
  209.     trans_close();
  210.  
  211.   if (err)
  212.     puts(err);
  213.  
  214.   exit(err ? 20 : 0);
  215.  
  216.   return 0;
  217. }
  218.  
  219. /*--------------------------quick entry allocator----------------------------*/
  220. #define CHUNKALLOC 100
  221.  
  222. struct EntryChunk {
  223.   struct EntryChunk *next;
  224.   ENTRY chunks[CHUNKALLOC];
  225. };
  226. #define CHUNK struct EntryChunk
  227.  
  228. int InCount;
  229. CHUNK *EntryChunk, *ChunkList;
  230.  
  231. char *salloc(len)
  232.   int len;
  233. {
  234.   char *t;
  235.  
  236.   if (!(t = (char *) malloc(len)))
  237.     exit_adt("out of memory\n");
  238.  
  239.   return t;
  240. }
  241.  
  242.  
  243. ENTRY *e_alloc()
  244. {
  245.   if (!InCount) {
  246.     InCount = CHUNKALLOC;
  247.     EntryChunk = (CHUNK *) salloc(sizeof(CHUNK));
  248.     EntryChunk->next = ChunkList;
  249.     ChunkList = EntryChunk;
  250.   }
  251.   return EntryChunk->chunks + --InCount;
  252. }
  253.  
  254. int e_add(l, e)
  255.   LIST *l;
  256.   ENTRY *e;
  257. {
  258.   ENTRY **oldlist;
  259.   int i;
  260.  
  261.   if (!l->mem) {
  262.     l->mem = 100;
  263.  
  264.     l->list = (ENTRY **) salloc(l->mem * sizeof(ENTRY *));
  265.   }
  266.   if (l->num == l->mem) {
  267.     oldlist = l->list;
  268.  
  269.     l->list = (ENTRY **) salloc(2 * l->mem * sizeof(ENTRY *));
  270.  
  271.     for (i = 0; i < l->num; i++)
  272.       l->list[i] = oldlist[i];
  273.  
  274.     l->mem *= 2;
  275.     free(oldlist);
  276.   }
  277.   l->list[l->num++] = e;
  278.   return 0;
  279. }
  280.  
  281. int l_reset(l)
  282.   LIST *l;
  283. {
  284.   if (l->list)
  285.     free(l->list);
  286.   l->list = 0;
  287.   l->mem = 0;
  288.   l->num = 0;
  289.   l->current = 0;
  290.   return 0;
  291. }
  292.  
  293. int l_store()
  294. {
  295.   int i;
  296.   ENTRY **e1, **e2;
  297.  
  298.   if (Alt->list)
  299.     free(Alt->list);
  300.  
  301.   if (Vis->mem)
  302.     Alt->list = (ENTRY **) salloc(Vis->mem * sizeof(ENTRY *));
  303.  
  304.   for (i = Vis->num - 1, e1 = Vis->list, e2 = Alt->list; i >= 0; i--)
  305.     *e2++ = *e1++;
  306.  
  307.   Alt->list = Vis->list;
  308.   Alt->num = Vis->num;
  309.   Alt->mem = Vis->mem;
  310.   Alt->offset = Vis->offset;
  311.   Alt->current = Vis->current;
  312.   Alt->sel = Vis->sel;
  313.   Alt->sort = Vis->sort;
  314.  
  315.   return 0;
  316. }
  317.  
  318. int e_freeall()
  319. {
  320.   CHUNK *c, *next;
  321.  
  322.   l_reset(Alt);
  323.   l_reset(Mark);
  324.   l_reset(Vis);
  325.   l_reset(File);
  326.  
  327.   for (c = ChunkList; c; c = next) {
  328.     next = c->next;
  329.     free(c);
  330.   }
  331.   ChunkList = 0;
  332.   InCount = 0;
  333.   GotComplete = GotLocal = GotRecent = 0;
  334.  
  335.   return 0;
  336. }
  337.  
  338. /*-------------------------string funcs for portability----------------------*/
  339. int mystrlen(s)
  340.   char *s;
  341. {
  342.   int n = 0;
  343.  
  344.   while (*s++)
  345.     n++;
  346.   return n;
  347. }
  348.  
  349. int mystrncpy(s1, s2, n)
  350.   char *s1, *s2;
  351.   int n;
  352. {
  353.   while (*s2 && n--)
  354.     *s1++ = *s2++;
  355.  
  356.   *s1++ = 0;
  357.  
  358.   return 0;
  359. }
  360.  
  361. char *mystrcpy(s1, s2)
  362.   char *s1, *s2;
  363. {
  364.   char *t = s1;
  365.  
  366.   while ((*s1++ = *s2++));
  367.  
  368.   return t;
  369. }
  370.  
  371. int mystrcmp(s1, s2)
  372.   char *s1, *s2;
  373. {
  374.   while (*s1 == *s2 && *s1)
  375.     s1++, s2++;
  376.  
  377.   return *s1 - *s2;
  378. }
  379.  
  380. #define LOWER(x) (x<='Z' && x>='A' ? x-'A'+'a' : x)
  381.  
  382. int mystricmp(s1, s2)
  383.   char *s1, *s2;
  384. {
  385.   while (LOWER(*s1) == LOWER(*s2) && *s1)
  386.     s1++, s2++;
  387.  
  388.   return LOWER(*s1) - LOWER(*s2);
  389. }
  390.  
  391. int mystrncmp(s1, s2, n)
  392.   char *s1, *s2;
  393.   int n;
  394. {
  395.   while (n && *s1 && *s1 == *s2)
  396.     s1++, s2++, n--;
  397.  
  398.   return n != 0 && *s1 - *s2;
  399. }
  400.  
  401. int mystrnicmp(s1, s2, n)
  402.   char *s1, *s2;
  403.   int n;
  404. {
  405.   while (n && *s1 && LOWER(*s1) == LOWER(*s2))
  406.     s1++, s2++, n--;
  407.  
  408.   return n != 0 && LOWER(*s1) - LOWER(*s2);
  409. }
  410.  
  411. char *myfgets(buf, len, file)
  412.   char *buf;
  413.   int len;
  414.   FILE *file;
  415. {
  416.   char *t, *r;
  417.  
  418.   if ((r = fgets(buf, len, file))) {
  419.     for (t = buf; *t && *t != '\n'; t++);
  420.  
  421.     *t = 0;
  422.   }
  423.   return r;
  424. }
  425.  
  426. char *mystristr(str1, str2)
  427.   char *str1, *str2;
  428. {
  429.   char c = LOWER(*str1), l = strlen(str1);
  430.  
  431.   for (;;) {
  432.     while (*str2 && LOWER(*str2) != c)
  433.       str2++;
  434.  
  435.     if (!*str2)
  436.       break;
  437.  
  438.     if (!mystrnicmp(str1, str2, l))
  439.       return str2;
  440.  
  441.     str2++;
  442.   }
  443.  
  444.   return 0;
  445. }
  446.  
  447. long myatoi(s)
  448.   char *s;
  449. {
  450.   long r = 0;
  451.  
  452.   while (*s && *s >= '0' && *s <= '9')
  453.     r = 10 * r + *s++ - '0';
  454.  
  455.   return r;
  456. }
  457.  
  458. char rdmbuf[200];
  459.  
  460. char *
  461. get_readme(e)
  462.   ENTRY *e;
  463. {
  464.   strcpy(rdmbuf,e->file);
  465.   strcpy(rdmbuf+strlen(rdmbuf)-e->readmelen, ".readme");
  466.   return rdmbuf;
  467. }
  468.  
  469. #define MYMIN(x,y) ((x)<(y) ? (x) : (y))
  470. #define MYMAX(x,y) ((x)>(y) ? (x) : (y))
  471.  
  472.  
  473. #ifdef AMIGA
  474.  
  475. char *glob_path (buf)
  476.   char *buf;
  477. {
  478.   return buf;
  479. }
  480.  
  481. #else
  482.  
  483. #include <pwd.h>
  484.  
  485. char *glob_path (buf)
  486.   char *buf;
  487. {
  488.   short bindex = 1;
  489.   struct passwd pw_info, *pw;
  490.   char buf2[300];
  491.  
  492.   if (buf[0] != '~')
  493.     return buf;
  494.  
  495.   pw_info.pw_dir = (char *) getenv("HOME");
  496.   if (buf[1] && buf[1] != '/') {
  497.     char username[128];
  498.  
  499.     while (buf[bindex] && buf[bindex] != '/')
  500.         ++bindex;
  501.     memcpy( username, buf+1, bindex-1);
  502.     username[bindex-1] = 0;
  503.  
  504.     if (pw = getpwnam(username))
  505.       pw_info.pw_dir = pw->pw_dir;
  506.     else
  507.       pw_info.pw_dir = "~";
  508.   }
  509.  
  510.   strcpy (buf2, pw_info.pw_dir);
  511.   strcat (buf2, buf + bindex);
  512.   strcpy (buf, buf2);
  513.  
  514.   return buf;
  515. }
  516. #endif
  517.  
  518.  
  519. /*-----------------------------options and settings--------------------------*/
  520. char *Options[] = {
  521.   "method", "ftp",
  522.   "fspsite", "epix.rrze.uni-erlangen.de,21",
  523.   "fspsites", "epix.rrze.uni-erlangen.de,21",
  524.   "mailserv", "ftp.doc.ic.ac.uk",
  525.   "timeout", "30",
  526.   "nomotd", "0",
  527.   "amotd", "0",
  528.   "lmotd", "0",
  529.   "sites", "0",
  530.   "locaminet", "/public/pub/aminet",
  531.   "unpack", "",
  532.   "transfer", "",
  533.   "newest", "0",
  534.   "hide", "",
  535.   "printer", "",
  536.   "dlpath", "",
  537.   "compress", "1",
  538.   "send", "sz",
  539.   "silentdl", "0",
  540.   "readmedl", "0",
  541.   "flatdl", "1",
  542.   "ftpsite", "ftp.eunet.ch",
  543.   "ftpmaster", "ftp.wustl.edu",
  544.   "ftpsites","\
  545. USA (MO),ftp.wustl.edu,128.252.135.4,,@\
  546. USA (WI),ftp.netnet.net,198.70.64.21,,@\
  547. USA (AZ),ftp.amigalib.com,165.247.33.6,,@\
  548. Australia,ftp.livewire.com.au,203.16.26.3,,@\
  549. Scandinavia,ftp.luth.se,130.240.16.39,,@\
  550. Switzerland,ftp.eunet.ch,146.228.10.11,,@\
  551. Switzerland,ftp.math.ethz.ch,129.132.104.6,,ftp.doc.ic.ac.uk@\
  552. Germany,ftp.germany.aminet.org,131.234.10.42,,@\
  553. Germany,kelly.uni-paderborn.de,131.234.128.206,,@\
  554. Germany,ftp.uni-stuttgart.de,129.96.18.15,aminet,kelly.uni-paderborn.de@\
  555. Germany,ftp.uni-erlangen.de,131.188.3.2,,kelly.uni-paderborn.de@\
  556. Germany,ftp.cs.tu-berlin.de,130.149.18.7,,kelly.uni-paderborn.de@\
  557. Germany,ftp.tu-chemnitz.de,134.109.132.28,,kelly.uni-paderborn.de@\
  558. Germany,ftp.fh-augsburg.de,141.82.16.242,,kelly.uni-paderborn.de@\
  559. Germany,ftp.uni-bremen.de,134.102.228.2,,kelly.uni-paderborn.de@\
  560. Germany,ftp.uni-kl.de,131.246.94.94,,kelly.uni-paderborn.de@\
  561. Germany,ftp.uni-trier.de,136.199.8.81,,kelly.uni-paderborn.de@\
  562. Germany,ftp.informatik.rwth-aachen.de,137.226.225.3,,kelly.uni-paderborn.de@\
  563. France,ftp.cnam.fr,163.173.128.15,,kelly.uni-paderborn.de@\
  564. France,aminet.grolier.fr,194.51.174.67,,kelly.uni-paderborn.de@\
  565. Austria,ftp.giga.or.at,131.130.12.58,,ftp.eunet.ch@\
  566. Italy,ftp.unina.it,192.132.34.17,,kelly.uni-paderborn.de@\
  567. Portugal,ftp.ua.pt,193.136.80.68,,kelly.uni-paderborn.de@\
  568. Spain,ftp.gui.uva.es,157.88.36.190,,kelly.uni-paderborn.de@\
  569. UK,ftp.doc.ic.ac.uk,146.169.17.5,,@\
  570. UK,micros.hensa.ac.uk,194.80.32.51,,ftp.doc.ic.ac.uk",
  571.   "findmethod", "0",
  572.   "findsite", "",
  573.   "findsites", "\
  574. USA (MO),ftp.wustl.edu,128.252.135.4,,@\
  575. Switzerland,amiga.icu.net.ch,146.228.204.2,,@\
  576. Germany,find.germany.aminet.org,131.234.38.2,,@\
  577. Portugal,ftp.ua.pt,193.136.80.68,,",
  578.   0, 0
  579. };
  580.  
  581. #define OBUFLEN 2000
  582. char obuf[OBUFLEN];
  583.  
  584. char *option_get(name)
  585.   char *name;
  586. {
  587.   char **t;
  588.  
  589.   for (t = Options; t[0]; t += 2)
  590.     if (!mystrcmp(name, t[0]))
  591.       return t[1];
  592.  
  593.   return "";
  594. }
  595.  
  596. int option_getnum(name)
  597.   char *name;
  598. {
  599.   return myatoi(option_get(name));
  600. }
  601.  
  602. int option_set(name, val)
  603.   char *name, *val;
  604. {
  605.   char **t;
  606.  
  607.   for (t = Options; t[0]; t += 2)
  608.     if (!mystrcmp(name, t[0]))
  609.       mystrcpy((t[1] = salloc(strlen(val) + 1)), val);
  610.  
  611.   return 0;
  612. }
  613.  
  614. int option_setnum(name, val)
  615.   char *name;
  616.   int val;
  617. {
  618.   char buf[20];
  619.  
  620.   sprintf(buf, "%d", val);
  621.   option_set(name, buf);
  622.  
  623.   return 0;
  624. }
  625.  
  626. int option_loadfh(f)
  627.   FILE *f;
  628. {
  629.   char *t;
  630.  
  631.   fgets(obuf, OBUFLEN, f);
  632.   if (mystrncmp("#adtrc-v2", obuf, 9))
  633.     return 1;
  634.  
  635.   while (myfgets(obuf, OBUFLEN, f)) {
  636.     while (*obuf && obuf[strlen(obuf)-1]=='\\' && 
  637.            myfgets(obuf+strlen(obuf)-1, OBUFLEN-strlen(obuf)-1, f)) ;
  638.       
  639.     for (t = obuf; *t && *t != '='; t++);
  640.  
  641.     if (*t == '=') {
  642.       *t++ = 0;
  643.       option_set(obuf, t);
  644.     }
  645.   }
  646.  
  647.   return 0;
  648. }
  649.  
  650. int option_load(name)
  651.   char *name;
  652. {
  653.   FILE *f;
  654.   int r;
  655.  
  656.   if (!(f = fopen(name, "r")))
  657.     return 1;
  658.  
  659.   r = option_loadfh(f);
  660.  
  661.   fclose(f);
  662.  
  663.   return r;
  664. }
  665.  
  666. int option_save(name)
  667.   char *name;
  668. {
  669.   FILE *f;
  670.   char **t;
  671.  
  672.   if (!(f = fopen(name, "w")))
  673.     return 1;
  674.  
  675.   fprintf(f, "#adtrc-v2\n");
  676.  
  677.   for (t = Options; t[0]; t += 2)
  678.     fprintf(f, "%s=%s\n", t[0], t[1]);
  679.  
  680.   fclose(f);
  681.  
  682.   return 0;
  683. }
  684.  
  685. /*-----------------------------input file parser-----------------------------*/
  686. #define PBUFSIZE 400
  687. char parsebuf[PBUFSIZE], p_error, *p_ptr;
  688.  
  689. int reset_token()
  690. {
  691.   p_ptr = parsebuf;
  692.   p_error = 0;
  693.   return 0;
  694. }
  695.  
  696.  
  697. char *get_token()
  698. {
  699.   char *t, *s, *d;
  700.  
  701.   if (!p_ptr) {
  702.     p_error = 1;
  703.     return "";
  704.   }
  705.   for (t = s = d = p_ptr; *s && *s != '@'; s++) {
  706.     if (*s != '\r')
  707.       *d++ = *s;
  708.   }
  709.  
  710.   if (!*s)
  711.     p_ptr = 0;
  712.   else {
  713.     *s = 0;
  714.     p_ptr = s + 1;
  715.   }
  716.  
  717.   return t;
  718. }
  719.  
  720.  
  721. long p_atoi(s)
  722.   char *s;
  723. {
  724.   long r = 0;
  725.  
  726.   while (*s && *s >= '0' && *s <= '9')
  727.     r = 10 * r + *s++ - '0';
  728.  
  729.   if (*s)
  730.     p_error = 1;
  731.  
  732.   return r;
  733. }
  734.  
  735.  
  736. int read_adt_v2(fh)
  737.   FILE *fh;
  738. {
  739.   ENTRY *e;
  740.   char *t;
  741.  
  742.   do {
  743.     if (*parsebuf == '#')
  744.       if (!mystrncmp(parsebuf, "#endadt", 7))
  745.     break;
  746.       else
  747.     continue;
  748.  
  749.     e = e_alloc();
  750.  
  751.     reset_token();
  752.  
  753.     e->time = p_atoi(get_token());
  754.  
  755.     mystrncpy(e->dir, get_token(), E_DIR);
  756.  
  757.     mystrncpy(e->file, get_token(), E_FILE);
  758.  
  759.     e->size = p_atoi(get_token());
  760.  
  761.     e->readmelen = p_atoi(get_token());
  762.  
  763.     e->readmesize = p_atoi(get_token());
  764.  
  765.     e->version = -1;
  766.  
  767.     e->osversion = -1;
  768.  
  769.     e->status = *get_token()=='R' ? STATUS_REMOTE : STATUS_LOCAL;
  770.  
  771.     mystrncpy(e->desc, get_token(), E_DESC);
  772.  
  773.     for (t = e->desc; *t; t++)
  774.       if (*t == '\n')
  775.     *t = 0;
  776.  
  777.     e->tagged = 0;
  778.  
  779.     if (!(p_error))
  780.       e_add(File, e);
  781.   } while (fgets(parsebuf, PBUFSIZE, fh));
  782.  
  783.   return 0;
  784. }
  785.  
  786. /*----------------------------------utility----------------------------------*/
  787. long newesttime()
  788. {
  789.   int i;
  790.   long newest = 0;
  791.  
  792.   for (i = 0; i < File->num; i++)
  793.     if ((File->list[i]->time < time(NULL)) && (File->list[i]->time > newest))
  794.       newest = File->list[i]->time;
  795.  
  796.   return newest;
  797. }
  798.  
  799. char *temp_name(buf, sub)
  800.   char *buf;
  801.   char *sub;
  802. {
  803.   sprintf(buf, "%s%s_%s", TEMPPATH, UserName, sub);
  804.   return buf;
  805. }
  806.  
  807. struct temp_file {
  808.   FILE *fh;
  809.   char name[100];
  810.   int (*cleanup) ();
  811. };
  812. #define TEMPFILE struct temp_file
  813.  
  814. int temp_delete(tfh)
  815.   TEMPFILE *tfh;
  816. {
  817.   if (*tfh->name)
  818.     unlink(tfh->name);
  819.   return 0;
  820. }
  821.  
  822. int temp_dummy()
  823. {
  824.   return 0;
  825. }
  826.  
  827. char tclose(tfh)
  828.   TEMPFILE *tfh;
  829. {
  830.   fclose(tfh->fh);
  831.   if (tfh->cleanup)
  832.     (*tfh->cleanup) (tfh);
  833.   return 0;
  834. }
  835.  
  836. int exists(name)
  837.   char *name;
  838. {
  839.   FILE *f;
  840.  
  841.   if ((f = fopen(name, "r")))
  842.     fclose(f);
  843.   return f != 0;
  844. }
  845.  
  846. char *tackon(buf, add)
  847.   char *buf, *add;
  848. {
  849.   if (*buf && (buf[strlen(buf) - 1] != '/' && buf[strlen(buf) - 1] != ':'))
  850.     strcat(buf, "/");
  851.   strcat(buf, add);
  852.  
  853.   return buf;
  854. }
  855.  
  856. char *basename(s)
  857.   char *s;
  858. {
  859.   char *b = s;
  860.  
  861.   for (; *s; s++)
  862.     if (*s == '/' || *s == ':')
  863.       b = s + 1;
  864.  
  865.   return b;
  866. }
  867.  
  868.  
  869. #define NUMLINES 500
  870. char *Lines[NUMLINES + 1];
  871. char LineBuf[200];
  872.  
  873. char **read_file(f, title)
  874.   FILE *f;
  875.   char *title;
  876. {
  877.   int i=0;
  878.   char *t;
  879.  
  880.   if (title) {
  881.     Lines[i]= (char *) salloc( mystrlen(title) + 1 );
  882.     mystrcpy (Lines[i++], title);
  883.   }
  884.  
  885.   for ( ; i < NUMLINES; i++) {
  886.     if (!(fgets(LineBuf, 200, f)))
  887.       break;
  888.     for (t = LineBuf; *t && *t != '\n'; t++);
  889.     *t = 0;
  890.     Lines[i] = (char *) salloc(mystrlen(LineBuf) + 1);
  891.     mystrcpy(Lines[i], LineBuf);
  892.   }
  893.   Lines[i] = 0;
  894.   return Lines;
  895. }
  896.  
  897. int free_file(strings)
  898.   char **strings;
  899. {
  900.   while (*strings)
  901.     free(*strings++);
  902.   return 0;
  903. }
  904.  
  905. /*-----------------------------------sorting---------------------------------*/
  906.  
  907. int cmp_age(e1, e2)
  908.   ENTRY *e1, *e2;
  909. {
  910.   return e2->time - e1->time;
  911. }
  912.  
  913. int cmp_dir(e1, e2)
  914.   ENTRY *e1, *e2;
  915. {
  916.   int t;
  917.  
  918.   return (t = mystricmp(e1->dir, e2->dir)) ? t : mystricmp(e1->file, e2->file);
  919. }
  920.  
  921. int cmp_size(e1, e2)
  922.   ENTRY *e1, *e2;
  923. {
  924.   return e2->size - e1->size;
  925. }
  926.  
  927. int cmp_name(e1, e2)
  928.   ENTRY *e1, *e2;
  929. {
  930.   return mystricmp(e1->file, e2->file);
  931. }
  932.  
  933. int cmp_rage(e2, e1)
  934.   ENTRY *e1, *e2;
  935. {
  936.   return e2->time - e1->time;
  937. }
  938.  
  939. int cmp_rdir(e2, e1)
  940.   ENTRY *e1, *e2;
  941. {
  942.   int t;
  943.  
  944.   return (t = mystricmp(e1->dir, e2->dir)) ? t : mystricmp(e1->file, e2->file);
  945. }
  946.  
  947. int cmp_rsize(e2, e1)
  948.   ENTRY *e1, *e2;
  949. {
  950.   return e2->size - e1->size;
  951. }
  952.  
  953. int cmp_rname(e2, e1)
  954.   ENTRY *e1, *e2;
  955. {
  956.   return mystricmp(e1->file, e2->file);
  957. }
  958.  
  959. struct sort_mode {
  960.   int (*cmp) ();
  961.   char *desc;
  962. };
  963. #define SORT struct sort_mode
  964.  
  965. SORT
  966. sort_age   = { cmp_age,   "by age (newest first)" },
  967. sort_dir   = { cmp_dir,   "by dir" },
  968. sort_size  = { cmp_size,  "by size" },
  969. sort_name  = { cmp_name,  "by name" },
  970. sort_rage  = { cmp_rage,  "by age (oldest first)" },
  971. sort_rdir  = { cmp_rdir,  "reverse by dir" },
  972. sort_rsize = { cmp_rsize, "reverse by size" },
  973. sort_rname = { cmp_rname, "reverse by name" };
  974.  
  975. int quick_sort(av, n, cmp)
  976.   ENTRY **av;
  977.   int n, (*cmp) ();
  978. {
  979.   ENTRY **i, **j, *x, *t;
  980.  
  981.   if (n > 0) {
  982.     i = av;
  983.     j = av + n - 1;
  984.     x = av[n >> 1];
  985.     do {
  986.       while (cmp(*i, x) < 0)
  987.     i++;
  988.       while (cmp(x, *j) < 0)
  989.     --j;
  990.       if (i <= j)
  991.     t = *i, *i = *j, *j = t, i++, j--;
  992.  
  993.     } while (i <= j);
  994.  
  995.     if (j + 1 - av < av + n - i) {
  996.       quick_sort(av, j + 1 - av, cmp);
  997.       quick_sort(i, av + n - i, cmp);
  998.     } else {
  999.       quick_sort(i, av + n - i, cmp);
  1000.       quick_sort(av, j + 1 - av, cmp);
  1001.     }
  1002.   }
  1003.   return 0;
  1004. }
  1005.  
  1006. int sort_list(list, sort)
  1007.   LIST *list;
  1008.   SORT *sort;
  1009. {
  1010.  
  1011.   quick_sort(list->list, list->num, sort->cmp);
  1012.  
  1013.   list->current = list->offset = 0;
  1014.  
  1015.   Vis->sort = sort->desc;
  1016.  
  1017.   return 0;
  1018. }
  1019.  
  1020.  
  1021. /*---------------------------------visibility--------------------------------*/
  1022.  
  1023. int allvisible()
  1024. {
  1025.   int i;
  1026.  
  1027.   l_store();
  1028.   l_reset(Vis);
  1029.  
  1030.   Vis->sel = "All files";
  1031.   for (i = 0; i < File->num; i++)
  1032.     e_add(Vis, File->list[i]);
  1033.  
  1034.   sort_list(Vis, &sort_dir);
  1035.  
  1036.   return 0;
  1037. }
  1038.  
  1039. int invisible()
  1040. {
  1041.   ENTRY **entr = Vis->list;
  1042.   char buf[200], *b, *h = option_get("hide");
  1043.   int i, j;
  1044.  
  1045.   while (*h) {
  1046.     b = buf;
  1047.     while (*h && *h != ' ' && *h != ',')
  1048.       *b++ = *h++;
  1049.     *b = 0;
  1050.  
  1051.     while (*h && (*h == ' ' || *h == ','))
  1052.       h++;
  1053.  
  1054.     if (!*buf)
  1055.       continue;
  1056.  
  1057.     for (i = j = 0; i < Vis->num; i++)
  1058.       if (mystrncmp(buf, entr[i]->dir, b - buf))
  1059.     entr[j++] = entr[i];
  1060.     Vis->num = j;
  1061.   }
  1062.   Vis->current = 0;
  1063.  
  1064.   return 0;
  1065. }
  1066.  
  1067. int newvisible()
  1068. {
  1069.   ENTRY **entr = File->list;
  1070.   int i;
  1071.  
  1072.   l_store();
  1073.   l_reset(Vis);
  1074.   Vis->sel = "New files";
  1075.  
  1076.   for (i = 0; i < File->num; i++)
  1077.     if (entr[i]->time > LastCall)
  1078.       e_add(Vis, entr[i]);
  1079.  
  1080.   invisible();
  1081.  
  1082.   if (!Vis->num && File->num)
  1083.     NoFilesString = "No new files since your last call, use v)iew k)nown to see older ones";
  1084.  
  1085.   sort_list(Vis, &sort_dir);
  1086.  
  1087.   return 0;
  1088. }
  1089.  
  1090. int dirvisible(dir)
  1091.   char *dir;
  1092. {
  1093.   ENTRY **entr = File->list;
  1094.   int i, l = strlen(dir);
  1095.  
  1096.   l_store();
  1097.   l_reset(Vis);
  1098.   Vis->sel = "Selected dir";
  1099.  
  1100.   for (i = 0; i < File->num; i++)
  1101.     if (!mystrncmp(entr[i]->dir, dir, l))
  1102.       e_add(Vis, entr[i]);
  1103.  
  1104.   if (!Vis->num && File->num)
  1105.     NoFilesString = "No files matching that directory specification";
  1106.  
  1107.   sort_list(Vis, &sort_dir);
  1108.  
  1109.   return 0;
  1110. }
  1111.  
  1112. int findstr(str)
  1113.   char *str;
  1114. {
  1115.   ENTRY **entr = File->list;
  1116.   int i;
  1117.  
  1118.   if (!*str)
  1119.     return 0;
  1120.  
  1121.   l_store();
  1122.   l_reset(Vis);
  1123.  
  1124.   for (i = 0; i < File->num; i++)
  1125.     if (mystristr(str, entr[i]->desc) || mystristr(str, entr[i]->file))
  1126.       e_add(Vis, entr[i]);
  1127.  
  1128.   Vis->sel = "Matching files";
  1129.  
  1130.   sort_list(Vis, &sort_dir);
  1131.  
  1132.   if (!Vis->num && File->num)
  1133.     NoFilesString = "No files matching substring, use f)ind to search again";
  1134.  
  1135.   return 0;
  1136. }
  1137.  
  1138.  
  1139. int strlimit(str)
  1140.   char *str;
  1141. {
  1142.   ENTRY **entr = Vis->list;
  1143.   int i, j;
  1144.  
  1145.   if (!*str)
  1146.     return 0;
  1147.  
  1148.   l_store();
  1149.   Vis->sel = "Matching files";
  1150.  
  1151.   for (i = j = 0; i < Vis->num; i++)
  1152.     if (mystristr(str, entr[i]->desc) || mystristr(str, entr[i]->file))
  1153.       entr[j++] = entr[i];
  1154.  
  1155.   Vis->num = j;
  1156.   Vis->current = 0;
  1157.  
  1158.   if (!Vis->num && File->num)
  1159.     NoFilesString = "No files matching substring, use v)iew to see more";
  1160.  
  1161.   return 0;
  1162. }
  1163.  
  1164. int togglevisible()
  1165. {
  1166.   LIST *l;
  1167.  
  1168.   l = Vis;
  1169.   Vis = Alt;
  1170.   Alt = l;
  1171.   return 0;
  1172. }
  1173.  
  1174.  
  1175. int markedvisible()
  1176. {
  1177.   ENTRY **entr;
  1178.   int i, j=0;
  1179.  
  1180.   l_store();
  1181.   Vis->sel = "Marked files";
  1182.  
  1183.   entr = Vis->list;
  1184.   for (i = 0; i < Vis->num; i++)
  1185.     if (entr[i]->tagged)
  1186.       entr[j++]=entr[i];
  1187.  
  1188.   if (!(Vis->num=j) && File->num)
  1189.     NoFilesString = "No tagged files";
  1190.  
  1191.   return 0;
  1192. }
  1193.  
  1194. int markedextract()
  1195. {
  1196.   ENTRY **entr = Vis->list;
  1197.   int i;
  1198.  
  1199.   l_reset(Mark);
  1200.  
  1201.   for (i = 0; i < Vis->num; i++)
  1202.     if (entr[i]->tagged)
  1203.       e_add(Mark, entr[i]);
  1204.  
  1205.   if (!Mark->num)
  1206.     e_add(Mark, entr[Vis->current]);
  1207.  
  1208.   return 0;
  1209. }
  1210.  
  1211.  
  1212.  
  1213. /*-----------------------------string formatting-----------------------------*/
  1214. char *ShowFiles = "New files by dir";
  1215. int CurSelected, Window;
  1216.  
  1217. char *str_topline(buf, len, list)
  1218.   LIST *list;
  1219.   int len;
  1220.   char *buf;
  1221. {
  1222.   int i;
  1223.   char buf2[40];
  1224.  
  1225.   for (i = 0; i < len; i++)
  1226.     buf[i] = ' ';
  1227.   buf[i] = 0;
  1228.  
  1229.   sprintf(buf2, "Showing: %d/%d", list->num, File->num);
  1230.   strcpy(buf, buf2);
  1231.   buf[strlen(buf)] = ' ';
  1232.  
  1233.   sprintf(buf2, "%s %s", Vis->sel, Vis->sort);
  1234.   strcpy(buf + len / 2 - strlen(buf2) / 2, buf2);
  1235.   buf[strlen(buf)] = ' ';
  1236.  
  1237.   sprintf(buf2, "Page: %d/%d", 1 + list->offset / Window, 1 + list->num / Window);
  1238.   strcpy(buf + len - strlen(buf2), buf2);
  1239.  
  1240.   return buf;
  1241. }
  1242.  
  1243.  
  1244. char sizestr[10];
  1245.  
  1246. char *str_ksize(size)
  1247.   long size;
  1248. {
  1249.   if (size == -1) {
  1250.     sprintf(sizestr, "?");
  1251.   } else {
  1252.     size = (size + 512) / 1024;
  1253.     if (size <= 999)
  1254.       sprintf(sizestr, "%dK", size);
  1255.     else if ((size + 512) / 1024 < 10)
  1256.       sprintf(sizestr, "%d.%dM", size / 1024, (size * 10 + 512) / 1024 % 10);
  1257.     else
  1258.       sprintf(sizestr, "%dM", (size + 512) / 1024);
  1259.   }
  1260.   return sizestr;
  1261. }
  1262.  
  1263.  
  1264. char *str_titles(buf)
  1265.   char *buf;
  1266. {
  1267.   switch (Dispmode) {
  1268.   case 0:
  1269.     strcpy(buf, " File                 Dir        Size Description\n");
  1270.     break;
  1271.   }
  1272.   return buf;
  1273. }
  1274.  
  1275.  
  1276.  
  1277. char *str_entry(e, n, max, buf, len)
  1278.   ENTRY **e;
  1279.   int n, max, len;
  1280.   char *buf;
  1281. {
  1282.   int i;
  1283.  
  1284.   if (n >= max) {
  1285.     for (i = 0; i < len; i++)
  1286.       buf[i] = ' ';
  1287.     buf[i] = 0;
  1288.     return buf;
  1289.   }
  1290.   switch (Dispmode) {
  1291.   case 0:
  1292.     sprintf(buf, "%c%-20.20s %-10.10s %4.4s%c%-80.80s",
  1293.         e[n]->tagged ? '+' : ' ',
  1294.         e[n]->file,
  1295.         e[n]->dir,
  1296.         str_ksize(e[n]->size),
  1297.         e[n]->readmesize > 100 ? '+' : ' ',
  1298.         e[n]->desc);
  1299.     buf[len - 1] = 0;
  1300.     break;
  1301.   }
  1302.  
  1303.  
  1304.   return buf;
  1305. }
  1306.  
  1307.  
  1308. char sitebuf[120];
  1309.  
  1310. int str_sitesplit(s, parts)
  1311.   char *s, **parts;
  1312. {
  1313.   char *d = sitebuf;
  1314.   int i;
  1315.  
  1316.   for (i = 0; i < 5; i++) {
  1317.     parts[i] = d;
  1318.     while (*s && *s != ',' && *s != '@')
  1319.       *d++ = *s++;
  1320.     if (*s == ',')
  1321.       s++;
  1322.     *d++ = 0;
  1323.   }
  1324.  
  1325.   return 0;
  1326. }
  1327.  
  1328. char *str_showline(entries, n, max, buf)
  1329.   char *entries, *buf;
  1330.   int n, max;
  1331. {
  1332.   char *s = entries;
  1333.   char *parts[10];
  1334.  
  1335.   if (n >= max)
  1336.     return "";
  1337.  
  1338.   for (; n > 0; n--)
  1339.     while (*s++ != '@');
  1340.  
  1341.   str_sitesplit(s, parts);
  1342.   sprintf(buf, "%-12.12s %24.24s", parts[0], parts[1]);
  1343.  
  1344.   return buf;
  1345. }
  1346.  
  1347. char centerbuf[250];
  1348.  
  1349. char *str_center(s, len)
  1350.   char *s;
  1351.   int len;
  1352. {
  1353.   int i = (len - strlen(s)) / 2 - 1;
  1354.  
  1355.   strcpy(centerbuf + i, s);
  1356.   while (i > 0)
  1357.     centerbuf[--i] = ' ';
  1358.  
  1359.   return centerbuf;
  1360. }
  1361.  
  1362.  
  1363. int str_longest(arr)
  1364.   char **arr;
  1365. {
  1366.   int l = 0;
  1367.  
  1368.   for (; *arr; arr++)
  1369.     if (strlen(*arr) > l)
  1370.       l = strlen(*arr);
  1371.   return l;
  1372. }
  1373.  
  1374. int str_shift(len, width)
  1375.   int len, width;
  1376. {
  1377.   return len < width ? (width - len) / 2 : 0;
  1378. }
  1379.  
  1380. LIST sitelist = {0, str_showline, 0, 0, 0, 0, 1, 0};
  1381.  
  1382. int setup_sitelist(sitesname, sitename, help)
  1383.   char *sitesname, *sitename, **help;
  1384. {
  1385.   int t, n = 1;
  1386.   char *sites = option_get(sitesname), *s;
  1387.   char buf[100], *d = buf;
  1388.  
  1389.   mystrcpy(buf, option_get("ftpsite"));
  1390.  
  1391.   for (s = sites; *s; ) {
  1392.     if (*s++ == '@') {
  1393.       if (*buf && !mystrncmp(s, buf, strlen(buf)))
  1394.     sitelist.current = n;
  1395.       n++;
  1396.     }
  1397.   }
  1398.  
  1399.   sitelist.list = (ENTRY **) sites;
  1400.   sitelist.num = n;
  1401.  
  1402.   if ((t = disp_choice(help, &sitelist)) < 0)
  1403.     return 1;
  1404.  
  1405.   for (s = sites; t > 0; t--)
  1406.     while (*s++ != '@');
  1407.  
  1408.   while (*s && *s != '@')
  1409.     *d++ = *s++;
  1410.   *d++ = 0;
  1411.  
  1412.   option_set(sitename, buf);
  1413.  
  1414.   return 0;
  1415. }
  1416.  
  1417. /*-----------------------------command key input-----------------------------*/
  1418. #define K_UP     300
  1419. #define K_DOWN   301
  1420. #define K_RIGHT  302
  1421. #define K_LEFT   303
  1422.  
  1423. int inp_getchr()
  1424. {
  1425.   int c;
  1426.  
  1427.   if ((c = disp_getchar()) != 27 && c != 155)
  1428.     return c;
  1429.  
  1430.   if (c == 27 && (c = disp_getchar()) != '[')
  1431.     return c;
  1432.  
  1433.   switch (c = disp_getchar()) {
  1434.   case 'A':
  1435.     return K_UP;
  1436.   case 'B':
  1437.     return K_DOWN;
  1438.   case 'C':
  1439.     return K_RIGHT;
  1440.   case 'D':
  1441.     return K_LEFT;
  1442.   }
  1443.   return 0;
  1444. }
  1445.  
  1446. /*-------------------------------initial setup-------------------------------*/
  1447. char *setup_showline(entries, n, max)
  1448.   TRANSFER entries[];
  1449.   int n, max;
  1450. {
  1451.   return n < max ? entries[n].text : "";
  1452. }
  1453.  
  1454. LIST setuplist = {(ENTRY **) TransferTypes, setup_showline, 0, 0, 0, 0, 1, 0};
  1455.  
  1456. char *FirstSetupHelp[] = {
  1457.   "ADT initial setup",
  1458.   "It seems that you've never used ADT before. ADT lets you access files",
  1459.   "stored in an Aminet database using various methods (FTP, FSP, mail",
  1460.   "servers and local files). The version you have here may not support all",
  1461.   "of those though. Select your transfer method now.",
  1462.   "NOTE: After setup, you can press 'h' or '?' in most places to get help.",0
  1463. };
  1464.  
  1465. char *SetupHelp[] = {
  1466.   "ADT transfer method setup",
  1467.   "Please select the way ADT should use to access files on Aminet", 0
  1468. };
  1469.  
  1470. int setup_method()
  1471. {
  1472.   TRANSFER *type;
  1473.   int n;
  1474.  
  1475.   setuplist.current = 0;
  1476.   setuplist.num = 0;
  1477.   for (type = TransferTypes; type->text; type++) {
  1478.     if (!mystrcmp(type->name, option_get("method")))
  1479.       setuplist.current = setuplist.num;
  1480.     setuplist.num++;
  1481.   }
  1482.  
  1483.   n = disp_choice(InitialSetup ? FirstSetupHelp : SetupHelp, &setuplist);
  1484.  
  1485.   if (n < 0) {
  1486.     if (InitialSetup)
  1487.       exit_adt("Cannot start up without a transfer method. Goodbye.");
  1488.   } else {
  1489.     if (trans_close)
  1490.       trans_close();
  1491.     option_set("method", TransferTypes[n].name);
  1492.     TransferTypes[n].init();
  1493.     trans_options();
  1494.   }
  1495.  
  1496.   return 0;
  1497. }
  1498.  
  1499.  
  1500. char *DefaultsHelp[] = {
  1501.   "ADT initial setup",
  1502.   "It seems that you've never used ADT before. ADT lets you access files",
  1503.   "stored in ADT databases using various methods (FTP, FSP, mailservers,",
  1504.   "local files. Your sysadmin has selected a default transfer method and",
  1505.   "default site for you. They will be saved as your local configuration",
  1506.   "when you q)uit ADT. You may change them anytime using the o)ptions",
  1507.   "command.",
  1508.   "Press any key to enter ADT", 0
  1509. };
  1510.  
  1511. int setup_defaults()
  1512. {
  1513.   option_set("newest", "0");
  1514.  
  1515.   return 0;
  1516. }
  1517.  
  1518.  
  1519.  
  1520. char *enum_showline(entries, n, max, buf)
  1521.   char **entries, *buf;
  1522.   int n, max;
  1523. {
  1524.   if (n >= max)
  1525.     return "";
  1526.   else
  1527.     return entries[n];
  1528. }
  1529.  
  1530.  
  1531. LIST enumlist = {0, enum_showline, 0, 0, 0, 0, 1, 0};
  1532.  
  1533. int setup_enumed(help, choices, var)
  1534.   char **help, **choices, *var;
  1535. {
  1536.   int n, lines, t;
  1537.  
  1538.   for (lines = 0; choices[lines]; lines++);
  1539.  
  1540.   n = option_getnum(var);
  1541.   if (n < 0)
  1542.     n = 0;
  1543.   if (n >= lines)
  1544.     n = lines - 1;
  1545.  
  1546.   enumlist.list = (ENTRY **) choices;
  1547.   enumlist.num = lines;
  1548.   enumlist.current = n;
  1549.  
  1550.   t = disp_choice(help, &enumlist);
  1551.  
  1552.   if (t >= 0)
  1553.     option_setnum(var, t);
  1554.  
  1555.   return t;
  1556. }
  1557.  
  1558.  
  1559. char *FindMethodHelp[] = {
  1560.   "Find method",
  1561.   "Please choose the method to use for finding files on Aminet. You can use",
  1562.   "an archie-like find server if you have Internet access. If you don't,",
  1563.   "or if you want to make several queries at once, or if your connection to",
  1564.   "Aminet is very fast (e.g. local files), it may be advisable for ADT to",
  1565.   "download the complete file list and do the queries locally. If you only",
  1566.   "want to search what's available at your site, pick the third option.", 0
  1567. }, *FindMethodList[] = {
  1568.   "Remote server search of complete Aminet index",
  1569.   "Local search of current Aminet site",
  1570.   "Local search of complete Aminet index", 0
  1571. };
  1572.  
  1573. char *FindSiteHelp[] = {
  1574.   "Find site selection",
  1575.   "Which server should be used for finding stuff? All servers have a complete",
  1576.   "Aminet index and can thus be used for searches on any of the complete sites", 0
  1577. };
  1578.  
  1579. int setup_findmethod()
  1580. {
  1581.   if (setup_enumed(FindMethodHelp, FindMethodList, "findmethod") == 0)
  1582.     setup_sitelist("findsites", "findsite", FindSiteHelp);
  1583.  
  1584.   option_save(ConfigFile);
  1585.  
  1586.   return 0;
  1587. }
  1588.  
  1589. /* ==============================GENERIC FILE TRANSFER======================== */
  1590. int trans_init()
  1591. {
  1592.   TRANSFER *t = TransferTypes;
  1593.   char *s = option_get("method");
  1594.  
  1595.   while (t->name && mystrcmp(t->name, s))
  1596.     t++;
  1597.  
  1598.   if (!t->name)
  1599.     return 1;
  1600.  
  1601.   t->init();
  1602.  
  1603.   return 0;
  1604. }
  1605.  
  1606.  
  1607. /* ==============================LOCAL FILE PACKAGE=========================== */
  1608. int CdRom;
  1609.  
  1610. int local_connect(progress)
  1611.   int (*progress) ();
  1612. {
  1613.   Connected = 1;
  1614.   return 0;
  1615. }
  1616.  
  1617. int local_remopen(tfh, remote)
  1618.   TEMPFILE *tfh;
  1619.   char *remote;
  1620. {
  1621.   strcpy(tfh->name, option_get("locaminet"));
  1622.   tackon(tfh->name, remote);
  1623.  
  1624.   tfh->cleanup = temp_dummy;
  1625.   tfh->fh = fopen(tfh->name, "r");
  1626.  
  1627.   NoFilesString = "Could not access remote file, use o)ptions s)ite to change path";
  1628.  
  1629.   return 0;
  1630. }
  1631.  
  1632. int local_download(remote, locdir, size, progress)
  1633.   char *remote, *locdir;
  1634.   long size;
  1635.   int (*progress) ();
  1636. {
  1637.   char buf[150], buf2[100];
  1638.  
  1639.   sprintf(buf, "Copying %s", remote);
  1640.   progress(buf);
  1641.  
  1642.   strcpy(buf2, option_get("locaminet"));
  1643.   tackon(buf2, remote);
  1644.  
  1645.   sprintf(buf, "%s %s %s", COPYCMD, buf2, locdir);
  1646.   system(buf);
  1647.  
  1648.   sprintf(buf, "Copied %s", remote);
  1649.   progress(buf);
  1650.  
  1651.   return 0;
  1652. }
  1653.  
  1654. int local_disconnect()
  1655. {
  1656.   Connected = 0;
  1657.   return 0;
  1658. }
  1659.  
  1660. #ifdef AMIGA
  1661. char *LocAminetHelp[] = {
  1662.   "Use a local Aminet database",
  1663.   "Please enter the absolute path to the Aminet files up to the aminet/",
  1664.   "directory, e.g. NET:aminet", 0
  1665. };
  1666.  
  1667. char *CdRomHelp[] = {
  1668.   "Use an Aminet CDROM",
  1669.   "Please enter the absolute path to your Aminet CDROM (or any other non",
  1670.   "updated Aminet file collection), including the Aminet/ end of the path,",
  1671.   "e.g. CD0:Aminet . Note that you need at least Aminet CD 2.", 0
  1672. };
  1673.  
  1674. #else
  1675.  
  1676. char *LocAminetHelp[] = {
  1677.   "Use a local Aminet database",
  1678.   "Please enter the absolute path to the Aminet files. You must not use the",
  1679.   "tilde ~ sign. Enter the path up to the aminet dir, eg. /ftp/pub/aminet .", 0
  1680. };
  1681.  
  1682. char *CdRomHelp[] = {
  1683.   "Please enter the absolute path to your Aminet CDROM (or any other non",
  1684.   "updated Aminet file collection), including the Aminet/ end of the path,",
  1685.   "e.g. CD0:Aminet . Note that you need at least Aminet CD 2.", 0
  1686. };
  1687. #endif
  1688.  
  1689.  
  1690.  
  1691.  
  1692. int local_options()
  1693. {
  1694.   char buf[100];
  1695.  
  1696.   if (InitialSetup)
  1697.     option_set("findmethod", "1");
  1698.  
  1699.  
  1700.   mystrcpy(buf, option_get("locaminet"));
  1701.   disp_inputstr(buf, CdRom ? CdRomHelp : LocAminetHelp);
  1702.   option_set("locaminet", buf);
  1703.  
  1704.   return 0;
  1705. }
  1706.  
  1707. int local_close()
  1708. {
  1709.   return 0;
  1710. }
  1711.  
  1712.  
  1713. int local_init()
  1714. {
  1715.   trans_options = local_options;
  1716.   trans_connect = local_connect;
  1717.   trans_remopen = local_remopen;
  1718.   trans_download = local_download;
  1719.   trans_disconnect = local_disconnect;
  1720.   trans_close = local_close;
  1721.  
  1722.   if ( !strcmp ( option_get("method"), "cdrom"))
  1723.     CdRom=1;
  1724.  
  1725.   return 0;
  1726. }
  1727.  
  1728. /* ==============================EXTERNAL FTP PACKAGE========================= */
  1729. #ifndef NO_EXTERNAL_FTP
  1730.  
  1731. FILE *xFtp;
  1732.  
  1733. int xftp_connect(progress)
  1734.   int (*progress) ();
  1735. {
  1736.   char *site = option_get("ftpsite");
  1737.   char *parts[10],passwd[32];
  1738.   char buf[100];
  1739.  
  1740.   if (Connected)
  1741.     return 0;
  1742.   Connected = 1;
  1743.  
  1744.   str_sitesplit(site, parts);
  1745.  
  1746.   sprintf(buf, "Connecting to %s", parts[1]);
  1747.   progress(buf);
  1748.  
  1749.   sprintf(passwd,"user ftp %s\n",getenv("USER"));
  1750.  
  1751.   fprintf(xFtp, "open %s\n", parts[1]);
  1752.   fprintf(xFtp, passwd);
  1753.   fprintf(xFtp, "cd pub/aminet\n");
  1754.   fprintf(xFtp, "bin\n");
  1755.  
  1756.   return 0;
  1757. }
  1758.  
  1759. #ifdef AMIGA
  1760. #define xftp_filesize(name) 0
  1761. #else
  1762.  
  1763. static long xftp_filesize(name)
  1764.   char *name;
  1765. {
  1766.   struct stat st;
  1767.  
  1768.   return stat(name, &st) ? -1 : st.st_size;
  1769. }
  1770. #endif
  1771.  
  1772. static int xftp_waitfile(local, size, progress, maxwait, pad, name)
  1773.   char *local;
  1774.   long size;
  1775.   int (*progress) (), maxwait;
  1776.   char *pad, *name;
  1777. {
  1778.   int got, prevgot = -1, timeout = 0;
  1779.   char buf[100];
  1780.  
  1781.   sprintf(buf, "Initiating download of %s", size < 0 ? name : local);
  1782.   progress(buf);
  1783.  
  1784.   while ((got = xftp_filesize(local)) < size || size < 0) {
  1785.  
  1786.     if (got != prevgot)
  1787.       timeout = 0;
  1788.  
  1789.     if (timeout > maxwait)
  1790.       return 1;
  1791.  
  1792.     if (++timeout > 10) {
  1793.       sprintf(buf, "Timeout %d on file %s", maxwait - timeout, local);
  1794.       progress(buf);
  1795.     }
  1796.     prevgot = got;
  1797.     if (got >= 0) {
  1798.       if (size >= 0)
  1799.     sprintf(buf, "Downloading %s, %3dK/%3dK",
  1800.         local, (got + 512) / 1024, (size + 512) / 1024);
  1801.       else
  1802.     sprintf(buf, "Downloading %s, %3dK", name, (got + 512) / 1024);
  1803.  
  1804.       progress(buf);
  1805.     }
  1806.     if (size < 0 && exists(pad))
  1807.       return 0;
  1808.  
  1809.     sleep(1);
  1810.   }
  1811.  
  1812.   return size >= 0 ? got < size : 0;
  1813. }
  1814.  
  1815. int xftp_remopen(tfh, remote, pack, progress)
  1816.   TEMPFILE *tfh;
  1817.   char *remote, *pack;
  1818.   int (*progress) ();
  1819. {
  1820.   char pad[100], buf[100], remname[100];
  1821.  
  1822.   sprintf(remname, "%s%s", remote, pack);
  1823.  
  1824.   temp_name(pad, "PAD");
  1825.   temp_name(tfh->name, "REMOTE");
  1826.   strcat(tfh->name, pack);
  1827.   tfh->cleanup = temp_delete;
  1828.  
  1829.   unlink(pad);
  1830.   unlink(tfh->name);
  1831.  
  1832.   fprintf(xFtp, "get %s %s\n", remname, tfh->name);
  1833.   fprintf(xFtp, "get info/adt/pad %s\n", pad);
  1834.   fflush(xFtp);
  1835.  
  1836.   xftp_waitfile(tfh->name, -1, progress, 30, pad, basename(remname));
  1837.  
  1838.   unlink(pad);
  1839.  
  1840.   if (*pack) {
  1841.     temp_name(tfh->name, "REMOTE");
  1842.     unlink(tfh->name);
  1843.     sprintf(buf, "%s %s", pack[2] ? "gzip -d" : "uncompress", tfh->name);
  1844.     system(buf);
  1845.   }
  1846.   tfh->fh = fopen(tfh->name, "r");
  1847.  
  1848.   return 0;
  1849. }
  1850.  
  1851.  
  1852. int xftp_download(remote, locdir, size, progress)
  1853.   char *remote, *locdir;
  1854.   int size, (*progress) ();
  1855. {
  1856.   char locname[200];
  1857.  
  1858.   strcpy(locname, locdir);
  1859.   tackon(locname, basename(remote));
  1860.  
  1861.   fprintf(xFtp, "get %s %s\n", remote, locname);
  1862.   fflush(xFtp);
  1863.  
  1864.   xftp_waitfile(locname, size, progress, 30, 0);
  1865.  
  1866.   return 0;
  1867. }
  1868.  
  1869.  
  1870. int xftp_disconnect()
  1871. {
  1872.   if (!Connected)
  1873.     return 0;
  1874.   Connected = 0;
  1875.  
  1876.   fprintf(xFtp, "close\n");
  1877.   fflush(xFtp);
  1878.   return 0;
  1879. }
  1880.  
  1881. char *XFTPHelp[] = {
  1882.   "External FTP client setup",
  1883.   "You need a site where you retrieve your files from. Pick one that is",
  1884.   "close to where you live, and later experiment around to find out which",
  1885.   "one's the best for you.", 0
  1886. };
  1887.  
  1888.  
  1889. int xftp_options()
  1890. {
  1891.   setup_sitelist("ftpsites", "ftpsite", XFTPHelp);
  1892.  
  1893.   return 0;
  1894. }
  1895.  
  1896. int xftp_close()
  1897. {
  1898.   if (xFtp) {
  1899.     fprintf(xFtp, "bye\n");
  1900.     pclose(xFtp);
  1901.     xFtp = 0;
  1902.     Connected = 0;
  1903.   }
  1904.   return 0;
  1905. }
  1906.  
  1907. int xftp_init()
  1908. {
  1909.   char buf[100];
  1910.  
  1911.   sprintf(buf, "ftp -n");
  1912.  
  1913.   if (!xFtp && !(xFtp = popen(buf, "w")))
  1914.     exit_adt("Could not start 'ftp'");
  1915.  
  1916.   trans_options = xftp_options;
  1917.   trans_connect = xftp_connect;
  1918.   trans_remopen = xftp_remopen;
  1919.   trans_download = xftp_download;
  1920.   trans_disconnect = xftp_disconnect;
  1921.   trans_close = xftp_close;
  1922.  
  1923.   return 0;
  1924. }
  1925.  
  1926. #endif
  1927.  
  1928.  
  1929. /* ==============================TCP functions========================= */
  1930. #ifndef NO_TCP_UTILITY
  1931.  
  1932. /* creates an new tcp socket and connects it to <host> on port <port>. returns
  1933.  * -1 if a failure occured. NOTE: host can either be a hostname or a
  1934.  * dot-notation of the internet adress */
  1935. int tcp_createsocket(host, port)
  1936.   char *host;
  1937.   int port;
  1938. {
  1939.   struct sockaddr_in sin;
  1940.   struct hostent *h;
  1941.   int connected, net = -1;
  1942.  
  1943.   if ((sin.sin_addr.s_addr = inet_addr(host)) == -1) {
  1944.     if (!(h = gethostbyname(host)))
  1945.       return -1;
  1946.     else {
  1947.       sin.sin_family = h->h_addrtype;
  1948.  
  1949. #ifndef NOT43
  1950.       memcpy((caddr_t) & sin.sin_addr, h->h_addr_list[0], h->h_length);
  1951. #else
  1952.       memcpy((caddr_t) & sin.sin_addr, h->h_addr, h->h_length);
  1953. #endif
  1954.     }
  1955.   } else
  1956.     sin.sin_family = AF_INET;
  1957.  
  1958.   sin.sin_port = htons(port);
  1959.  
  1960.   for (connected = 1; connected && (connected < 30); connected++) {
  1961.     if ((net = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  1962.       return -1;
  1963.  
  1964.     if (connect(net, (struct sockaddr *) & sin, sizeof(sin)) >= 0) {
  1965.       connected = 0;
  1966.       break;
  1967.     } else
  1968.       close(net);
  1969.   }
  1970.  
  1971.   if (!connected)
  1972.     return net;
  1973.   else
  1974.     return -1;
  1975. }
  1976.  
  1977. #endif
  1978.  
  1979. /* ==============================BUILTIN FTP PACKAGE========================= */
  1980. #ifndef NO_BUILTIN_FTP
  1981.  
  1982. #ifndef BFTP_BUFSIZE
  1983. # define BFTP_BUFSIZE 10000
  1984. #endif
  1985.  
  1986. FILE *bftp_io = NULL;
  1987.  
  1988. char *BFTPHelp[] =
  1989. {
  1990.   "Builtin FTP client setup",
  1991.   "You'll need a site where you retrieve your files from. Pick one that is",
  1992.   "close to where you live, and later experiment around to find out which",
  1993.   "one's the best for you.", 0
  1994. };
  1995.  
  1996. int bftp_options()
  1997. {
  1998.   return setup_sitelist("ftpsites", "ftpsite", BFTPHelp);
  1999. }
  2000.  
  2001. int bftp_disconnect()
  2002. {
  2003.   Connected = 0;
  2004.  
  2005.   if (bftp_io)
  2006.     fclose(bftp_io);
  2007.   bftp_io = NULL;
  2008.  
  2009.   return 0;
  2010. }
  2011.  
  2012. int bftp_close()
  2013. {
  2014.   return bftp_disconnect();
  2015. }
  2016.  
  2017. /* Send FTP command and wait for reply. Returns 0 on failure. */
  2018. int bftp_cmd(cmd)
  2019.   char *cmd;
  2020. {
  2021.   char buf[256];
  2022.   int result;
  2023.  
  2024.   if (!bftp_io)
  2025.     return 0;
  2026.  
  2027.   if (cmd) {
  2028.     fflush(bftp_io);
  2029.     rewind(bftp_io);
  2030.     fputs(cmd, bftp_io);
  2031.   }
  2032.   fflush(bftp_io);
  2033.   rewind(bftp_io);
  2034.   if (!fgets(buf, sizeof(buf), bftp_io))
  2035.     return 0;
  2036.  
  2037.   result = myatoi(buf);
  2038.  
  2039.   while ((buf[3] != ' ') || (myatoi(buf) != result)) {
  2040.     if (!fgets(buf, sizeof(buf), bftp_io))
  2041.       return 0;
  2042.   }
  2043.  
  2044.   return (result >= 100) && (result < 400);
  2045. }
  2046.  
  2047. int bftp_getdataconnection()
  2048. {
  2049.   struct sockaddr_in sin;
  2050.   struct hostent *hp;
  2051.   int d, i;
  2052.   unsigned char *a, *p;
  2053.   char buf[80];
  2054.  
  2055.   gethostname(buf, sizeof(buf));
  2056.   hp = gethostbyname(buf);
  2057.  
  2058.   /* Port is not set, let system choose */
  2059.   memset((char *) &sin, '\0', sizeof(sin));
  2060.   memcpy((char *) &sin.sin_addr, hp->h_addr, hp->h_length);
  2061.   sin.sin_family = hp->h_addrtype;
  2062.  
  2063.   if ((d = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0)
  2064.     return -1;
  2065.  
  2066.   i = sizeof(sin);
  2067.   if ((bind(d, (struct sockaddr *) & sin, i) < 0) ||
  2068.       (getsockname(d, (struct sockaddr *) & sin, &i) < 0) ||
  2069.       (listen(d, 1) < 0)) {
  2070.     close(d);
  2071.     return -1;
  2072.   }
  2073.   a = (unsigned char *) &sin.sin_addr;
  2074.   p = (unsigned char *) &sin.sin_port;
  2075.  
  2076.   sprintf(buf, "PORT %d,%d,%d,%d,%d,%d\n", a[0], a[1], a[2], a[3], p[0], p[1]);
  2077.   if (!bftp_cmd(buf)) {
  2078.     close(d);
  2079.     return -1;
  2080.   }
  2081.   return d;
  2082. }
  2083.  
  2084. int bftp_getfile(remote, local, size, progress)
  2085.   char *remote, *local;
  2086.   int size, (*progress) ();
  2087. {
  2088.   FILE *out = NULL;
  2089.   int s = -1, d = -1, i, got = 0, result = 0;
  2090.   char *buf, *msg = NULL, tmp[80];
  2091.   struct sockaddr_in sin;
  2092.  
  2093.   if (!Connected)
  2094.     return 0;
  2095.  
  2096.   buf = salloc(BFTP_BUFSIZE);
  2097.  
  2098.   sprintf(buf, "Getting %s...", remote);
  2099.   progress(buf);
  2100.  
  2101.   if ((s = bftp_getdataconnection()) >= 0) {
  2102.     sprintf(buf, "RETR %s\n", remote);
  2103.     if (bftp_cmd(buf)) {
  2104.       i = sizeof(sin);
  2105.       if ((d = accept(s, (struct sockaddr *) & sin, &i)) >= 0) {
  2106.     if ((out = fopen(local, "w"))) {
  2107.       int len, k, start = time(NULL), t;
  2108.       float kps;
  2109.  
  2110.       while ((len = read(d, buf, BFTP_BUFSIZE)) > 0) {
  2111.         if (fwrite(buf, len, 1, out) != 1) {
  2112.           close(s);
  2113.           fclose(out);
  2114.           msg = "Error writing to local file";
  2115.           break;
  2116.         }
  2117.         got += len;
  2118.  
  2119.         if (progress) {
  2120.           k = (got + 512) / 1024;
  2121.           kps = (float)got / (float)((t = time(NULL) - start) ? t * 1024 : 1024);
  2122.           kps = (int)(kps*10.0) / 10.0;
  2123.  
  2124.           if (size > 0)
  2125.         sprintf(tmp, "Downloading %s, %4dK/%4dK (%#3.3g Kbyte/s)",
  2126.             remote, k, (size + 512) / 1024, kps);
  2127.           else
  2128.         sprintf(tmp, "Downloading %s, %4dK (%#3.3g Kbyte/s)", remote, k, kps);
  2129.  
  2130.           progress(tmp);
  2131.         }
  2132.       }
  2133.  
  2134.       if (bftp_cmd(NULL) && ((size <= 0) || (got == size)))
  2135.         result = 1;
  2136.       else {
  2137.         sprintf(buf, "Error getting file %s (got %d bytes instead of %d)", 
  2138.             remote, got, size);
  2139.         msg = buf;
  2140.       }
  2141.     } else
  2142.       msg = "Cannot create local file";
  2143.       } else
  2144.     msg = "Cannot establish data connection to ftp site";
  2145.     } else
  2146.       msg = "Cannot get file from ftp site";
  2147.   } else
  2148.     msg = "Cannot initiate data connection to ftp site";
  2149.  
  2150.   if (progress && msg) {
  2151.     sleep(1);
  2152.     progress(msg);
  2153.     sleep(2);
  2154.   }
  2155.  
  2156.   if (d >= 0)
  2157.     close(d);
  2158.   if (s >= 0)
  2159.     close(s);
  2160.   if (out)
  2161.     fclose(out);
  2162.   free(buf);
  2163.  
  2164.   return result;
  2165. }
  2166.  
  2167. int bftp_connect(progress, remote)
  2168.   int (*progress) ();
  2169.   int remote;
  2170. {
  2171.   char *parts[10], buf[100], passwd[32] , *msg = NULL;
  2172.   struct servent *sp;
  2173.   int s, port = 21;
  2174.   char *site;
  2175.  
  2176.   if (Connected)
  2177.     return 1;
  2178.   Connected = 1;
  2179.  
  2180.   str_sitesplit(option_get("ftpsite"), parts);
  2181.  
  2182.   if (remote)
  2183.     sprintf(buf, "Connecting to %s (master site)", site=parts[*parts[4]? 4:1]);
  2184.   else
  2185.     sprintf(buf, "Connecting to %s", site=parts[1]);
  2186.  
  2187.   progress(buf);
  2188.  
  2189.   if ((sp = getservbyname("ftp", "tcp")))
  2190.     port = ntohs(sp->s_port);
  2191.  
  2192.   sprintf(passwd,"PASS %s@\n",getenv("USER"));             /* take users login name as passwd */
  2193.  
  2194.   if ((s = tcp_createsocket(site, port)) >= 0) {
  2195.     if ((bftp_io = fdopen(s, "r+"))) {
  2196.       sprintf (buf, "CWD %s\n", *parts[3] ? parts[3] : "pub/aminet");
  2197.       if (bftp_cmd(NULL) &&
  2198.       bftp_cmd("USER ftp\n") &&
  2199.       bftp_cmd(passwd) &&
  2200.       bftp_cmd( buf ) &&
  2201.       bftp_cmd("TYPE I\n"))
  2202.     return 0;
  2203.       else
  2204.     msg = "Login failed, probably user limit reached, retry later.";
  2205.     } else {
  2206.       close(s);
  2207.       msg = "Could not communicate with ftp site.";
  2208.     }
  2209.   } else
  2210.     msg = "Could not connect to ftp site.";
  2211.  
  2212.   bftp_close();
  2213.  
  2214.   if (msg) {
  2215.     sleep(1);
  2216.     progress(msg);
  2217.     sleep(2);
  2218.   }
  2219.  
  2220.   return 1;
  2221. }
  2222.  
  2223. int bftp_remopen(tfh, remote, pack, progress)
  2224.   TEMPFILE *tfh;
  2225.   char *remote, *pack;
  2226.   int (*progress) ();
  2227. {
  2228.   char buf[200];
  2229.  
  2230.   tfh->fh = NULL;
  2231.   temp_name(tfh->name, "RECENT");
  2232.   strcat(tfh->name, pack);
  2233.   tfh->cleanup = temp_delete;
  2234.  
  2235.   unlink(tfh->name);
  2236.  
  2237.   sprintf(buf, "%s%s", remote, pack);
  2238.  
  2239.   if (bftp_getfile(buf, tfh->name, 0, progress)) {
  2240.     if (*pack) {
  2241.       temp_name(tfh->name, "RECENT");
  2242.       unlink(tfh->name);
  2243.  
  2244.       progress ("Uncompressing");
  2245.       if (pack[2]) {
  2246.         sprintf(buf,"gzip -d <%s%s >%s", tfh->name, pack, tfh->name);
  2247.       } else {
  2248.         sprintf(buf,"uncompress <%s%s >%s", tfh->name, pack, tfh->name);
  2249.       }
  2250.       system(buf);
  2251.       sprintf(buf,"%s%s",tfh->name,pack);
  2252.       unlink (buf);
  2253.     }
  2254.     tfh->fh = fopen(tfh->name, "r");
  2255.   }
  2256.   NoFilesString = "Could not download index file";
  2257.  
  2258.   return 0;
  2259. }
  2260.  
  2261. int bftp_download(remote, locdir, size, progress)
  2262.   char *remote, *locdir;
  2263.   int size, (*progress) ();
  2264. {
  2265.   char buf[200];
  2266.  
  2267.   strcpy(buf, locdir);
  2268.   tackon(buf, basename(remote));
  2269.  
  2270.   bftp_getfile(remote, buf, size, progress);
  2271.  
  2272.   return 0;
  2273. }
  2274.  
  2275. int bftp_init()
  2276. {
  2277.   Connected = 0;
  2278.   trans_options = bftp_options;
  2279.   trans_connect = bftp_connect;
  2280.   trans_disconnect = bftp_disconnect;
  2281.   trans_remopen = bftp_remopen;
  2282.   trans_download = bftp_download;
  2283.   trans_close = bftp_close;
  2284.  
  2285.   return 0;
  2286. }
  2287.  
  2288. #endif
  2289.  
  2290. /* =================================FIND CLIENT=============================== */
  2291. #ifndef NO_FIND_CLIENT
  2292.  
  2293. #define FINDD_PORT 1848
  2294.  
  2295. FILE *findd_fgrep(host, string, max)
  2296.   char *host, *string;
  2297.   int max;
  2298. {
  2299.   int fd;
  2300.   char buf[200];
  2301.   int port= FINDD_PORT;
  2302.  
  2303.   sprintf(buf, "Connecting to findserver %s...", host);
  2304.   disp_clear();
  2305.   disp_report(buf);
  2306.  
  2307.   if ((fd = tcp_createsocket(host, port)) >= 0) {
  2308.     sprintf(buf, "max %d ; ADTfind %s ; quit\r\n", max, string);
  2309.     write(fd, buf, strlen(buf));
  2310.     return fdopen(fd, "r");
  2311.   } else {
  2312.     sleep(1);
  2313.     disp_report("Could not connect to find server");
  2314.     sleep(2);
  2315.   }
  2316.  
  2317.   return NULL;
  2318. }
  2319.  
  2320.  
  2321. #else
  2322.  
  2323. char *NoFinddHelp[] =
  2324. {
  2325.   "Sorry, no find daemon compiled into this version", 0
  2326. };
  2327.  
  2328. FILE *findd_fgrep(host, port, string, max)
  2329.   char *host, *string;
  2330.   int port, max;
  2331. {
  2332.   disp_confirm(NoFinddHelp, 0);
  2333.   return NULL;
  2334. }
  2335.  
  2336. #endif
  2337.  
  2338. /* =================================MAIN PROGRAM============================== */
  2339.  
  2340. int adt_connect (progress, remote)
  2341.   int (*progress) ();
  2342.   int remote;
  2343. {
  2344.   return trans_connect (progress, remote);
  2345. }
  2346.  
  2347. int adt_disconnect ()
  2348. {
  2349.   trans_disconnect ();
  2350.   return 0;
  2351. }
  2352.  
  2353. #ifdef SIGINT
  2354. void adt_breakcheck (sig)
  2355.   int sig;
  2356. {
  2357.   signal(SIGINT, adt_breakcheck);
  2358.  
  2359.   if (!MaskSIGINT || (MaskSIGINT && GotSIGINT))
  2360.     exit_adt ("Aborted");
  2361.   GotSIGINT=1;
  2362. }
  2363. #endif
  2364.  
  2365.  
  2366. int tagcurrent()
  2367. {
  2368.   if (Vis->num && Vis->list[Vis->current])
  2369.     Vis->list[Vis->current]->tagged ^= 1;
  2370.  
  2371.   return 0;
  2372. }
  2373.  
  2374. int tagall()
  2375. {
  2376.   int tag, i;
  2377.   ENTRY **e = Vis->list;
  2378.  
  2379.   if (Vis->num) {
  2380.     tag = Vis->list[0]->tagged ^ 1;
  2381.     for (i = 0; i < Vis->num; i++)
  2382.       e[i]->tagged = tag;
  2383.   }
  2384.   return 0;
  2385. }
  2386.  
  2387. char transferdesc[200];
  2388.  
  2389. char *transferstr()
  2390. {
  2391.   char *proc = Action ? (Action == 2 ? "unpack" : "send") : "none";
  2392.  
  2393.   sprintf(transferdesc,
  2394.       "Action: %-6s  Path: %-16.16s  Readmes: %c  Subdirs: %c  Verbose: %c",
  2395.       proc, Path, Readme ? 'y' : 'n', Flat ? 'n' : 'y', Silent ? 'n' : 'y');
  2396.  
  2397.   return transferdesc;
  2398. }
  2399.  
  2400. int progress_dummy()
  2401. {
  2402.   return 0;
  2403. }
  2404.  
  2405. int make_dirs(path)
  2406.   char *path;
  2407. {
  2408.   char buf[200], *s = path, *d = buf;
  2409.  
  2410.   do {
  2411.     while (*s && *s != '/')
  2412.       *d++ = *s++;
  2413.  
  2414.     *d = 0;
  2415.  
  2416.     if (access(buf, 3))
  2417.       makedir(buf, 0755);
  2418.  
  2419.     if (*s)
  2420.       *d++ = *s++;
  2421.   } while (*s);
  2422.  
  2423.   return 0;
  2424. }
  2425.  
  2426.  
  2427. int do_action(locdir, remname)
  2428.   char *locdir, *remname;
  2429. {
  2430.   char locname[200];
  2431.   char buf[200];
  2432.   int len;
  2433.  
  2434.   strcpy(locname, locdir);
  2435.   tackon(locname, basename(remname));
  2436.  
  2437.   if (Action == 1) {
  2438.     sprintf(buf, "%s %s", option_get("send"), locname);
  2439.     system(buf);
  2440.     sleep(2);
  2441.     disp_refresh();
  2442.   }
  2443.   if (Action == 2) {
  2444.     len = mystrlen(locname);
  2445.  
  2446.     if (len > 4 && !mystricmp(locname + len - 4, ".lha")) {
  2447.       puts("");
  2448.       sprintf(buf, "cd %s;lha e %s", locdir, locname);
  2449.       system(buf);
  2450.       disp_refresh();
  2451.     } else if (len > 2 && !mystrcmp(locname + len - 2, ".Z")) {
  2452.       puts("");
  2453.       sprintf(buf, "cd %s;uncompress %s", locdir, locname);
  2454.       system(buf);
  2455.       disp_refresh();
  2456.     } else if (len > 3 && !mystrcmp(locname + len - 3, ".gz")) {
  2457.       puts("");
  2458.       sprintf(buf, "cd %s;gzip -d %s", locdir, locname);
  2459.       system(buf);
  2460.       disp_refresh();
  2461.     }
  2462.   }
  2463.   return 0;
  2464. }
  2465.  
  2466. int get_files(progress, showfile)
  2467.   int (*progress) (), (*showfile) ();
  2468. {
  2469.   ENTRY *e;
  2470.   char locdir[200], remname[200];
  2471.   int i, p, err = 0, n;
  2472.  
  2473.   if (Silent)
  2474.     progress = progress_dummy;
  2475.  
  2476.  
  2477.   MaskSIGINT = 1;
  2478.  
  2479.   for (p=0; p<2; p++) {
  2480.  
  2481.     for (i = n = 0; i < Vis->num; i++)
  2482.       if ( (Vis->list[i]->status & 1) == p)
  2483.         n++;
  2484.  
  2485.     if (!n)
  2486.       continue;
  2487.  
  2488.     if (adt_connect(progress, p))
  2489.       continue;
  2490.  
  2491.     for (i = 0; i < Vis->num; i++) {
  2492.       e = Vis->list[i];
  2493.  
  2494.       if ((e->status & 1) != p)
  2495.         continue;
  2496.  
  2497.       showfile (Vis, i);
  2498.  
  2499.       mystrcpy(locdir, option_get("dlpath"));
  2500.       glob_path(locdir);
  2501.       if (!Flat)
  2502.         tackon(locdir, e->dir);
  2503.       make_dirs(locdir);
  2504.  
  2505.       strcpy(remname, e->dir);
  2506.       tackon(remname, e->file);
  2507.  
  2508.       if (!*locdir)
  2509.         strcpy(locdir, CURDIR);
  2510.  
  2511.       if ((err = trans_download(remname, locdir, e->size, progress)))
  2512.         break;
  2513.  
  2514.       if ( GotSIGINT )
  2515.         break;
  2516.  
  2517.       do_action(locdir, remname);
  2518.  
  2519.       if (Readme) {
  2520.         strcpy(remname, e->dir); 
  2521.         tackon(remname, get_readme(e));
  2522.  
  2523.         if ((err = trans_download(remname, locdir, e->readmesize, progress)))
  2524.       break;
  2525.  
  2526.         if ( GotSIGINT )
  2527.           break;
  2528.  
  2529.         do_action(locdir, remname);
  2530.       }
  2531.  
  2532.       if (GotSIGINT) {
  2533.         progress ("Interrupted");
  2534.         break;
  2535.       }
  2536.  
  2537.       e->tagged = 0;
  2538.       showfile (Vis, i);
  2539.  
  2540.     }
  2541.  
  2542.     adt_disconnect();
  2543.  
  2544.     if (err)
  2545.       disp_status("Error during download");
  2546.  
  2547.   }
  2548.  
  2549.   MaskSIGINT = GotSIGINT = 0;
  2550.  
  2551.   return 0;
  2552. }
  2553.  
  2554. int find_string(string, progress)
  2555.   char *string;
  2556.   int (*progress) ();
  2557. {
  2558.   FILE *fh;
  2559.   char *site;
  2560.   char *parts[10];
  2561.  
  2562.   NoFilesString = "No files found matching your pattern";
  2563.   Vis->sel = "Found files";
  2564.  
  2565.   if (!*option_get("findmethod"))
  2566.     if (setup_findmethod())
  2567.       return 1;
  2568.  
  2569.   switch (option_getnum("findmethod")) {
  2570.  
  2571.   case 0:
  2572.  
  2573.     GotComplete = GotLocal = GotRecent = 0;
  2574.  
  2575.     site = option_get("findsite");
  2576.  
  2577.     progress("Searching...");
  2578.  
  2579.     str_sitesplit(site, parts);
  2580.  
  2581.     fh = findd_fgrep(parts[1], string, 100);
  2582.  
  2583.     if (fh) {
  2584.       e_freeall();
  2585.       fgets(parsebuf, 120, fh);
  2586.       read_adt_v2(fh);
  2587.       allvisible();
  2588.       fclose(fh);
  2589.     }
  2590.     Vis->sel = "Found files";
  2591.     sort_list(Vis, &sort_dir);
  2592.  
  2593.     break;
  2594.  
  2595.   case 1:
  2596.  
  2597.     get_sitelocal();
  2598.     progress("Searching...");
  2599.     findstr(string);
  2600.     break;
  2601.  
  2602.   case 2:
  2603.  
  2604.     get_complete();
  2605.     progress("Searching...");
  2606.     findstr(string);
  2607.     break;
  2608.  
  2609.   }
  2610.  
  2611.   return 0;
  2612. }
  2613.  
  2614. int print_listing(width)
  2615.   int width;
  2616. {
  2617.   ENTRY **list = Vis->list;
  2618.   FILE *f;
  2619.   char file[300];
  2620.   int i;
  2621.   long now = time(NULL);
  2622.  
  2623.   strcpy (file, glob_path( option_get("printer")));
  2624.  
  2625.   if (!*file || !(f = fopen(file, "w")))
  2626.     return 0;
  2627.  
  2628.   if (width == 1) {
  2629.  
  2630.     fputs("|File                Dir        Size Description\n", f);
  2631.     fputs("|------------------- ---------- ---- -----------\n", f);
  2632.  
  2633.   } else {
  2634.  
  2635.     fputs("|File                Dir        Size Age  Description\n", f);
  2636.     fputs("|------------------- ---------- ---- ---  -----------\n", f);
  2637.  
  2638.   }
  2639.  
  2640.  
  2641.   for (i = 0; i < Vis->num; i++) {
  2642.  
  2643.     if (width == 1) {
  2644.  
  2645.       fprintf(f, "%-20.20s %-10.10s %4.4s%c%-42.42s\n",
  2646.           list[i]->file,
  2647.           list[i]->dir,
  2648.           str_ksize(list[i]->size),
  2649.           list[i]->readmesize > 100 ? '+' : ' ',
  2650.           list[i]->desc);
  2651.  
  2652.     } else {
  2653.  
  2654.       fprintf(f, "%-20.20s %-10.10s %4.4s %3.3d %c%-.80s\n",
  2655.           list[i]->file,
  2656.           list[i]->dir,
  2657.           str_ksize(list[i]->size),
  2658.           (now - list[i]->time) / 86400,
  2659.           list[i]->readmesize > 100 ? '+' : ' ',
  2660.           list[i]->desc);
  2661.  
  2662.     }
  2663.   }
  2664.  
  2665.   fclose(f);
  2666.  
  2667.   return 0;
  2668. }
  2669.  
  2670.  
  2671. int display_remote(name, title)
  2672.   char *name;
  2673.   char *title;
  2674. {
  2675.   TEMPFILE tfh;
  2676.   char **strings;
  2677.  
  2678.   trans_remopen(&tfh, name, "", disp_status);
  2679.  
  2680.   if (tfh.fh) {
  2681.  
  2682.     strings = read_file(tfh.fh, title);
  2683.     disp_more(strings);
  2684.     free_file(strings);
  2685.     tclose(&tfh);
  2686.  
  2687.   } else {
  2688.  
  2689.     disp_status ("Could not open remote file");
  2690.  
  2691.   }
  2692.  
  2693.   return 0;
  2694. }
  2695.  
  2696.  
  2697. /* =================================CURSES PACKAGE============================ */
  2698. #ifndef NO_CURSES
  2699.  
  2700. int debug(str)
  2701.   char *str;
  2702. {
  2703.   move(0, 0);
  2704.   addstr(str);
  2705.   refresh();
  2706.   sleep(1);
  2707.   return 0;
  2708. }
  2709.  
  2710. int cur_dispinit()
  2711. {
  2712.   initscr();
  2713.   nl();
  2714.   noecho();
  2715.   cbreak();
  2716.   return 0;
  2717. }
  2718.  
  2719. int cur_getchar()
  2720. {
  2721.   int c=getchr();
  2722. #ifdef SHOW_KEYS
  2723.   static int foo;
  2724.   char buf[20];
  2725.   sprintf(buf,"%2x",c);
  2726.   move(0, (foo+=2)%8);
  2727.   addstr(buf);
  2728. #endif
  2729.  
  2730.   return c;
  2731. }
  2732.  
  2733.  
  2734. #define Y_LISTTITLE 2
  2735. #define Y_LISTSTART 3
  2736. #define Y_LISTEND   (LINES-6)
  2737. #define Y_INFO      (LINES-5)
  2738. #define Y_COMMAND   (LINES-3)
  2739. #define Y_STATUS    (LINES-1)
  2740.  
  2741. #define X_COMMAND   9
  2742.  
  2743.  
  2744. int cur_helpblock(help)
  2745.   char **help;
  2746. {
  2747.   int i, m = str_shift(str_longest(help), COLS);
  2748.  
  2749.   clear();
  2750.  
  2751.   move(0, 0);
  2752.   addstr(str_center(help[0], COLS));
  2753.  
  2754.   for (i = 0; help[i + 1]; i++) {
  2755.     move(2 + i, m);
  2756.     addstr(help[i + 1]);
  2757.   }
  2758.  
  2759.   return i;
  2760. }
  2761.  
  2762. char *cur_getstringat(buf, x, y)
  2763.   char *buf;
  2764.   int x, y;
  2765. {
  2766.   char bak[300];
  2767.   int c, l = strlen(buf), p = l, i;
  2768.  
  2769.   mystrcpy(bak, buf);
  2770.  
  2771.   move(y, x);
  2772.   addstr(buf);
  2773.  
  2774.   for (;;) {
  2775.     move(y, x + p);
  2776.     refresh();
  2777.     switch (c = inp_getchr()) {
  2778.  
  2779.     case 1:
  2780.       p = 0;
  2781.       break;
  2782.  
  2783.     case 5:
  2784.       p = l;
  2785.       break;
  2786.  
  2787.     case 8: case 127:
  2788.       if (p == 0)
  2789.     break;
  2790.  
  2791.       for (i = --p; i < l; i++)
  2792.     buf[i] = buf[i + 1];
  2793.       buf[--l] = ' ';
  2794.  
  2795.       move(y, x + p);
  2796.       addstr(buf + p);
  2797.       buf[l] = 0;
  2798.       break;
  2799.  
  2800.     case 13: case 10:
  2801.       goto done;
  2802.  
  2803.     case K_RIGHT:
  2804.       if (p < l)
  2805.     p++;
  2806.       break;
  2807.  
  2808.     case K_LEFT:
  2809.       if (p > 0)
  2810.     p--;
  2811.       break;
  2812.  
  2813.     default:
  2814.       if (c < ' ' || c > 127 || l > COLS - x - 1)
  2815.     break;
  2816.  
  2817.       for (i = l; i > p; i--)
  2818.     buf[i + 1] = buf[i];
  2819.       buf[++l] = 0;
  2820.       buf[p] = c;
  2821.  
  2822.       move(y, x + p);
  2823.       addstr(buf + p);
  2824.       p++;
  2825.       break;
  2826.     }
  2827.  
  2828.   }
  2829.  
  2830. done:
  2831.   return buf;
  2832.  
  2833. }
  2834.  
  2835. int OptLen;
  2836.  
  2837. char *cur_inputstr(buf, help)
  2838.   char *buf, **help;
  2839. {
  2840.   int x = str_shift(str_longest(help), COLS);
  2841.   int y = 3 + cur_helpblock(help);
  2842.  
  2843.   move(y, x);
  2844.   addstr("> ");
  2845.  
  2846.   return cur_getstringat(buf, x + 2, y);
  2847. }
  2848.  
  2849.  
  2850. char *cur_getstring(buf)
  2851.   char *buf;
  2852. {
  2853.   int y = Y_COMMAND, x = X_COMMAND + OptLen;
  2854.   char *ret;
  2855.  
  2856.   move(y, x);
  2857.   addstr(": ");
  2858.   x += 2;
  2859.   OptLen += 2;
  2860.  
  2861.   ret = cur_getstringat(buf, x, y);
  2862.  
  2863.   OptLen = x + strlen(buf) + 1;
  2864.  
  2865.   return ret;
  2866. }
  2867.  
  2868. char dbuf[300];
  2869.  
  2870. int cur_displist(list)
  2871.   LIST *list;
  2872. {
  2873.   int i;
  2874.   char *line;
  2875.   char *t = NULL, c = 0;
  2876.  
  2877.   Window = Y_LISTEND - list->top;
  2878.  
  2879.   if (!list->num) {
  2880.     move(LINES / 2, 0);
  2881.     addstr(str_center(NoFilesString, COLS - 1));
  2882.     return 0;
  2883.   }
  2884.  
  2885.   list->offset = list->current / Window * Window;
  2886.  
  2887.   for (i = 0; i < Window; i++) {
  2888.     line = list->disp(list->list, list->offset + i, list->num, dbuf, Width);
  2889.  
  2890.     if (*line)
  2891.       move(list->top + i, list->type ? (Width - strlen(line)) / 2 : 0);
  2892.     else {
  2893.       move(list->top + i, 0);
  2894.       clrtoeol();
  2895.     }
  2896.  
  2897.     if (list->offset + i != list->current) {
  2898.       addstr(line);
  2899.     } else {
  2900.       if (list->type == 0) {
  2901.     for (t = line + 1; *t != ' '; t++);
  2902.     c = t[1];
  2903.     t[1] = 0;
  2904.       }
  2905.       standout();
  2906.       addstr(line);
  2907.       standend();
  2908.  
  2909.       if (list->type == 0) {
  2910.     t[1] = c;
  2911.     addstr(t + 1);
  2912.       }
  2913.     }
  2914.   }
  2915.  
  2916.   return 0;
  2917. }
  2918.  
  2919. int cur_dispfiles(list)
  2920.   LIST *list;
  2921. {
  2922.   Window = Y_LISTEND - Y_LISTSTART;
  2923.  
  2924.   if (list == Vis) {
  2925.     move(0, 0);
  2926.     addstr(str_topline(dbuf, Width - 1, list));
  2927.   }
  2928.  
  2929.   cur_displist(list);
  2930.  
  2931.   return 0;
  2932. }
  2933.  
  2934.  
  2935. int cur_dispmask()
  2936. {
  2937.   Window = Y_LISTEND - Y_LISTSTART;
  2938.  
  2939.   Vis->disp = str_entry;
  2940.   Vis->top = Y_LISTSTART;
  2941.  
  2942.   clear();
  2943.   move(Y_LISTTITLE, 0);
  2944.   addstr(str_titles(dbuf, Width - 1));
  2945.  
  2946.   cur_dispfiles(Vis);
  2947.  
  2948.   move(Y_INFO, 0);
  2949.   addstr(str_center(Vis->cmds, Width - 1));
  2950.  
  2951.   move(Y_COMMAND, 0);
  2952.   addstr("Command: ");
  2953.  
  2954.   refresh();
  2955.   return 0;
  2956. }
  2957.  
  2958. int cur_mark(list, on)
  2959.   LIST *list;
  2960.   int on;
  2961. {
  2962.   char *t = NULL, *line;
  2963.  
  2964.   line = list->disp(list->list, list->current, list->num, dbuf, Width - 1);
  2965.  
  2966.   if (list->type == 0) {
  2967.     for (t = line + 1; *t != ' '; t++);
  2968.     t[1] = 0;
  2969.   }
  2970.   move(list->top + list->current - list->offset,
  2971.        list->type ? (Width - strlen(line)) / 2 : 0);
  2972.  
  2973.   if (on)
  2974.     standout();
  2975.   addstr(line);
  2976.   if (on)
  2977.     standend();
  2978.  
  2979.   if (list->type == 0)
  2980.     t[1] = ' ';
  2981.  
  2982.   return 0;
  2983. }
  2984.  
  2985. int cur_gomid(list)
  2986.   LIST *list;
  2987. {
  2988.   int left = list->num - list->offset;
  2989.  
  2990.   list->current = list->offset + (left < Window ? left : Window) / 2;
  2991.   return 0;
  2992. }
  2993.  
  2994.  
  2995. int cur_moveto(list, pos)
  2996.   LIST *list;
  2997.   int pos;
  2998. {
  2999.   if (!list->num)
  3000.     return 0;
  3001.  
  3002.   if (pos < 0)
  3003.     pos = 0;
  3004.  
  3005.   if (pos > list->num - 1)
  3006.     pos = list->num - 1;
  3007.  
  3008.   if (pos == list->current)
  3009.     return 0;
  3010.  
  3011.   cur_mark(list, 0);
  3012.   list->current = pos;
  3013.  
  3014.   if (pos / Window * Window == list->offset) {
  3015.  
  3016.     cur_mark(list, 1);
  3017.  
  3018.   } else {
  3019.  
  3020.     list->offset = pos / Window * Window;
  3021.     cur_dispfiles(list);
  3022.  
  3023.   }
  3024.  
  3025.   return 0;
  3026. }
  3027.  
  3028. int cur_listnav(list, c)
  3029.   LIST *list;
  3030.   int c;
  3031. {
  3032.   switch (c) {
  3033.   case K_DOWN:
  3034.   case K_CTRL + 'N':
  3035.   case 'j':
  3036.     cur_moveto(list, list->current + 1);
  3037.     break;
  3038.  
  3039.   case K_UP:
  3040.   case K_CTRL + 'P':
  3041.   case 'k':
  3042.     cur_moveto(list, list->current - 1);
  3043.     break;
  3044.  
  3045.   case K_RIGHT:
  3046.   case ' ':
  3047.   case K_CTRL + 'F':
  3048.     cur_moveto(list, (list->current + Window)/Window*Window);
  3049.     break;
  3050.  
  3051.   case K_LEFT:
  3052.   case K_CTRL + 'H':
  3053.   case K_CTRL + 'B':
  3054.   case 'b':
  3055.     cur_moveto(list, (list->current - Window)/Window*Window);
  3056.     break;
  3057.  
  3058.   case K_CTRL + 'I':
  3059.     cur_moveto(list, list->current + 5);
  3060.     break;
  3061.  
  3062.   case '<':
  3063.     cur_moveto(list, 0);
  3064.     break;
  3065.  
  3066.   case '>':
  3067.     cur_moveto(list, list->num - 1);
  3068.     break;
  3069.  
  3070.   case K_CTRL + 'L':
  3071.     touchwin (stdscr);
  3072.     refresh();
  3073.     break;
  3074.  
  3075.   default:
  3076.     return 0;
  3077.  
  3078.   }
  3079.  
  3080.   return 1;
  3081. }
  3082.  
  3083. int cur_choice(help, list)
  3084.   char **help;
  3085.   LIST *list;
  3086. {
  3087.   char *cmd = "Select using cursor keys, press RETURN to accept or q to cancel.";
  3088.   int c, ret = 0;
  3089.  
  3090.   list->top = 3 + cur_helpblock(help);
  3091.  
  3092.   cur_displist(list);
  3093.  
  3094.   move(Y_COMMAND, list->type ? (Width - strlen(cmd)) / 2 : 0);
  3095.   addstr(cmd);
  3096.  
  3097.   refresh();
  3098.  
  3099.   for (;;) {
  3100.     c = inp_getchr();
  3101.     if (c == 'q')
  3102.       return -1;
  3103.     if (c == 10 || c == 13) {
  3104.       ret = list->current;
  3105.       goto done;
  3106.     }
  3107.     cur_listnav(list, c);
  3108.     move(Y_COMMAND, strlen(cmd) + (list->type ? (Width - strlen(cmd)) / 2 : 0));
  3109.     refresh();
  3110.   }
  3111.  
  3112. done:
  3113.   return ret;
  3114. }
  3115.  
  3116. int cur_cmdstr(string)
  3117.   char *string;
  3118. {
  3119.   move(Y_COMMAND, X_COMMAND);
  3120.   addstr(string);
  3121.   refresh();
  3122.   OptLen = strlen(string);
  3123.  
  3124.   return 0;
  3125. }
  3126.  
  3127. int cur_subopt(string)
  3128.   char *string;
  3129. {
  3130.   char buf[200], *b = buf;
  3131.   int c, i;
  3132.  
  3133.   cur_cmdstr(string);
  3134.  
  3135.   c = inp_getchr();
  3136.  
  3137.   for (i = 0; string[i] && string[i] != ' '; i++)    /* view   */
  3138.     *b++ = string[i];
  3139.   *b++ = ' ';
  3140.  
  3141.   for (i = strlen(string) - 1; i > 0; i--)    /* a)ll   */
  3142.     if (string[i] == ')' && string[i - 1] == c)
  3143.       break;
  3144.  
  3145.   if (i > 0) {            /* all    */
  3146.     *b++ = string[++i - 2];
  3147.     while (string[i] && string[i] != ' ')
  3148.       *b++ = string[i++];
  3149.   }
  3150.   OptLen = b - buf;
  3151.  
  3152.   while (b < buf + strlen(string))    /* blanks */
  3153.     *b++ = ' ';
  3154.   *b++ = 0;
  3155.  
  3156.   move(Y_COMMAND, X_COMMAND);
  3157.   addstr(buf);
  3158.   move(Y_COMMAND, X_COMMAND + OptLen);
  3159.   refresh();
  3160.   return c;
  3161. }
  3162.  
  3163. char statusbuf[300];
  3164.  
  3165.  
  3166. int cur_statusat(string, y)
  3167.   char *string;
  3168.   int y;
  3169. {
  3170.   int i, sh;
  3171.  
  3172.   for (i = 0; i < COLS - 1; i++)
  3173.     statusbuf[i] = ' ';
  3174.   statusbuf[i] = 0;
  3175.  
  3176.   strcpy(statusbuf + (sh = str_shift(strlen(string), COLS)), string);
  3177.   statusbuf[strlen(statusbuf)] = ' ';
  3178.  
  3179.   move(y, 0);
  3180.   addstr(statusbuf);
  3181.   move(y, sh + strlen(string));
  3182.   refresh();
  3183.  
  3184.   return 0;
  3185. }
  3186.  
  3187. int cur_status(string)
  3188.   char *string;
  3189. {
  3190.   cur_statusat(string, Y_STATUS);
  3191.  
  3192.   return 0;
  3193. }
  3194.  
  3195. int cur_clear()
  3196. {
  3197.   clear();
  3198.   refresh();
  3199.   return 0;
  3200. }
  3201.  
  3202. int cur_report(string)
  3203.   char *string;
  3204. {
  3205.   cur_statusat(string, LINES / 2);
  3206.   return 0;
  3207. }
  3208.  
  3209. int cur_nosubopt()
  3210. {
  3211.   char buf[200], *b = buf;
  3212.  
  3213.   while (OptLen--)
  3214.     *b++ = ' ';
  3215.   *b++ = 0;
  3216.   move(Y_COMMAND, X_COMMAND);
  3217.   addstr(buf);
  3218.   refresh();
  3219.   cur_status("");
  3220.   return 0;
  3221. }
  3222.  
  3223. int cur_more(strings)
  3224.   char **strings;
  3225. {
  3226.   int i, c, lines, offset = 0, len = str_longest(strings);
  3227.   char buf[100], *title = *strings++;
  3228.  
  3229.   for (lines = 0; strings[lines] || lines == 0; lines++);
  3230.  
  3231.   do {
  3232.     clear();
  3233.  
  3234.     move(0, str_shift(strlen(title), len));
  3235.     standout();
  3236.     addstr(title);
  3237.     standend();
  3238.  
  3239.     for (i = 0; i < LINES - 4 && offset + i < lines; i++) {
  3240.       move(2 + i, 0);
  3241.       addstr(strings[offset + i]);
  3242.     }
  3243.  
  3244.     if (offset + i < lines)
  3245.       sprintf(buf, " --- More (%d%%), b)ack, q)uit --- ",
  3246.           (offset + i) * 100 / lines);
  3247.     else
  3248.       strcpy(buf, " --- End --- ");
  3249.  
  3250.     move(MYMIN(LINES - 1, 3 + offset + i), str_shift(strlen(buf), len));
  3251.     standout();
  3252.     addstr(buf);
  3253.     standend();
  3254.     refresh();
  3255.  
  3256.     c = inp_getchr();
  3257.     if (c == 27 || c == 'q')
  3258.       break;
  3259.     else if (c == 'b' || c == K_CTRL + 'H')
  3260.       offset = MYMAX(0, offset - (LINES - 4));
  3261.     else
  3262.       offset += LINES - 4;
  3263.  
  3264.   } while (offset < lines);
  3265.  
  3266.   return 0;
  3267. }
  3268.  
  3269.  
  3270. char *MainHelp[] = {
  3271.   "Aminet Download Tool Help",
  3272.   "Welcome to the Aminet Download Tool. You can select, inspect and download",
  3273.   "files here. The command keys available:",
  3274.   "",
  3275.   "cursor    navigate on list",
  3276.   "blank     next page (also cursor right)",
  3277.   "backspace previous page (also cursor left)",
  3278.   "tab       move down five",
  3279.   "<  >      start and end of list",
  3280.   "",
  3281.   "d)ownload receive selected file(s) after setting options",
  3282.   "f)ind     locate a file anywhere on Aminet",
  3283.   "h)elp     this page",
  3284.   "o)ptions  setup page",
  3285.   "p)rint    create a listing on disk or printer",
  3286.   "q)uit     leave, remembering this call",
  3287.   "Q)uit     leave, without remembering this call",
  3288.   "r)eadme   display the .readme of current file",
  3289.   "s)ort     change sorting of displayed list",
  3290.   "t)ag      mark/unmark current file for later download (also RETURN)",
  3291.   "T)ag      mark/unmark all files",
  3292.   "v)iew     select which files to show",
  3293.   "",
  3294.   "Press ? at any submenu to get help about the commands there.",
  3295.   0
  3296. };
  3297.  
  3298. char *ViewHelp[] = {
  3299.   "The v)iew command",
  3300.   "This command selects which files to display in ATD. The suboptions:",
  3301.   "",
  3302.   "a)ll      shows the complete list of all files on Aminet, downloading it",
  3303.   "          first if necessary. No files are hidden.",
  3304.   "d)ir      pick from the currently known files the ones from the directory",
  3305.   "          you specify.",
  3306.   "h)ide     selects one or more directory (separated by commas) that should",
  3307.   "          not be shown. This info is stored in .adtrc on exit",
  3308.   "k)nown    shows all currently known files, including those that are normally",
  3309.   "          hidden",
  3310.   "l)imit    only show the files which have the given string somewhere in their",
  3311.   "          description or file name",
  3312.   "m)arked   only shows the files that have previously been marked using the",
  3313.   "          t)ag command",
  3314.   "n)ew      shows the new files since your previous call minus the hidden ones,",
  3315.   "          downloading the list if necessary",
  3316.   "s)ite     shows the list of files available at the site you are currently",
  3317.   "          connected to",
  3318.   "t)oggle   toggle between the current list and the previously displayed one.",
  3319.   0
  3320. };
  3321.  
  3322. char *SortHelp[] = {
  3323.   "The s)ort command",
  3324.   "Using this command you can select what order the files should be shown by",
  3325.   "",
  3326.   "a)ge      sorts by age, showing the newest files on top",
  3327.   "A)ge      like a)ge but showing the oldest files on top",
  3328.   "d)ir      sorts alphabetically by directory, subsorting by name",
  3329.   "D)ir      like d)ir but reverse order",
  3330.   "n)ame     sorts alphabetically by file name",
  3331.   "N)ame     like n)ame but reverse order",
  3332.   "s)ize     sorts by file size, largest on top",
  3333.   "S)ize     like s)ize, but smallst on top",
  3334.   0
  3335. };
  3336.  
  3337. int cur_editvar(varname, string)
  3338.   char *varname, *string;
  3339. {
  3340.   char buf[100];
  3341.  
  3342.   cur_status(string);
  3343.   mystrncpy(buf, option_get(varname), 99);
  3344.   cur_getstring(buf);
  3345.   option_set(varname, buf);
  3346.   return 0;
  3347. }
  3348.  
  3349. int cur_showfile(list, i)
  3350.   LIST *list;
  3351.   int i;
  3352. {
  3353.   cur_moveto (list, i);
  3354.   cur_mark   (list, 0);
  3355.   cur_mark   (list, 1);
  3356.  
  3357.   return 0;
  3358. }
  3359.  
  3360. char *DownloadHelp[] = {
  3361.   "The d)ownload command",
  3362.   "This command lets you receive files from Aminet. The suboptions:",
  3363.   "",
  3364.   "a)ction   select what to do after the download. Possibilities are either",
  3365.   "          nothing, transfer using zmodem, or archive unpacking",
  3366.   "b)egin    actually perform the download, using the current settings",
  3367.   "          selected by the other keys",
  3368.   "p)ath     lets you enter the destination path for the files, will be",
  3369.   "          created if it does not exist",
  3370.   "q)uit     do not start download, leave all undownloaded files tagged,",
  3371.   "          and return to main files selection page",
  3372.   "r)eadme   toggle between downloading the .readme files along with the",
  3373.   "          archives and not doing so",
  3374.   "s)ubdirs  toggle between putting all files in the same directory vs",
  3375.   "          re-creating the Aminet directory structure",
  3376.   "v)erbose  toggle between quiet and verbose download, where quiet suspends",
  3377.   "          all screen output until all files have been downloaded.",
  3378.   "",
  3379.   "The current settings are displayed in the bottom line. If you want to",
  3380.   "change those settings permanently, use o)ptions d)ownload.",
  3381.   0
  3382. };
  3383.  
  3384. int cur_download()
  3385. {
  3386.   LIST *l;
  3387.   int cont = 1;
  3388.   char path[300];
  3389.  
  3390.   markedextract();
  3391.  
  3392.   l = Vis;
  3393.   Vis = Mark;
  3394.   Mark = l;
  3395.  
  3396.   Flat = option_getnum("flatdl");
  3397.   Readme = option_getnum("readmedl");
  3398.   Silent = option_getnum("silentdl");
  3399.   strcpy(Path, option_get("dlpath"));
  3400.  
  3401.   cur_dispmask();
  3402.  
  3403.   do {
  3404.     cur_status(transferstr());
  3405.     cur_cmdstr("");
  3406.  
  3407.     switch (inp_getchr()) {
  3408.     case '?':
  3409.     case 'h':
  3410.       cur_more(DownloadHelp);
  3411.       cur_dispmask();
  3412.       break;
  3413.  
  3414.     case 'p':
  3415.       cur_cmdstr("path");
  3416.       cur_editvar("dlpath", "Enter path to download files to");
  3417.       strcpy(Path, option_get("dlpath"));
  3418.       strcpy(path, Path);
  3419.       make_dirs (glob_path (path));
  3420.       cur_nosubopt();
  3421.       break;
  3422.  
  3423.     case 'b':
  3424.       cur_moveto(Vis, 0);
  3425.       get_files(cur_status, cur_showfile);
  3426.       cur_nosubopt();
  3427.       cont = 0;
  3428.       break;
  3429.  
  3430.     case 'a':
  3431.       Action = ++Action % 3;
  3432.       break;
  3433.     case 'q':
  3434.       cont = 0;
  3435.       break;
  3436.     case 'r':
  3437.       Readme = !Readme;
  3438.       break;
  3439.     case 's':
  3440.       Flat = !Flat;
  3441.       break;
  3442.     case 'v':
  3443.       Silent = !Silent;
  3444.       break;
  3445.     }
  3446.  
  3447.   } while (cont);
  3448.  
  3449.   l = Vis;
  3450.   Vis = Mark;
  3451.   Mark = l;
  3452.  
  3453.   return 0;
  3454. }
  3455.  
  3456. char *OptionsHelp[] = {
  3457.   "The o)ptions command",
  3458.   "Using the o)ptions command you can modify various settings of ADT. They",
  3459.   "will be saved in .adtrc when you leave ADT using the q)uit command, but",
  3460.   "not if you use Q)uit. The settings you can modify are:",
  3461.   "",
  3462.   "c)ompression lets you pick the compression type used for downloading",
  3463.   "             Aminet contents files.",
  3464.   "d)ownload    will pick the defaults for downloading readmes, verbose or",
  3465.   "             quiet download, download path and so on",
  3466.   "f)ind        lets you pick the method used for finding things on Aminet,",
  3467.   "             ie. download and local search vs. using a search server",
  3468.   "m)ethod      will choose the method used to transfer files, e.g. FTP",
  3469.   "             mail server or local files",
  3470.   "p)rint       lets you choose the format of the listings generated by ADT",
  3471.   "             mostly wide vs. narrow format",
  3472.   "s)ite        this lets you pick the location you want to get your files",
  3473.   "             from, for example which FTP site to use", 0
  3474. };
  3475.  
  3476.  
  3477. char *CompressOptHelp[] = {
  3478.   "Compression type",
  3479.   "Please select the compression method to use for transmitting the Aminet",
  3480.   "index files. If you have very fast access (like local files), pick no",
  3481.   "compression, otherwise pick compress, unless you have 'gzip' in your",
  3482.   "path, which compresses even better at the same speed. Note, we're only",
  3483.   "talking about decompression here, its only the choice between different",
  3484.   "versions of the index files in fact.", 0
  3485. }, *CompressList[] = {
  3486.   "  none  ",
  3487.   "compress",
  3488.   "  gzip  ", 0
  3489. };
  3490.  
  3491. char *FlatOptHelp[] = {
  3492.   "Flat or tree download",
  3493.   "Please choose whether to put all downloaded files in the same",
  3494.   "directory or to create the correct subdirectory as on Aminet ",
  3495.   "for each file downloaded", 0
  3496. }, *FlatDlList[] = {
  3497.   "subdir (create subdirs)",
  3498.   "flat   (same directory)", 0
  3499. };
  3500.  
  3501. char *ReadmeOptHelp[] = {
  3502.   "Readme download",
  3503.   "Please choose whether or not to download the .readme files",
  3504.   "along with the archives", 0
  3505. }, *ReadmeDlList[] = {
  3506.   "download archives only",
  3507.   "download .readme files too", 0
  3508. };
  3509.  
  3510. char *QuietOptHelp[] = {
  3511.   "Silent download",
  3512.   "Please choose wheter or not to perform transfers quietly. If you turn on",
  3513.   "quiet mode, no screen output happens until the download is completey over.",
  3514.   "This allows you to interrupt ADT using CTRL-Z and put it in the background",
  3515.   "using 'bg' to download quietly in the background", 0
  3516. }, *QuietDlList[] = {
  3517.   "give progress reports",
  3518.   "download quietly", 0
  3519. };
  3520.  
  3521. char *FindSitesHelp[] = {
  3522.   "Find site",
  3523.   "Here you can pick the find server to use for your queries. Feel free to",
  3524.   "them all and choose the fastest. All find servers have the complete list",
  3525.   "of all Aminet files online", 0
  3526. };
  3527.  
  3528. char FindString[120];
  3529.  
  3530. int cur_cmdkeys(c)
  3531.   int c;
  3532. {
  3533.   char buf[200];
  3534.   SORT *sorttype;
  3535.   int noredraw = 0, width = 0;
  3536.  
  3537.   buf[0] = 0;
  3538.  
  3539.   switch (c) {
  3540.  
  3541.   case 'd':
  3542.     if (Vis->num)
  3543.       cur_download();
  3544.     break;
  3545.  
  3546.   case 'f':
  3547.     cur_cmdstr("find");
  3548.     cur_status("(Use 'adt -f <keyword>' to start finds from the command line)");
  3549.     FindString[0] = 0;
  3550.     cur_getstring(FindString);
  3551.     if (*FindString)
  3552.       find_string(FindString, cur_status);
  3553.     break;
  3554.  
  3555.   case 'o':
  3556. options:
  3557.     switch (cur_subopt("options c)ompression d)ownload f)ind m)ethod s)ite")) {
  3558.     case '?':
  3559.     case 'h':
  3560.       cur_more(OptionsHelp);
  3561.       cur_dispmask();
  3562.       goto options;
  3563.  
  3564.     case 'c':
  3565.       setup_enumed(CompressOptHelp, CompressList, "compress");
  3566.       break;
  3567.  
  3568.     case 'd':
  3569.       cur_editvar("dlpath", "Enter path to download files to"),
  3570.       cur_editvar("send", "Enter command to use for sending files, eg. 'sz'");
  3571.       setup_enumed(FlatOptHelp, FlatDlList, "flatdl");
  3572.       setup_enumed(ReadmeOptHelp, ReadmeDlList, "readmedl");
  3573.       setup_enumed(QuietOptHelp, QuietDlList, "quietdl");
  3574.       break;
  3575.  
  3576.     case 'f':
  3577.       setup_findmethod();
  3578.       break;
  3579.  
  3580.     case 'm':
  3581.       trans_close();
  3582.       e_freeall();
  3583.       setup_method();
  3584.       get_recent();
  3585.       newvisible();
  3586.       NoFilesString = "Use v)iew or f)ind to get files to the display";
  3587.       break;
  3588.  
  3589.     case 's':
  3590.       if (trans_options())
  3591.         break;
  3592.       if (CdRom) {
  3593.         get_sitelocal();
  3594.         allvisible();
  3595.       } else {
  3596.         get_recent();
  3597.         newvisible();
  3598.       }
  3599.       break;
  3600.  
  3601.     default:
  3602.       noredraw = 1;
  3603.     }
  3604.     cur_nosubopt();
  3605.  
  3606.     break;
  3607.  
  3608.   case 'p':
  3609.     cur_status("Narrow format fits 80 columns, wide format format 132 columns");
  3610.     switch (cur_subopt("print n)arrow w)ide")) {
  3611.     case 'n':
  3612.       width = 1;
  3613.       break;
  3614.     case 'w':
  3615.       width = 2;
  3616.       break;
  3617.     }
  3618.     if (width) {
  3619.       cur_editvar("printer", "Enter the file to print the visible files to");
  3620.       print_listing(width);
  3621.     }
  3622.     cur_nosubopt();
  3623.     noredraw = 1;
  3624.     break;
  3625.  
  3626.   case 'q':
  3627.     cur_cmdstr("quit (and save config file)");
  3628.     option_save(ConfigFile);
  3629.     exit_adt(0);
  3630.     break;
  3631.  
  3632.   case 'Q':
  3633.     cur_cmdstr("quit (without saving config file)");
  3634.     exit_adt(0);
  3635.     break;
  3636.  
  3637.   case 'v':
  3638. view:
  3639.     switch (cur_subopt("view a)ll d)ir h)ide k)nown l)imit m)arked n)ew s)ite t)oggle")) {
  3640.     case '?':
  3641.       cur_more(ViewHelp);
  3642.       cur_dispmask();
  3643.       goto view;
  3644.  
  3645.     case 'a':
  3646.       if (!GotComplete) {
  3647.     get_complete();
  3648.     allvisible();
  3649.       }
  3650.       break;
  3651.  
  3652.     case 'd':
  3653.       cur_status("Select directory to show exclusively");
  3654.       dirvisible(cur_getstring(buf));
  3655.       cur_status("");
  3656.       break;
  3657.  
  3658.     case 'h':
  3659.       cur_editvar("hide", "Enter directories to hide permanently");
  3660.       invisible();
  3661.       break;
  3662.  
  3663.     case 'k':
  3664.       allvisible();
  3665.       break;
  3666.  
  3667.     case 'l':
  3668.       cur_status("Enter string to match in currently displayed descriptions");
  3669.       strlimit(cur_getstring(buf));
  3670.       cur_status("");
  3671.       break;
  3672.  
  3673.     case 'm':
  3674.       markedvisible();
  3675.       break;
  3676.  
  3677.     case 'n':
  3678.       get_recent();
  3679.       newvisible();
  3680.       break;
  3681.  
  3682.     case 's':
  3683.       if (!GotLocal) {
  3684.     get_sitelocal();
  3685.     cur_clear();
  3686.     cur_report("Sorting...");
  3687.     allvisible();
  3688.       }
  3689.       break;
  3690.  
  3691.     case 't':
  3692.       togglevisible();
  3693.       break;
  3694.  
  3695.     default:
  3696.       noredraw = 1;
  3697.     }
  3698.  
  3699.     cur_nosubopt();
  3700.     break;
  3701.  
  3702.   case 'r':
  3703.     if (Vis->num) {
  3704.       ENTRY *e=Vis->list[Vis->current];
  3705.  
  3706.       strcpy(buf, e->dir);
  3707.       tackon(buf, get_readme(e));
  3708.       adt_connect (disp_status, e->status & 1);
  3709.       display_remote(buf, get_readme(e));
  3710.       adt_disconnect();
  3711.     }
  3712.     break;
  3713.  
  3714.   case 's':
  3715.     sorttype = 0;
  3716. sort:
  3717.     switch (cur_subopt("sort a)ge d)ir n)ame s)ize")) {
  3718.     case '?':
  3719.       cur_more(SortHelp);
  3720.       cur_dispmask();
  3721.       goto sort;
  3722.     case 'a':
  3723.       sorttype = &sort_age;
  3724.       break;
  3725.     case 'd':
  3726.       sorttype = &sort_dir;
  3727.       break;
  3728.     case 'n':
  3729.       sorttype = &sort_name;
  3730.       break;
  3731.     case 's':
  3732.       sorttype = &sort_size;
  3733.       break;
  3734.     case 'A':
  3735.       sorttype = &sort_rage;
  3736.       break;
  3737.     case 'D':
  3738.       sorttype = &sort_rdir;
  3739.       break;
  3740.     case 'N':
  3741.       sorttype = &sort_rname;
  3742.       break;
  3743.     case 'S':
  3744.       sorttype = &sort_rsize;
  3745.       break;
  3746.     }
  3747.     if (sorttype) {
  3748.       cur_status("Sorting...");
  3749.       sort_list(Vis, sorttype);
  3750.       cur_dispfiles(Vis);
  3751.       cur_status("");
  3752.     }
  3753.     noredraw = 1;
  3754.     cur_nosubopt();
  3755.     break;
  3756.  
  3757.   case 'h':
  3758.   case '?':
  3759.     cur_more(MainHelp);
  3760.     break;
  3761.  
  3762.   case 't':
  3763.   case 13: case 10:
  3764.     noredraw = 1;
  3765.     if (!Vis->num)
  3766.       break;
  3767.     cur_mark(Vis, 0);
  3768.     tagcurrent();
  3769.     cur_mark(Vis, 1);
  3770.     cur_moveto(Vis, Vis->current + 1);
  3771.     break;
  3772.  
  3773.   case 'T':
  3774.     tagall();
  3775.     break;
  3776.  
  3777.   default:
  3778.     noredraw = 1;
  3779.  
  3780.   }
  3781.  
  3782.   if (!noredraw)
  3783.     cur_dispmask();
  3784.  
  3785.   return 0;
  3786. }
  3787.  
  3788.  
  3789.  
  3790. int cur_mainloop()
  3791. {
  3792.   int c;
  3793.  
  3794.   refresh();
  3795.   cur_dispmask();
  3796.   refresh();
  3797.  
  3798.   while ((c = inp_getchr())) {
  3799.     cur_listnav(Vis, c);
  3800.     cur_cmdkeys(c);
  3801.     move(Y_COMMAND, X_COMMAND);
  3802.     refresh();
  3803.   }
  3804.  
  3805.   return 0;
  3806. }
  3807.  
  3808. int cur_cleanup()
  3809. {
  3810.   nocbreak();
  3811.   echo();
  3812.   endwin();
  3813. #ifndef AMIGA
  3814.   puts("");
  3815. #endif
  3816.   return 0;
  3817. }
  3818.  
  3819. int cur_getcmd()
  3820. {
  3821.   return getchr();
  3822. }
  3823.  
  3824.  
  3825. int cur_confirm(strings, retry)
  3826.   char **strings;
  3827.   int retry;
  3828. {
  3829.   int i, j, m = str_shift(str_longest(strings), COLS);
  3830.  
  3831.   for (i = 0; strings[i]; i++);
  3832.  
  3833.   clear();
  3834.  
  3835.   for (j = 0; j < i; j++) {
  3836.     move((LINES - i - 2) / 2 + j, m);
  3837.     addstr(strings[j]);
  3838.   }
  3839.  
  3840.   move((LINES - i - 2) / 2 + j + 1, m + str_longest(strings) - strlen("Press any key"));
  3841.   addstr("Press any key");
  3842.  
  3843.   refresh();
  3844.   inp_getchr();
  3845.  
  3846.   return 0;
  3847. }
  3848.  
  3849. int cur_refresh()
  3850. {
  3851.   refresh();
  3852.  
  3853.   return 0;
  3854. }
  3855.  
  3856. #endif
  3857.  
  3858. /*---------------------------------main program------------------------------*/
  3859. int init_vars()
  3860. {
  3861.   char *d, *t;
  3862.   int i;
  3863.  
  3864.   mystrcpy(HomeDir, (t = (char *) getenv("HOME")) ? t : "");
  3865.  
  3866.   if (*HomeDir) {
  3867.     d = UserName;
  3868.     for (i = 0; HomeDir[i]; i++)
  3869.       if (HomeDir[i] == '/')
  3870.     d = UserName;
  3871.       else
  3872.     *d++ = HomeDir[i];
  3873.     *d++ = 0;
  3874.   }
  3875. #ifdef AMIGA
  3876.   mystrcpy(ConfigFile, "S:.adtrc");
  3877. #else
  3878.   mystrcpy(ConfigFile, HomeDir);
  3879.   tackon(ConfigFile, ".adtrc");
  3880. #endif
  3881.  
  3882.   Alt->sort = Vis->sel = "";
  3883.   Alt->sort = Vis->sort = "";
  3884.   Alt->cmds = Vis->cmds = "d)ownload f)ind h)elp o)ptions p)rint q)uit r)eadme s)ort t)ag v)iew";
  3885.  
  3886.   Mark->sel = "Files to be downloaded";
  3887.   Mark->sort = "";
  3888.   Mark->cmds = "a)ction b)egin p)ath q)uit r)eadmes s)ubdirs v)erbose";
  3889.  
  3890.   return 0;
  3891. }
  3892.  
  3893. char recentbuf[100];
  3894. char *FirstConnectHelp[] = {
  3895.   "This seems to be the first time you connect. You'll be seeing the last",
  3896.   "14 days' uploads now. Next time you connect, all the files that were",
  3897.   "uploaded since this connection will be shown.", 0
  3898. };
  3899.  
  3900. char *LongAgoHelp[] = {
  3901.   "Your last connection was more than 14 days ago, but you'll only be seeing",
  3902.   "the last 14 days' uploads.  If you want to see everything, use v)iew a)ll",
  3903.   "and filter accordingly.", 0
  3904. };
  3905.  
  3906. int get_list(title, name)
  3907.   char *title, *name;
  3908. {
  3909.   TEMPFILE tfh;
  3910.   char buf[250];
  3911.   char *packer = "";
  3912.   long amotd = 0, lmotd = 0, sites = 0;
  3913.  
  3914.   e_freeall();
  3915.  
  3916.   if (option_getnum("compress") == 1)
  3917.     packer = ".Z";
  3918.  
  3919.   if (option_getnum("compress") == 2)
  3920.     packer = ".gz";
  3921.  
  3922.   sprintf(buf, "info/adt/%s", name);
  3923.  
  3924.   disp_clear();
  3925.   disp_report(title);
  3926.  
  3927.   adt_connect(disp_report, STATUS_LOCAL);
  3928.  
  3929.   NoFilesString = "Could not download index file";
  3930.   trans_remopen(&tfh, buf, packer, disp_report);
  3931.  
  3932.   if (tfh.fh) {
  3933.  
  3934.     disp_report("Reading index");
  3935.     do {
  3936.       *parsebuf = 0;
  3937.       fgets(parsebuf, PBUFSIZE, tfh.fh);
  3938.       if (!mystrncmp(parsebuf, "#amotd=", 7))
  3939.     amotd = p_atoi(parsebuf + 7);
  3940.       if (!mystrncmp(parsebuf, "#lmotd=", 7))
  3941.     lmotd = p_atoi(parsebuf + 7);
  3942.       if (!mystrncmp(parsebuf, "#sites=", 7))
  3943.     sites = p_atoi(parsebuf + 7);
  3944.  
  3945.     } while (*parsebuf == '#');
  3946.  
  3947.     read_adt_v2(tfh.fh);
  3948.     tclose(&tfh);
  3949.  
  3950.   }
  3951.  
  3952.   if (!option_getnum("nomotd")) {
  3953.     if (amotd > option_getnum("amotd")) {
  3954.       disp_clear();
  3955.       disp_report("Retrieving new Aminet message of the day");
  3956.       display_remote("info/adt/aminet-motd","Aminet message of the day");
  3957.       option_setnum("amotd", amotd);
  3958.     }
  3959.     if (lmotd > option_getnum("lmotd")) {
  3960.       disp_clear();
  3961.       disp_report("Retrieving new local message of the day");
  3962.       display_remote("info/adt/local-motd","Mirror message of the day");
  3963.       option_setnum("lmotd", lmotd);
  3964.     }
  3965.   }
  3966.   if (sites > option_getnum("sites")) {
  3967.     disp_clear();
  3968.     disp_report("Updating mirror list");
  3969.     trans_remopen(&tfh, "info/adt/sites", "", disp_status);
  3970.     if (tfh.fh) {
  3971.       option_loadfh(tfh.fh);
  3972.       tclose(&tfh);
  3973.     }
  3974.     option_setnum("sites", sites);
  3975.   }
  3976.  
  3977.   adt_disconnect();
  3978.  
  3979.   return 0;
  3980. }
  3981.  
  3982. int get_complete()
  3983. {
  3984.   if (!GotComplete)
  3985.     get_list("Downloading the list of all Aminet files", "ADT_AMINET");
  3986.  
  3987.   GotComplete = GotLocal = GotRecent = 1;
  3988.  
  3989.   return 0;
  3990. }
  3991.  
  3992. int get_sitelocal()
  3993. {
  3994.   if (!GotLocal)
  3995.     get_list("Downloading the list of files on this site", "ADT_LOCAL");
  3996.  
  3997.   GotLocal = GotRecent = 1;
  3998.  
  3999.   return 0;
  4000. }
  4001.  
  4002.  
  4003. int get_recent()
  4004. {
  4005.   long age;
  4006.  
  4007.   if (GotRecent)
  4008.     return 0;
  4009.  
  4010.   GotRecent = 1;
  4011.  
  4012.   LastCall = myatoi(option_get("newest"));
  4013.   age = time(NULL) - LastCall;
  4014.  
  4015.   if (LastCall == 0) {
  4016.     disp_confirm(FirstConnectHelp, 0);
  4017.     get_list("Downloading the list of new files", "ADT_RECENT_14");
  4018.   } else if (age < 7 * 86400) {
  4019.     get_list("Downloading the list of new files", "ADT_RECENT_7");
  4020.   } else if (age < 14 * 86400) {
  4021.     get_list("Downloading the list of new files", "ADT_RECENT_14");
  4022.   } else {
  4023.     disp_confirm(LongAgoHelp, 0);
  4024.     get_list("Downloading the list of new files", "ADT_RECENT_14");
  4025.   }
  4026.  
  4027.   if (newesttime() > option_getnum("newest"))
  4028.     option_setnum("newest", newesttime());
  4029.  
  4030.   return 0;
  4031. }
  4032.  
  4033. int init_display()
  4034. {
  4035.   disp_init = cur_dispinit;
  4036.   disp_getchar = cur_getchar;
  4037.   disp_cleanup = cur_cleanup;
  4038.   disp_choice = cur_choice;
  4039.   disp_mainloop = cur_mainloop;
  4040.   disp_report = cur_report;
  4041.   disp_status = cur_status;
  4042.   disp_confirm = cur_confirm;
  4043.   disp_more = cur_more;
  4044.   disp_inputstr = cur_inputstr;
  4045.   disp_clear = cur_clear;
  4046.   disp_refresh = cur_refresh;
  4047.  
  4048.   disp_init();
  4049.  
  4050. #ifdef SIGINT
  4051.   signal (SIGINT, adt_breakcheck);
  4052. #endif
  4053.  
  4054.   return 0;
  4055. }
  4056.  
  4057.  
  4058. int init_config()
  4059. {
  4060.   if (option_load(ConfigFile) || trans_init()) {
  4061.  
  4062.     InitialSetup = 1;            /* was 1 originally, but must be 0 to use predefined options */
  4063.     setup_method();
  4064.     InitialSetup = 0;
  4065.     option_save(ConfigFile);
  4066.  
  4067.   }
  4068.   return 0;
  4069. }
  4070.  
  4071. int show_usage()
  4072. {
  4073.   puts("Usage: adt               (show new files since last call)");
  4074.   puts("       adt -f pattern    (find pattern using configured method)");
  4075.   puts("       adt -l            (show files local to configured site)");
  4076.   puts("       adt -n            (don't connect)");
  4077.   exit_adt(0);
  4078.   return 0;
  4079. }
  4080.  
  4081. int parse_commandline(argc, argv)
  4082.   int argc;
  4083.   char *argv[];
  4084. {
  4085.   if (argc <= 1) {
  4086.     if (CdRom) {
  4087.       get_sitelocal();
  4088.       allvisible();
  4089.     } else {
  4090.       get_recent();
  4091.       newvisible();
  4092.     }
  4093.     return 0;
  4094.   }
  4095.   if (argv[1][0] != '-' || !argv[1][1] || argv[1][2])
  4096.     show_usage();
  4097.  
  4098.   switch (argv[1][1]) {
  4099.   case 'f':
  4100.     if (argc != 3)
  4101.       show_usage();
  4102.     find_string(argv[2], cur_report);
  4103.     break;
  4104.  
  4105.   case 'l':
  4106.     if (argc != 2)
  4107.       show_usage();
  4108.     get_sitelocal();
  4109.     newvisible();
  4110.     break;
  4111.  
  4112.   case 'n':
  4113.     if (argc != 2)
  4114.       show_usage();
  4115.     NoFilesString="Use o)ptions to connect to a service/site";
  4116.     break;
  4117.  
  4118.   default:
  4119.     show_usage();
  4120.   }
  4121.  
  4122.   return 0;
  4123. }
  4124.  
  4125.  
  4126. int main(argc, argv)
  4127.   int argc;
  4128.   char *argv[];
  4129. {
  4130.   init_vars();
  4131.   init_display();
  4132.   init_config();
  4133.  
  4134.   parse_commandline(argc, argv);
  4135.   disp_mainloop();
  4136.  
  4137.   exit_adt(0);
  4138.   return 0;
  4139. }
  4140.  
  4141. TRANSFER TransferTypes[] =
  4142. {
  4143. #ifndef NO_BUILTIN_FTP
  4144.   "bftp",   "Builtin FTP: Use internal ftp routines to download files     ", bftp_init,
  4145. #endif
  4146. #ifndef NO_EXTERNAL_FTP
  4147.   "ftp",   "External FTP: Use the 'ftp' program to download files         ", xftp_init,
  4148. #endif
  4149.   "local", "Local files : Access a local, updated Aminet file collection  ", local_init,
  4150.   "cdrom", "CD-ROM      : Access an Aminet CD-ROM or non-updated files    ", local_init,
  4151.   0, 0, 0
  4152. };
  4153.  
  4154.  
  4155. /* to delete: ftp.log, pad, recent, short */
  4156.  
  4157.