home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / TELECOM / rn_4_3_blars.lzh / rn.c < prev    next >
C/C++ Source or Header  |  1990-10-13  |  13KB  |  565 lines

  1. /*  rn -- new readnews program
  2.  *
  3.  *  Original Author: lwall@sdcrdcf.UUCP (Larry Wall)
  4.  *  Organization: System Development Corporation, Santa Monica
  5.  *
  6.  *  begun:   01/14/83
  7.  *    1.0: 04/08/83
  8.  *      2.0: 09/01/83
  9.  *      RRN/RN: 11/01/89
  10. */
  11.  
  12. static char rnid[] = "@(#)$Header: rn.c,v 4.3.2.4 90/04/03 23:11:33 sob Exp $";
  13. static char patchlevel[] = "Patch #: 47";
  14.  
  15. /* $Log:    rn.c,v $
  16.  * Revision 4.3.2.4  90/04/03  23:11:33  sob
  17.  * Added more information to the version command.
  18.  * 
  19.  * Revision 4.3.2.3  90/03/22  23:05:23  sob
  20.  * Fixes provided by Wayne Davison <drivax!davison>
  21.  * 
  22.  * Revision 4.3.2.2  89/11/28  01:51:25  sob
  23.  * Removed redundant #include directive.
  24.  * 
  25.  * Revision 4.3.2.1  89/11/08  02:27:38  sob
  26.  * Release of RN 4.3 with RRN that can be compiled from the same
  27.  * sources as either version of the program.
  28.  * 
  29.  * Revision 4.3.1.4  85/09/10  11:05:13  lwall
  30.  * Improved %m in in_char().
  31.  * 
  32.  * Revision 4.3.1.3  85/05/16  16:47:10  lwall
  33.  * Catchup confirmation didn't grok -t.
  34.  * 
  35.  * Revision 4.3.1.2  85/05/13  09:34:53  lwall
  36.  * Fixed default after do_newsgroup() returns from Q command.
  37.  * 
  38.  * Revision 4.3.1.1  85/05/10  11:38:08  lwall
  39.  * Branch for patches.
  40.  * 
  41.  * Revision 4.3  85/05/01  11:47:56  lwall
  42.  * Baseline for release with 4.3bsd.
  43.  * 
  44.  */
  45.  
  46. #include "INTERN.h"
  47. #include "common.h"
  48. #include "rn.h"
  49. #include "EXTERN.h"
  50. #include "rcstuff.h"
  51. #include "term.h"
  52. #include "final.h"
  53. #include "ngdata.h"
  54. #include "util.h"
  55. #include "only.h"
  56. #include "ngsrch.h"
  57. #include "help.h"
  58. #include "last.h"
  59. #include "init.h"
  60. #include "intrp.h"
  61. #include "rcln.h"
  62. #include "sw.h"
  63. #include "addng.h"
  64. #include "ng.h"
  65.  
  66. void
  67. rn_init()
  68. {
  69.     ;
  70. }
  71.  
  72. void
  73. main(argc,argv)
  74. int argc;
  75. char *argv[];
  76. {
  77.     bool foundany = initialize(argc,argv);
  78.     register char *s;
  79.     bool oh_for_the_good_old_days = FALSE;
  80.     
  81.     if (maxngtodo)
  82.     starthere = 0;
  83.     else if (!foundany) {        /* nothing to do? */
  84. #ifdef VERBOSE
  85.     if (verbose)
  86.         fputs("\
  87. No unread news in subscribed-to newsgroups.  To subscribe to a new\n\
  88. newsgroup use the g<newsgroup> command.\n\
  89. ",stdout) FLUSH;
  90. #endif
  91.     starthere = nextrcline;
  92.     }
  93.  
  94.     /* loop through all unread news */
  95.  
  96.     {
  97.     char promptbuf[80];
  98.     bool special = FALSE;        /* temporarily allow newsgroup */
  99.                     /*   with no unread news? */
  100.     bool retry;            /* cycle back to top of list? */
  101.     NG_NUM recent_ng = 0;
  102.     
  103.     current_ng = 0;
  104.     do {
  105.         retry = FALSE;
  106.         if (findlast) {
  107.         findlast = FALSE;
  108.         starthere = 0;
  109.         if (*lastngname) {
  110.             if ((ng = find_ng(lastngname)) == nextrcline)
  111.             ng = 0;
  112.             else {
  113.             set_ngname(lastngname);
  114.                 set_toread(ng);
  115.             if (toread[ng] <= TR_NONE)
  116.                 ng = 0;
  117.             }
  118.         }
  119.         }
  120.         else {
  121.         ng = starthere;
  122.         starthere = 0;
  123.         }
  124.         while (ng <= nextrcline) {    /* for each newsgroup */
  125.         mode = 'n';
  126.         if (ng >= nextrcline) {    /* after the last newsgroup? */
  127.             ng = nextrcline;    /* force it to 1 after */
  128. #ifdef ONLY
  129.             if (maxngtodo) {
  130.             if (retry)
  131. #ifdef VERBOSE
  132.                 IF(verbose)
  133.                 printf("\nRestriction %s%s still in effect.\n",
  134.                     ngtodo[0],
  135.                     maxngtodo > 1 ? ", etc." : nullstr) FLUSH;
  136.                 ELSE
  137. #endif
  138. #ifdef TERSE
  139.                 fputs("\n(\"Only\" mode.)\n",stdout) FLUSH;
  140. #endif
  141.             else {
  142. #ifdef VERBOSE
  143.                 IF(verbose)
  144.                 fputs("\nNo articles under restriction.",
  145.                   stdout) FLUSH;
  146.                 ELSE
  147. #endif
  148. #ifdef TERSE
  149.                 fputs("\nNo \"only\" articles.",stdout) FLUSH;
  150. #endif
  151.                 end_only();    /* release the restriction */
  152.                 retry = TRUE;
  153.             }
  154.             }
  155. #endif
  156.             dfltcmd = (retry ? "npq" : "qnp");
  157. #ifdef VERBOSE
  158.             IF(verbose)
  159.             sprintf(promptbuf,
  160.                 "\n******** End of newsgroups--what next? [%s] ",
  161.                 dfltcmd);
  162.             ELSE
  163. #endif
  164. #ifdef TERSE
  165.             sprintf(promptbuf,
  166.                 "\n**** End--next? [%s] ", dfltcmd);
  167. #endif
  168.         }
  169.         else {
  170.             bool shoe_fits;    /* newsgroup matches restriction? */
  171.  
  172.             if (toread[ng] >= TR_NONE) {    /* recalc toread? */
  173.             set_ngname(rcline[ng]);
  174.             if (shoe_fits = (special || inlist(ngname)))
  175.                 set_toread(ng);
  176.             if (paranoid) {
  177.                 recent_ng = current_ng;
  178.                 current_ng = ng;
  179.                 cleanup_rc();
  180.                     /* this may move newsgroups around */
  181.                 ng = current_ng;
  182.                 set_ngname(rcline[ng]);
  183.             }
  184.             }
  185.             if (toread[ng] < (maxngtodo||special ? TR_NONE : TR_ONE) || !shoe_fits) {
  186.                     /* unwanted newsgroup? */
  187.             ng++;        /* then skip it */
  188.             continue;
  189.             }
  190.     reprompt_newsgroup:
  191.             dfltcmd = "ynq";
  192. #ifdef VERBOSE
  193.             IF(verbose)
  194.             sprintf(promptbuf,
  195.                 "\n******** %3ld unread article%c in %s--read now? [%s] ",
  196.                 (long)toread[ng], (toread[ng]==TR_ONE ? ' ' : 's'),
  197.                 ngname, dfltcmd);    /* format prompt string */
  198.             ELSE
  199. #endif
  200. #ifdef TERSE
  201.             sprintf(promptbuf,
  202.                 "\n**** %3ld in %s--read? [%s] ",
  203.                 (long)toread[ng],
  204.                 ngname,dfltcmd);    /* format prompt string */
  205. #endif
  206.         }
  207.         special = FALSE;    /* go back to normal mode */
  208.         if (ng != current_ng) {
  209.             recent_ng = current_ng;
  210.                     /* remember previous newsgroup */
  211.             current_ng = ng;    /* remember current newsgroup */
  212.         }
  213.     reask_newsgroup:
  214.         unflush_output();    /* disable any ^O in effect */
  215.         fputs(promptbuf,stdout) FLUSH;/* print prompt */
  216.         fflush(stdout);
  217.     reinp_newsgroup:
  218.         eat_typeahead();
  219.         getcmd(buf);
  220.         if (errno || *buf == '\f') {
  221.             putchar('\n') FLUSH; /* if return from stop signal */
  222.             goto reask_newsgroup;    /* give them a prompt again */
  223.         }
  224.         setdef(buf,dfltcmd);
  225. #ifdef VERIFY
  226.         printcmd();
  227. #endif
  228.         switch (*buf) {
  229.         case 'p':        /* find previous unread newsgroup */
  230.             do {
  231.             if (ng <= 0)
  232.                 break;
  233.             ng--;
  234.             if (toread[ng] == TR_NONE)
  235.                 set_toread(ng);
  236.             } while (toread[ng] <= TR_NONE);
  237.             break;
  238.         case 'P':        /* goto previous newsgroup */
  239.             do {
  240.             if (ng <= 0)
  241.                 break;
  242.             ng--;
  243.             } while (toread[ng] < TR_NONE);
  244.             special = TRUE;    /* don't skip it if toread==0 */
  245.             break;
  246.         case '-':
  247.             ng = recent_ng;    /* recall previous newsgroup */
  248.             special = TRUE;    /* don't skip it if toread==0 */
  249.             break;
  250.         case 'q': case 'Q': case 'x':    /* quit? */
  251.             oh_for_the_good_old_days = (*buf == 'x');
  252.             putchar('\n') FLUSH;
  253.             ng = nextrcline+1;    /* satisfy */
  254.             retry = FALSE;    /*   loop conditions */
  255.             break;
  256.         case '^':
  257.             putchar('\n') FLUSH;
  258.             ng = 0;
  259.             break;
  260.         case 'n': case '+':    /* find next unread newsgroup */
  261.             if (ng == nextrcline) {
  262.             putchar('\n') FLUSH;
  263.             retry = TRUE;
  264.             }
  265.             else if (toread[ng] > TR_NONE)
  266.             retry = TRUE;
  267.             ng++;
  268.             break;
  269.         case 'N':        /* goto next newsgroup */
  270.             ng++;
  271.             special = TRUE;    /* and don't skip it if toread==0 */
  272.             break;
  273.         case '1':        /* goto 1st newsgroup */
  274.             ng = 0;
  275.             special = TRUE;    /* and don't skip it if toread==0 */
  276.             break;
  277.         case '$':
  278.             ng = nextrcline;    /* goto last newsgroup */
  279.             retry = TRUE;
  280.             break;
  281.         case 'L':
  282.             list_newsgroups();
  283.             goto reask_newsgroup;
  284.         case '/': case '?':    /* scan for newsgroup pattern */
  285. #ifdef NGSEARCH
  286.             switch (ng_search(buf,TRUE)) {
  287.             case NGS_ABORT:
  288.             goto reinp_newsgroup;
  289.             case NGS_INTR:
  290. #ifdef VERBOSE
  291.             IF(verbose)
  292.                 fputs("\n(Interrupted)\n",stdout) FLUSH;
  293.             ELSE
  294. #endif
  295. #ifdef TERSE
  296.                 fputs("\n(Intr)\n",stdout) FLUSH;
  297. #endif
  298.             ng = current_ng;
  299.             goto reask_newsgroup;
  300.             case NGS_FOUND:
  301.             special = TRUE;    /* don't skip it if toread==0 */
  302.             break;
  303.             case NGS_NOTFOUND:
  304. #ifdef VERBOSE
  305.             IF(verbose)
  306.                 fputs("\n\nNot found--use g to add newsgroups\n",
  307.                 stdout) FLUSH;
  308.             ELSE
  309. #endif
  310. #ifdef TERSE
  311.                 fputs("\n\nNot found\n",stdout) FLUSH;
  312. #endif
  313.             goto reask_newsgroup;
  314.             }
  315. #else
  316.             notincl("/");
  317. #endif
  318.             break;
  319.         case 'm':
  320. #ifndef RELOCATE
  321.             notincl("m");
  322.             break;
  323. #endif            
  324.         case 'g':    /* goto named newsgroup */
  325.             if (!finish_command(FALSE))
  326.                     /* if they didn't finish command */
  327.             goto reinp_newsgroup;    /* go try something else */
  328.             for (s = buf+1; *s == ' '; s++);
  329.                     /* skip leading spaces */
  330.             if (!*s)
  331.             strcpy(s,ngname);
  332. #ifdef RELOCATE
  333.             if (!get_ng(s,*buf=='m'))    /* try to find newsgroup */
  334. #else
  335.             if (!get_ng(s,FALSE))    /* try to find newsgroup */
  336. #endif
  337.             ng = current_ng;/* if not found, go nowhere */
  338.             special = TRUE;    /* don't skip it if toread==0 */
  339.             break;
  340. #ifdef DEBUGGING
  341.         case 'D':
  342.             printf("\nTries: %d Hits: %d\n",
  343.             softtries,softtries-softmisses) FLUSH;
  344.             goto reask_newsgroup;
  345. #endif
  346.         case '!':        /* shell escape */
  347.             if (escapade())     /* do command */
  348.             goto reinp_newsgroup;
  349.                     /* if rubbed out, re input */
  350.             goto reask_newsgroup;
  351.         case Ctl('k'):        /* edit global KILL file */
  352.             edit_kfile();
  353.             goto reask_newsgroup;
  354.         case 'c':        /* catch up */
  355. #ifdef CATCHUP
  356. reask_catchup:
  357. #ifdef VERBOSE
  358.         IF(verbose)
  359.             in_char("\nDo you really want to mark everything as read? [yn] ", 'C');
  360.         ELSE
  361. #endif
  362. #ifdef TERSE
  363.             in_char("\nReally? [ynh] ", 'C');
  364. #endif
  365.             putchar('\n') FLUSH;
  366.             setdef(buf,"y");
  367.             if (*buf == 'h') {
  368. #ifdef VERBOSE
  369.             printf("Type y or SP to mark all articles as read.\n");
  370.             printf("Type n to leave articles marked as they are.\n");
  371. #else
  372.             printf("y or SP to mark all read.\n");
  373.             printf("n to forget it.\n");
  374. #endif
  375.             goto reask_catchup;
  376.             }
  377.             else if (*buf!=' ' && *buf!='y' && *buf!='n' && *buf!='q') {
  378.             printf(hforhelp);
  379.             settle_down();
  380.             goto reask_catchup;
  381.             } else if ( (*buf == ' ' || *buf == 'y') && ng<nextrcline )
  382.             catch_up(ng);
  383.             else
  384.             retry = TRUE;
  385.             ng++;
  386. #else
  387.             notincl("c");
  388. #endif
  389.             break;
  390.         case 'u':        /* unsubscribe */
  391.             if (ng < nextrcline && toread[ng] >= TR_NONE) {
  392.                     /* unsubscribable? */
  393.             printf(unsubto,rcline[ng]) FLUSH;
  394.             rcchar[ng] = NEGCHAR;
  395.                     /* unsubscribe to (from?) it */
  396.             toread[ng] = TR_UNSUB;
  397.                     /* and make line invisible */
  398.             ng++;        /* do an automatic 'n' */
  399.             }
  400.             break;
  401.         case 'h': {        /* help */
  402.             int cmd;
  403.  
  404.             if ((cmd = help_ng()) > 0)
  405.             pushchar(cmd);
  406.             goto reask_newsgroup;
  407.         }
  408.         case 'a':
  409. #ifndef FINDNEWNG
  410.             notincl("a");
  411.             goto reask_newsgroup;
  412. #else
  413.             /* FALL THROUGH */
  414. #endif
  415.         case 'o':
  416. #ifdef ONLY
  417.         {
  418. #ifdef FINDNEWNG
  419.             bool doscan = (*buf == 'a');
  420. #endif
  421.  
  422.             if (!finish_command(TRUE)) /* get rest of command */
  423.             goto reinp_newsgroup;    /* if rubbed out, try something else */
  424.             end_only();
  425.             if (buf[1]) {
  426.             bool minusd = instr(buf+1,"-d") != Nullch;
  427.  
  428.             sw_list(buf+1);
  429.             if (minusd)
  430.                 cwd_check();
  431.             putchar('\n') FLUSH;
  432. #ifdef FINDNEWNG
  433.             if (doscan && maxngtodo)
  434.                 scanactive();
  435. #endif
  436.             }
  437.             ng = 0;        /* simulate ^ */
  438.             retry = FALSE;
  439.             break;
  440.         }
  441. #else
  442.             notincl("o");
  443.             goto reask_newsgroup;
  444. #endif
  445.         case '&':
  446.             if (switcheroo()) /* get rest of command */
  447.             goto reinp_newsgroup;    /* if rubbed out, try something else */
  448.             goto reask_newsgroup;
  449.         case 'l': {        /* list other newsgroups */
  450.             if (!finish_command(TRUE)) /* get rest of command */
  451.             goto reinp_newsgroup;    /* if rubbed out, try something else */
  452.             for (s = buf+1; *s == ' '; s++);
  453.                         /* skip leading spaces */
  454.             sprintf(cmd_buf,"%s '%s'",filexp(NEWSGROUPS),s);
  455.             resetty();
  456.             if (doshell(sh,cmd_buf))
  457. #ifdef VERBOSE
  458.             IF(verbose)
  459.                 fputs("    (Error from newsgroups program)\n",
  460.                 stdout) FLUSH;
  461.             ELSE
  462. #endif
  463. #ifdef TERSE
  464.                 fputs("(Error)\n",stdout) FLUSH;
  465. #endif
  466.             noecho();
  467.             crmode();
  468.             goto reask_newsgroup;
  469.         }
  470.         case '.': case '=':
  471.         case 'y': case 'Y': /* do normal thing */
  472.             if (ng >= nextrcline) {
  473.             fputs("\nNot on a newsgroup.",stdout) FLUSH;
  474.             goto reask_newsgroup;
  475.             }
  476.             if (*buf == '=')
  477.             s = savestr("=");
  478.             else if (*buf == '.') {    /* start command? */
  479.             if (!finish_command(FALSE)) /* get rest of command */
  480.                 goto reinp_newsgroup;
  481.             s = savestr(buf+1);
  482.                     /* do_newsgroup will free it */
  483.             }
  484.             else
  485.             s = Nullch;
  486.             if (toread[ng])
  487.             retry = TRUE;
  488.             switch (do_newsgroup(s)) {
  489.             case NG_ERROR:
  490.             case NG_NORM:
  491.             ng++;
  492.             break;
  493.             case NG_ASK:
  494.             goto reprompt_newsgroup;
  495.             case NG_MINUS:
  496.             ng = recent_ng;    /* recall previous newsgroup */
  497.             special = TRUE;    /* don't skip it if toread==0 */
  498.             break;
  499.             }
  500.             break;
  501. #ifdef STRICTCR
  502.         case '\n':
  503.             fputs(badcr,stdout) FLUSH;
  504.             goto reask_newsgroup;
  505. #endif
  506.         case 'v':
  507.             printf("\n%s",rnid);
  508.             printf("\n%s",patchlevel);
  509.             printf("\nSend bugs to rrn@lib.tmc.edu\n") FLUSH;
  510.             goto reask_newsgroup;
  511.         default:
  512.             printf("\n%s",hforhelp) FLUSH;
  513.             settle_down();
  514.             goto reask_newsgroup;
  515.         }
  516.         }
  517.     } while (retry);
  518.     }
  519.  
  520.     /* now write .newsrc back out */
  521.  
  522.     write_rc();
  523.  
  524.     if (oh_for_the_good_old_days)
  525.     get_old_rc();
  526.  
  527.     finalize(0);            /* and exit */
  528. }
  529.  
  530. /* set current newsgroup */
  531.  
  532. void
  533. set_ngname(what)
  534. char *what;
  535. {
  536.     int len = strlen(what)+1;
  537.  
  538.     growstr(&ngname,&ngnlen,len);
  539.     strcpy(ngname,what);
  540.     growstr(&ngdir,&ngdlen,len);
  541.     strcpy(ngdir,getngdir(ngname));
  542. }
  543.  
  544. static char *myngdir;
  545. static int ngdirlen = 0;
  546.  
  547. char *
  548. getngdir(ngnam)
  549. char *ngnam;
  550. {
  551.     register char *s;
  552.  
  553.     growstr(&myngdir,&ngdirlen,strlen(ngnam)+1);
  554.     strcpy(myngdir,ngnam);
  555.     for (s = myngdir; *s; s++)
  556.     if (*s == '.')
  557.         *s = '/';
  558. #ifdef OSK
  559.     else if (*s == '-')
  560.         *s = '_';
  561. #endif
  562.     return myngdir;
  563. }
  564.  
  565.