home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / UNIX / GOPHER / BBGOPHER.C < prev    next >
Encoding:
C/C++ Source or Header  |  1993-09-14  |  28.1 KB  |  1,089 lines

  1. #include <sys/types.h>
  2. #include <sys/socket.h>
  3. #include <netinet/in.h>
  4. #include <netdb.h>
  5. #include <fcntl.h>
  6. #include <stdio.h>
  7. #include <malloc.h>
  8.  
  9. #define CONFIGPATH    "/usr/local/etc/bbgopher.conf"
  10.  
  11. #define DEFAULTTITLE  "BBGopher 1.6 (%s)"
  12. #define DEFAULTPORT   70
  13. #define DEFAULTHOST   "gopher"
  14. #define DEFAULTPAGER  ""
  15. #define DEFAULTTELNET "telnet"
  16. #define DEFAULTTN3270 "tn3270"
  17. #define DEFAULTGIF    ""
  18. #define DEFAULTIMG    ""
  19. #define DEFAULTLINES  19
  20. #define DEFAULTDIR    ""
  21. #define DEFAULTMAILER "/usr/lib/sendmail"
  22. #define MAXSTACKLEN   250
  23. #define MAXMENULEN    2500
  24.  
  25. #define G_OK         0
  26. #define G_HOST       1
  27. #define G_SOCKET     2
  28. #define G_CONNECT    3
  29. #define G_STACK      4
  30. #define G_MENU       5
  31. #define G_MEMORY     6
  32. #define G_CREATE     7
  33.  
  34. typedef struct
  35. {
  36.    char  type;
  37.    char* display;
  38.    char* selector;
  39.    char* hostname;
  40.    short port;
  41. } GO4ENTRY;
  42.  
  43. typedef struct
  44. {
  45.    char  type;
  46.    char* display;
  47.    char  acf[128];
  48.    char  supported;
  49. } TYPEENTRY;
  50.  
  51. TYPEENTRY KnownTypes[] =
  52. {
  53.    { '0', "TXT", "", 1 },
  54.    { '1', "DIR", "", 1 },
  55.    { '2', "CSO", "", 0 },
  56.    { '3', "ERR", "", 0 },
  57.    { '4', "HQX", "", 1 },
  58.    { '5', "DOS", "", 1 },
  59.    { '6', "UUE", "", 1 },
  60.    { '7', "IDX", "", 1 },
  61.    { '8', "TEL", "", 1 },
  62.    { '9', "BIN", "", 1 },
  63.    { '+', "DUP", "", 0 },
  64.    { 'g', "GIF", "", 0 },
  65.    { 'I', "PIC", "", 0 },
  66.    { 'T', "TN3", "", 1 },
  67.    { 'i', "INF", "", 1 },
  68.    { 0, 0 }
  69. };
  70.  
  71. char               Title[256];
  72. char               DefHost[256];
  73. short              DefPort;
  74. char               HelpFile[256];
  75. char               Pager[256];
  76. char               Telnet[256];
  77. char               TN3270[256];
  78. char               GIFViewer[256];
  79. char               IMGViewer[256];
  80. char               Directory[256];
  81. char               Mailer[256];
  82. char               BookMark[256];
  83. char               BadPorts[256];
  84. short              Lines;
  85. short              Twirly;
  86. short              SkipACF;
  87. short              SkipType;
  88. short              ClearScreen;
  89. GO4ENTRY           Stack[MAXSTACKLEN];
  90. short              StackLen;
  91. GO4ENTRY           Menu[MAXMENULEN];
  92. short              MenuLen;
  93. struct sockaddr_in sain;
  94. struct hostent*    host;
  95. int                sock;
  96. FILE*              sd;
  97. int                BM;
  98.  
  99. #define NUMTWIRLYCHARS 4
  100. char TwirlyChars[NUMTWIRLYCHARS + 1] = "-\\|/";
  101.  
  102. ValidNumber( number, string )
  103. int   number;
  104. char* string;
  105. {
  106.    int   n1, n2, r;
  107.    char* e;
  108.  
  109.    while( *string )
  110.    {
  111.       r = 0;
  112.       while( *string == ' ' || *string == '\t' || *string == ',' )
  113.          string++;
  114.       n1 = 0;
  115.       n2 = 0;
  116.       if( *string >= '0' && *string <= '9' )
  117.       {
  118.          n1 = atoi( string );
  119.          while( *string >= '0' && *string <= '9' )
  120.             string++;
  121.       }
  122.       if( *string == '-' )
  123.       {
  124.          r = 1;
  125.          string++;
  126.          n2 = atoi( string );
  127.          while( *string >= '0' && *string <= '9' )
  128.             string++;
  129.       }
  130.       if( r )
  131.       {
  132.          if( number >= n1 && number <= n2 )
  133.             return 1;
  134.       }
  135.       else if( number == n1 )
  136.          return 1;
  137.    }
  138.    return 0;
  139. }
  140.  
  141. CheckUser( type )
  142. char type;
  143. {
  144.    FILE* fp;
  145.    char  line[80];
  146.    char* uid;
  147.    int   i;
  148.  
  149.    for( i = 0; KnownTypes[i].type; i++ )
  150.       if( KnownTypes[i].type == type )
  151.          break;
  152.    if( KnownTypes[i].type == 0 )
  153.       return 0;
  154.    fp = fopen( KnownTypes[i].acf, "r" );
  155.    if( !fp )
  156.       return 1;
  157.    uid = (char*) getlogin();
  158.    for( fgets( line, 80, fp ); !feof( fp ); fgets( line, 80, fp ) )
  159.    {
  160.       line[strlen( line ) - 1] = 0;
  161.       if( strcasecmp( line, uid ) == 0 )
  162.       {
  163.          fclose( fp );
  164.          return 1;
  165.       }
  166.    }
  167.    fclose( fp );
  168.    return 0;
  169. }
  170.  
  171. SupportedType( type )
  172. char type;
  173. {
  174.    int i;
  175.  
  176.    for( i = 0; KnownTypes[i].type; i++ )
  177.       if( KnownTypes[i].type == type )
  178.          return KnownTypes[i].supported;
  179.    return 0;
  180. }
  181.  
  182. newEntry( ent, type, display, selector, hostname, port )
  183. GO4ENTRY* ent;
  184. char      type;
  185. char*     display;
  186. char*     selector;
  187. char*     hostname;
  188. short     port;
  189. {
  190.    if( display && (ent->display = (char*) malloc( strlen( display ) + 1 )) == 0 )
  191.       return 0;
  192.    if( selector && (ent->selector = (char*) malloc( strlen( selector ) + 1 )) == 0 )
  193.    {
  194.       free( ent->display );
  195.       return 0;
  196.    }
  197.    if( hostname && (ent->hostname = (char*) malloc( strlen( hostname ) + 1 )) == 0 )
  198.    {
  199.       free( ent->selector );
  200.       free( ent->display );
  201.       return 0;
  202.    }
  203.    ent->type = type;
  204.    if( display )
  205.       strcpy( ent->display, display );
  206.    else
  207.       ent->display = 0;
  208.    if( selector )
  209.       strcpy( ent->selector, selector );
  210.    else
  211.       ent->selector = 0;
  212.    if( hostname )
  213.       strcpy( ent->hostname, hostname );
  214.    else
  215.       ent->hostname = 0;
  216.    ent->port = port;
  217.    return 1;
  218. }
  219.  
  220. delEntry( ent )
  221. GO4ENTRY* ent;
  222. {
  223.    if( ent->hostname )
  224.       free( ent->hostname );
  225.    if( ent->selector )
  226.       free( ent->selector );
  227.    if( ent->display );
  228.       free( ent->display );
  229.    return 1;
  230. }
  231.  
  232. char* TypeLookup( type )
  233. char type;
  234. {
  235.    int         i;
  236.    static char buf[10];
  237.  
  238.    for( i = 0; KnownTypes[i].type; i++ )
  239.       if( KnownTypes[i].type == type )
  240.          return KnownTypes[i].display;
  241.    sprintf( buf, " %c ", type );
  242.    return buf;
  243. }
  244.  
  245. int DisplayLookup( display )
  246. char* display;
  247. {
  248.    int i;
  249.  
  250.    for( i = 0; i < KnownTypes[i].type; i++ )
  251.       if( !strcasecmp( KnownTypes[i].display, display ) )
  252.          return i;
  253.    return -1;
  254. }
  255.  
  256. Connect( selector, hostname, port )
  257. char* selector;
  258. char* hostname;
  259. short port;
  260. {
  261.    if( port == 0 )
  262.       port = DefPort;
  263.    if( ValidNumber( port, BadPorts ) )
  264.    {
  265.       printf( "Sorry, but access to that service is not allowed.\n\n" );
  266.       return G_CONNECT;
  267.    }
  268.    if( hostname == 0 )
  269.       hostname = DefHost;
  270.    if( (host = gethostbyname( hostname )) == 0 )
  271.       return G_HOST;
  272.    if( (sock = socket( AF_INET, SOCK_STREAM, 0 )) < 0 )
  273.       return G_SOCKET;
  274.    bzero( &sain, sizeof(sain) );
  275.    sain.sin_family = AF_INET;
  276.    sain.sin_port = htons( port );
  277.    bcopy( host->h_addr, &sain.sin_addr, host->h_length );
  278.    if( connect( sock, (struct sockaddr*) &sain, sizeof(sain) ) < 0 )
  279.       return G_CONNECT;
  280.    if( selector )
  281.       write( sock, selector, strlen( selector ) );
  282.    write( sock, "\r\n", 2 );
  283.    sd = fdopen( sock, "r" );
  284.    return G_OK;
  285. }
  286.  
  287. Disconnect()
  288. {
  289.    close( sock );
  290. }
  291.  
  292. Page( file )
  293. char* file;
  294. {
  295.    FILE* fp;
  296.    char  line[256];
  297.    int   n = 0;
  298.  
  299.    fp = fopen( file, "r" );
  300.    if( !fp )
  301.       return 0;
  302.    if( ClearScreen )
  303.       printf( "\033[2J\033[H" );
  304.    else
  305.       putchar( '\n' );
  306.    for( fgets( line, 256, fp ); !feof( fp ); fgets( line, 256, fp ) )
  307.    {
  308.       printf( line );
  309.       if( ++n == 22 )
  310.       {
  311.          printf( "[MORE...]" );
  312.          *line = 0;
  313.          fflush( stdin );
  314.          fgets( line, 2, stdin );
  315.          fflush( stdin );
  316.          n = 0;
  317.          if( *line == 'q' || *line == 'Q' )
  318.             break;
  319.       }
  320.    }
  321.    fclose( fp );
  322.    return 1;
  323. }
  324.  
  325. GetData( file, binary )
  326. char* file;
  327. int   binary;
  328. {
  329.    FILE* fp;
  330.    int   l = 0;
  331.    int   t = 0;
  332.    char  line[256];
  333.    char  ch;
  334.  
  335.    fp = fopen( file, "w" );
  336.    if( !fp )
  337.       return G_CREATE;
  338.    if( Twirly )
  339.       putchar( ' ' );
  340.    if( binary )
  341.       for( ch = getc( sd ); !feof( sd ); ch = getc( sd ) )
  342.       {
  343.          putc( ch, fp );
  344.          if( Twirly && ++l == 1024 )
  345.          {
  346.             l = 0;
  347.             putchar( '\b' );
  348.             putchar( TwirlyChars[t] );
  349.             t++;
  350.             if( t == NUMTWIRLYCHARS )
  351.                t = 0;
  352.             fflush( stdout );
  353.          }
  354.       }
  355.    else
  356.       for( fgets( line, 255, sd ); !feof( sd ); fgets( line, 255, sd ) )
  357.       {
  358.          l = strlen( line ) - 1;
  359.          if( line[l] == '\n' && line[l - 1] == '\r' )
  360.          {
  361.             line[l - 1] = '\n';
  362.             line[l] = 0;
  363.          }
  364.          if( *line == '.' && (line[1] == '\r' || line[1] == '\n') )
  365.             break;
  366.          fprintf( fp, line );
  367.          if( Twirly )
  368.          {
  369.             putchar( '\b' );
  370.             putchar( TwirlyChars[t] );
  371.             t++;
  372.             if( t == NUMTWIRLYCHARS )
  373.                t = 0;
  374.             fflush( stdout );
  375.          }
  376.       }
  377.    if( Twirly )
  378.       printf( "\b \b" );
  379.    fclose( fp );
  380.    return G_OK;
  381. }
  382.  
  383. GetFile( selector, hostname, port, type, binary )
  384. char* selector;
  385. char* hostname;
  386. short port;
  387. {
  388.    char line[81];
  389.    int  rc;
  390.  
  391.    printf( "Local name for %s file? ", type );
  392.    fflush( stdin );
  393.    fgets( line, 80, stdin );
  394.    fflush( stdin );
  395.    printf( "\n" );
  396.    line[strlen( line ) - 1] = 0;
  397.    if( *line == 0 )
  398.       return G_OK;
  399.    if( (rc = Connect( selector, hostname, port )) != G_OK )
  400.       return rc;
  401.    printf( "Retrieving file..." );
  402.    fflush( stdout );
  403.    rc = GetData( line, binary );
  404.    printf( "\n\n" );
  405.    Disconnect();
  406.    return rc;
  407. }
  408.  
  409. MailFile( filename )
  410. char* filename;
  411. {
  412.    FILE* fi;
  413.    FILE* fo;
  414.    char* tmp;
  415.    char  to[81];
  416.    char  sub[81];
  417.    char  ch;
  418.  
  419.    printf( "To [%s]: ", getlogin() );
  420.    fflush( stdin );
  421.    fgets( to, 80, stdin );
  422.    to[strlen( to ) - 1] = 0;
  423.    if( *to == 0 )
  424.       strcpy( to, (char*) getlogin() );
  425.    printf( "Subject: " );
  426.    fflush( stdin );
  427.    fgets( sub, 80, stdin );
  428.    fflush( stdin );
  429.    printf( "\n" );
  430.    sub[strlen( sub ) - 1] = 0;
  431.    if( *sub == 0 )
  432.       strcpy( sub, "No Subject Specified" );
  433.    printf( "Mailing file...\n\n" );
  434.    tmp = tempnam( "/tmp", "bbgo" );
  435.    if( (fo = fopen( tmp, "w" )) == NULL )
  436.    {
  437.       free( tmp );
  438.       return G_CREATE;
  439.    }
  440.    fi = fopen( filename, "r" );
  441.    fprintf( fo, "To: %s\n", to );
  442.    fprintf( fo, "Subject: %s\n", sub );
  443.    fprintf( fo, "\n" );
  444.    for( ch = fgetc( fi ); !feof( fi ); ch = fgetc( fi ) )
  445.       fputc( ch, fo );
  446.    fclose( fi );
  447.    fclose( fo );
  448.    sprintf( sub, "%s %s < %s", Mailer, to, tmp );
  449.    system( sub );
  450.    unlink( tmp );
  451.    free( tmp );
  452.    return G_OK;
  453. }
  454.  
  455. SaveFile( filename )
  456. char* filename;
  457. {
  458.    FILE* fi;
  459.    FILE* fo;
  460.    char  line[81];
  461.    char  temp[81];
  462.    char* l;
  463.    char  ch;
  464.  
  465.    printf( "Local name for TXT file? " );
  466.    fflush( stdin );
  467.    fgets( line, 80, stdin );
  468.    fflush( stdin );
  469.    printf( "\n" );
  470.    line[strlen( line ) - 1] = 0;
  471.    if( *line == 0 )
  472.       return G_OK;
  473.    if( *Directory )
  474.    {
  475.       l = (char*) rindex( line, '/' );
  476.       if( l )
  477.          *l++ = 0;
  478.       else
  479.          l = line;
  480.       *temp = 0;
  481.       if( *Directory == '~' )
  482.       {
  483.          strcpy( temp, (char*) getenv( "HOME" ) );
  484.          strcat( temp, &Directory[1] );
  485.       }
  486.       else
  487.          strcat( temp, Directory );
  488.       if( temp[strlen( temp ) - 1] != '/' )
  489.          strcat( temp, "/" );
  490.       strcat( temp, l );
  491.       l = temp;
  492.    }
  493.    else
  494.       l = line;
  495.    printf( "Saving file...\n\n" );
  496.    fflush( stdout );
  497.    if( (fo = fopen( l, "w" )) == NULL )
  498.       return G_CREATE;
  499.    fi = fopen( filename, "r" );
  500.    for( ch = fgetc( fi ); !feof( fi ); ch = fgetc( fi ) )
  501.       fputc( ch, fo );
  502.    fclose( fi );
  503.    fclose( fo );
  504.    return G_OK;
  505. }
  506.  
  507. ReadText( selector, hostname, port )
  508. char* selector;
  509. char* hostname;
  510. short port;
  511. {
  512.    char* tmp;
  513.    char  line[256];
  514.    int   l;
  515.    int   rc;
  516.  
  517.    if( (rc = Connect( selector, hostname, port )) != G_OK )
  518.       return rc;
  519.    printf( "Retrieving text..." );
  520.    fflush( stdout );
  521.    tmp = tempnam( "/tmp", "bbgo" );
  522.    if( (rc = GetData( tmp, 0 )) != G_OK )
  523.    {
  524.       free( tmp );
  525.       return rc;
  526.    }
  527.    printf( "\n" );
  528.    Disconnect();
  529.    if( *Pager == 0 || !strcasecmp( Pager, "default" ) )
  530.       Page( tmp );
  531.    else
  532.    {
  533.       sprintf( line, Pager, tmp );
  534.       if( !strstr( Pager, "%s" ) )
  535.       {
  536.          strcat( line, " " );
  537.          strcat( line, tmp );
  538.       }
  539.       system( line );
  540.    }
  541.    printf( "\nPress ENTER to continue, M to mail, S to save: " );
  542.    fflush( stdin );
  543.    fgets( line, 5, stdin );
  544.    fflush( stdin );
  545.    printf( "\n" );
  546.    rc = G_OK;
  547.    if( *line == 'm' || *line == 'M' )
  548.       rc = MailFile( tmp );
  549.    else if( *line == 's' || *line == 'S' )
  550.       rc = SaveFile( tmp );
  551.    unlink( tmp );
  552.    free( tmp );
  553.    return rc;
  554. }
  555.  
  556. DoSearch( selector, hostname, port )
  557. char* selector;
  558. char* hostname;
  559. short port;
  560. {
  561.    char buf[256];
  562.    char line[81];
  563.    int  rc;
  564.  
  565.    printf( "Please enter your search criteria (you may use 'and' and 'or'):\n" );
  566.    fflush( stdin );
  567.    fgets( line, 80, stdin );
  568.    fflush( stdin );
  569.    printf( "\n" );
  570.    line[strlen( line ) - 1] = 0;
  571.    if( *line == 0 )
  572.       return G_OK;
  573.    sprintf( buf, "%s\t%s\r\n", selector, line );
  574.    if( (rc = Connect( buf, hostname, port )) != G_OK )
  575.       return rc;
  576.    printf( "Searching...\n" );
  577.    rc = ReadMenu( "Index Search Results", buf, hostname, port, 0, 0 );
  578.    Disconnect();
  579.    return rc;
  580. }
  581.  
  582. ReadMenu( display, selector, hostname, port, connect, fd )
  583. char* display;
  584. char* selector;
  585. char* hostname;
  586. short port;
  587. int   connect;
  588. FILE* fd;
  589. {
  590.    char               line[1025];
  591.    char*              e;
  592.    GO4ENTRY           ent;
  593.    int                rc;
  594.    int                t;
  595.  
  596.    if( connect )
  597.       if( (rc = Connect( selector, hostname, port )) != G_OK )
  598.          return rc;
  599.    if( StackLen >= MAXSTACKLEN )
  600.    {
  601.       if( connect )
  602.          Disconnect();
  603.       return G_STACK;
  604.    }
  605.    if( BM )
  606.    {
  607.       StackLen--;
  608.       delEntry( &Stack[StackLen] );
  609.       StackLen--;
  610.       BM = 0;
  611.    }
  612.    if( !newEntry( &Stack[StackLen], '1', display, selector, hostname, port ) )
  613.    {
  614.       if( connect )
  615.          close( sock );
  616.       return G_MEMORY;
  617.    }
  618.    StackLen++;
  619.    MenuLen = 0;
  620.    t = 0;
  621.    if( Twirly )
  622.       putchar( ' ' );
  623.    if( fd == NULL )
  624.       fd = sd;
  625.    for( fgets( line, 1024, fd ); !feof( fd ); fgets( line, 1024, fd ) )
  626.    {
  627.       if( *line == '.' && (line[1] == '\r' || line[1] == '\n') )
  628.          break;
  629.       e = line;
  630.       ent.type = *e++;
  631.       ent.display = e;
  632.       while( *e && *e != '\t' )   e++;
  633.       if( *e )   *e++ = 0;
  634.       ent.selector = e;
  635.       while( *e && *e != '\t' )   e++;
  636.       if( *e )   *e++ = 0;
  637.       ent.hostname = e;
  638.       while( *e && *e != '\t' )   e++;
  639.       if( *e )   *e++ = 0;
  640.       ent.port = atoi( e );
  641.       if( SkipType && !SupportedType( ent.type ) )
  642.          continue;
  643.       if( SkipACF && !CheckUser( ent.type ) )
  644.          continue;
  645.       if( !newEntry( &Menu[MenuLen], ent.type, ent.display, ent.selector, ent.hostname, ent.port ) )
  646.       {
  647.          Disconnect();
  648.          return G_MEMORY;
  649.       }
  650.       MenuLen++;
  651.       if( MenuLen == MAXMENULEN )
  652.          break;
  653.       if( Twirly )
  654.       {
  655.          putchar( '\b' );
  656.          putchar( TwirlyChars[t] );
  657.          t++;
  658.          if( t == NUMTWIRLYCHARS )
  659.             t = 0;
  660.          fflush( stdout );
  661.       }
  662.    }
  663.    if( Twirly )
  664.       printf( "\b \b" );
  665.    if( connect )
  666.       Disconnect();
  667.    return G_OK;
  668. }
  669.  
  670. SaveBookmark( n )
  671. int n;
  672. {
  673.    FILE* fp;
  674.    char  buf[256];
  675.  
  676.    strcpy( buf, (char*) getenv( "HOME" ) );
  677.    strcat( buf, "/" );
  678.    strcat( buf, BookMark );
  679.    if( (fp = fopen( buf, "a" )) == 0 )
  680.       return;
  681.    fprintf( fp, "%c%s\t%s\t%s\t%d\n", Menu[n].type, Menu[n].display, Menu[n].selector, Menu[n].hostname, Menu[n].port );
  682.    fclose( fp );
  683.    printf( "Bookmark saved...\n\n" );
  684.    return;
  685. }
  686.  
  687. DelBookmark( n )
  688. int n;
  689. {
  690.    FILE* fp;
  691.    int   i;
  692.    char  buf[256];
  693.  
  694.    strcpy( buf, (char*) getenv( "HOME" ) );
  695.    strcat( buf, "/" );
  696.    strcat( buf, BookMark );
  697.  
  698.    if( n < MenuLen - 1 )
  699.       bcopy( &Menu[n + 1], &Menu[n], sizeof(GO4ENTRY) * (MenuLen - n - 1) );
  700.    MenuLen--;
  701.    if( (fp = fopen( buf, "w" )) == 0 )
  702.       return;
  703.    for( i = 0; i < MenuLen; i++ )
  704.       fprintf( fp, "%c%s\t%s\t%s\t%d\n", Menu[i].type, Menu[i].display, Menu[i].selector, Menu[i].hostname, Menu[i].port );
  705.    fclose( fp );
  706.    printf( "Bookmark deleted...\n\n" );
  707.    return;
  708. }
  709.  
  710. CompareEntries( ent1, ent2 )
  711. GO4ENTRY* ent1;
  712. GO4ENTRY* ent2;
  713. {
  714.    return strcasecmp( ent1->display, ent2->display );
  715. }
  716.  
  717. ReadBookmarks()
  718. {
  719.    FILE* fp;
  720.    char  buf[256];
  721.  
  722.    strcpy( buf, (char*) getenv( "HOME" ) );
  723.    strcat( buf, "/" );
  724.    strcat( buf, BookMark );
  725.    if( (fp = fopen( buf, "r" )) == 0 )
  726.       return 0;
  727.    ReadMenu( "* Bookmarks *", 0, 0, 0, 0, fp );
  728.    fclose( fp );
  729.    qsort( Menu, MenuLen, sizeof(GO4ENTRY), CompareEntries );
  730.    return 1;
  731. }
  732.  
  733. ProcessMenu()
  734. {
  735.    int   i, n;
  736.    int   top;
  737.    char* s;
  738.    char  buf[256];
  739.  
  740.    top = 0;
  741. page:
  742.    if( ClearScreen )
  743.       printf( "\033[2J\033[H" );
  744.    printf( "%s\n%s", Title, Stack[StackLen - 1].display );
  745.    if( Stack[StackLen - 1].hostname )
  746.       printf( " (%s)", Stack[StackLen - 1].hostname );
  747.    printf( "\n\n" );
  748.    if( MenuLen == 0 )
  749.       printf( "There are no menu items available.\n" );
  750.    else for( i = 0, n = top; i < Lines && n < MenuLen; i++, n++ )
  751.    {
  752.       if( Menu[n].type == 'i' )
  753.          printf( "%3d %-.75s\n", n + 1, Menu[n].display );
  754.       else
  755.          printf( "%3d <%s> %-.69s\n", n + 1, TypeLookup( Menu[n].type ), Menu[n].display );
  756.    }
  757.    putchar( '\n' );
  758. loop:
  759.    do
  760.    {
  761.       *buf = 0;
  762.       if( MenuLen == 0 )
  763.          printf( "Help, Quit or Previous: " );
  764.       else
  765.          printf( "[1-%d], Help, Quit, %s, List, Previous, Up, or Down: ", MenuLen, BM ? "Delete" : "=, Bookmarks, Save" );
  766.       fflush( stdin );
  767.       fgets( buf, 15, stdin );
  768.       fflush( stdin );
  769.       buf[strlen( buf ) - 1] = 0;
  770.    } while( *buf == 0 && MenuLen <= Lines );
  771.    printf( "\n" );
  772.    if( *buf == 'h' || *buf == 'H' )
  773.    {
  774.       if( *Pager == 0 || !strcasecmp( Pager, "default" ) )
  775.          Page( HelpFile );
  776.       else
  777.       {
  778.          sprintf( buf, Pager, HelpFile );
  779.          if( !strstr( Pager, "%s" ) )
  780.          {
  781.             strcat( buf, " " );
  782.             strcat( buf, HelpFile );
  783.          }
  784.          system( buf );
  785.       }
  786.       printf( "\nPress ENTER to continue" );
  787.       fflush( stdin );
  788.       fgets( buf, 5, stdin );
  789.       fflush( stdin );
  790.       printf( "\n" );
  791.       goto page;
  792.    }
  793.    if( *buf == 'q' || *buf == 'Q' )
  794.       return -2;
  795.    if( !BM && *buf == '=' )
  796.    {
  797.       for( s = buf; *s && *s != ' '; s++ );
  798.       n = atoi( s );
  799.       if( n < 0 || n > MenuLen )
  800.          printf( "You must specify a valid item number to save as a bookmark (eg: s 1).\n\n" );
  801.       else if( n == 0 )
  802.       {
  803.          printf( "Type:     %s\n", TypeLookup( Stack[StackLen - 1].type ) );
  804.          printf( "Title:    %s\n", Stack[StackLen - 1].display );
  805.          printf( "Host:     %s\n", Stack[StackLen - 1].hostname );
  806.          printf( "Port:     %d\n", Stack[StackLen - 1].port );
  807.          printf( "Selector: %s\n\n", Stack[StackLen - 1].selector ? Stack[StackLen - 1].selector : "" );
  808.       }
  809.       else
  810.       {
  811.          printf( "Type:     %s\n", TypeLookup( Menu[n - 1].type ) );
  812.          printf( "Title:    %s\n", Menu[n - 1].display );
  813.          printf( "Host:     %s\n", Menu[n - 1].hostname );
  814.          printf( "Port:     %d\n", Menu[n - 1].port );
  815.          printf( "Selector: %s\n\n", Menu[n - 1].selector ? Menu[n - 1].selector : "" );
  816.       }
  817.       goto loop;
  818.    }
  819.    if( !BM && (*buf == 'b' || *buf == 'B') )
  820.       return -3;
  821.    if( !BM && (*buf == 's' || *buf == 'S') )
  822.    {
  823.       for( s = buf; *s && *s != ' '; s++ );
  824.       n = atoi( s );
  825.       if( n < 1 || n > MenuLen )
  826.          printf( "You must specify a valid item number to save as a bookmark (eg: s 1).\n\n" );
  827.       else
  828.          SaveBookmark( n - 1 );
  829.       goto loop;
  830.    }
  831.    if( BM && (*buf == 'd' || *buf == 'D') )
  832.    {
  833.       for( s = buf; *s && *s != ' '; s++ );
  834.       n = atoi( s );
  835.       if( n < 1 || n > MenuLen )
  836.          printf( "You must specify a valid item number to delete. (eg: d 1)\n\n" );
  837.       else
  838.          DelBookmark( n - 1 );
  839.       goto loop;
  840.    }
  841.    if( *buf == 'p' || *buf == 'P' )
  842.       return -1;
  843.    if( *buf == 'l' || *buf == 'L' )
  844.       goto page;
  845.    if( *buf == 'd' || *buf == 'D' || *buf == 0 )
  846.    {
  847.       top += Lines - 1;
  848.       if( top >= MenuLen - 1 )
  849.          top = 0;
  850.       goto page;
  851.    }
  852.    if( *buf == 'u' || *buf == 'U' )
  853.    {
  854.       if( top == 0 )
  855.          top = MenuLen - Lines;
  856.       else
  857.          top -= Lines - 1;
  858.       if( top < 0 )
  859.          top = 0;
  860.       goto page;
  861.    }
  862.    i = atoi( buf );
  863.    if( i < 1 || i > MenuLen )
  864.    {
  865.       printf( "Please enter a command or a number between 1 and %d.\n\n", MenuLen );
  866.       goto loop;
  867.    }
  868.    i--;
  869.    if( Menu[i].type == 'i' )
  870.    {
  871.       printf( "That menu item is informational only.\n\n" );
  872.       goto loop;
  873.    }
  874.    if( !SupportedType( Menu[i].type ) )
  875.    {
  876.       printf( "Sorry, that type of menu item isn't currently supported.\n\n" );
  877.       goto loop;
  878.    }
  879.    if( !CheckUser( Menu[i].type ) )
  880.    {
  881.       printf( "Sorry, but you don't have access to that item.\n\n" );
  882.       goto loop;
  883.    }
  884.    return i;
  885. }
  886.  
  887. Setup()
  888. {
  889.    FILE* fp;
  890.    char  line[91];
  891.    char* var;
  892.    char* val;
  893.    char* e;
  894.    int   i;
  895.  
  896.    strcpy( Title, DEFAULTTITLE );
  897.    strcpy( DefHost, DEFAULTHOST );
  898.    DefPort = DEFAULTPORT;
  899.    *BadPorts = 0;
  900.    strcpy( Pager, DEFAULTPAGER );
  901.    strcpy( Telnet, DEFAULTTELNET );
  902.    strcpy( TN3270, DEFAULTTN3270 );
  903.    strcpy( Directory, DEFAULTDIR );
  904.    Lines = DEFAULTLINES;
  905.    Twirly = 1;
  906.    ClearScreen = 0;
  907.    SkipACF = 0;
  908.    SkipType = 1;
  909.    fp = fopen( CONFIGPATH, "r" );
  910.    if( !fp )
  911.       return 0;
  912.    for( fgets( line, 90, fp ); !feof( fp ); fgets( line, 90, fp ) )
  913.    {
  914.       e = (char*) rindex( line, '#' );
  915.       if( e )
  916.          *e-- = 0;
  917.       else
  918.       {
  919.          e = line + strlen( line ) - 1;
  920.          *e-- = 0;
  921.       }
  922.       for( var = line; *var == ' ' || *var == '\t'; var++ );
  923.       for( val = var; *val && *val != ' ' && *val != '\t'; val++ );
  924.       if( *val )   *val++ = 0;
  925.       while( *val == ' ' || *val == '\t' )
  926.          val++;
  927.       if( *val == '\"' )   val++;
  928.       while( *e == ' ' || *e == '\t' )
  929.          *e-- = 0;
  930.       if( *e == '\"' )   *e = 0;
  931.       if( *var == 0 || *var == '#' )
  932.          continue;
  933.       if( !strcasecmp( var, "TITLE" ) )
  934.          strcpy( Title, val );
  935.       else if( !strcasecmp( var, "SERVER" ) )
  936.          strcpy( DefHost, val );
  937.       else if( !strcasecmp( var, "PORT" ) )
  938.          DefPort = atoi( val );
  939.       else if( !strcasecmp( var, "BADPORTS" ) )
  940.          strcpy( BadPorts, val );
  941.       else if( !strcasecmp( var, "HELPFILE" ) )
  942.          strcpy( HelpFile, val );
  943.       else if( !strcasecmp( var, "PAGER" ) )
  944.          strcpy( Pager, val );
  945.       else if( !strcasecmp( var, "WORKDIR" ) )
  946.          strcpy( Directory, val );
  947.       else if( !strcasecmp( var, "MAILER" ) )
  948.          strcpy( Mailer, val );
  949.       else if( !strcasecmp( var, "BOOKMARK" ) )
  950.          strcpy( BookMark, val );
  951.       else if( !strcasecmp( var, "TELNET" ) )
  952.          strcpy( Telnet, val );
  953.       else if( !strcasecmp( var, "TN3270" ) )
  954.          strcpy( TN3270, val );
  955.       else if( !strcasecmp( var, "LINES" ) )
  956.          Lines = atoi( val );
  957.       else if( !strcasecmp( var, "TWIRLY" ) )
  958.          Twirly = (*val == 'y' || *val == 'Y' || *val == '1' );
  959.       else if( !strcasecmp( var, "CLEAR" ) )
  960.          ClearScreen = (*val == 'y' || *val == 'Y' || *val == '1' );
  961.       else if( !strcasecmp( var, "SKIPACF" ) )
  962.          SkipACF = (*val == 'y' || *val == 'Y' || *val == '1' );
  963.       else if( !strcasecmp( var, "SKIPTYPE" ) )
  964.          SkipType = (*val == 'y' || *val == 'Y' || *val == '1' );
  965.       else if( !strncasecmp( var, "ACF", 3 ) && (i = DisplayLookup( &var[3] )) != -1 )
  966.          strcpy( KnownTypes[i].acf, val );
  967.       else
  968.          printf( "Warning: unrecognised option in configuration file (%s)\n", var );
  969.    }
  970.    return 1;
  971. }
  972.  
  973. main( argc, argv )
  974. int   argc;
  975. char* argv[];
  976. {
  977.    int   ok;
  978.    int   rc;
  979.    int   rc2;
  980.    char  buf[10];
  981.  
  982.    printf( "\nBBGopher 1.6 - Written by Mark Morley (September '93)\n" );
  983.    if( !Setup() )
  984.       printf( "Warning: no configuration file found, using defaults.\n" );
  985.    putchar( '\n' );
  986.    StackLen = 0;
  987.    if( argc > 1 )
  988.    {
  989.       strcpy( DefHost, argv[1] );
  990.       if( argc > 2 )
  991.          DefPort = atoi( argv[2] );
  992.    }
  993.    rc = ReadMenu( "Default Gopher Server", 0, DefHost, DefPort, 1, 0 );
  994.    if( rc != G_OK )
  995.    {
  996.       printf( "Sorry, but I was unable to connect to %s on port %d\n", DefHost, DefPort );
  997.       exit( 1 );
  998.    }
  999.    BM = 0;
  1000.    ok = 1;
  1001.    while( ok )
  1002.    {
  1003.       rc = ProcessMenu();
  1004.       switch( rc )
  1005.       {
  1006.          case -1 : BM = 0;
  1007.                    if( StackLen > 1 )
  1008.                    {
  1009.                       StackLen--;
  1010.                       delEntry( &Stack[StackLen] );
  1011.                       StackLen--;
  1012.                       ReadMenu( Stack[StackLen].display, Stack[StackLen].selector, Stack[StackLen].hostname, Stack[StackLen].port, 1, 0 );
  1013.                    }
  1014.                    break;
  1015.          case -2 : ok = 0;
  1016.                    break;
  1017.          case -3 : if( BM == 0 )
  1018.                    {
  1019.                       ReadBookmarks();
  1020.                       BM = 1;
  1021.                    }
  1022.                    break;
  1023.          default : if( BM && StackLen > 1 )
  1024.                    {
  1025.                       StackLen--;
  1026.                       delEntry( &Stack[StackLen] );
  1027.                    }
  1028.                    BM = 0;
  1029.                    switch( Menu[rc].type )
  1030.                    {
  1031.                       case '0' : rc2 = ReadText( Menu[rc].selector, Menu[rc].hostname, Menu[rc].port );
  1032.                                  break;
  1033.                       case '1' : rc2 = ReadMenu( Menu[rc].display, Menu[rc].selector, Menu[rc].hostname, Menu[rc].port, 1, 0 );
  1034.                                  break;
  1035.                       case '4' : rc2 = GetFile( Menu[rc].selector, Menu[rc].hostname, Menu[rc].port, "Mac HQX", 1 );
  1036.                                  break;
  1037.                       case '5' : rc2 = GetFile( Menu[rc].selector, Menu[rc].hostname, Menu[rc].port, "DOS binary", 1 );
  1038.                                  break;
  1039.                       case '6' : rc2 = GetFile( Menu[rc].selector, Menu[rc].hostname, Menu[rc].port, "UU encoded", 0 );
  1040.                                  break;
  1041.                       case '7' : rc2 = DoSearch( Menu[rc].selector, Menu[rc].hostname, Menu[rc].port );
  1042.                                  break;
  1043.                       case '8' : if( *Menu[rc].selector )
  1044.                                     printf( "Try logging in as '%s'\n\n", Menu[rc].selector );
  1045.                                  sprintf( buf, "%s %s %d", Telnet, Menu[rc].hostname, Menu[rc].port ? Menu[rc].port : 23 );
  1046.                                  system( buf );
  1047.                                  rc2 = G_OK;
  1048.                                  break;
  1049.                       case '9' : rc2 = GetFile( Menu[rc].selector, Menu[rc].hostname, Menu[rc].port, "binary", 1 );
  1050.                                  break;
  1051.                       case 'T' : sprintf( buf, "%s %s %d", TN3270, Menu[rc].hostname, Menu[rc].port ? Menu[rc].port : 23 );
  1052.                                  system( buf );
  1053.                                  rc2 = G_OK;
  1054.                                  break;
  1055.                    }
  1056.                    if( rc2 != G_OK )
  1057.                    {
  1058.                       printf( "ERROR: " );
  1059.                       switch( rc2 )
  1060.                       {
  1061.                          case G_HOST    : printf( "Couldn't resolve hostname '%s'\n", Menu[rc].hostname );
  1062.                                           break;
  1063.                          case G_SOCKET  : printf( "Socket error!\n" );
  1064.                                           break;
  1065.                          case G_CONNECT : printf( "Couldn't connect to %s\n", Menu[rc].hostname );
  1066.                                           break;
  1067.                          case G_CREATE : printf( "Couldn't create local file.\n" );
  1068.                                           break;
  1069.                          default        : printf( "Code = %d\n", rc2 );
  1070.                                           break;
  1071.                       }
  1072.                       putchar( '\n' );
  1073.                    }
  1074.                    break;
  1075.       }
  1076.    }
  1077.    while( MenuLen )
  1078.    {
  1079.       MenuLen--;
  1080.       delEntry( &Menu[MenuLen] );
  1081.    }
  1082.    while( StackLen )
  1083.    {
  1084.       StackLen--;
  1085.       delEntry( &Stack[StackLen] );
  1086.    }
  1087. }
  1088.  
  1089.