home *** CD-ROM | disk | FTP | other *** search
/ ftp.uv.es / 2014.11.ftp.uv.es.tar / ftp.uv.es / pub / mvs / NNMVS.DISTRIB.CNTL < prev    next >
Text File  |  1993-08-16  |  996KB  |  29,953 lines

  1. //JOBNAME JOB ACCOUNT,'NAME'
  2. //*------------------------------------------------------------------*/
  3. //*                                                                  */
  4. //* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1993    */
  5. //*                                                                  */
  6. //* This software is provided on an "AS IS" basis. All warranties,   */
  7. //* including the implied warranties of merchantability and fitness, */
  8. //* are expressly denied.                                            */
  9. //*                                                                  */
  10. //* Provided this copyright notice is included, this software may    */
  11. //* be freely distributed and not offered for sale.                  */
  12. //*                                                                  */
  13. //* Changes or modifications may be made and used only by the maker  */
  14. //* of same, and not further distributed. Such modifications should  */
  15. //* be mailed to the author for consideration for addition to the    */
  16. //* software and incorporation in subsequent releases.               */
  17. //*                                                                  */
  18. //*------------------------------------------------------------------*/
  19. //*
  20. //*    NNMVS - MVS NNTP News Reader
  21. //*
  22. //*  Version: 3  Release: 2
  23. //*
  24. //* Author: Steve Bacher <seb@draper.com>
  25. //*
  26. //* Date: 13 Aug 1993
  27. //*
  28. //*-------------------------------------------------------------------
  29. //*
  30. //* This job creates the distribution libraries (PDS's).
  31. //*
  32. //* Run this JCL to create the PDS's, after customizing to suit.
  33. //* (Obviously, put in a good JOB statement first.)
  34. //* To customize the JCL, change the defaults on the //MDLOAD PROC
  35. //* statement to your liking, particularly the PREFIX default.
  36. //* You might also want to change the final qualifiers of the PDS's
  37. //* created - to do this, find the // EXEC MDLOAD statements and
  38. //* change the value of the TO parameter.
  39. //*
  40. //* See the $$README file (of the CNTL PDS, first in this stream)
  41. //* for the rest of the installation instructions.
  42. //*
  43. //MDLOAD PROC CLS='*',BS='6160',U='3380',V='',
  44. //      TRK1='60',TRK2='10',DIR='35',RLSE='RLSE',
  45. //      PREFIX='NNMVS.INSTALL.'
  46. //*
  47. //IEBUPDTE EXEC PGM=IEBUPDTE,PARM=NEW
  48. //SYSPRINT DD SYSOUT=&CLS
  49. //SYSUT2 DD DISP=(NEW,CATLG,DELETE),DSN=&PREFIX.&TO,
  50. //  DCB=(RECFM=FB,LRECL=80,BLKSIZE=&BS),
  51. //  SPACE=(TRK,(&TRK1,&TRK2,&DIR),&RLSE),UNIT=&U,VOL=SER=&V
  52. //*
  53. //  PEND
  54. //*
  55. //CNTL     EXEC MDLOAD,BS='6160',TRK1='10',TRK2='1',TO='CNTL'
  56. //SYSIN    DD   DATA,DLM='?!'
  57. ./ ADD NAME=$$README
  58.  
  59. ------------------------------------------------------------------------
  60.  
  61.  Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992, 1993
  62.  
  63.  SAS enhancements copyright (c) 1992 SAS Institute, Inc.
  64.  
  65.  This software is provided on an "AS IS" basis.  All warranties,
  66.  including the implied warranties of merchantability and fitness,
  67.  are expressly denied.
  68.  
  69.  Provided this copyright notice is included, this software may
  70.  be freely distributed and not offered for sale.
  71.  
  72.  Changes or modifications may be made and used only by the maker
  73.  of same, and not further distributed.  Such modifications should
  74.  be mailed to the author for consideration for addition to the
  75.  software and incorporation in subsequent releases.
  76.  
  77. ------------------------------------------------------------------------
  78.  
  79.  MVS NNTP News Reader - Version 3 Release 2
  80.  
  81.  Author:          Steve Bacher <seb1525@mvs.draper.com>
  82.  Enhancements by: Dale Ingold  <snoddi@mvs.sas.com>
  83.  
  84. ------------------------------------------------------------------------
  85.  
  86.  New Features and Changes in member $CHANGES of the distribution.
  87.  
  88. ------------------------------------------------------------------------
  89.  
  90.  Contents of PDS's belonging to NNMVS distribution:
  91.  
  92.  Member     PDS Type    Description
  93.  
  94.  $$README   CNTL        This file
  95.  $CHANGES   CNTL        New features and changes
  96.  $MISC      CNTL        Miscellaneous gotchas and installation notes
  97.  ALLOAD     CNTL        JCL to allocate NNMVS load and object libraries
  98.  AUTH       CNTL        Sample server authorization file
  99.  COMPILE    CNTL        JCL to compile *** SOURCE DISTRIBUTION ONLY ***
  100.  GRAMMAR    CNTL        Description of NNMVS batch expression syntax
  101.  HELP       CNTL        Description of NNMVS batch language
  102.  LINK       CNTL        JCL to linkedit the load module
  103.  NNMVS      CNTL        JCL to run NNMVS in batch
  104.  NNMVSHLP   CNTL        TSO HELP for the NNMVSP version of the exec
  105.  NNMFIUCV   CLIST       Exec to check for multiple socket applications
  106.  NNMVS      CLIST       Exec by which users invoke the news reader
  107.  NNMVSC     CLIST       CLIST by which users invoke the news reader
  108.  NNMVSL     CLIST       CLIST to run multiple-news-server ISPF dialog
  109.  NNMVSP     CLIST       Exec using XPROC to parse CLIST-style parms
  110.  NNMMAIL    CLIST       Exec called by news reader to send mail
  111.  NNM...     PANEL       ISPF regular panels
  112.  TNNM...    PANEL       ISPF tutorial panels
  113.  NNM..      H           C headers      *** SOURCE DISTRIBUTION ONLY ***
  114.  NNM..      C           C source       *** SOURCE DISTRIBUTION ONLY ***
  115.  NN...      OBJ         Object modules *** OBJECT DISTRIBUTION ONLY ***
  116.  
  117. --------------------------------------------------------------------
  118.  
  119.  Directions:
  120.  
  121.  Assuming the PDS's have been created:
  122.  
  123.  1. Customize the ALLOAD and COMPILE JCL members to reflect your
  124.  local conventions.  Note:  If you intend to place the executable into
  125.  an existing library, you can suppress that part of the ALLOAD JCL.
  126.  The name of the data set created must match across both members.
  127.  
  128.  2. Customize the NNUSER header file as shown by the comments therein.
  129.  Note in particular the defines for your TCP/IP and your C compiler.
  130.  There are changes to the linkedit JCL that are related to these.
  131.  
  132.  3. Choose which exec you want to use:
  133.  
  134.     NNMVS - the traditional REXX exec, not much parameter passing
  135.     NNMVSP - REXX exec that uses XPROC to parse CLIST-style parms
  136.     NNMVSC - CLIST that accepts CLIST-style parameters
  137.  
  138.  If you don't have XPROC (the utility that allows a REXX exec to parse
  139.  CLIST-style parameters), you can get it from ftp.mic.ucla.edu in the
  140.  directory /pub/mvs/utils, part of the TSOREXX distribution.  I highly
  141.  recommend that you get the TSOREXX distribution, which contains both
  142.  XPROC and XWRITENR, if you do a lot of conversion from CLIST to REXX.
  143.  
  144.  If you really can't or won't get XPROC, you can use the CLIST, but
  145.  keep in mind that there are some things the CLIST just can't do that
  146.  the REXX exec can.  Refer to the comments therein for more details.
  147.  
  148.  Customize whichever of the above you pick to define the names of the
  149.  MVS libraries to contain the panel and load library members.  The load
  150.  library must be the one specified in the ALLOAD JCL, if you are
  151.  creating it anew.  Observe the comments relating to the use of LIBDEF
  152.  and ISPF APPLIDs.
  153.  
  154.  Note that if you install one of the REXX execs, you must also install
  155.  the NNMFIUCV exec in the same library.  This exec implements a crude
  156.  check for an existing TCP/IP socket application (e.g. another NNMVS)
  157.  in a different PIE MultiTSO session.  It prevents your users from
  158.  crashing TCP/IP, so it is highly recommended that you make use of it.
  159.  
  160.  4. Customize the NNMMAIL exec to invoke your local mailer, or
  161.  otherwise insure that messages sent via MAIL or REPLY arrive at their
  162.  intended destination.
  163.  
  164.  5. If you are running ISPF Version 2 or earlier, edit the NNMVS panels
  165.  whose names begin "NNMP...".  These are popups, and will not work
  166.  under ISPF Version 2 unless you change the )BODY line.  Remove the
  167.  WINDOW(...) parameter from the )BODY line of each panel so that the
  168.  line just says )BODY or )BODY EXPAND(``), as the case may be.
  169.  
  170.  Note:  You may wish to customize the TNNMSERV tutorial panel to
  171.  include the names of all available NNTP servers at your site.
  172.  
  173.  Now, to install:
  174.  
  175.  6. Submit the ALLOAD JCL to allocate the load library from which the
  176.  executable program will be run, as well as the object library in which
  177.  the compiled object modules will be stored.
  178.  
  179.  7. Submit the COMPILE JCL to compile all the C sources and create the
  180.  required object modules in the object library built in the above step.
  181.  
  182.  8. Submit the LINK JCL to create the executable NNMVS load module
  183.  from the object modules created in the above step.  This will create
  184.  or replace the load module NNMMAIN.
  185.  
  186.  Note:  The linkedit must complete with a return code of zero.  If not,
  187.  don't use the resultant load module.  Check the libraries you specified
  188.  on the link step to see what went wrong.
  189.  
  190.  In the future, if you have to recompile individual modules, you can use
  191.  the same JCL to compile only those modules, and the link will include
  192.  the new modules in the existing executable load module.  To do this,
  193.  you must retain the object library built above.
  194.  
  195.  *********************************************************************
  196.  
  197.  IMPORTANT:  If you are running TCP/IP V2R2 or higher on MVS, you must
  198.  change the following library names in the compile and link JCL:
  199.  
  200.    TCPIP.COMMMAC   should be changed to  TCPIP.SEZACMAC
  201.    TCPIP.COMMTXT   should be changed to  TCPIP.SEZACMTX
  202.  
  203.  *********************************************************************
  204.  
  205.  Note:  If you have defined C370V1 in the NNUSER header file, you must
  206.  also include the system linklist load library or libraries containing
  207.  ISPLINK, ISPEXEC and IKJEFF18 when linking.  Otherwise you may delete
  208.  the lines from the linkedit JCL that reference them.
  209.  
  210.  Note:  You need not include the PASCAL libraries or the AMPZMVSB
  211.  module if you are using TCP/IP Version 2 or higher, in which case
  212.  you must also define TCPIPV2 in the NNUSER headerfile.
  213.  
  214.  9. Copy the HELP member of the CNTL library into the data set which
  215.  will be allocated to ddname NNBATHLP by the NNMVS batch mode JCL
  216.  procedure.  This data set contains the text printed by the batch HELP
  217.  command.  The distributed proc calls this 'NNMVS.HELP' - change it to
  218.  match the name of your data set (sequential, or member of a PDS).
  219.  
  220.  10. Copy the NNMVS (or NNMVSC or NNMVSP) and NNMMAIL execs into your
  221.  installation CLIST or REXX library.  Also copy the NNMVSL exec if
  222.  you want access to Leonard Woren's experimental multiple-server dialog.
  223.  
  224.  11. If you use the NNMVSP version of the exec, copy the NNMVSHLP
  225.  member of the CNTL PDS into your installation TSO HELP library
  226.  under the same name as you gave the exec, so folks can type HELP xxx
  227.  where xxx is the name of the exec.  If you have local help that you
  228.  want to include (like names of local servers, posting guidelines,
  229.  or whatever), create a HELP member called NNMVSLOC and install it
  230.  in the same library.
  231.  
  232.  12. Copy all the members of the panel PDS into the ISPF panel library
  233.  specified in the NNMVS exec.
  234.  
  235. --------------------------------------------------------------------
  236.  
  237.  Note:  Make sure that the C/370 run time library is available,
  238.  either in the system link list or in the ISPLLIB concatenation,
  239.  before attempting to run NNMVS.
  240.  
  241.  If the C/370 runtime library is not in the link list or otherwise
  242.  available to ISPF at execution time, you may arrange for it to be
  243.  allocated via LIBDEF in the NNMVS exec (I haven't tried this).
  244.  
  245. --------------------------------------------------------------------
  246.  
  247.  Questions?  Comments?  Suggestions?  Gripes?  Requests?  Musings?
  248.  
  249.  You can communicate all of these via the LISTSERV mailing list
  250.  NNMVS-L, maintained at VM.USC.EDU.  To get on this list, send mail to
  251.  LISTSERV@USCVM (or LISTSERV@VM.USC.EDU) with the following line in
  252.  the message body:
  253.  
  254.    SUBSCRIBE NNMVS-L firstname lastname
  255.  
  256.  Please keep in mind that further requests (e.g. to unsubscribe from
  257.  the list) must be sent to the LISTSERV address, *not* to the list.
  258.  The response you'll get from the SUBSCRIBE message will tell you
  259.  about this and more - so be sure to save it.
  260.  
  261. --------------------------------------------------------------------
  262.  
  263.  Please email all other correspondence to...
  264.  
  265.  Steve Bacher      <seb@draper.com>
  266.  
  267. ./ ADD NAME=$CHANGES
  268.  
  269.  New Features in V3 R2
  270.  
  271.   New commands:
  272.  
  273.    ROT13 (while viewing an article) toggles "rot13" encoding on and off.
  274.  
  275.    RESCAN (from newsgroup or article display) updates the status of
  276.           all newsgroups by refetching the server's active file
  277.  
  278.   New selection codes:
  279.  
  280.    $ on a newsgroup fetches unread articles and sorts them by subject
  281.  
  282.    @ on a newsgroup fetches all articles and sorts them by subject
  283.  
  284.   Miscellaneous improvements:
  285.  
  286.    more accurate locked "getting more articles" displays
  287.  
  288.    fixed bug going to next article and following the subject thread
  289.  
  290.  New Features in V3
  291.  
  292.   Newsgroup article management is radically different, which should
  293.   result in improvements in response time and memory usage, as well
  294.   as avoiding out-of-memory abends.
  295.  
  296.   A new pseudo-browse interface replaces the BRIF code, enabling
  297.   more commands while browsing a news article.
  298.  
  299.   The PRT command is implemented, similar to EXTRACT except that it
  300.   prints to the SYSOUT class of your choice.
  301.  
  302.   You have the option of letting the cursor remain next to the most
  303.   recently selected newsgroup or article.
  304.  
  305.   New commands to simplify debugging have been added.
  306.  
  307.   Additional installation-time customization for different levels
  308.   of ISPF.
  309.  
  310.   Miscellaneous bug fixes and feature tweaks.
  311.  
  312.  Latest Fixes to V2 R4
  313.  
  314.  NNMCLRNG.C: - Fix memory leak when exiting from NNMVS.
  315.  
  316.  NNMDLANG.C: - Fix 0C4 in "new newsgroups" function when the server
  317.                has duplicate entries in the active.times file.
  318.  
  319.              - Check for bad output from news server's active file
  320.                in the NNTP LIST command, adjust counts and display a
  321.                nasty message so the user can nag the administrator.
  322.  
  323.  NNMBPEXT.C: - Fix bug whereby all article headers were being
  324.                retrieved even when EXTRACT UNREAD was requested
  325.                in a batch job, causing excessive resource usage
  326.                and memory blowouts.
  327.  
  328.  New Features In V2 R4
  329.  
  330.  * Memory usage has been improved significantly.
  331.  
  332.  * Handling of missing/expired articles has been improved.
  333.  
  334.  * Miscellaneous Bug Fixes
  335.  
  336.  * Enhancements to NNMVSP Exec
  337.  
  338.  New Features In V2 R3 M2
  339.  
  340.  * New commands:
  341.  
  342.  - SORT Subject / Number - in article viewing mode, you may use this
  343.    command to sort the article display by subject or return it to the
  344.    default article-number order.  Note that this may require a lot of
  345.    processing, both to retrieve article titles and to perform the
  346.    sorting, which tries to match messages up with "re:" replies.
  347.    When the LOCATE command is issued from an article display in this
  348.    mode, it takes a character string rather than a number.
  349.  
  350.  - QUIT - from almost any panel, terminates NNMVS immediately.
  351.    It works like repeated END's, which means that it will save
  352.    your NEWSRC file.  (QUIT from display-new-newsgroups or
  353.    display-bogus-newsgroups skips updating NEWSRC, though, for
  354.    your protection.)
  355.  
  356.  * Miscellaneous changes:
  357.  
  358.    The MARKALL and UNMARKALL commands now prompt you as to whether
  359.    you want to mark all the articles in the newsgroup or just the
  360.    ones currently shown in the table.
  361.  
  362.  * The extra blank line that used to appear at the bottom of articles
  363.    is gone.  There may be some effects on article extraction,
  364.    particularly when append mode is used, but in general this means
  365.    that what you get is more like what is really out there.
  366.  
  367.  * In POST and MAIL, the format of the inserted message and the
  368.    dashed line separating the signature from the body have been
  369.    changed to be more in accordance with standard practice.
  370.  
  371.  * Even more tweaking of missing article handling.  It's better
  372.    than it was, and may even be considered acceptable now.
  373.  
  374.  * Removed Features
  375.  
  376.    Apologies:  The PATH variable in batch has been removed.
  377.    It was of dubious value (I'm sure you don't miss it).
  378.    Basically, we needed the slot to implement subject sorting.
  379.  
  380.  New Features In V2 R3 M1
  381.  
  382.  * A user option to turn automatic scrolling on or off in the
  383.    newsgroup and article display tables has been added.
  384.  
  385.  * In POST and MAIL, headers are no longer inserted into the text of
  386.    your reply.  Instead, a message of the form
  387.     "In article <messageid> on <date>, <author> writes:"
  388.    is inserted.
  389.  
  390.  * Remaining bugs and pitfalls of missing articles are finally
  391.    cleared up (hopefully).
  392.  
  393.  * The ONLY and FIND commands in article display mode will cause
  394.    fetching of article headers if you are in "A" (all articles) mode.
  395.  
  396.  * An OPTION operand has been added to the NNMVS exec, and support has
  397.    been added to NNMVS so that you will go directly to the requested
  398.    option if you use this and provide a number of other values.
  399.  
  400.  * An attempt to protect users from crashing TCP/IP with multiple
  401.    copies of socket applications is included.
  402.  
  403.  New Features In V2 R3
  404.  
  405.  * New Commands for Controlling Newsgroup and Article Displays
  406.  
  407.    Note: In the following descriptions of operands, "strings" are
  408.    unquoted single words or strings quoted with either single or double
  409.    quotes.  Case is ignored.
  410.  
  411.    The following new commands are available on the newsgroup display:
  412.  
  413.      ORDER {Alphabetic/List} - specify the order in which the groups are
  414.      listed.  The initial setting is A (alphabetic).  You may change to
  415.      L (list) to view the newsgroups in the same order as the NNTP
  416.      server's active file (what the NNTP "LIST" command returns).
  417.  
  418.      ONLY "string" - limit the newsgroup display to newsgroups with
  419.      "string" in the name.  Type ONLY with no operands to restore
  420.      the display to all newsgroups (or registered, depending).
  421.  
  422.      FIND "string" {NEXT/PREV/FIRST/LAST} - position the newsgroup
  423.      display to the next, previous, first or last group which has
  424.      "string" in the name.  FIND with no operands repeats the find.
  425.  
  426.    The following new commands are available on the article display:
  427.  
  428.      ONLY "string" - limit the article display to articles with
  429.      "string" in the subject.  Type ONLY with no operands to restore
  430.      the display to all articles (read or unread, depending).
  431.  
  432.      FIND "string" {NEXT/PREV/FIRST/LAST} - position the article
  433.      display to the next, previous, first or last article which has
  434.      "string" in the subject.  FIND with no operands repeats the find.
  435.  
  436.  * New Options for Navigating Article Views
  437.  
  438.    The following new commands are available from article browse:
  439.  
  440.      NEXTU or NU - like NEXT but goes to the next unread article.
  441.  
  442.      NEXTT or NT - like NEXT but goes to the next article currently in
  443.                    the table.  When you use ONLY to filter the article
  444.                    display, NEXTT honors the filter.  NEXT doesn't.
  445.  
  446.      NEXTS or NS - like NEXT but goes to the next article in the current
  447.                    subject thread.
  448.  
  449.      PREVU(PU), PREVT(PT), PREVS(PS) are analogous to the above.
  450.  
  451.      FIRSTSUBJ or FS - goes to the first article in the current
  452.                        subject thread.
  453.      LASTSUBJ or LS  - goes to the last article in the current
  454.                        subject thread.
  455.      NEWSUBJ or NS   - goes to the first unread article of a subject
  456.                        other than the current thread.
  457.      SUBJECT or SUBJ - displays or changes the current subject.
  458.  
  459.  * Prompting to Protect Existing Data Sets on EXTRACT
  460.  
  461.    When you use the EXTRACT command, if the data set already exists
  462.    you will get a pop-up asking you to confirm that you want to
  463.    reuse the data set.  Simply press ENTER to do so.
  464.  
  465.  * Changes To Commands
  466.  
  467.    The NNTP command may now be specified like this:
  468.  
  469.      NNTP   - by itself, puts you in the NNTP panel, as before
  470.      NNTP nntp-command   - executes NNTP command immediately
  471.  
  472.      For example:  NNTP GROUP COMP.LANG.LISP
  473.                    NNTP HELP
  474.  
  475.    The OPTIONS command has been changed to take you to a menu of
  476.    general options.  The RFC822 header settings are now option 1.
  477.    You can type OPT 1 to go directly there if you don't want to
  478.    see the extra panel.  Also, in BROWSE, you can type HEADERS
  479.    (or HEADER) instead of OPTION to go directly to the RFC822
  480.    header setting panel.
  481.  
  482.    In addition to RFC822 header display options, you may now specify
  483.    how you want screen displays to tell you about operations in process.
  484.    (There are some fancy new ways that NNMVS can do this.)
  485.    You can also control the prompting for overwriting on EXTRACT.
  486.  
  487.  * Changes to Selection Codes
  488.  
  489.    When you select "A" to see all the articles in a newsgroup,
  490.    NNMVS will fill in the title lines.  No more empty lines.
  491.    To save processing, it will get only those that are necessary
  492.    to fill your screen.  Scrolling down (or up) will get the next
  493.    batch - this will appear to be slower.
  494.  
  495.    Also, only those articles that have actually been fetched (not
  496.    just the headers) will be retained in the table when you switch
  497.    back to using "S" to look at the articles in the newsgroup.
  498.  
  499.    Note that whether you select "A" or "S" will affect subject
  500.    searches.  If you selected "S", subject searches will be limited
  501.    to unread or already-retrieved articles.  If you selected "A",
  502.    subject searches will retrieve previously read articles, and
  503.    potentially take longer.
  504.  
  505.    You can select "N" to view only new (unseen) articles.  "N" is
  506.    like "S" except that articles are removed from the display once
  507.    they are read whenever you reenter the article display or change
  508.    the viewing criteria.
  509.  
  510.    The "Z" option, which will remain undocumented for now, is similar
  511.    to the "A" option except that it retrieves NO articles headers,
  512.    read or unread.  Good for quick entry into a huge newsgroup, but
  513.    not very good at recording the correct status of the articles.
  514.  
  515.    You can select "C" to cancel an article by posting a control request
  516.    to the server.  You must be the original author (poster) of the
  517.    article to be allowed to cancel it.  Cancellation is implemented
  518.    by sending a control message to the NNTP server.
  519.  
  520.  * POST, FOLLOWUP and REPLY now allow you to specify a Reply-to email
  521.    address and a signature file.  In addition, you may specify a
  522.    Followup-to list of newsgroups on POST or FOLLOWUP.
  523.  
  524.  * FOLLOWUP and REPLY now follow the RFC1036 rules for generating
  525.    the default lists of newsgroups to post to and mail address to
  526.    reply to.  FOLLOWUP even checks if the Followup-to: header says
  527.    "poster" or contains an email address, and strongly suggests
  528.    that you email instead of posting.  Since BITNET postings dont
  529.    conform to RFC standards, the actual From: address is displayed
  530.    for REPLY in case you need to type it in.
  531.  
  532.  * New Batch mode variable CHECKPOINT allows you to control whether the
  533.    NEWSRC file gets rewritten on every change or just at the end of a
  534.    batch run.  Good for preventing NEWSRC wipeouts on 322 abends.
  535.  
  536.  * Support for Multiple NNMVS's in a Single TSO Session
  537.    (assuming that they're talking to two different servers and
  538.    that you have the required TCP/IP multitasking socket support
  539.    APAR from IBM).
  540.  
  541.    Basically, it dynamically generates a ddname for the newsrc file,
  542.    and you can specify different newsrc files, so there you go.
  543.  
  544.    Warning:  PIE users - DO NOT run 2 NNMVS's from different PIE
  545.    sessions - the IBM TCP/IP fix doesn't work for this!  Use ISPF
  546.    split screen to do it.
  547.  
  548.  * Optional Driver CLIST and REXX exec using XPROC to specify
  549.    parameters in CLIST-style Syntax
  550.  
  551.    See installation instructions for details.
  552.  
  553. ./ ADD NAME=$MISC
  554.  
  555. Miscellaneous Notes and Gotchas
  556.  
  557. ========================================================================
  558.  
  559.  * C/370 Kanji Feature
  560.  
  561.  If your C/370 was not installed properly (e.g. you assumed that CBIPO
  562.  would take care of everything - you wretched fool!), it is possible
  563.  that you have the wrong national language for messages.  This will
  564.  become apparent as soon as you fail to open a file, since the C/370
  565.  perror() function will write gibberish to stderr.  To fix this, bug
  566.  your MVS systems programmer to reinstall C/370, e.g. with JDL1214
  567.  and without JCLB212 (for V2R1).  It may be more complicated than that.
  568.  
  569. ========================================================================
  570.  
  571.  * C/370 Attention Handling
  572.  
  573. C/370 doesn't handle PA1 (attention) interrupts properly - in fact,
  574. it completely screws them up, so you end up in an unbreakable loop
  575. when you try to break out of a C/370 application running under ISPF
  576. that uses the TCP/IP socket library.
  577.  
  578. As a temporary circumvention, you should apply a zap to module IBMBLIIA
  579. in your run-time load library.  The zap for C/370 V2R1, for example,
  580. looks like this:
  581.  
  582.    NAME IBMBLIIA IBMBLII1
  583.    VER 2250 0A60
  584.    REP 2250 1BFF
  585.  
  586.   I.E., find the SVC 96 (STAX) instruction and NOP it.
  587.  
  588.   Go ahead and apply it (preferably to a copy of IBMBLIIA in a user
  589.   library from which you run your favorite C/370 application, like
  590.   NNMVS, for example).  Now you can feel free to do anything you like,
  591.   because you can always attention out.
  592.  
  593.   If you find that you need this zap, please make sure that IBM hears
  594.   from you about the problem.   The more customers they hear from, the
  595.   more likely it is that something will be done to fix it.
  596.  
  597.   Be aware that this turns off attention handling entirely - but this
  598.   has turned out to be the only desirable behavior.  Note that SIGINT
  599.   handling has never worked in C/370.  If you don't believe this, then
  600.   just compile and run the sample program in member SIGFAIL.
  601.  
  602. ./ ADD NAME=ALLOAD
  603. //JOBNAME  JOB ACCOUNT,'NAME'
  604. //*                                                                  */
  605. //* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  606. //*                                                                  */
  607. //* This software is provided on an "AS IS" basis.  All warranties,  */
  608. //* including the implied warranties of merchantability and fitness, */
  609. //* are expressly denied.                                            */
  610. //*                                                                  */
  611. //* Provided this copyright notice is included, this software may    */
  612. //* be freely distributed and not offered for sale.                  */
  613. //*                                                                  */
  614. //* Changes or modifications may be made and used only by the maker  */
  615. //* of same, and not further distributed.  Such modifications should */
  616. //* be mailed to the author for consideration for addition to the    */
  617. //* software and incorporation in subsequent releases.               */
  618. //*                                                                  */
  619. //* Allocate NNMVS load and object libraries before install
  620. //*
  621. //NNALLOC PROC U='3380',V=''
  622. //*
  623. //IEFBR14  EXEC PGM=IEFBR14
  624. //ALLOCDD  DD   DISP=(NEW,CATLG,DELETE),DSN=&LIB,
  625. //         DCB=(RECFM=&RF,LRECL=&LR,BLKSIZE=&BS),
  626. //         SPACE=(&BS,(&PRI,&SEC,&DIR)),UNIT=&U,VOL=SER=&V
  627. //*
  628. //         PEND
  629. //*
  630. //* The ALLOCL step allocates the load library from which the
  631. //* executable program will be run.  If you intend to place the
  632. //* executable into an existing library, you can skip this step.
  633. //* Otherwise, the name must match the name used on the LOADLIB
  634. //* parameter of the NNLINK procedure in the COMPILE JCL.
  635. //*
  636. //* The ALLOCO step allocates the object library into which the
  637. //* source modules will be compiled.  This library is required
  638. //* for the compile and link steps, but is not required for run
  639. //* time execution.  However, you may wish to keep the object
  640. //* library around in case there are fixes for which you will be
  641. //* recompiling individual NNMVS source modules.
  642. //*
  643. //ALLOCL   EXEC NNALLOC,PRI=50,SEC=50,DIR=35,RF=U,LR=,BS=6233,
  644. //         LIB='NNMVS.LOAD'
  645. //ALLOCO   EXEC NNALLOC,PRI=500,SEC=100,DIR=70,RF=FB,LR=80,BS=2960,
  646. //         LIB='NNMVS.INSTALL.OBJ'
  647. //*
  648. ./ ADD NAME=AUTH
  649. #
  650. # This file is used by NNTP clients (NNMVS) on this system to connect
  651. # to news servers that require authentication, according to the new
  652. # NNTO authorization protocol.  It is ignored if the news server does
  653. # not support this protocol.  If the news server supports it, the user
  654. # must be defined in the server host's /etc/passwd file and its uid
  655. # must be the same as the uid of the user "nntp" - otherwise the server
  656. # will disconnect the client.
  657. #
  658. # A server given here without a user or password will be accepted
  659. # by NNMVS without an attempt to gain the server's authorization.
  660. #
  661. # serverhost  user  password
  662. #
  663.   AUTHHOST    NNTP  JOSHUA
  664.   NOAUTHHOST
  665. ./ ADD NAME=COMPILE
  666. //JOBNAME  JOB ACCOUNT,'NAME'
  667. //*                                                                  */
  668. //* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  669. //*                                                                  */
  670. //* This software is provided on an "AS IS" basis.  All warranties,  */
  671. //* including the implied warranties of merchantability and fitness, */
  672. //* are expressly denied.                                            */
  673. //*                                                                  */
  674. //* Provided this copyright notice is included, this software may    */
  675. //* be freely distributed and not offered for sale.                  */
  676. //*                                                                  */
  677. //* Changes or modifications may be made and used only by the maker  */
  678. //* of same, and not further distributed.  Such modifications should */
  679. //* be mailed to the author for consideration for addition to the    */
  680. //* software and incorporation in subsequent releases.               */
  681. //*                                                                  */
  682. //*********************************************************************
  683. //*
  684. //* Compile some or all NNMVS C/370 sources to make the SYSLIN input
  685. //* to the linkedit of the executable NNMMAIN load module.
  686. //*
  687. //NNCCL  PROC MEMBER=,
  688. //            SRCLIB='NNMVS.INSTALL.C',          NNMVS C source PDS
  689. //            HDRLIB='NNMVS.INSTALL.H',          NNMVS C headers PDS
  690. //            OBJLIB='NNMVS.INSTALL.OBJ',        NNMVS C headers PDS
  691. //            COMMHDR='TCPIP.COMMMAC',           C/370 TCP/IP headers
  692. //            C370HDR='SYS1.EDCHDRS',            C/370 standard headers
  693. //            SYSMSGS='SYS1.EDCMSGS',            C/370 messages file
  694. //            SYSMSGM='EDCMSGE',                 C/370 message member
  695. //            VIOUNIT=VIO,                       Temporary disk unit
  696. //            OUTCLAS='*',                          SYSOUT class
  697. //            CPARMS='SOURCE EXPMAC NOAGGR NOXREF', Compile parameters
  698. //            TEST=TEST                             TEST or NOTEST
  699. //*
  700. //CCOMP     EXEC PGM=EDCCOMP,PARM='MARGINS(1,72) &TEST &CPARMS'
  701. //SYSMSGS   DD DISP=SHR,DSN=&SYSMSGS(&SYSMSGM)
  702. //SYSIN     DD DISP=SHR,DSN=&SRCLIB(&MEMBER)
  703. //SYSLIN    DD DISP=OLD,DSN=&OBJLIB(&MEMBER)
  704. //SYSLIB    DD DISP=SHR,DSN=&COMMHDR
  705. //          DD DISP=SHR,DSN=&C370HDR
  706. //USERLIB   DD DISP=SHR,DSN=&HDRLIB
  707. //SYSPRINT  DD SYSOUT=&OUTCLAS
  708. //SYSCPRT   DD SYSOUT=&OUTCLAS
  709. //SYSUT1    DD DSN=&&SYSUT1,UNIT=&VIOUNIT,DISP=(NEW,DELETE),
  710. //   SPACE=(32000,(30,30)),DCB=(RECFM=FB,LRECL=80,BLKSIZE=3200)
  711. //SYSUT4    DD DSN=&&SYSUT4,UNIT=&VIOUNIT,DISP=(NEW,DELETE),
  712. //   SPACE=(32000,(30,30)),DCB=(RECFM=FB,LRECL=80,BLKSIZE=3200)
  713. //SYSUT6    DD DSN=&&SYSUT6,UNIT=&VIOUNIT,DISP=(NEW,DELETE),
  714. //   SPACE=(32000,(30,30)),DCB=(RECFM=FB,LRECL=3200,BLKSIZE=12800)
  715. //SYSUT7    DD DSN=&&SYSUT7,UNIT=&VIOUNIT,DISP=(NEW,DELETE),
  716. //   SPACE=(32000,(30,30)),DCB=(RECFM=FB,LRECL=3200,BLKSIZE=12800)
  717. //SYSUT8    DD DSN=&&SYSUT8,UNIT=&VIOUNIT,DISP=(NEW,DELETE),
  718. //   SPACE=(32000,(30,30)),DCB=(RECFM=FB,LRECL=3200,BLKSIZE=12800)
  719. //SYSUT9    DD DSN=&&SYSUT9,UNIT=&VIOUNIT,DISP=(NEW,DELETE),
  720. //   SPACE=(32000,(30,30)),DCB=(RECFM=VB,LRECL=137,BLKSIZE=882)
  721. //SYSUT10   DD SYSOUT=&OUTCLAS
  722. //*
  723. //         PEND
  724. //*
  725. //NNMADDNG EXEC NNCCL,MEMBER=NNMADDNG
  726. //NNMADJUA EXEC NNCCL,MEMBER=NNMADJUA
  727. //NNMALLAV EXEC NNCCL,MEMBER=NNMALLAV
  728. //NNMALLOC EXEC NNCCL,MEMBER=NNMALLOC
  729. //NNMAUTH  EXEC NNCCL,MEMBER=NNMAUTH
  730. //NNMBATCH EXEC NNCCL,MEMBER=NNMBATCH
  731. //NNMBBEXP EXEC NNCCL,MEMBER=NNMBBEXP
  732. //NNMBCONN EXEC NNCCL,MEMBER=NNMBCONN
  733. //NNMBDECL EXEC NNCCL,MEMBER=NNMBDECL
  734. //NNMBFLUS EXEC NNCCL,MEMBER=NNMBFLUS
  735. //NNMBGCMD EXEC NNCCL,MEMBER=NNMBGCMD
  736. //NNMBGDO  EXEC NNCCL,MEMBER=NNMBGDO
  737. //NNMBGEXP EXEC NNCCL,MEMBER=NNMBGEXP
  738. //NNMBGTOK EXEC NNCCL,MEMBER=NNMBGTOK
  739. //NNMBPDEC EXEC NNCCL,MEMBER=NNMBPDEC
  740. //NNMBPDER EXEC NNCCL,MEMBER=NNMBPDER
  741. //NNMBPELS EXEC NNCCL,MEMBER=NNMBPELS
  742. //NNMBPEXE EXEC NNCCL,MEMBER=NNMBPEXE
  743. //NNMBPEXT EXEC NNCCL,MEMBER=NNMBPEXT
  744. //NNMBPFOR EXEC NNCCL,MEMBER=NNMBPFOR
  745. //NNMBPHEL EXEC NNCCL,MEMBER=NNMBPHEL
  746. //NNMBPIF  EXEC NNCCL,MEMBER=NNMBPIF
  747. //NNMBPLIS EXEC NNCCL,MEMBER=NNMBPLIS
  748. //NNMBPMAR EXEC NNCCL,MEMBER=NNMBPMAR
  749. //NNMBPNNT EXEC NNCCL,MEMBER=NNMBPNNT
  750. //NNMBPPUT EXEC NNCCL,MEMBER=NNMBPPUT
  751. //NNMBPQUE EXEC NNCCL,MEMBER=NNMBPQUE
  752. //NNMBPQUI EXEC NNCCL,MEMBER=NNMBPQUI
  753. //NNMBPREG EXEC NNCCL,MEMBER=NNMBPREG
  754. //NNMBPSET EXEC NNCCL,MEMBER=NNMBPSET
  755. //NNMBPVAR EXEC NNCCL,MEMBER=NNMBPVAR
  756. //NNMBSOUT EXEC NNCCL,MEMBER=NNMBSOUT
  757. //NNMBSYNT EXEC NNCCL,MEMBER=NNMBSYNT
  758. //NNMBTEXT EXEC NNCCL,MEMBER=NNMBTEXT
  759. //NNMBTRAS EXEC NNCCL,MEMBER=NNMBTRAS
  760. //NNMBVGET EXEC NNCCL,MEMBER=NNMBVGET
  761. //NNMBVPUT EXEC NNCCL,MEMBER=NNMBVPUT
  762. //NNMBXFAR EXEC NNCCL,MEMBER=NNMBXFAR
  763. //NNMBXFNG EXEC NNCCL,MEMBER=NNMBXFNG
  764. //NNMCAR   EXEC NNCCL,MEMBER=NNMCAR
  765. //NNMCLRNG EXEC NNCCL,MEMBER=NNMCLRNG
  766. //NNMCLRTX EXEC NNCCL,MEMBER=NNMCLRTX
  767. //NNMCNRF  EXEC NNCCL,MEMBER=NNMCNRF
  768. //NNMCONN  EXEC NNCCL,MEMBER=NNMCONN
  769. //NNMCOPY  EXEC NNCCL,MEMBER=NNMCOPY
  770. //NNMDCAN  EXEC NNCCL,MEMBER=NNMDCAN
  771. //NNMDFAIL EXEC NNCCL,MEMBER=NNMDFAIL
  772. //NNMDISC  EXEC NNCCL,MEMBER=NNMDISC
  773. //NNMDISPL EXEC NNCCL,MEMBER=NNMDISPL
  774. //NNMDLANG EXEC NNCCL,MEMBER=NNMDLANG
  775. //NNMDMAIL EXEC NNCCL,MEMBER=NNMDMAIL
  776. //NNMDMENU EXEC NNCCL,MEMBER=NNMDMENU
  777. //NNMDNG   EXEC NNCCL,MEMBER=NNMDNG
  778. //NNMDNNTP EXEC NNCCL,MEMBER=NNMDNNTP
  779. //NNMDOIT  EXEC NNCCL,MEMBER=NNMDOIT
  780. //NNMDPOST EXEC NNCCL,MEMBER=NNMDPOST
  781. //NNMDSOPT EXEC NNCCL,MEMBER=NNMDSOPT
  782. //NNMDUMP  EXEC NNCCL,MEMBER=NNMDUMP
  783. //NNMESRVR EXEC NNCCL,MEMBER=NNMESRVR
  784. //NNMESTNG EXEC NNCCL,MEMBER=NNMESTNG
  785. //NNMFREEM EXEC NNCCL,MEMBER=NNMFREEM
  786. //NNMGETDS EXEC NNCCL,MEMBER=NNMGETDS
  787. //NNMGETM  EXEC NNCCL,MEMBER=NNMGETM
  788. //NNMGSRVL EXEC NNCCL,MEMBER=NNMGSRVL
  789. //NNMIERR  EXEC NNCCL,MEMBER=NNMIERR
  790. //NNMIGET  EXEC NNCCL,MEMBER=NNMIGET
  791. //NNMINIT  EXEC NNCCL,MEMBER=NNMINIT
  792. //NNMISPF  EXEC NNCCL,MEMBER=NNMISPF
  793. //NNMIVGET EXEC NNCCL,MEMBER=NNMIVGET
  794. //NNMIVPUT EXEC NNCCL,MEMBER=NNMIVPUT
  795. //NNMMAIN  EXEC NNCCL,MEMBER=NNMMAIN
  796. //NNMMARR  EXEC NNCCL,MEMBER=NNMMARR
  797. //NNMMARU  EXEC NNCCL,MEMBER=NNMMARU
  798. //NNMNNTP  EXEC NNCCL,MEMBER=NNMNNTP
  799. //NNMONRF  EXEC NNCCL,MEMBER=NNMONRF
  800. //NNMOUTTX EXEC NNCCL,MEMBER=NNMOUTTX
  801. //NNMPICK  EXEC NNCCL,MEMBER=NNMPICK
  802. //NNMPMSG  EXEC NNCCL,MEMBER=NNMPMSG
  803. //NNMPNG   EXEC NNCCL,MEMBER=NNMPNG
  804. //NNMQAR   EXEC NNCCL,MEMBER=NNMQAR
  805. //NNMQNG   EXEC NNCCL,MEMBER=NNMQNG
  806. //NNMRARH  EXEC NNCCL,MEMBER=NNMRARH
  807. //NNMRART  EXEC NNCCL,MEMBER=NNMRART
  808. //NNMRBFM  EXEC NNCCL,MEMBER=NNMRBFM
  809. //NNMRECON EXEC NNCCL,MEMBER=NNMRECON
  810. //NNMRPERR EXEC NNCCL,MEMBER=NNMRPERR
  811. //NNMSAVE  EXEC NNCCL,MEMBER=NNMSAVE
  812. //NNMSOCKT EXEC NNCCL,MEMBER=NNMSOCKT
  813. //NNMSOPT  EXEC NNCCL,MEMBER=NNMSOPT
  814. //NNMSORT  EXEC NNCCL,MEMBER=NNMSORT
  815. //NNMSSRVR EXEC NNCCL,MEMBER=NNMSSRVR
  816. //NNMSTRLC EXEC NNCCL,MEMBER=NNMSTRLC
  817. //NNMSUMAT EXEC NNCCL,MEMBER=NNMSUMAT
  818. //NNMTSO   EXEC NNCCL,MEMBER=NNMTSO
  819. //NNMUNALC EXEC NNCCL,MEMBER=NNMUNALC
  820. //NNMUPDT  EXEC NNCCL,MEMBER=NNMUPDT
  821. //NNMVAR   EXEC NNCCL,MEMBER=NNMVAR
  822. //NNMVIEW  EXEC NNCCL,MEMBER=NNMVIEW
  823. //NNMVNG   EXEC NNCCL,MEMBER=NNMVNG
  824. //NNMVTX   EXEC NNCCL,MEMBER=NNMVTX
  825. //NNMXARTT EXEC NNCCL,MEMBER=NNMXARTT
  826. //NNMXARTX EXEC NNCCL,MEMBER=NNMXARTX
  827. //NNMXLIST EXEC NNCCL,MEMBER=NNMXLIST
  828. //NNMXTX   EXEC NNCCL,MEMBER=NNMXTX
  829. //*
  830. ./ ADD NAME=GRAMMAR
  831.  
  832.         Grammar for NNMVS batch mode expressions.
  833.  
  834. /*-------------------------------------------------------------------*/
  835.  
  836. exp         :       choice
  837.             :       "IF" exp "THEN" exp "ELSE" exp
  838.                                        /* IF flag THEN any ELSE any */
  839.  
  840. choice      :       relation
  841.             :       choice logop relation   /* flag | flag -> flag  */
  842.  
  843. relation    :       value
  844.             :       value relop value       /* any > any   -> flag  */
  845.  
  846. value       :       quantity
  847.             :       quantity quantity       /* any any    -> string */
  848.  
  849. quantity    :       term
  850.             :       quantity addop term     /* num + num  -> number */
  851.  
  852. term        :       factor
  853.             :       term mulop factor       /* num * num -> number  */
  854.  
  855. factor      :       constant
  856.             :       variable                /* FOO, if declared     */
  857.             :       unop factor             /* - number  -> number  */
  858.             :       "(" exp ")"             /* (a + b * c > d | e ) */
  859.  
  860. constant    :       number
  861.             :       string
  862.             :       flag
  863.  
  864. unop        :       "+"
  865.             :       "-"
  866.             :       "!"
  867.             :       "^"
  868.  
  869. addop       :       "+"
  870.             :       "-"
  871.  
  872. mulop       :       "*"
  873.             :       "/"
  874.  
  875. logop       :       "&"
  876.             :       "|"
  877.  
  878.  
  879. relop       :       "="
  880.             :       ">"
  881.             :       "<"
  882.             :       "=="
  883.             :       ">="
  884.             :       "<="
  885.             :       "!="
  886.             :       "!>"
  887.             :       "!<"
  888.             :       "^="
  889.             :       "^>"
  890.             :       "^<"
  891.             :       "IN"
  892.  
  893. variable    :       [a-z]*
  894.  
  895. number      :       [0-9]*
  896.  
  897. string      :       ""...""
  898.  
  899. flag        :       "TRUE"
  900.             :       "FALSE"
  901.             :       "ON"
  902.             :       "OFF"
  903.             :       "YES"
  904.             :       "NO"
  905. ./ ADD NAME=HELP
  906.                     NNMVS Batch Mode Help
  907.  
  908.  The following commands are available:
  909.  
  910.  Top-Level Commands (in top-level mode, picking newsgroups)
  911.  
  912.    FOR ALL | REGISTERED | UNREGISTERED {WHEN filter} commandlist;
  913.  
  914.       where filter is any flag expression, evaluated per newsgroup,
  915.       and commandlist is a single command or DO; commands; END;
  916.       and the commands are per-newsgroup commands.
  917.  
  918.  Per-Newsgroup Commands (in newsgroup mode, picking articles)
  919.  
  920.    REGISTER
  921.    DEREGISTER
  922.    EXTRACT ALL | READ | UNREAD
  923.    QUERY
  924.    FOR ALL | READ | UNREAD | num {TO num} {WHEN filter} commandlist
  925.  
  926.       where filter is any flag expression, evaluated per article,
  927.       and commandlist is a single command or DO; commands; END
  928.       and the commands are per-article commands.
  929.  
  930.  Per-Article Commands (in article mode)
  931.  
  932.    MARK {READ | UNREAD}
  933.    LIST
  934.    EXTRACT
  935.    QUERY
  936.  
  937.  Miscellaneous Commands
  938.  
  939.    IF condition THEN commandlist; {ELSE commandlist;}
  940.  
  941.       where condition is any flag expression,
  942.       and commandlist is a single command or DO; commands; END;
  943.       and the commands are of the same mode as the one in which
  944.       the IF occurs.
  945.  
  946.    PUT stringexpression               # writes to output file
  947.    EXEC stringexpression              # executes system command
  948.    NNTP stringexpression              # transmits NNTP request
  949.    QUIT                               # terminates NNMVS
  950.    VARS                               # dumps current variables
  951.  
  952.    {SET} variable { = } expression
  953.  
  954.      Variable must be builtin or declared (see DECLARE below)
  955.  
  956.    DECLARE variable {STRING | NUMBER | FLAG}
  957.  
  958.      Note:  DECLARE is the only command which is executed immediately.
  959.             All other commands are parsed and then the entire command
  960.             stream is executed only if no errors were detected.
  961.  
  962.  Built-in Variables
  963.  
  964.  LOCALPATH (string)  - the hosts's local path name
  965.  DATETIME  (string)  - a time stamp
  966.  SERVER    (string)  - the name of the NNTP server host.  Must be set
  967.                        by the user before attempting a connection.
  968.  OUTFILE   (string)  - the name of an alternate output file for the
  969.                        PUT commands and any commands (like NNTP) that
  970.                        write text.  The default setting, "", uses the
  971.                        NNBATOUT DD.  The value may be a data set name
  972.                        (appended to) or in the form DD:ddname.
  973.  SERVERLIST (flag)   - default is TRUE.  Normally NNMVS will ask for
  974.                        the current list of newsgroups from the NNTP
  975.                        server when it begins processing newsgroups.
  976.                        If you want to suppress this and just use the
  977.                        groups named in NEWSRC, set SERVERLIST to FALSE.
  978.                        Note that this may not save time, and in fact
  979.                        may result in more processing, since NNMVS will
  980.                        issue a GROUP request to each group requested
  981.                        when it has not issued a LIST request.
  982.  AUTOREGISTER (flag) - default is FALSE.  If this is set to TRUE,
  983.                        new newsgroups will automatically be registered
  984.                        in the NEWSRC file; otherwise they will be added
  985.                        as unregistered newsgroups.
  986.  AUTODELETE   (flag) - default is TRUE.  If this is set to TRUE,
  987.                        bogus newsgroups (groups in the NEWSRC file that
  988.                        are not known to the server) will be deleted
  989.                        from the NEWSRC file.  Set this to FALSE to keep
  990.                        such newsgroups in NEWSRC anyway.
  991.  ERROR        (flag) - set to TRUE whenever an NNMVS batch command
  992.                        operation fails.  This is reset by each NNMVS
  993.                        batch command, so grab it early.
  994.  EXACTCASE    (flag) - default is FALSE.  When this is FALSE, string
  995.                        comparisons and tests succeed regardless of upper
  996.                        or lower case.  When this is set to TRUE, string
  997.                        comparisons and tests succeed only if the strings
  998.                        match exactly.  Thus, "a" = "A" when EXACTCASE is
  999.                        FALSE, but not when EXACTCASE is TRUE.
  1000.  
  1001.  Variables meaningful to the EXTRACT command:
  1002.  
  1003.  TABEXPAND    (flag) - default is TRUE.  Controls whether tab characters
  1004.                        are to be expanded on EXTRACT.  (Note that tabs
  1005.                        are always expanded on PUT and LIST.)
  1006.  APPEND       (flag) - default is TRUE.  Controls how articles are to be
  1007.                        extracted to sequential files by EXTRACT.
  1008.                        If APPEND is set to FALSE, existing sequential
  1009.                        files will be overwritten.  This option is not
  1010.                        applicable to partitioned data sets (PDS's).
  1011.  SEPARATOR  (string) - default is the null string.  If this is set to
  1012.                        a value other than the null string, the value
  1013.                        will be written between articles as a separator
  1014.                        line.  Meaningful only when APPEND is TRUE.
  1015.  BLANKSEP     (flag) - default is FALSE.  If TRUE, a blank line will be
  1016.                        generated before the separator line when it us
  1017.                        written out between articles.  Otherwise the
  1018.                        separator line, if used, will follow the end of
  1019.                        the preceding article immediately.  Meaningful
  1020.                        only when SEPARATOR and APPEND are set.
  1021.  AUTOMARK     (flag) - default is TRUE.  When this is TRUE, the EXTRACT
  1022.                        operation will mark unread articles READ upon
  1023.                        successful extraction.  It has no effect on
  1024.                        read articles or articles that failed extraction.
  1025.                        Set it to FALSE to prevent EXTRACT from marking
  1026.                        extracted articles read.
  1027.  
  1028.  Variables meaningful in per-newsgroup mode and modes below:
  1029.  
  1030.  GROUP      (string) - the name of the current newsgroop.
  1031.  REGISTERED (flag)   - TRUE if newsgroup is registered.
  1032.  NEWGROUP   (flag)   - TRUE if newsgroup is a new group (found by the
  1033.                        server LIST request but not in NEWSRC).
  1034.  NOSUCHGROUP (flag)  - TRUE if the newsgroup is "bogus" (in NEWSRC but
  1035.                        not found by the server LIST request).
  1036.  COUNT      (number) - the total number of articles in the newsgroup.
  1037.  UNREAD     (number) - the total number of new (unread) articles in the
  1038.                        newsgroup since the last time NNMVS used this
  1039.                        NEWSRC file.
  1040.  FIRST      (number) - the number of the first article in the group.
  1041.  LAST       (number) - the number of the last article in the group.
  1042.  
  1043.  Variables meaningful in per-article mode and modes below:
  1044.  
  1045.  NUMBER     (number) - the current article number.
  1046.  READ       (flag)   - TRUE if article has already been read.
  1047.  MISSING    (flag)   - TRUE if article cannot be retrieved from server.
  1048.  SUBJECT    (string) - text of the Subject: header.
  1049.  DATE       (string) - text of the Date: header, with day name removed.
  1050.  FROM       (string) - text of From: header, author of the article.
  1051.  MESSAGEID  (string) - text of the Message-ID: header.
  1052.  
  1053.  Expression Syntax
  1054.  
  1055.  Expressions can be string expressions, number expressions, or
  1056.  flag expressions.  They can contain constants, variables, and
  1057.  arithmetic or logical expressions.  Strings may be concatenated
  1058.  by placing one next to another, e. g. "foo" "bar".
  1059.  
  1060.  String constants are enclosed in double quotes, with the backslash
  1061.  acting as an escape with which to enclose embedded double quotes.
  1062.  
  1063.  Numeric constants are integers only.
  1064.  
  1065.  Flag constants may be represented as TRUE FALSE ON OFF YES NO.
  1066.  
  1067.  Arithmetic operators:  + - * / as well as unary + and -
  1068.  Logical    operators:  & |     as well as unary !
  1069.  Relational operators:  = != > < >= <= !> !<
  1070.  (Note: == is an alias for =, and ^ may be used wherever ! is.)
  1071.  
  1072.  For strings, the additional relational operator IN is available, e.g.
  1073.  
  1074.    "foo" IN SUBJECT
  1075.  
  1076.  The notation (IF expression THEN expression ELSE expression) is
  1077.  allowed within expressions.
  1078.  
  1079.  The following synonyms are accepted:
  1080.  
  1081.    AND OR NOT EQ NE GT LT GE LE NG NL
  1082.  
  1083.  The character # marks the beginning of a comment.
  1084.  
  1085. Extracting Files
  1086.  
  1087.  EXTRACT writes the contents of one or more news articles out to a file
  1088.  whose name is determined from a table allocated to DDname NNEXTTAB.
  1089.  
  1090.  The format of the extract table is one line per newsgroup as follows:
  1091.  
  1092.   groupname filename
  1093.  
  1094.  where filename is a FULLY QUALIFIED name (quotes ignored) of one of
  1095.  the following formats:
  1096.  
  1097.   sequential data set name
  1098.   wildcarded sequential data set name
  1099.   wildcarded partitioned data set name
  1100.  
  1101.  "Wildcarded" means that there is an asterisk "*" in a strategic
  1102.  position in the file name.  It must be preceded by at least one
  1103.  alphanumeric character and may not be followed by one.
  1104.  
  1105.  When the extraction is done, the asterisk is replaced with the number
  1106.  of the article, zero padded on the left to fill out that segment of
  1107.  the name.
  1108.  
  1109.  Examples:
  1110.  
  1111.   comp.group.one   MYID.COMP.GROUP.SEQ.FOO*
  1112.   comp.group.two   MYID.COMP.GROUP.SEQ.ALL
  1113.   comp.group.three MYID.COMP.GROUP.THREE.PDS(X*)
  1114.   comp.group.four  MYID.COMP.GROUP.NUMBER*.PDS(ANYMEM)
  1115.  
  1116.  So...
  1117.  
  1118.   comp.windows.x  SEB1525.COMP.WINDOWS.X.TEXT.#*
  1119.  
  1120.  defines a series of sequential data sets
  1121.  COMP.WINDOWS.X.TEXT.#0000001
  1122.  COMP.WINDOWS.X.TEXT.#0000002
  1123.  
  1124.  etc.
  1125.  
  1126.  PDS members can be expressed this way:
  1127.  
  1128.   comp.os.vms     COMP.OS.VMS.PDS(VMS*)
  1129.  
  1130.  which gives
  1131.  
  1132.   COMP.OS.VMS.PDS(VMS00001)
  1133.   COMP.OS.VMS.PDS(VMS00002)
  1134.  
  1135.  etc.  If the article number takes more digits, it steals some
  1136.  character positions away from the characters immediately preceding
  1137.  the asterisk.  For example, using the above model:
  1138.  
  1139.   COMP.OS.VMS.PDS(VM142857)
  1140.  
  1141.  The file need not already exist.  If it does not, NNMVS will attempt
  1142.  to guess the appropriate size when it allocates it, as the EXTRACT
  1143.  command does in foreground.
  1144.  
  1145. ./ ADD NAME=LINK
  1146. //JOBNAME  JOB ACCOUNT,'NAME'
  1147. //*                                                                  */
  1148. //* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1993    */
  1149. //*                                                                  */
  1150. //* This software is provided on an "AS IS" basis.  All warranties,  */
  1151. //* including the implied warranties of merchantability and fitness, */
  1152. //* are expressly denied.                                            */
  1153. //*                                                                  */
  1154. //* Provided this copyright notice is included, this software may    */
  1155. //* be freely distributed and not offered for sale.                  */
  1156. //*                                                                  */
  1157. //* Changes or modifications may be made and used only by the maker  */
  1158. //* of same, and not further distributed.  Such modifications should */
  1159. //* be mailed to the author for consideration for addition to the    */
  1160. //* software and incorporation in subsequent releases.               */
  1161. //*                                                                  */
  1162. //*********************************************************************
  1163. //*
  1164. //* Linkedit the executable NNMVS load module.
  1165. //*
  1166. //NNLINK PROC LOADLIB='NNMVS.LOAD',              Executable load library
  1167. //            OBJLIB='NNMVS.INSTALL.OBJ',        Input object PDS
  1168. //            PLIBASE='SYS1.PLIBASE',            PL/1   link library
  1169. //            EDCBASE='SYS1.SEDCBASE',           C/370  link library
  1170. //            IBMBASE='SYS1.SIBMBASE',           PL/1+C common library
  1171. //            COMMTXT='TCPIP.COMMTXT',           TCP/IP link library
  1172. //            VIOUNIT=VIO,                       Temporary disk unit
  1173. //            OUTCLAS='*',                          SYSOUT class
  1174. //            LPARMS='LIST,LET,MAP',                Linkedit parameters
  1175. //            TEST=NOTEST                           TEST or NOTEST
  1176. //*
  1177. //LKED      EXEC PGM=IEWL,PARM='AMODE(31),&TEST,&LPARMS'
  1178. //SYSPRINT  DD SYSOUT=&OUTCLAS
  1179. //SYSLIB    DD DISP=SHR,DSN=&PLIBASE
  1180. //          DD DISP=SHR,DSN=&EDCBASE
  1181. //          DD DISP=SHR,DSN=&IBMBASE
  1182. //          DD DISP=SHR,DSN=&COMMTXT
  1183. //SYSLMOD   DD DISP=SHR,DSN=&LOADLIB
  1184. //SYSUT1    DD DSN=&&SYSUT1,UNIT=&VIOUNIT,DISP=(NEW,DELETE),
  1185. //          SPACE=(32000,(30,30))
  1186. //*
  1187. //         PEND
  1188. //*
  1189. //*
  1190. //* Link NNMMAIN load module.
  1191. //*
  1192. //NNLINK EXEC NNLINK
  1193. //LKED.SYSLIN DD DISP=SHR,DSN=&OBJLIB(NNMADDNG)
  1194. //            DD DISP=SHR,DSN=&OBJLIB(NNMADJUA)
  1195. //            DD DISP=SHR,DSN=&OBJLIB(NNMALLAV)
  1196. //            DD DISP=SHR,DSN=&OBJLIB(NNMALLOC)
  1197. //            DD DISP=SHR,DSN=&OBJLIB(NNMAUTH)
  1198. //            DD DISP=SHR,DSN=&OBJLIB(NNMBATCH)
  1199. //            DD DISP=SHR,DSN=&OBJLIB(NNMBBEXP)
  1200. //            DD DISP=SHR,DSN=&OBJLIB(NNMBCONN)
  1201. //            DD DISP=SHR,DSN=&OBJLIB(NNMBDECL)
  1202. //            DD DISP=SHR,DSN=&OBJLIB(NNMBFLUS)
  1203. //            DD DISP=SHR,DSN=&OBJLIB(NNMBGCMD)
  1204. //            DD DISP=SHR,DSN=&OBJLIB(NNMBGDO)
  1205. //            DD DISP=SHR,DSN=&OBJLIB(NNMBGEXP)
  1206. //            DD DISP=SHR,DSN=&OBJLIB(NNMBGTOK)
  1207. //            DD DISP=SHR,DSN=&OBJLIB(NNMBPDEC)
  1208. //            DD DISP=SHR,DSN=&OBJLIB(NNMBPDER)
  1209. //            DD DISP=SHR,DSN=&OBJLIB(NNMBPELS)
  1210. //            DD DISP=SHR,DSN=&OBJLIB(NNMBPEXE)
  1211. //            DD DISP=SHR,DSN=&OBJLIB(NNMBPEXT)
  1212. //            DD DISP=SHR,DSN=&OBJLIB(NNMBPFOR)
  1213. //            DD DISP=SHR,DSN=&OBJLIB(NNMBPHEL)
  1214. //            DD DISP=SHR,DSN=&OBJLIB(NNMBPIF)
  1215. //            DD DISP=SHR,DSN=&OBJLIB(NNMBPLIS)
  1216. //            DD DISP=SHR,DSN=&OBJLIB(NNMBPMAR)
  1217. //            DD DISP=SHR,DSN=&OBJLIB(NNMBPNNT)
  1218. //            DD DISP=SHR,DSN=&OBJLIB(NNMBPPUT)
  1219. //            DD DISP=SHR,DSN=&OBJLIB(NNMBPQUE)
  1220. //            DD DISP=SHR,DSN=&OBJLIB(NNMBPQUI)
  1221. //            DD DISP=SHR,DSN=&OBJLIB(NNMBPREG)
  1222. //            DD DISP=SHR,DSN=&OBJLIB(NNMBPSET)
  1223. //            DD DISP=SHR,DSN=&OBJLIB(NNMBPVAR)
  1224. //            DD DISP=SHR,DSN=&OBJLIB(NNMBSOUT)
  1225. //            DD DISP=SHR,DSN=&OBJLIB(NNMBSYNT)
  1226. //            DD DISP=SHR,DSN=&OBJLIB(NNMBTEXT)
  1227. //            DD DISP=SHR,DSN=&OBJLIB(NNMBTRAS)
  1228. //            DD DISP=SHR,DSN=&OBJLIB(NNMBVGET)
  1229. //            DD DISP=SHR,DSN=&OBJLIB(NNMBVPUT)
  1230. //            DD DISP=SHR,DSN=&OBJLIB(NNMBXFAR)
  1231. //            DD DISP=SHR,DSN=&OBJLIB(NNMBXFNG)
  1232. //            DD DISP=SHR,DSN=&OBJLIB(NNMCAR)
  1233. //            DD DISP=SHR,DSN=&OBJLIB(NNMCLRNG)
  1234. //            DD DISP=SHR,DSN=&OBJLIB(NNMCLRTX)
  1235. //            DD DISP=SHR,DSN=&OBJLIB(NNMCNRF)
  1236. //            DD DISP=SHR,DSN=&OBJLIB(NNMCONN)
  1237. //            DD DISP=SHR,DSN=&OBJLIB(NNMCOPY)
  1238. //            DD DISP=SHR,DSN=&OBJLIB(NNMDCAN)
  1239. //            DD DISP=SHR,DSN=&OBJLIB(NNMDFAIL)
  1240. //            DD DISP=SHR,DSN=&OBJLIB(NNMDISC)
  1241. //            DD DISP=SHR,DSN=&OBJLIB(NNMDISPL)
  1242. //            DD DISP=SHR,DSN=&OBJLIB(NNMDLANG)
  1243. //            DD DISP=SHR,DSN=&OBJLIB(NNMDMAIL)
  1244. //            DD DISP=SHR,DSN=&OBJLIB(NNMDMENU)
  1245. //            DD DISP=SHR,DSN=&OBJLIB(NNMDNG)
  1246. //            DD DISP=SHR,DSN=&OBJLIB(NNMDNNTP)
  1247. //            DD DISP=SHR,DSN=&OBJLIB(NNMDOIT)
  1248. //            DD DISP=SHR,DSN=&OBJLIB(NNMDPOST)
  1249. //            DD DISP=SHR,DSN=&OBJLIB(NNMDSOPT)
  1250. //            DD DISP=SHR,DSN=&OBJLIB(NNMDUMP)
  1251. //            DD DISP=SHR,DSN=&OBJLIB(NNMESRVR)
  1252. //            DD DISP=SHR,DSN=&OBJLIB(NNMESTNG)
  1253. //            DD DISP=SHR,DSN=&OBJLIB(NNMFREEM)
  1254. //            DD DISP=SHR,DSN=&OBJLIB(NNMGETDS)
  1255. //            DD DISP=SHR,DSN=&OBJLIB(NNMGETM)
  1256. //            DD DISP=SHR,DSN=&OBJLIB(NNMGSRVL)
  1257. //            DD DISP=SHR,DSN=&OBJLIB(NNMIERR)
  1258. //            DD DISP=SHR,DSN=&OBJLIB(NNMIGET)
  1259. //            DD DISP=SHR,DSN=&OBJLIB(NNMINIT)
  1260. //            DD DISP=SHR,DSN=&OBJLIB(NNMISPF)
  1261. //            DD DISP=SHR,DSN=&OBJLIB(NNMIVGET)
  1262. //            DD DISP=SHR,DSN=&OBJLIB(NNMIVPUT)
  1263. //            DD DISP=SHR,DSN=&OBJLIB(NNMMAIN)
  1264. //            DD DISP=SHR,DSN=&OBJLIB(NNMMARR)
  1265. //            DD DISP=SHR,DSN=&OBJLIB(NNMMARU)
  1266. //            DD DISP=SHR,DSN=&OBJLIB(NNMNNTP)
  1267. //            DD DISP=SHR,DSN=&OBJLIB(NNMONRF)
  1268. //            DD DISP=SHR,DSN=&OBJLIB(NNMOUTTX)
  1269. //            DD DISP=SHR,DSN=&OBJLIB(NNMPICK)
  1270. //            DD DISP=SHR,DSN=&OBJLIB(NNMPMSG)
  1271. //            DD DISP=SHR,DSN=&OBJLIB(NNMPNG)
  1272. //            DD DISP=SHR,DSN=&OBJLIB(NNMQAR)
  1273. //            DD DISP=SHR,DSN=&OBJLIB(NNMQNG)
  1274. //            DD DISP=SHR,DSN=&OBJLIB(NNMRARH)
  1275. //            DD DISP=SHR,DSN=&OBJLIB(NNMRART)
  1276. //            DD DISP=SHR,DSN=&OBJLIB(NNMRBFM)
  1277. //            DD DISP=SHR,DSN=&OBJLIB(NNMRECON)
  1278. //            DD DISP=SHR,DSN=&OBJLIB(NNMRPERR)
  1279. //            DD DISP=SHR,DSN=&OBJLIB(NNMSAVE)
  1280. //            DD DISP=SHR,DSN=&OBJLIB(NNMSOCKT)
  1281. //            DD DISP=SHR,DSN=&OBJLIB(NNMSOPT)
  1282. //            DD DISP=SHR,DSN=&OBJLIB(NNMSORT)
  1283. //            DD DISP=SHR,DSN=&OBJLIB(NNMSSRVR)
  1284. //            DD DISP=SHR,DSN=&OBJLIB(NNMSTRLC)
  1285. //            DD DISP=SHR,DSN=&OBJLIB(NNMSUMAT)
  1286. //            DD DISP=SHR,DSN=&OBJLIB(NNMTSO)
  1287. //            DD DISP=SHR,DSN=&OBJLIB(NNMUNALC)
  1288. //            DD DISP=SHR,DSN=&OBJLIB(NNMUPDT)
  1289. //            DD DISP=SHR,DSN=&OBJLIB(NNMVAR)
  1290. //            DD DISP=SHR,DSN=&OBJLIB(NNMVIEW)
  1291. //            DD DISP=SHR,DSN=&OBJLIB(NNMVNG)
  1292. //            DD DISP=SHR,DSN=&OBJLIB(NNMVTX)
  1293. //            DD DISP=SHR,DSN=&OBJLIB(NNMXARTT)
  1294. //            DD DISP=SHR,DSN=&OBJLIB(NNMXARTX)
  1295. //            DD DISP=SHR,DSN=&OBJLIB(NNMXLIST)
  1296. //            DD DISP=SHR,DSN=&OBJLIB(NNMXTX)
  1297. //            DD *
  1298.  ENTRY   CEESTART
  1299.  NAME    NNMMAIN(R)
  1300. /*
  1301. ./ ADD NAME=NNMVS
  1302. //*                                                                  */
  1303. //* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  1304. //*                                                                  */
  1305. //* This software is provided on an "AS IS" basis.  All warranties,  */
  1306. //* including the implied warranties of merchantability and fitness, */
  1307. //* are expressly denied.                                            */
  1308. //*                                                                  */
  1309. //* Provided this copyright notice is included, this software may    */
  1310. //* be freely distributed and not offered for sale.                  */
  1311. //*                                                                  */
  1312. //* Changes or modifications may be made and used only by the maker  */
  1313. //* of same, and not further distributed.  Such modifications should */
  1314. //* be mailed to the author for consideration for addition to the    */
  1315. //* software and incorporation in subsequent releases.               */
  1316. //*                                                                  */
  1317. //NNMVS    PROC DEBUG=,                 say DEBUG=D for debugging
  1318. //             LOADLIB='NNMVS.LOAD',    must match LOADLIB in LINK job
  1319. //             HELP='NNMVS.HELP',              for batch HELP command
  1320. //             NEWSRC='USERID.BATCH.NEWSRC',   separate NEWSRC file
  1321. //             EXTTAB='USERID.NNMVS.EXTTAB'    table used by EXTRACT
  1322. //*
  1323. //* NNMVS batch mode.
  1324. //*
  1325. //NN       EXEC PGM=NNMMAIN,PARM='-B&DEBUG'
  1326. //STEPLIB  DD   DISP=SHR,DSN=&LOADLIB
  1327. //NNNEWSRC DD   DISP=OLD,DSN=&NEWSRC
  1328. //NNEXTTAB DD   DISP=SHR,DSN=&EXTTAB
  1329. //NNBATHLP DD   DISP=SHR,DSN=&HELP
  1330. //SYSPRINT DD   SYSOUT=*
  1331. //SYSERR   DD   SYSOUT=*
  1332. //NNBATOUT DD   SYSOUT=*,DCB=(RECFM=VB,LRECL=255)
  1333. //NNDEBUG  DD   SYSOUT=*
  1334. //NNBATIN  DD   DDNAME=SYSIN
  1335. //*
  1336. //         PEND NNMVS
  1337. ./ ADD NAME=NNMVSHLP
  1338. )F Function -
  1339.  
  1340.  NNMVS is a newsreader for reading and posting articles in USENET
  1341.  newsgroups.
  1342.  
  1343.  NNMVS is an NNTP (network news transfer protocol) client that accesses
  1344.  USENET news from a host machine elsewhere on your network that is
  1345.  running an NNTP news server, and displays the news via ISPF.  You must
  1346.  tell NNMVS where this news server is; it does not know otherwise.
  1347.  
  1348.  NNMVS remembers which articles you have read in a "newsrc" data set.
  1349.  You specify the name of this data set on the primary menu, along
  1350.  with the name of the news server host.  Note that both of these
  1351.  are given useful defaults when you start up NNMVS.
  1352.  
  1353.  If you have never used NNMVS before, you use the blank or L option to
  1354.  build up your NEWSRC file from a list retrieved from the server.
  1355.  Then, to limit the list to your favorite newsgroups, you can register
  1356.  (subscribe to) the ones you want while viewing the newsgroup list.
  1357.  
  1358.  You can use L or blank all the time to enter NNMVS.  However,
  1359.  once you have used and built a NEWSRC file, you may wish to use a
  1360.  different entry option to reduce startup time.
  1361.  You can avoid retrieving the whole list by using the R option
  1362.  to view only registered (subscribed) newsgroups, or the A option to
  1363.  view all newsgroups listed in your NEWSRC file.
  1364.  
  1365.  The disadvantage to using A or R is that you do not get the latest
  1366.  additions to the news system when the newsgroup list shows up.
  1367.  But there are ways to get around this.  For example, you can use the
  1368.  N option to get a list of newsgroups added since the last time you
  1369.  retrieved the newsgroup list (i.e. used L or N).
  1370.  
  1371.  If you want to go to a particular newsgroup directly, you can do so
  1372.  via the G option.  When you use this, you must provide the name of
  1373.  the desired newsgroup.
  1374.  
  1375. )I NNMVSLOC          - local NNMVS help goes in member NNMVSLOC
  1376.  
  1377. )X Syntax -
  1378.  
  1379.    %NNMVS
  1380.               SERVER('news server host')
  1381.               GROUP('newsgroup name')
  1382.               NEWSRC('data set name')
  1383.               OPTION(A/G/L/N/O/P/R/X)
  1384.               REGISTERSTATUS(Yes/No/Prompt)
  1385.               FORCE
  1386.               DEBUG
  1387.               TEST
  1388.               BATCH
  1389.               BATCHIN('batch input file name')
  1390.               BATCHOUT('batch output file name')
  1391.               NEW
  1392.               OLD
  1393.  
  1394.    Required:  none
  1395.  
  1396.    Defaults:  User is prompted (via ISPF panel) for all omitted values
  1397.  
  1398.    Notes:     If OPTION is given, then direct entry into the news
  1399.               reader occurs, without display of the NNMVS primary menu.
  1400.               However, if so, then SERVER and NEWSRC are required, and
  1401.               GROUP is also required if OPTION(G) is specified.
  1402.  
  1403.               If BATCH is given, then NEWSRC is required.
  1404.  
  1405. )O Operands -
  1406.  
  1407. ))SERVER('news server host')
  1408.  
  1409.               The hostname of the machine running the news server.
  1410.               Note that an IP address may be specified, but this
  1411.               is obviously not recommended.
  1412.  
  1413.               If an asterisk "*" is specified as the server name,
  1414.               an experimental dialog is invoked which displays an
  1415.               ISPF table of news servers with associated NEWSRC
  1416.               data set names.  You select the news server you want
  1417.               (or add a line associating that server with a specific
  1418.               NEWSRC file).  This feature is courtesy of Leonard Woren
  1419.               (LDW@MVSA.USC.EDU, SHARE installation code USC).
  1420.  
  1421. ))GROUP('newsgroup name')
  1422.  
  1423.               The name of a specific newsgroup you want to see,
  1424.               rather than the list of all newsgroups.  If you specify
  1425.               this, it will merely fill in the corresponding field of
  1426.               the NNMVS primary menu, unless you also specify the
  1427.               keyword OPTION(G) and values for SERVER and NEWSRC.
  1428.  
  1429. ))NEWSRC('data set name')
  1430.  
  1431.               The name of your "newsrc" file, a sequential data set
  1432.               which keeps track of which articles you've already read
  1433.               in which newsgroups.  If this data set does not exist,
  1434.               NNMVS will create it.
  1435.  
  1436.               It is a good idea to use the same NEWSRC file all the
  1437.               time for one news server, but to use separate NEWSRC
  1438.               files for different news servers (should there be any).
  1439.  
  1440.               If you specify this, it will merely fill in the
  1441.               corresponding field of the NNMVS primary menu, unless
  1442.               you also specify values for SERVER and OPTION.
  1443.  
  1444.               If an asterisk "*" is specified as the NEWSRC name,
  1445.               an experimental dialog is invoked which displays an
  1446.               ISPF table of news servers with associated NEWSRC
  1447.               data set names.  You select the news server you want
  1448.               (or add a line associating that server with a specific
  1449.               NEWSRC file).  This feature is courtesy of Leonard Woren
  1450.               (LDW@MVSA.USC.EDU, SHARE installation code USC).
  1451.  
  1452. ))OPTION(A/G/L/N/O/P/R/X)
  1453.  
  1454.               The initial option to start up NNMVS without seeing
  1455.               the primary menu, where the meanings of the letters
  1456.               are those as displayed on the menu:
  1457.  
  1458.               L - List all newsgroups from server
  1459.               N - List new newsgroups from server since last N or L
  1460.               A - Show items from all newsgroups listed in NEWSRC file
  1461.               R - Show items from registered newsgroups in NEWSRC file
  1462.               G - Go directly to the newsgroup named by operand GROUP
  1463.               P - Enter native NNTP protocol commands
  1464.               O - Specify NNMVS options defaults
  1465.               X - Exit NNMVS
  1466.  
  1467.               If you specify this, you must also specify values for
  1468.               SERVER and NEWSRC.  Also, if you specify OPTION(G), you
  1469.               must provide a value for the GROUP keyword.
  1470.  
  1471. ))REGISTERSTATUS(Yes/No/Prompt)
  1472.  
  1473.               When you specify OPTION(R), NNMVS decides whether to
  1474.               get the current status of each registered newsgroup,
  1475.               since it doesn't get that information for free as it
  1476.               does when you use the "L" (list) option.  Therefore,
  1477.               it normally prompts you with a popup asking you if it
  1478.               is OK to do this, since it takes time.
  1479.  
  1480.               Specify REGISTERSTATUS(Y) to tell NNMVS to go ahead and
  1481.               do this.  REGISTERSTATUS(N) says not to.  The default,
  1482.               REGISTERSTATUS(P), tells NNMVS to prompt as it would if
  1483.               you selected option R from the primary menu.
  1484.  
  1485. ))FORCE
  1486.  
  1487.               NNMVS tries to determine if there is a TCP/IP socket
  1488.               application active elsewhere in your TSO environment
  1489.               before starting up, to prevent TCP/IP errors.  If it
  1490.               tells you that there is another client active but in
  1491.               truth there is none and you know it, you can use the
  1492.               FORCE keyword to make NNMVS proceed whether it finds
  1493.               this to be the case or not.
  1494.  
  1495. ))DEBUG
  1496.  
  1497.               Set debugging mode on.  You must preallocate a file to
  1498.               ddname NNDEBUG for this to work.  This can be allocated
  1499.               to the terminal or a log file.  When debug mode is on,
  1500.               messages describing memory allocation and deallocation
  1501.               and NNTP commands sent are dumped to the debug file.
  1502.  
  1503. ))TEST
  1504.  
  1505.               Activate C/370 interactive test (INSPECT).  NNMVS must
  1506.               have been compiled with the TEST option for this to be
  1507.               effective.  Note that you can also issue the TEST command
  1508.               inside NNMVS to get to INSPECT, again provided that NNMVS
  1509.               was compiled with the TEST option.
  1510. ))BATCH
  1511.  
  1512.               Invoke NNMVS in batch mode.  When BATCH is specified,
  1513.               NEWSRC must also be specified.  The files specified by
  1514.               BATCHIN and BATCHOUT are allocated and you supply
  1515.               NNMVS batch commands in the BATCHIN file (typically the
  1516.               terminal).  You specify the news server via the command
  1517.  
  1518.               server = "foobar";
  1519.  
  1520.               where foobar should be replaced with the actual name of
  1521.               the NNTP server host.
  1522.  
  1523.               Note that no batch commands will be executed until the
  1524.               entire batch language program is read in and EOF is met.
  1525.  
  1526.               For help with the batch language, execute NNMVS in batch
  1527.               mode and supply the command "HELP".
  1528.  
  1529. ))BATCHIN('batch input file name')
  1530.  
  1531.               the data set allocated for input to NNMVS batch mode.
  1532.               Default is * (the terminal).
  1533.  
  1534.               Note that no batch commands will be executed until the
  1535.               entire batch language program is read in and EOF is met.
  1536.  
  1537.               For help with the batch language, execute NNMVS in batch
  1538.               mode and supply the command "HELP".
  1539.  
  1540. ))BATCHOUT('batch output file name')
  1541.  
  1542.               the data set allocated for output from NNMVS batch mode.
  1543.               Default is * (the terminal).
  1544.  
  1545.               For help with the batch language, execute NNMVS in batch
  1546.               mode and supply the command "HELP".
  1547.  
  1548. ))NEW
  1549.  
  1550.               Use a new (testing) release of NNMVS.  This is dependent
  1551.               upon your installation's procedures for providing
  1552.               parallel releases of software for users to run online in
  1553.               test mode.
  1554.  
  1555. ))OLD
  1556.  
  1557.               Use an old (backup) release of NNMVS.  This is dependent
  1558.               upon your installation's procedures for providing
  1559.               parallel releases of software for users to run online in
  1560.               test mode.
  1561.  
  1562. ./ ADD NAME=SIGFAIL
  1563.  
  1564. #include <stdio.h>
  1565. #include <stdlib.h>
  1566. #include <signal.h>
  1567.  
  1568. static void
  1569. handler() {
  1570.  printf("SIGINT handler has been called.\n");
  1571.  exit(8);
  1572. }
  1573.  
  1574. static int
  1575. ask(question)
  1576. char *question;
  1577. {
  1578.  char ans[81];
  1579.  
  1580.  for (;;) {
  1581.    printf("%s",question);
  1582.    fgets(ans,79,stdin);
  1583.    switch (ans[0]) {
  1584.      case 'y':
  1585.      case 'Y': return 1;
  1586.      case 'n':
  1587.      case 'N': return 0;
  1588.      default: printf("Bad answer, %s\n",ans);
  1589.               continue;
  1590.    }
  1591.  }
  1592. }
  1593.  
  1594. main(argc,argv)
  1595. int argc;
  1596. char **argv;
  1597. {
  1598.  int sigp;
  1599.  int loopp;
  1600.  int i;
  1601.  
  1602.  printf(
  1603.   "This program demonstrates that SIGINT is not handled on MVS.\n");
  1604.  printf(
  1605.   "It does NOT prove or disprove anything about attention handling\n");
  1606.  printf(
  1607.   "in C/370 in general, except possibly for how output to stdout\n");
  1608.  printf(
  1609.   "and stderr are affected by an attention interruption.\n\n");
  1610.  printf(
  1611.   "At the end of the program, a line of output is written to each\n");
  1612.  printf(
  1613.   "of the two output files.  If you see either one, that means that\n");
  1614.  printf(
  1615.   "C/370 has intercepted the attention, but you will observe that\n");
  1616.  printf(
  1617.   "it has not been handled by a SIGINT routine and it also has not\n");
  1618.  printf(
  1619.   "allowed the program to be terminated by the operating system.\n\n");
  1620.  
  1621.  sigp  = ask("Do you want to signal abort on interrupts? (y or n)");
  1622.  loopp = ask("Do you want to loop forever without output? (y or n)");
  1623.  
  1624.  if (sigp) {
  1625.    printf("Doing signal(SIGINT,handler)\n");
  1626.    if (signal(SIGINT,handler) == SIG_ERR)
  1627.        perror("Could not set SIGINT");
  1628.  }
  1629.  
  1630.  printf("OK, hit PA1 now\n");
  1631.  
  1632.  if (loopp) {
  1633.    for (;;) ;
  1634.  }
  1635.  else {
  1636.    for (i=0;i<5000;i++) {
  1637.     printf("I=%d\n",i);
  1638.    }
  1639.  }
  1640.  printf("I'm finished (on stdout)\n");
  1641.  fprintf(stderr,"I'm finished (on stderr)\n");
  1642. }
  1643.  
  1644. ./ ENDUP
  1645. ?!
  1646. //CLIST    EXEC MDLOAD,BS='6160',TRK1='5',TRK2='1',TO='CLIST'
  1647. //SYSIN    DD   DATA,DLM='?!'
  1648. ./ ADD NAME=NNMFIUCV
  1649. /* REXX.  This exec scans the job pack queues for IUCVMULT and returns
  1650.  * with an error code if IUCVMULT is already loaded under a
  1651.  * different TCB. This can only happen under PIE MultiTSO or a
  1652.  * similar product that makes multiple job step TCB's.
  1653.  */
  1654.  
  1655. trace off
  1656. signal on novalue
  1657.  
  1658. search_name = "IUCVMULT"
  1659. count = 0
  1660. foundtcb. = ""
  1661. current_tcb  = getword24("21C")
  1662. current_job_step_tcb = getword24(current_tcb,"7C")
  1663. current_ascb = getword24("224")
  1664. current_asxb = getword31(current_ascb,"6C")
  1665. first_tcb    = getword24(current_asxb,"4")
  1666. tcb = first_tcb
  1667. motherflag = 0
  1668. do forever
  1669.  if motherflag = 0 then do
  1670.   call process
  1671.   daughter_tcb = getword24(tcb,"88")
  1672.   if daughter_tcb \= "00000000" then do
  1673.    tcb = daughter_tcb
  1674.    iterate
  1675.   end
  1676.  end
  1677.  motherflag = 0
  1678.  sister_tcb = getword24(tcb, "80")
  1679.  if sister_tcb \= "00000000" then do
  1680.   tcb = sister_tcb
  1681.   iterate
  1682.  end
  1683.  mother_tcb = getword24(tcb, "84")
  1684.  if mother_tcb \= "00000000" then do
  1685.   tcb = mother_tcb
  1686.   motherflag = 1
  1687.   iterate
  1688.  end
  1689.  leave
  1690. end
  1691.  
  1692. if count = 0 then return 0
  1693. problem = 0
  1694. do i = 1 to count
  1695.  if foundtcb.i = current_job_step_tcb then do
  1696.   /*
  1697.   say search_name "is already loaded under current TCB at "foundtcb.i"."
  1698.   */
  1699.  end
  1700.  else do
  1701.   /*
  1702.   say search_name "is loaded under different TCB at "foundtcb.i"."
  1703.   */
  1704.   problem = 1
  1705.  end
  1706. end
  1707.  
  1708. if problem = 1 then return 1
  1709.  
  1710. else return 0
  1711.  
  1712. process:
  1713.  
  1714.  jpq = getword31(tcb,"2C")
  1715.  cde = jpq
  1716.  do while cde \= "00000000"
  1717.   cde_contents = storage(cde,32)
  1718.   cde_name = substr(cde_contents,9,8)
  1719.   cde_epa  = substr(cde_contents,9,8)
  1720.   if search_name = cde_name then do
  1721.    count = count + 1
  1722.    foundtcb.count = tcb
  1723.   end
  1724.   cde = getword31(cde,"0")
  1725.  end
  1726.  
  1727. return
  1728.  
  1729. getword31: parse arg addr, offset
  1730. temp1 = x2d(addr)
  1731. if offset = "" then temp2 = 0
  1732. else temp2 = x2d(offset)
  1733. return c2x(storage(d2x(temp1+temp2),4))
  1734.  
  1735. getword24: parse arg addr, offset
  1736. temp1 = x2d(addr)
  1737. if offset = "" then temp2 = 0
  1738. else temp2 = x2d(offset)
  1739. return "00"c2x(storage(d2x(temp1+temp2+1),3))
  1740.  
  1741. ./ ADD NAME=NNMVS
  1742. /* REXX. Syntax:  NNMVS  (we'll do the rest)   */
  1743.  
  1744. /*********************************************************************/
  1745. /*                                                                   */
  1746. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     */
  1747. /*                                                                   */
  1748. /* This software is provided on an "AS IS" basis.  All warranties,   */
  1749. /* including the implied warranties of merchantability and fitness,  */
  1750. /* are expressly denied.                                             */
  1751. /*                                                                   */
  1752. /* Provided this copyright notice is included, this software may     */
  1753. /* be freely distributed and not offered for sale.                   */
  1754. /*                                                                   */
  1755. /* Changes or modifications may be made and used only by the maker   */
  1756. /* of same, and not further distributed.  Such modifications should  */
  1757. /* be mailed to the author for consideration for addition to the     */
  1758. /* software and incorporation in subsequent releases.                */
  1759. /*                                                                   */
  1760. /*********************************************************************/
  1761.  
  1762. /* *** Customize the following lines for your installation. *** */
  1763. /*                                                              */
  1764. /* Note:  If you wish to specify a different ISPF APPLID for    */
  1765. /* NNMVS, you will have to use the SELECT service to invoke     */
  1766. /* the load module.  If so, uncomment the LIBDEF's for ISPLLIB  */
  1767. /* and the SELECT call, and comment out the TSO CALL call.      */
  1768. /*                                                              */
  1769. /* Note:  If you choose a panel library that is in TSO users'   */
  1770. /* default ISPF allocations, you can remove the LIBDEF call.    */
  1771. /*                                                              */
  1772.  
  1773. nnmprefix      = "NNMVS"
  1774. nnmpanelsuffix = "ISPPLIB"
  1775. nnmloadsuffix  = "LOAD"
  1776. nnmlmod        = "NNMMAIN"
  1777. nnmpanel       = nnmprefix"."nnmpanelsuffix
  1778. nnmload        = nnmprefix"."nnmloadsuffix
  1779. nnmappl        = "ISR"
  1780.  
  1781. trace off
  1782. signal on novalue
  1783. libdeffed = 0
  1784. parse arg args
  1785. "ISPQRY"
  1786. if rc > 0 then do
  1787.  parse source . . execname . execds .
  1788.  if execds = "?" then
  1789.   icmd = "%"execname args
  1790.  else
  1791.   icmd = "EX '"execds"("execname")'" quote(args)
  1792.  call startispf "NEWAPPL("nnmappl") CMD("icmd")"
  1793.  exit
  1794. end
  1795. signal on failure
  1796. signal on halt
  1797. testparm = "-"
  1798. if wordpos("TEST", translate(args)) > 0 then testparm = testparm || "t"
  1799. else ,
  1800. if wordpos("DEBUG",translate(args)) > 0 then testparm = testparm || "d"
  1801. else testparm = ""
  1802.  
  1803. if find_iucvmult() <> 0 then do
  1804.  say,
  1805. "A TCP/IP socket application may be active elsewhere in your session."
  1806.  say "Please terminate the other application before trying this one."
  1807.  exit
  1808. end
  1809.  
  1810. call libdef
  1811. call nnm_dialog
  1812.  
  1813. cleanup:
  1814. if libdeffed then call unlibdef
  1815. exit
  1816. error:failure:halt:say "NNMVS: Severe lossage."
  1817. say "Statement:" sourceline(sigl)
  1818. exit
  1819.  
  1820. nnm_dialog:
  1821.  
  1822. address TSO "CALL" "'"nnmload"("nnmlmod")'" quote(testparm)
  1823. /*
  1824.  * address ISPEXEC,
  1825.  *         "SELECT PGM("nnmlmod") PARM("quote(testparm)")",
  1826.  *         "NEWAPPL("nnmappl") PASSLIB"
  1827.  */
  1828. if rc \= 0 then say "Return code from" nnmlmod "program is" rc
  1829. return
  1830.  
  1831. libdef:
  1832. address ISPEXEC "LIBDEF ISPPLIB DATASET  ID('"nnmpanel"')"
  1833. /*
  1834.  * address ISPEXEC "LIBDEF ISPLLIB DATASET  ID('"nnmload"')"
  1835.  */
  1836. libdeffed = 1
  1837. return
  1838.  
  1839. unlibdef:
  1840. /*
  1841.  * address ISPEXEC "LIBDEF ISPLLIB DATASET"
  1842.  */
  1843. address ISPEXEC "LIBDEF ISPPLIB DATASET"
  1844. libdeffed = 0
  1845. return
  1846.  
  1847. /*
  1848.  * The following function starts ISPF from READY mode.
  1849.  * Beware:  splitting the screen starts up an identical copy of the
  1850.  *          application, which may not be desirable.
  1851.  */
  1852.  
  1853. startispf: parse arg string
  1854. "ISPSTART" string
  1855. return
  1856.  
  1857. /* The following function enquotes a string. */
  1858.  
  1859. quote: parse arg string
  1860. ix = 1
  1861. do forever
  1862.  ix = pos("'",string,ix)
  1863.  if ix = 0 then return "'"string"'"
  1864.  string = insert("'",string,ix)
  1865.  ix=ix+2
  1866. end
  1867.  
  1868. find_iucvmult: procedure
  1869.  
  1870. call nnmfiucv
  1871.  
  1872. return result
  1873.  
  1874. ./ ADD NAME=NNMVSC
  1875. PROC 0 TEST DEBUG BATCH +
  1876.        SERVER() GROUP() NEWSRC() OPTION() REGISTERSTATUS()
  1877.  
  1878. /*********************************************************************/
  1879. /*                                                                   */
  1880. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     */
  1881. /*                                                                   */
  1882. /* This software is provided on an "AS IS" basis.  All warranties,   */
  1883. /* including the implied warranties of merchantability and fitness,  */
  1884. /* are expressly denied.                                             */
  1885. /*                                                                   */
  1886. /* Provided this copyright notice is included, this software may     */
  1887. /* be freely distributed and not offered for sale.                   */
  1888. /*                                                                   */
  1889. /* Changes or modifications may be made and used only by the maker   */
  1890. /* of same, and not further distributed.  Such modifications should  */
  1891. /* be mailed to the author for consideration for addition to the     */
  1892. /* software and incorporation in subsequent releases.                */
  1893. /*                                                                   */
  1894. /*********************************************************************/
  1895.  
  1896. /**********************************************************************/
  1897. /*                                                                    */
  1898. /* This is the CLIST version of the NNMVS driver.  You may wish to    */
  1899. /* use this in place of the REXX version if:                          */
  1900. /*                                                                    */
  1901. /* - you don't have REXX (huh???)                                     */
  1902. /* - you don't have XPROC (you can probably get it from the same      */
  1903. /*   place you got NNMVS)                                             */
  1904. /* - you are experiencing RACF/ACF2/other-security-system problems    */
  1905. /*   trying to define access to the NNTP authorization file with      */
  1906. /*   program pathing rules or the equivalent                          */
  1907. /*                                                                    */
  1908. /* The disadvantages are:                                             */
  1909. /*                                                                    */
  1910. /* - You can use the CLIST from READY mode only implicitly.  In other */
  1911. /*   words, a user won't be able to type EXEC 'library.clist(NNMVS)'  */
  1912. /*   from READY mode - it must be in SYSPROC and executed by name.    */
  1913. /*                                                                    */
  1914. /* - You don't get the check for multiple TCP/IP applications.        */
  1915. /*                                                                    */
  1916. /* Of course, even if you don't have XPROC, you may still want to use */
  1917. /* the REXX exec instead - you just have to take out the XPROC call   */
  1918. /* and forget about being able to pass parameters to the exec.  That  */
  1919. /* isn't such a great loss, since none of the params are required.    */
  1920. /*                                                                    */
  1921. /**********************************************************************/
  1922.  
  1923. /* *** Customize the following lines for your installation. *** */
  1924. /*                                                              */
  1925. /* Note:  If you wish to specify a different ISPF APPLID for    */
  1926. /* NNMVS, you will have to use the SELECT service to invoke     */
  1927. /* the load module.  If so, uncomment the LIBDEF's for ISPLLIB  */
  1928. /* and the SELECT call, and comment out the TSO CALL call.      */
  1929. /*                                                              */
  1930. /* Note:  If you choose a panel library that is in TSO users'   */
  1931. /* default ISPF allocations, you can remove the LIBDEF call.    */
  1932. /*                                                              */
  1933.  
  1934. SET NNMCLIST       = NNMVS     /* name of this CLIST */
  1935. SET NNMPREFIX      = NNMVS
  1936. SET NNMPANELSUFFIX = ISPPLIB
  1937. SET NNMLOADSUFFIX  = LOAD
  1938. SET NNMLMOD        = NNMMAIN
  1939. SET NNMPANEL       = &STR(&NNMPREFIX..&NNMPANELSUFFIX)
  1940. SET NNMLOAD        = &STR(&NNMPREFIX..&NNMLOADSUFFIX)
  1941. SET NNMAPPL        = ISR
  1942.  
  1943. CONTROL NOCAPS
  1944.  
  1945. SET STACKED = N
  1946. SET LIBDEFFED = N
  1947. ISPQRY
  1948. IF &LASTCC > 0 THEN DO
  1949.  SET ICMD = &NRSTR(&NNMCLIST &TEST &DEBUG &BATCH +
  1950.                    SERVER('&SERVER') GROUP('&GROUP') +
  1951.                    NEWSRC('&NEWSRC') OPTION('&OPTION') +
  1952.                    REGISTERSTATUS('®ISTERSTATUS'))
  1953.  ISPSTART NEWAPPL(&NNMAPPL) CMD(&NRSTR(&ICMD))
  1954.  EXIT
  1955. END
  1956.  
  1957. IF &NRSTR(&OPTION) ^= &STR() THEN DO
  1958.  IF &LENGTH(&NRSTR(&OPTION)) ^= 1 +
  1959.   | &SYSINDEX(&NRSTR(&OPTION),TDB) ^= 0 THEN DO
  1960.   WRITE NNMVS: Invalid option, &NRSTR(&OPTION).
  1961.   EXIT CODE(12)
  1962.  END
  1963.  IF &NRSTR(&SERVER) = &STR() THEN DO
  1964.   WRITE NNMVS: SERVER required when OPTION specified.
  1965.   EXIT CODE(12)
  1966.  END
  1967.  IF &NRSTR(&NEWSRC) = &STR() THEN DO
  1968.   WRITE NNMVS: NEWSRC required when OPTION specified.
  1969.   EXIT CODE(12)
  1970.  END
  1971.  IF &NRSTR(&OPTION) = G && &NRSTR(&GROUP) = &STR() THEN DO
  1972.   WRITE NNMVS: GROUP required when OPTION(G) specified.
  1973.   EXIT CODE(12)
  1974.  END
  1975.  IF &NRSTR(REGISTERSTATUS) = &STR() THEN SET REGISTERSTATUS = PROMPT
  1976. END
  1977.  
  1978. SET TESTPARM = &STR(-)
  1979. IF &TEST  = TEST  THEN SET TESTPARM = &STR(&TESTPARM.t)
  1980. IF &DEBUG = DEBUG THEN SET TESTPARM = &STR(&TESTPARM.d)
  1981. IF &BATCH = BATCH THEN SET TESTPARM = &STR(&TESTPARM.b)
  1982.  
  1983. ISPEXEC LIBDEF ISPPLIB DATASET ID('&NNMPANEL')
  1984.  
  1985. /* ISPEXEC LIBDEF ISPLLIB DATASET ID('&NNMLOAD')
  1986.  
  1987. SET LIBDEFFED = Y
  1988.  
  1989. IF &NRSTR(&SERVER) NE THEN DO
  1990.  SET NNSERVER = &NRSTR(&SERVER)
  1991.  ISPEXEC VPUT (NNSERVER)
  1992. END
  1993.  
  1994. IF &NRSTR(&GROUP) NE THEN DO
  1995.  SET NNGROUPI = &NRSTR(&GROUP)
  1996.  ISPEXEC VPUT (NNGROUPI)
  1997. END
  1998.  
  1999. IF &NRSTR(&NEWSRC) NE THEN DO
  2000.  SET NNNEWSRF = &NRSTR(&NEWSRC)
  2001.  ISPEXEC VPUT (NNNEWSRF)
  2002. END
  2003.  
  2004. SET VPUTVARS =
  2005.  
  2006. IF &NRSTR(&SERVER) ^= &STR() THEN DO
  2007.  SET NNSERVER = &NRSTR(&SERVER)
  2008.  SET VPUTVARS = &STR(&VPUTVARS NNSERVER)
  2009. END
  2010.  
  2011. IF &NRSTR(&GROUP) ^= &STR() | &NRSTR(&OPTION) = G THEN DO
  2012.  SET NNGROUPI = &NRSTR(&GROUP)
  2013.  SET VPUTVARS = &STR(&VPUTVARS NNGROUPI)
  2014. END
  2015.  
  2016. IF &NRSTR(&NEWSRC) ^= &STR() THEN DO
  2017.  SET NNNEWSRF = &NRSTR(&NEWSRC)
  2018.  SET L = &LENGTH(&NRSTR(&NEWSRC))
  2019.  IF   &SUBSTR(1,&NEWSRC) = &STR(') +
  2020.    && &SUBSTR(&L,&NEWSRC) = &STR(') THEN DO
  2021.   SET NNNEWSRC = &SUBSTR(2:&L-1,&NRSTR(&NEWSRC))
  2022.  END
  2023.  ELSE SET NNNEWSRC = &NRSTR(&SYSPREF..&NEWSRC)
  2024.  SET VPUTVARS = &STR(&VPUTVARS NNNEWSRF NNNEWSRC)
  2025. END
  2026.  
  2027. IF &NRSTR(®ISTERSTATUS) ^= &STR() THEN DO
  2028.  SET NNREGNNG = &SUBSTR(1,&NRSTR(®ISTERSTATUS)
  2029.  SET VPUTVARS = &STR(&VPUTVARS NNREGNNG)
  2030. END
  2031.  
  2032. IF &STR(VPUTVARS) ^= &STR() THEN DO
  2033.  ISPEXEC VPUT (VPUTVARS) PROFILE
  2034. END
  2035.  
  2036. IF &NRSTR(&OPTION) ^= &STR() THEN DO
  2037.  SET TESTPARM = &NRSTR(&TESTPARM.&OPTION)
  2038. END
  2039.  
  2040. CALL '&NNMLOAD(&NNMLMOD)' '&NRSTR(&TESTPARM)'
  2041. /*
  2042. /* address ISPEXEC,
  2043. /* ISPEXEC SELECT PGM(&NNMLMOD) PARM('&NRSTR(&TESTPARM)') +
  2044. /*         NEWAPPL(&NNMAPPL) PASSLIB
  2045. /*
  2046. IF &LASTCC NE 0 THEN DO
  2047.  WRITE Return code from &NNMLMOD program is &LASTCC
  2048. END
  2049.  
  2050. IF &LIBDEFFED = Y THEN DO
  2051.  
  2052.  /* ISPEXEC LIBDEF ISPLLIB DATASET
  2053.  
  2054.  ISPEXEC LIBDEF ISPPLIB DATASET
  2055.  SET LIBDEFFED = N
  2056. END
  2057.  
  2058. EXIT
  2059.  
  2060. ./ ADD NAME=NNMVSL
  2061. /* REXX.  From Leonard D. Woren <ldw@mvsa.usc.edu>.
  2062.  *        Modified by SEB to remove MSGS file and other stuff...
  2063.  *
  2064.  */
  2065. trace off
  2066. signal on failure
  2067. signal on novalue
  2068.  
  2069. "XPROC 0 DEBUG LIST NEW OLD"
  2070. if rc <> 0 then return rc
  2071.  
  2072. If debug = 'DEBUG' Then Trace I
  2073. If list  = 'LIST'  Then Trace C
  2074. Address ISPEXEC
  2075.  
  2076. nnmvs_command = "%NNMVSP" new old
  2077. panel_name    = "NNL"
  2078. prof = "ISPPROF"
  2079. Address TSO "PIECHECK"
  2080. piecc = Rc
  2081. Select
  2082.    When(piecc =   0) Then Nop   /* not under pie */
  2083.    When(piecc =  12) Then Nop   /* no piecheck cmd ==> not under pie */
  2084.    When(piecc = 241) Then Nop   /* pie session 1 */
  2085.    Otherwise         prof = 'IS1PROF'
  2086.    End  /* select */
  2087.  
  2088. "CONTROL ERRORS RETURN"
  2089. "TBOPEN NNLIST WRITE LIBRARY("prof") SHARE"
  2090. If Rc > 8 then signal ispf_error
  2091. If Rc = 0 Then "TBTOP NNLIST"
  2092. Else Do
  2093.    "TBCREATE NNLIST WRITE LIBRARY("prof") NAMES(SERVER NEWSRC)"
  2094.    If Rc ^= 0 Then signal ispf_error
  2095.    End
  2096. csr = ""
  2097. dispcc = 0
  2098.  
  2099.  
  2100. Do Forever
  2101.    "TBQUERY NNLIST ROWNUM(ROWNUM)"
  2102.    If Rc > 8 then signal ispf_error
  2103.    If rownum = 0 Then Do
  2104.       server = ""
  2105.       newsrc = ""
  2106.       "TBADD NNLIST"
  2107.       If RC > 8 then signal ispf_error
  2108.       csr = "CURSOR(SERVER) CSRROW(1)"
  2109.       End
  2110.  
  2111.    "TBTOP   NNLIST"
  2112.    If Rc > 8 then signal ispf_error
  2113.    nnsel = ""
  2114.    If dispcc = 4 Then "TBDISPL NNLIST"
  2115.                  Else "TBDISPL NNLIST PANEL("panel_name")" csr
  2116.    dispcc = Rc
  2117.    csr = ""
  2118.  
  2119.    If dispcc = 8 Then Do
  2120.       "TBCLOSE NNLIST PAD(50) LIBRARY("prof")"
  2121.       If Rc > 8 then signal ispf_error
  2122.       return 0
  2123.       End
  2124.  
  2125.    If (dispcc ^= 0 & dispcc ^= 4) Then Do
  2126.       Say "TBDISPL Rc =" dispcc
  2127.       Say zerrsm
  2128.       Say zerrlm
  2129.       "TBCLOSE NNLIST PAD(50) LIBRARY("prof")"
  2130.       If Rc > 8 then signal ispf_error
  2131.       return 16
  2132.       End
  2133.  
  2134.    If zcmd = "" Then Do  /* look for line commands */
  2135.       Upper nnsel
  2136.       Select
  2137.          When (nnsel = "" ) Then "TBPUT NNLIST"
  2138.          When (nnsel = "D") Then Do
  2139.             /*
  2140.             "CONTROL DISPLAY SAVE"
  2141.             "DISPLAY PANEL(NNLDEL)"
  2142.             delcc = Rc
  2143.             "CONTROL DISPLAY RESTORE"
  2144.             if delcc > 8 then signal ispf_error
  2145.             If delcc = 0 Then */ "TBDELETE NNLIST"
  2146.             Iterate
  2147.             End
  2148.          When (nnsel = "I") Then Do
  2149.             server = ""
  2150.             newsrc = ""
  2151.             "TBADD NNLIST"
  2152.             if Rc > 8 then signal ispf_error
  2153.             "TBQUERY NNLIST POSITION(NEWROW)"
  2154.             if Rc > 8 then signal ispf_error
  2155.             csr = "CURSOR(SERVER) CSRROW("newrow")"
  2156.             Iterate
  2157.             End
  2158.          When (nnsel = "R") Then Do
  2159.             "TBADD NNLIST"
  2160.             if Rc > 8 then signal ispf_error
  2161.             "TBQUERY NNLIST POSITION(NEWROW)"
  2162.             if Rc > 8 then signal ispf_error
  2163.             csr = "CURSOR(SERVER) CSRROW("newrow")"
  2164.             Iterate
  2165.             End
  2166.          When (nnsel = "S") Then Do
  2167.             "TBCLOSE NNLIST PAD(50) LIBRARY("prof")"
  2168.             cc = Rc
  2169.             if cc > 8 then signal ispf_error
  2170.             If cc ^= 0 Then Say "TBCLOSE rc =" cc
  2171.             operands = ""
  2172.             If server ^= "" Then operands =          "SERVER("server")"
  2173.             If newsrc ^= "" Then operands = operands "NEWSRC("newsrc")"
  2174.             Address TSO nnmvs_command operands
  2175.             return 0
  2176.             End
  2177.          Otherwise Do
  2178.             badsel = nnsel
  2179.             zerrsm   = badsel "invalid"
  2180.             zerrlm   = badsel "is not a valid line command"
  2181.             zerralrm = "YES"
  2182.             zerrhm   = "*"
  2183.             "SETMSG MSG(ISRZ002)"
  2184.             If Rc > 8 Then signal ispf_error
  2185.             End
  2186.          End /* select */
  2187.       End  /* zcmd = "" */
  2188. Else Do  /* zcmd ^= "" */
  2189.       badcmd = Word(zcmd,1)
  2190.       zerrsm   = "Invalid command"
  2191.       zerrlm   = badcmd "is not a valid primary command"
  2192.       zerralrm = "YES"
  2193.       zerrhm   = "*"
  2194.       "SETMSG MSG(ISRZ002)"
  2195.       If Rc > 8 Then signal ispf_error
  2196.       End  /* zcmd ^= "" */
  2197.    End  /* main loop */
  2198.  
  2199. return 0
  2200.  
  2201. /* ISPF dialog error handling. */
  2202.  
  2203. ispf_error:
  2204. address ISPEXEC "DISPLAY PANEL(ISPTERM)"
  2205. signal cleanup
  2206.  
  2207. error:failure:halt:say "NNMVSL: Severe lossage."
  2208. say "Statement:" sourceline(sigl)
  2209. exit
  2210. ./ ADD NAME=NNMVSP
  2211. /* REXX. Syntax:  NNMVS  (see XPROC for the rest)   */
  2212.  
  2213. /*********************************************************************/
  2214. /*                                                                   */
  2215. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     */
  2216. /*                                                                   */
  2217. /* This software is provided on an "AS IS" basis.  All warranties,   */
  2218. /* including the implied warranties of merchantability and fitness,  */
  2219. /* are expressly denied.                                             */
  2220. /*                                                                   */
  2221. /* Provided this copyright notice is included, this software may     */
  2222. /* be freely distributed and not offered for sale.                   */
  2223. /*                                                                   */
  2224. /* Changes or modifications may be made and used only by the maker   */
  2225. /* of same, and not further distributed.  Such modifications should  */
  2226. /* be mailed to the author for consideration for addition to the     */
  2227. /* software and incorporation in subsequent releases.                */
  2228. /*                                                                   */
  2229. /*********************************************************************/
  2230.  
  2231. /* *** Customize the following lines for your installation. *** */
  2232. /*                                                              */
  2233. /* If nnmpanel is set to "", it will not be LIBDEF'd.           */
  2234. /* If nnmload  is set to "", it will not be LIBDEF'd.           */
  2235. /*                                                              */
  2236.  
  2237. save_prompt = prompt("ON")
  2238. "XPROC 0 TEST DEBUG FORCE NEW OLD BATCH BATCHIN(*) BATCHOUT(*)
  2239.          SERVER() GROUP() NEWSRC() OPTION() REGISTERSTATUS()"
  2240. if rc <> 0 then exit rc
  2241. call prompt save_prompt
  2242.  
  2243. select
  2244.  when new = "NEW" then do
  2245.   nnmprefix      = "NNMVS"     /* or use "new" (testing) parameters */
  2246.   nnmpanelsuffix = "ISPPLIB"   /* or use "new" (testing) parameters */
  2247.   nnmloadsuffix  = "LOAD"      /* or use "new" (testing) parameters */
  2248.   nnmlmod        = "NNMMAIN"   /* or use "new" (testing) parameters */
  2249.  end
  2250.  when old = "OLD" then do
  2251.   nnmprefix      = "NNMVS"     /* or use "old" (backup) parameters */
  2252.   nnmpanelsuffix = "ISPPLIB"   /* or use "old" (backup) parameters */
  2253.   nnmloadsuffix  = "LOAD"      /* or use "old" (backup) parameters */
  2254.   nnmlmod        = "NNMMAIN"   /* or use "old" (backup) parameters */
  2255.  end
  2256.  otherwise do
  2257.   nnmprefix      = "NNMVS"
  2258.   nnmpanelsuffix = "ISPPLIB"
  2259.   nnmloadsuffix  = "LOAD"
  2260.   nnmlmod        = "NNMMAIN"
  2261.  end
  2262. end
  2263.  
  2264. nnmpanel       = nnmprefix"."nnmpanelsuffix
  2265. nnmload        = nnmprefix"."nnmloadsuffix
  2266. nnmappl        = "ISR"
  2267. batchhelp      = "'"nnmprefix".HELP.TEXT'"
  2268. nnmvswizard    = "Steve Bacher <seb@draper.com>"   /* next of kin */
  2269. nnmvsmeister   = ""               /* TSOID of NNMVS's Big Brother */
  2270.  
  2271. trace off
  2272. signal on novalue
  2273. libdeffed = 0
  2274.  
  2275. if batch = "" then do
  2276.  "ISPQRY"
  2277.  if rc > 0 then do
  2278.   parse arg args
  2279.   parse source . . execname . execds .
  2280.   if execds = "?" then
  2281.    icmd = "%"execname args
  2282.   else
  2283.    icmd = "EX '"execds"("execname")'" quote(args)
  2284.   call startispf "NEWAPPL("nnmappl") CMD("icmd")"
  2285.   exit
  2286.  end
  2287. end
  2288.  
  2289. signal on failure
  2290. signal on halt
  2291.  
  2292. if option <> "" then do
  2293.  if length(option) <> 1 | pos(option,"TDB") <> 0 then do
  2294.   say "NNMVS: Invalid option, "option"."
  2295.   exit 12
  2296.  end
  2297.  if server = "" then do
  2298.   say "NNMVS: SERVER is required when OPTION is specified."
  2299.   exit 12
  2300.  end
  2301.  if newsrc = "" then do
  2302.   say "NNMVS: NEWSRC is required when OPTION is specified."
  2303.   exit 12
  2304.  end
  2305.  if option = "G" & group = "" then do
  2306.   say "NNMVS: GROUP is required when OPTION(G) is specified."
  2307.   exit 12
  2308.  end
  2309.  if registerstatus = "" then registerstatus = "PROMPT"
  2310. end
  2311.  
  2312. testparm = "-"
  2313. if test  = "TEST"  then testparm = testparm || "t"
  2314. if debug = "DEBUG" then testparm = testparm || "d"
  2315. if batch = "BATCH" then testparm = testparm || "b"
  2316.  
  2317. if find_iucvmult() <> 0 then do
  2318.  say,
  2319. "A TCP/IP socket application may be active elsewhere in your session."
  2320.  if force = "FORCE" then do
  2321.   say "Proceeding anyhow, because you specified the FORCE keyword."
  2322.  end
  2323.  else do
  2324.   say "Please terminate the other application before trying this one."
  2325.   say "Or, if you are sure it's OK, try again with the FORCE keyword."
  2326.   exit 8
  2327.  end
  2328. end
  2329.  
  2330. if batch <> "" then call nnm_batch
  2331. else do
  2332.  call libdef
  2333.  call nnm_dialog
  2334. end
  2335.  
  2336. cleanup:
  2337. if libdeffed then call unlibdef
  2338. exit
  2339.  
  2340. error:    say "NNMVS:  Lossage has occurred."
  2341.           say "Statement:" sourceline(sigl)
  2342.           if nnmvswizard <> "" then say "Please notify" nnmvswizard"."
  2343.           signal cleanup
  2344. failure:  say "NNMVS:  A failure has eventuated."
  2345.           say "Statement:" sourceline(sigl)
  2346.           if nnmvswizard <> "" then say "Please notify" nnmvswizard"."
  2347.           signal cleanup
  2348. halt:     say "NNMVS:  A halt has been detected."
  2349.           signal cleanup
  2350.  
  2351. nnm_dialog:
  2352.  
  2353. /* SERVER(*) --> (USC) Leonard Woren's server-table dialog */
  2354.  
  2355. if server = "*" | newsrc = "*" then do
  2356.  nnmvsl_cmd = "%NNMVSL" new old
  2357.  address ISPEXEC "SELECT CMD("nnmvsl_cmd") PASSLIB NEWAPPL("nnmappl")"
  2358.  return
  2359. end
  2360.  
  2361. vputvars = ""
  2362.  
  2363. if server <> "" then do
  2364.  nnserver = server
  2365.  vputvars = vputvars "NNSERVER"
  2366. end
  2367.  
  2368. if group <> "" | option = "G" then do
  2369.  nngroupi = group
  2370.  vputvars = vputvars "NNGROUPI"
  2371. end
  2372.  
  2373. if newsrc <> "" then do
  2374.  nnnewsrf = newsrc
  2375.  if left(newsrc,1) = "'" then nnnewsrc = strip(newsrc,"B","'")
  2376.  else nnnewsrc = sysvar("SYSPREF")"."newsrc
  2377.  vputvars = vputvars "NNNEWSRF NNNEWSRC"
  2378. end
  2379.  
  2380. if registerstatus <> "" then do
  2381.  nnregnng = left(registerstatus,1)
  2382.  vputvars = vputvars "NNREGNNG"
  2383. end
  2384.  
  2385. if vputvars <> "" then do
  2386.  address ISPEXEC "VPUT ("vputvars") PROFILE"
  2387. end
  2388.  
  2389. if option <> "" then do
  2390.  testparm = testparm || option
  2391. end
  2392.  
  2393. call let_me_know
  2394.  
  2395. zerrmsg = ""
  2396. zerrsm  = ""
  2397. zerrlm  = ""
  2398.  
  2399. if nnmload = "" then do
  2400.  address ISPEXEC "SELECT NEWAPPL("nnmappl") PASSLIB" ,
  2401.                  "PGM("nnmlmod") PARM("testparm")"
  2402. end
  2403. else do
  2404.  command = "CALL '"nnmload"("nnmlmod")'" quote(testparm)
  2405.  address ISPEXEC "SELECT NEWAPPL("nnmappl") PASSLIB CMD("command")"
  2406. end
  2407.  
  2408. if rc <> 0 then say "Return code from" nnmlmod "program is" rc
  2409.  
  2410. address ISPEXEC "VGET (ZERRSM ZERRLM)"
  2411. if zerrsm  <> "" then do
  2412.  say zerrmsg":" zerrsm
  2413.  say zerrlm
  2414. end
  2415.  
  2416. return
  2417.  
  2418. nnm_batch:
  2419.  
  2420. if newsrc = "" then do
  2421.  say "NNMVS: NEWSRC is required when BATCH is specified."
  2422.  exit 12
  2423. end
  2424.  
  2425. if server <> "" ,
  2426.  | group  <> "" ,
  2427.  | registerstatus <> "" ,
  2428.  | option <> "" then do
  2429.  say "NNMVS: SERVER, GROUP, OPTION, REGISTERSTATUS not valid",
  2430.             "when BATCH is specified."
  2431.  exit 12
  2432. end
  2433.  
  2434. address TSO "ALLOC FI(NNBATIN)  DA("batchin")  SHR REU"
  2435. if rc <> 0 then return
  2436. address TSO "ALLOC FI(NNBATOUT) DA("batchout") OLD REU"
  2437. if rc <> 0 then return
  2438. address TSO "ALLOC FI(NNBATHLP) DA("batchhelp") SHR REU"
  2439. if rc <> 0 then return
  2440. address TSO "ALLOC FI(NNNEWSRC) DA("newsrc")   OLD REU"
  2441. if rc <> 0 then return
  2442.  
  2443. call let_me_know "BATCH"
  2444.  
  2445. address TSO "CALL '"nnmload"("nnmlmod")'" quote(testparm)
  2446. nrc = rc
  2447. address TSO "FREE FI(NNBATIN NNBATOUT NNBATHLP NNNEWSRC)"
  2448.  
  2449. if nrc <> 0 then say "Return code from" nnmlmod "program is" nrc
  2450.  
  2451. return
  2452.  
  2453. let_me_know:
  2454. if nnmvsmeister = "" | nnmvsmeister = userid() then return
  2455. parse arg letarg
  2456. parse source . . execname . execds .
  2457. call outtrap "X."
  2458. address TSO,
  2459.  "SEND" quote(execds"("execname")" letarg date("U") time()" "),
  2460.         "U("nnmvsmeister") LOGON"
  2461. call outtrap "OFF"
  2462. return
  2463.  
  2464. libdef:
  2465. if nnmpanel <> "" then do
  2466.  address ISPEXEC "LIBDEF ISPPLIB DATASET ID('"nnmpanel"')"
  2467.  if rc <> 0 then do; call ispf_error rc; exit rc; end
  2468. end
  2469. if nnmload <> "" then do
  2470.  address ISPEXEC "LIBDEF ISPLLIB DATASET ID('"nnmload"')"
  2471.  if rc <> 0 then do; call ispf_error rc; exit rc; end
  2472. end
  2473. libdeffed = 1
  2474. return
  2475.  
  2476. unlibdef:
  2477. if nnmload <> "" then do
  2478.  address ISPEXEC "LIBDEF ISPLLIB DATASET"
  2479.  if rc <> 0 then call ispf_error rc
  2480. end
  2481. if nnmpanel <> "" then do
  2482.  address ISPEXEC "LIBDEF ISPPLIB DATASET"
  2483.  if rc <> 0 then call ispf_error rc
  2484. end
  2485. libdeffed = 0
  2486. return
  2487.  
  2488. ispf_error: parse arg ispfrc
  2489.  
  2490. say "NNMVS: ISPF dialog service error detected..."
  2491. say
  2492. say zerrmsg":" zerrsm
  2493. say zerrlm
  2494. say
  2495.  
  2496. return ispfrc
  2497.  
  2498. /*
  2499.  * The following function starts ISPF from READY mode.
  2500.  * Beware:  splitting the screen starts up an identical copy of the
  2501.  *          application, which may not be desirable.
  2502.  */
  2503.  
  2504. startispf: parse arg string
  2505. "ISPSTART" string
  2506. return
  2507.  
  2508. /* The following function enquotes a string. */
  2509.  
  2510. quote: parse arg string
  2511. ix = 1
  2512. do forever
  2513.  ix = pos("'",string,ix)
  2514.  if ix = 0 then return "'"string"'"
  2515.  string = insert("'",string,ix)
  2516.  ix=ix+2
  2517. end
  2518.  
  2519. /* The following function scans the job pack queues for IUCVMULT and
  2520.  * returns with an error code if IUCVMULT is already loaded under a
  2521.  * different TCB. This can only happen under PIE MultiTSO or a
  2522.  * similar product that makes multiple job step TCB's.
  2523.  */
  2524.  
  2525. find_iucvmult: procedure
  2526.  
  2527. call nnmfiucv
  2528.  
  2529. return result
  2530.  
  2531. ./ ADD NAME=NNMMAIL
  2532. /* REXX */
  2533.  
  2534. /*********************************************************************/
  2535. /*                                                                   */
  2536. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     */
  2537. /*                                                                   */
  2538. /* This software is provided on an "AS IS" basis.  All warranties,   */
  2539. /* including the implied warranties of merchantability and fitness,  */
  2540. /* are expressly denied.                                             */
  2541. /*                                                                   */
  2542. /* Provided this copyright notice is included, this software may     */
  2543. /* be freely distributed and not offered for sale.                   */
  2544. /*                                                                   */
  2545. /* Changes or modifications may be made and used only by the maker   */
  2546. /* of same, and not further distributed.  Such modifications should  */
  2547. /* be mailed to the author for consideration for addition to the     */
  2548. /* software and incorporation in subsequent releases.                */
  2549. /*                                                                   */
  2550. /*********************************************************************/
  2551.  
  2552. /**********************************************************************/
  2553. /*                                                                    */
  2554. /* Argument 1: mail data set                                          */
  2555. /* Argument 2: recipient(s)                                           */
  2556. /*                                                                    */
  2557. /**********************************************************************/
  2558.  
  2559. trace off
  2560. address TSO
  2561.  
  2562. /* Tailor these to your installation requirements. */
  2563.  
  2564. local_userid    = userid()
  2565. local_domain    = "MVS"
  2566. local_origin    = "mvs.draper.com"
  2567. local_smtp_node = "SMTPSRV"
  2568.  
  2569. parse arg maildsn to
  2570.  
  2571. if pos("@",to) = 0 then to = to"@"local_origin
  2572. else do
  2573.  parse var to before "<" after ">" junk
  2574.  if after <> "" then to = after
  2575. end
  2576.  
  2577. "ALLOC FI(NNMMAILI) SHR REU DA("maildsn")"
  2578. if rc \= 0 then return rc
  2579. "EXECIO * DISKR NNMMAILI (FINIS STEM IN.)"
  2580. if rc \= 0 then return rc
  2581. "newstack"
  2582. say   "HELO" local_domain
  2583. queue "HELO" local_domain
  2584. say   "MAIL FROM:<"local_userid"@"local_origin">"
  2585. queue "MAIL FROM:<"local_userid"@"local_origin">"
  2586. say   "RCPT TO:<"to">"
  2587. queue "RCPT TO:<"to">"
  2588. queue "DATA"
  2589. do i = 1 to in.0
  2590.  if left(in.i,1) = "." then queue "."in.i
  2591.  else if in.i = "" then queue " "
  2592.  else queue in.i
  2593. end
  2594. queue "."
  2595. queue "QUIT"
  2596. queue ""
  2597. "EXECIO * DISKW NNMMAILI (FINIS)"
  2598. if rc \= 0 then return rc
  2599. "delstack"
  2600. "FREE FI(NNMMAILI)"
  2601.  
  2602. "TRANSMIT" local_domain"."local_smtp_node,
  2603.            "DATASET("maildsn") NOEPILOG NOLOG NOPROLOG"
  2604.  
  2605. return 0
  2606.  
  2607. /* The following function enquotes a string. */
  2608. quote:
  2609. parse arg string
  2610. ix = 1
  2611. do forever
  2612.  ix = pos("'",string,ix)
  2613.  if ix = 0 then return "'"string"'"
  2614.  string = insert("'",string,ix)
  2615.  ix=ix+2
  2616. end
  2617. ./ ENDUP
  2618. ?!
  2619. //H        EXEC MDLOAD,BS='6160',TRK1='5',TRK2='1',TO='H'
  2620. //SYSIN    DD   DATA,DLM='?!'
  2621. ./ ADD NAME=NN
  2622.  
  2623.  /********************************************************************/
  2624.  /*                                                                  */
  2625.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  2626.  /*                                                                  */
  2627.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  2628.  /*                                                                  */
  2629.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  2630.  /* including the implied warranties of merchantability and fitness, */
  2631.  /* are expressly denied.                                            */
  2632.  /*                                                                  */
  2633.  /* Provided this copyright notice is included, this software may    */
  2634.  /* be freely distributed and not offered for sale.                  */
  2635.  /*                                                                  */
  2636.  /* Changes or modifications may be made and used only by the maker  */
  2637.  /* of same, and not further distributed.  Such modifications should */
  2638.  /* be mailed to the author for consideration for addition to the    */
  2639.  /* software and incorporation in subsequent releases.               */
  2640.  /*                                                                  */
  2641.  /********************************************************************/
  2642.  
  2643. /* --------------------- "nn.h" include member --------------------- */
  2644.  
  2645. #pragma linkage(ispexec,OS)
  2646. #pragma linkage(isplink,OS)
  2647. #pragma linkage(ikjeff18,OS)
  2648.  
  2649. /****** Installation-customized defines. *****************************/
  2650.  
  2651. #include "nnuser.h"
  2652.  
  2653. #ifndef  C370V1
  2654. #ifndef  C370V2
  2655. #ifndef  SASC
  2656.  install_error_neither_C370V1_C370V2_nor_SASC_was_defined;
  2657. #endif
  2658. #endif
  2659. #endif
  2660.  
  2661. #ifndef  TCPIPV1
  2662. #ifndef  TCPIPV2
  2663. #ifndef  SNSTCP
  2664.  install_error_neither_TCPIPV1_nor_TCPIPV2_nor_SNSTCP_was_defined;
  2665. #endif
  2666. #endif
  2667. #endif
  2668.  
  2669. #ifndef  ISPFV2
  2670. #ifndef  ISPFV3
  2671.  install_error_neither_ISPFV2_nor_ISPFV3_was_defined;
  2672. #endif
  2673. #endif
  2674.  
  2675. #define  MVS
  2676.  
  2677. #ifdef  SNSTCPIP
  2678. #ifndef I370
  2679. #define SNSC370
  2680. #endif
  2681. #endif
  2682.  
  2683. #ifdef C370V2
  2684. #pragma checkout(suspend)
  2685. #endif
  2686.  
  2687. /****** Clean up compiler warnings BEFORE time.h gets 'em ************/
  2688.  
  2689. #ifndef  SASC
  2690. #define  localtime            LOCALTIM
  2691. #endif
  2692.  
  2693. /****** Include all header files that are necessary. *****************/
  2694.  
  2695. #include <manifest.h>
  2696. #include <sys/types.h>
  2697. #include <sys/socket.h>
  2698. #include <netdb.h>
  2699. #include <netinet/in.h>
  2700. #include <sys/uio.h>
  2701. #include <sys/ioctl.h>
  2702. /*
  2703. #include <tcperrno.h>
  2704. */
  2705. #include <ctype.h>
  2706. #include <errno.h>
  2707. #include <limits.h>
  2708. #include <setjmp.h>
  2709. #include <stdio.h>
  2710. #include <stdarg.h>
  2711. #include <stdlib.h>
  2712. #include <string.h>
  2713. #include <stddef.h>
  2714. #include <time.h>
  2715. /*
  2716. #include <signal.h>
  2717. */
  2718.  
  2719. #ifndef  SASC
  2720. #include <ctest.h>
  2721. #endif
  2722.  
  2723. #ifdef   SASC
  2724. #include "nnsasc.h"
  2725. #endif
  2726.  
  2727. /****** Version-dependent stuff **************************************/
  2728.  
  2729. #ifdef   C370V1
  2730. #undef   FETCH
  2731. #endif
  2732.  
  2733. #ifdef   C370V2
  2734. #define  FETCH
  2735. #endif
  2736.  
  2737. #ifdef   TCPIPV1
  2738. #define  TCP_DEBUG            tcp_debug
  2739. #endif
  2740.  
  2741. #ifdef   TCPIPV2
  2742. #define  TCP_DEBUG            sock_debug
  2743. #endif
  2744.  
  2745. #ifdef   DEBUG
  2746. #define  TCP_DEBUG_ON         TCP_DEBUG(1)
  2747. #define  TCP_DEBUG_OFF        TCP_DEBUG(0)
  2748. #else
  2749. #define  TCP_DEBUG_ON         /* */
  2750. #define  TCP_DEBUG_OFF        /* */
  2751. #endif
  2752.  
  2753. #ifdef   ISPFV3
  2754. #define  ZERRLM_SIZE          513
  2755. #else
  2756. #define  ZERRLM_SIZE          73
  2757. #endif
  2758.  
  2759. /****** Preprocessor bookkeeping *************************************/
  2760.  
  2761. #ifndef  MAX
  2762. #define  MAX(A,B)             ((A) > (B) ? (A) : (B))
  2763. #endif
  2764. #ifndef  MIN
  2765. #define  MIN(A,B)             ((A) < (B) ? (A) : (B))
  2766. #endif
  2767.  
  2768. #define  Bool                 char
  2769. #define  Fool                 unsigned int /* for function arguments */
  2770.  
  2771. #define  COMMANDSIZE          12
  2772.  
  2773. #define  READ_BYTES           1024
  2774. #define  SERVER_BUF_MSGSIZE   1024
  2775. #define  CLIENT_BUF_MSGSIZE   1024
  2776. #define  TEXT_BYTES           1024
  2777. #define  INTERNET_SIZE        256
  2778.  
  2779. #define  GROUP_NAME_SIZE      255
  2780.  
  2781. #define  NNTP_PORT_NUMBER     119
  2782.  
  2783. #define  SOCKET_GETCHAR_ERROR (-1)
  2784. #define  SOCKET_NO_MORE       (-2)
  2785. #define  SOCKET_READ_NOTHING  (-3)
  2786.  
  2787. #define  NO_NNTP_MESSAGE_NUM  (-1)
  2788. #define  NO_VALUE             (-1)
  2789. #define  PHONY_NEWS_ARTICLE   (-1)
  2790.  
  2791. #define  Rstruc               register struct
  2792.  
  2793. #define  EQUAL                !strcmp
  2794. #define  UNEQUAL              strcmp
  2795.  
  2796. #define  NEWSRC_ORDER         'N'
  2797. #define  NNTP_LIST_ORDER      'L'
  2798. #define  ALPHABETICAL_ORDER   'A'
  2799.  
  2800. #define  FIND_NEXT            'N'
  2801. #define  FIND_FIRST           'F'
  2802. #define  FIND_LAST            'L'
  2803. #define  FIND_PREV            'P'
  2804. #define  FIND_ALL             'A'
  2805. #define  FIND_CHARS           '\0'
  2806. #define  FIND_WORD            'W'
  2807. #define  FIND_PREFIX          'P'
  2808. #define  FIND_SUFFIX          'S'
  2809. #define  FIND_CAPS            '\0'
  2810. #define  FIND_ASIS            'A'
  2811. #define  FIND_HEX             'X'
  2812. #define  FIND_GENERIC         'P'
  2813. #define  FIND_BADFORM         '\0'
  2814. #define  FIND_UNQUOTED        'U'
  2815. #define  FIND_QUOTED          'Q'
  2816. #define  FIND_C               'C'
  2817. #define  FIND_X               'X'
  2818. #define  FIND_T               'T'
  2819. #define  FIND_P               'P'
  2820.  
  2821. #define  MAX_INT               (int)0x7fffffff
  2822. #define  LOCATE_INT            (int)0x7ffffffe
  2823.  
  2824. #define  SELECTION_ALL        'A'
  2825. #define  SELECTION_REG        'R'
  2826. #define  SELECTION_NNTP       'P'
  2827. #define  SELECTION_GROUP      'G'
  2828. #define  SELECTION_LIST       'L'
  2829. #define  SELECTION_NEWG       'N'
  2830. #define  SELECTION_OPTS       'O'
  2831. #define  SELECTION_EXIT       'X'
  2832. #define  SELECTION_LIST_DISCONNECT  'Z'
  2833.  
  2834. #define  NO_ACTION            '\0'
  2835. #define  READ                 'R'
  2836. #define  RETRIEVED            'V'
  2837. #define  EXTRACTED            'X'
  2838. #define  PRINTED              'P'
  2839. #define  UNREAD               'U'
  2840. #define  MISSING              'M'
  2841. #define  ERROR                'E'
  2842. #define  CANCELLED            'C'
  2843.  
  2844. #define  CARRIAGE_RETURN      ('\r')
  2845.  
  2846. #ifdef   MVS
  2847. #ifdef   I370
  2848. #define  LINE_FEED            (0x15)
  2849. #else
  2850. #define  LINE_FEED            (0x25)
  2851. #endif
  2852. #else
  2853. #define  LINE_FEED            (0x0a)
  2854. #endif
  2855.  
  2856. #ifdef   MVS
  2857. #ifdef   I370
  2858. #define  EtoA                 htoncs
  2859. #define  AtoE                 ntohcs
  2860. #else
  2861. #ifdef   SNSTCPIP
  2862. #define  EtoA                 etoa
  2863. #define  AtoE                 atoe
  2864. #else
  2865. #define  EtoA(x)              ebcdictoascii[x]
  2866. #define  AtoE(x)              asciitoebcdic[x]
  2867. #define  ebcdictoascii        ebcdicto
  2868. #define  asciitoebcdic        asciitoe
  2869. #endif
  2870. #endif
  2871. #endif
  2872.  
  2873. #ifdef SNSC370
  2874. #define EBCDIC_TO_ASCII(A,B) EtoA(A,B)
  2875. #define ASCII_TO_EBCDIC(A,B) AtoE(A,B)
  2876. #else
  2877. #define EBCDIC_TO_ASCII(A,B) {int _i; \
  2878.                               for (_i=0; _i<(B); ++_i) \
  2879.                                   (A)[_i] = EtoA((A)[_i]); \
  2880.                              }
  2881. #define ASCII_TO_EBCDIC(A,B) {int _i; \
  2882.                               for (_i=0; _i<(B); ++_i) \
  2883.                                   (A)[_i] = AtoE((A)[_i]); \
  2884.                              }
  2885. #endif
  2886.  
  2887. #ifdef TCPIPV1
  2888. #define REPORT_TCP_ERROR(A)  /* */
  2889. #endif
  2890.  
  2891. #ifdef TCPIPV2
  2892. #define REPORT_TCP_ERROR(A)  tcperror(A)
  2893. #endif
  2894.  
  2895. #ifdef SNSTCPIP
  2896. #define REPORT_TCP_ERROR(A)  fprintf(stderr,\
  2897.                                     "\nTCP error on %s: errno = %d\n",\
  2898.                                     A,GET_ERRNO)
  2899. #endif
  2900.  
  2901. #ifdef SNSC370
  2902. #define Accept(A,B,C)        accept((A),(struct sockaddr *)(B),(C))
  2903. #define Bind(A,B,C)          bind((A),(struct sockaddr *)(B),(C))
  2904. #define Connect(A,B,C)       connect((A),(struct sockaddr *)(B),(C))
  2905. #define Gethostbyaddr(A,B,C) gethostbyaddr((char *)(A),(B),(C))
  2906. #define Getpeername(A,B,C)   getpeername((A),(struct sockaddr *)(B),(C))
  2907. #define Getsockopt(A,B,C,D)  getsockopt((A),(B),(char *)(C),(D))
  2908. #define EWOULDBLOCK          ESWOULDBLOCK
  2909. #define errno                GET_ERRNO
  2910. #else
  2911. #define Accept               accept
  2912. #define Bind                 bind
  2913. #define Connect              connect
  2914. #define Gethostbyaddr        gethostbyaddr
  2915. #define Getpeername          getpeername
  2916. #define Getsockopt           getsockopt
  2917. #endif
  2918.  
  2919. #ifdef   FETCH
  2920. #define  ISPLINK              (np->isplink_pointer)
  2921. #define  ISPEXEC              (np->ispexec_pointer)
  2922. #else
  2923. #define  ISPLINK              isplink
  2924. #define  ISPEXEC              ispexec
  2925. #endif
  2926.  
  2927. #ifndef I370
  2928.  
  2929. #define  WRITE_FILEMODE     "w,recfm=vb,lrecl=259,blksize=6233"
  2930. #define  APPEND_FILEMODE    "a,recfm=vb,lrecl=259,blksize=6233"
  2931. #define  SYSOUT_FILEMODE    "w,recfm=vba,lrecl=133"
  2932. #define  FILEMODE             "recfm=vb,lrecl=259,blksize=6233"
  2933. #define  FILEMODE_A           "recfm=vba,lrecl=133"
  2934.  
  2935. #define  OPEN_TEXT_FILE_FOR_WRITE(F)  \
  2936.          fopen((F),WRITE_FILEMODE)
  2937.  
  2938. #define  OPEN_TEXT_FILE_FOR_APPEND(F)  \
  2939.          fopen((F),APPEND_FILEMODE)
  2940.  
  2941. #define  OPEN_TEXT_FILE_FOR_WRITE_OR_APPEND(F,B)  \
  2942.          fopen((F),(B) ? APPEND_FILEMODE : WRITE_FILEMODE)
  2943.  
  2944. #define  OPEN_OUTPUT_FILE_FOR_WRITE_OR_APPEND(F,B)  \
  2945.          fopen((F),(B) ? "a" : WRITE_FILEMODE)
  2946.  
  2947. #define  OPEN_SYSOUT_FILE(F)  \
  2948.          fopen((F),SYSOUT_FILEMODE)
  2949.  
  2950. #define  TEST_IF_FILE_EXISTS(P,F)  (P=fopen((F),"r"))
  2951. #define  CLEANUP_IF_FILE_EXISTS(P) (void)fclose(P)
  2952.  
  2953. #else
  2954.  
  2955. #define  WRITE_FILEMODE     "w,recfm=v,reclen=255,blksize=6233"
  2956. #define  APPEND_FILEMODE    "a,recfm=v,reclen=255,blksize=6233"
  2957. #define  SYSOUT_FILEMODE    "w,recfm=v,reclen=133,print=yes"
  2958. #define  FILEMODE             "recfm=v,reclen=255,blksize=6233"
  2959. #define  FILEMODE_A           "recfm=v,reclen=133,print=yes"
  2960.  
  2961. #define  OPEN_TEXT_FILE_FOR_WRITE(F)  \
  2962.          afopen((F),"w","seq",FILEMODE)
  2963.  
  2964. #define  OPEN_TEXT_FILE_FOR_APPEND(F)  \
  2965.          afopen((F),"a","seq",FILEMODE)
  2966.  
  2967. #define  OPEN_TEXT_FILE_FOR_WRITE_OR_APPEND(F,B)  \
  2968.          afopen((F),(B)?"a":"w","seq",FILEMODE)
  2969.  
  2970. #define  OPEN_OUTPUT_FILE_FOR_WRITE_OR_APPEND(F,B)  \
  2971.          afopen((F),(B)?"a":"w","seq",FILEMODE)
  2972.  
  2973. #define  OPEN_SYSOUT_FILE(F)  \
  2974.          afopen((F),"w","seq",FILEMODE_A)
  2975.  
  2976. #define  TEST_IF_FILE_EXISTS(F,P)  (access((F),0) == 0)
  2977. #define  CLEANUP_IF_FILE_EXISTS(P) /* */
  2978.  
  2979. #endif
  2980.  
  2981. #define ebdtoasc(C) {char *__cp;\
  2982.                      for(__cp = C;*__cp;__cp++) *__cp = EtoA(*__cp);}
  2983.  
  2984. #define asctoebd(C) {char *__cp;\
  2985.                      for(__cp = C;*__cp;__cp++) *__cp = AtoE(*__cp);}
  2986.  
  2987. #define uppercase_in_place(C) {char *__cp;\
  2988.                      for(__cp=C;*__cp;__cp++) *__cp = toupper(*__cp);}
  2989.  
  2990. #define lowercase_in_place(C) {char *__cp;\
  2991.                      for(__cp=C;*__cp;__cp++) *__cp = tolower(*__cp);}
  2992.  
  2993. #define strip_trailing_in_place(C) {char *__cp;\
  2994.                      for(__cp=strchr((C),'\0');\
  2995.                          __cp>C && isspace(*(__cp-1)); __cp--);\
  2996.                      *__cp='\0';}
  2997.  
  2998. #define uppercase_and_strip_trailing_in_place(C) {char *__cp;\
  2999.                      for(__cp=C;*__cp;__cp++) *__cp = toupper(*__cp);\
  3000.                      for(; __cp>C && isspace(*(__cp-1)); __cp--);\
  3001.                      *__cp='\0';}
  3002.  
  3003. #define lowercase_and_strip_trailing_in_place(C) {char *__cp;\
  3004.                      for(__cp=C;*__cp;__cp++) *__cp = tolower(*__cp);\
  3005.                      for(; __cp>C && isspace(*(__cp-1)); __cp--);\
  3006.                      *__cp='\0';}
  3007.  
  3008. #define copy_uppercase(A,B) {char *__cA,*__cB;\
  3009.                      for (__cA=A,__cB=B; *__cB;__cA++,__cB++)\
  3010.                          *__cA = toupper(*__cB);\
  3011.                      *__cA='\0';}
  3012.  
  3013. #define copy_lowercase(A,B) {char *__cA,*__cB;\
  3014.                      for (__cA=A,__cB=B; *__cB;__cA++,__cB++)\
  3015.                          *__cA = tolower(*__cB);\
  3016.                      *__cA='\0';}
  3017.  
  3018. #define copy_uppercase_and_strip_trailing(A,B,C) {char *__cA,*__cB;\
  3019.                      for (__cA=A,__cB=B; *__cB;__cA++,__cB++)\
  3020.                          *__cA = toupper(*__cB);\
  3021.                      for (; __cA>A && isspace(*(__cA-1)); __cA--);\
  3022.                      *__cA='\0';C=__cA;}
  3023.  
  3024. #define copy_lowercase_and_strip_trailing(A,B,C) {char *__cA,*__cB;\
  3025.                      for (__cA=A,__cB=B; *__cB;__cA++,__cB++)\
  3026.                          *__cA = tolower(*__cB);\
  3027.                      for (; __cA>A && isspace(*(__cA-1)); __cA--);\
  3028.                      *__cA='\0';C=__cA;}
  3029.  
  3030. #define skip_whitespace(C)        (C) + strspn((C)," \t")
  3031. #define skip_ISPF_whitespace(C)   (C) + strspn((C)," ,\t")
  3032. #define find_whitespace(A,B)      if (!(A=strpbrk((B)," \t")))\
  3033.                                      A = strchr((B),'\0');
  3034. #define find_ISPF_whitespace(A,B) if (!(A=strpbrk((B)," ,\t")))\
  3035.                                      A = strchr((B),'\0');
  3036.  
  3037. #define  DATAOUT_LOW          0x01
  3038. #define  DATAOUT_HIGH         0x02
  3039. #define  DATAIN_LOW           0x03
  3040. #define  DATAIN_HIGH          0x04
  3041. #define  DATAOUT_BLUE         DATAOUT_LOW
  3042. #define  DATAOUT_GREEN        0x05
  3043. #define  DATAOUT_PINK         0x06
  3044. #define  DATAOUT_RED          0x07
  3045. #define  DATAOUT_TURQ         0x08
  3046. #define  DATAOUT_WHITE        DATAOUT_HIGH
  3047. #define  DATAOUT_YELLOW       0x09
  3048. #define  DATAIN_BLUE          0x0a
  3049. #define  DATAIN_GREEN         DATAIN_LOW
  3050. #define  DATAIN_PINK          0x0b
  3051. #define  DATAIN_RED           DATAIN_HIGH
  3052. #define  DATAIN_TURQ          0x0c
  3053. #define  DATAIN_WHITE         0x0d
  3054. #define  DATAIN_YELLOW        0x0e
  3055.  
  3056. #define  S99VRBAL  0x01             /* ALLOCATION                    */
  3057. #define  S99VRBUN  0x02             /* UNALLOCATION                  */
  3058. #define  S99VRBCC  0x03             /* CONCATENATION                 */
  3059. #define  S99VRBDC  0x04             /* DECONCATENATION               */
  3060. #define  S99VRBRI  0x05             /* REMOVE IN-USE                 */
  3061. #define  S99VRBDN  0x06             /* DDNAME ALLOCATION             */
  3062. #define  S99VRBIN  0x07             /* INFORMATION RETRIEVAL         */
  3063. #define  S99NOCNV  0x40             /* ALLOC FUNCTION-DO NOT USE AN  */
  3064.                                     /* EXISTING ALLOCATION TO SATISFY*/
  3065.                                     /* THE REQUEST                   */
  3066. #define  DALDDNAM   0x0001          /* DDNAME                        */
  3067. #define  DALDSNAM   0x0002          /* DSNAME                        */
  3068. #define  DALMEMBR   0x0003          /* MEMBER NAME                   */
  3069. #define  DALSTATS   0x0004          /* DATA SET STATUS               */
  3070. #define  DALNDISP   0x0005          /* DATA SET DISPOSITION          */
  3071. #define  DALTRK     0x0007          /* TRACK SPACE TYPE              */
  3072. #define  DALBLKLN   0x0009          /* BLOCK LENGTH                  */
  3073. #define  DALPRIME   0x000a          /* PRIMARY SPACE ALLOCATION      */
  3074. #define  DALSECND   0x000b          /* SECONDARY SPACE ALLOCATION    */
  3075. #define  DALDIR     0x000c          /* DIRECTORY BLOCK ALLOCATION    */
  3076. #define  DALSYSOU   0x0018          /* SYSOUT                        */
  3077. #define  DALSFMNO   0x001a          /* SYSOUT FORMS NUMBER           */
  3078. #define  DALCOPYS   0x001d          /* SYSOUT COPIES                 */
  3079. #define  DALUCS     0x0029          /* UNIVERSAL CHARACTER SET       */
  3080. #define  DALBLKSZ   0x0030          /* DCB BLOCKSIZE                 */
  3081. #define  DALDSORG   0x003c          /* DATA SET ORGANIZATION         */
  3082. #define  DALLRECL   0x0042          /* DCB LOGICAL RECORD LENGTH     */
  3083. #define  DALRECFM   0x0049          /* DCB RECORD FORMAT             */
  3084. #define  DALPERMA   0x0052          /* PERMANENTLY ALLOCATED ATTRIB  */
  3085. #define  DALRTDDN   0x0055          /* RETURN DDNAME                 */
  3086. #define  DALRTDSN   0x0056          /* RETURN DSNAME                 */
  3087. #define  DALRTORG   0x0057          /* RETURN D.S. ORGANIZATION      */
  3088. #define  DALSUSER   0x0058          /* SYSOUT REMOTE WORKSTATION     */
  3089. #define  DUNDDNAM   0x0001          /* DDNAME                        */
  3090. #define  DUNDSNAM   0x0002          /* DSNAME                        */
  3091. #define  DUNUNALC   0x0007          /* UNALLOC OPTION                */
  3092.  
  3093. #define  SHR        0x08
  3094. #define  NEW        0x04
  3095. #define  MOD        0x02
  3096. #define  OLD        0x01
  3097. #define  KEEP       0x08
  3098. #define  DELETE     0x04
  3099. #define  CATLG      0x02
  3100. #define  UNCATLG    0x01
  3101. #define  RECFM_F    0x80
  3102. #define  RECFM_V    0x40
  3103. #define  RECFM_U    0xc0
  3104. #define  RECFM_D    0x20
  3105. #define  RECFM_T    0x20
  3106. #define  RECFM_B    0x10
  3107. #define  RECFM_S    0x08
  3108. #define  RECFM_A    0x04
  3109. #define  RECFM_M    0x02
  3110. #define  RECFM_FB   (RECFM_F | RECFM_B)
  3111. #define  RECFM_VB   (RECFM_V | RECFM_B)
  3112. #define  DSORG_PS   0x4000
  3113. #define  DSORG_PO   0x0200
  3114.  
  3115. /************************ Newsgroup status ***************************/
  3116.  
  3117. #define NO_SUCH_GROUP             0x80
  3118. #define NEW_GROUP                 0x40
  3119. #define GROUP_FROM_NEWSRC         0x20
  3120. #define GROUP_LISTED              0x10
  3121. #define GROUP_SELECTED_UNREAD     0x08
  3122. #define GROUP_SELECTED_READ       0x04
  3123. #define GROUP_ERROR               0x02
  3124. #define GROUP_IN_TABLE            0x01
  3125.  
  3126. #define GROUP_SELECTED    (GROUP_SELECTED_UNREAD | GROUP_SELECTED_READ)
  3127.  
  3128. /* Note that the test GroupSelected means unread OR read, but the
  3129.  * assignment SetGroupSelected means set unread AND read selected
  3130.  * assignment OffGroupSelected means set unread AND read unselected.
  3131.  */
  3132.  
  3133. #define NoSuchGroup(X)            ((X)->status & NO_SUCH_GROUP)
  3134. #define NewGroup(X)               ((X)->status & NEW_GROUP)
  3135. #define GroupFromNewsrc(X)        ((X)->status & GROUP_FROM_NEWSRC)
  3136. #define GroupListed(X)            ((X)->status & GROUP_LISTED)
  3137. #define GroupSelectedUnread(X)    ((X)->status & GROUP_SELECTED_UNREAD)
  3138. #define GroupSelectedRead(X)      ((X)->status & GROUP_SELECTED_READ)
  3139. #define GroupError(X)             ((X)->status & GROUP_ERROR)
  3140. #define GroupInTable(X)           ((X)->status & GROUP_IN_TABLE)
  3141.  
  3142. #define GroupSelected(X)          ((X)->status & GROUP_SELECTED)
  3143.  
  3144. #define SetNoSuchGroup(X)          (X)->status |= NO_SUCH_GROUP
  3145. #define SetNewGroup(X)             (X)->status |= NEW_GROUP
  3146. #define SetGroupFromNewsrc(X)      (X)->status |= GROUP_FROM_NEWSRC
  3147. #define SetGroupListed(X)          (X)->status |= GROUP_LISTED
  3148. #define SetGroupSelectedUnread(X)  (X)->status |= GROUP_SELECTED_UNREAD
  3149. #define SetGroupSelectedRead(X)    (X)->status |= GROUP_SELECTED_READ
  3150. #define SetGroupError(X)           (X)->status |= GROUP_ERROR
  3151. #define SetGroupInTable(X)         (X)->status |= GROUP_IN_TABLE
  3152.  
  3153. #define SetGroupSelected(X)        (X)->status |= GROUP_SELECTED
  3154.  
  3155. #define OffNoSuchGroup(X)          (X)->status &= ~NO_SUCH_GROUP
  3156. #define OffNewGroup(X)             (X)->status &= ~NEW_GROUP
  3157. #define OffGroupFromNewsrc(X)      (X)->status &= ~GROUP_FROM_NEWSRC
  3158. #define OffGroupListed(X)          (X)->status &= ~GROUP_LISTED
  3159. #define OffGroupSelectedUnread(X)  (X)->status &= ~GROUP_SELECTED_UNREAD
  3160. #define OffGroupSelectedRead(X)    (X)->status &= ~GROUP_SELECTED_READ
  3161. #define OffGroupError(X)           (X)->status &= ~GROUP_ERROR
  3162. #define OffGroupInTable(X)         (X)->status &= ~GROUP_IN_TABLE
  3163.  
  3164. #define OffGroupSelected(X)        (X)->status &= ~GROUP_SELECTED
  3165.  
  3166. #define GroupListedOnly(X)        (GroupListed(X) && !GroupSelected(X))
  3167. #define GroupFromNNTP(X)          (GroupListed(X) || GroupSelected(X))
  3168. #define GroupFromNewsrcOnly(X)    (GroupFromNewsrc(X) && \
  3169.                                    !GroupListed(X) && \
  3170.                                    !GroupSelected(X))
  3171. #define BogusGroup(X)             (!GroupListed(X) && !GroupSelected(X))
  3172.  
  3173. #define ClearGroupStatus(X)        (X)->status = 0x00
  3174. #define NullGroupStatus(X)        ((X)->status == 0x00)
  3175.  
  3176. /************************* Article status ****************************/
  3177.  
  3178. #define NO_SUCH_ARTICLE           0x80
  3179. #define ARTICLE_ABSENT            0x40
  3180. #define ARTICLE_ERROR             0x20
  3181. #define ARTICLE_BAD_DATA          0x10
  3182. #define ARTICLE_HEAD_RETRIEVED    0x08
  3183. #define ARTICLE_BODY_RETRIEVED    0x04
  3184.  
  3185. #define ARTICLE_RETRIEVED         (ARTICLE_HEAD_RETRIEVED | \
  3186.                                    ARTICLE_BODY_RETRIEVED)
  3187.  
  3188. #define NoSuchArticle(X)          ((X)->status & NO_SUCH_ARTICLE)
  3189. #define ArticleAbsent(X)          ((X)->status & ARTICLE_ABSENT)
  3190. #define ArticleError(X)           ((X)->status & ARTICLE_ERROR)
  3191. #define ArticleBadData(X)         ((X)->status & ARTICLE_BAD_DATA)
  3192. #define ArticleHeadRetrieved(X)   ((X)->status & ARTICLE_HEAD_RETRIEVED)
  3193. #define ArticleBodyRetrieved(X)   ((X)->status & ARTICLE_BODY_RETRIEVED)
  3194.  
  3195. #define SetNoSuchArticle(X)        (X)->status |= NO_SUCH_ARTICLE
  3196. #define SetArticleAbsent(X)        (X)->status |= ARTICLE_ABSENT
  3197. #define SetArticleError(X)         (X)->status |= ARTICLE_ERROR
  3198. #define SetArticleBadData(X)       (X)->status |= ARTICLE_BAD_DATA
  3199. #define SetArticleHeadRetrieved(X) (X)->status |= ARTICLE_HEAD_RETRIEVED
  3200. #define SetArticleBodyRetrieved(X) (X)->status |= ARTICLE_BODY_RETRIEVED
  3201.  
  3202. #define OffNoSuchArticle(X)        (X)->status &=~NO_SUCH_ARTICLE
  3203. #define OffArticleAbsent(X)        (X)->status &=~ARTICLE_ABSENT
  3204. #define OffArticleError(X)         (X)->status &=~ARTICLE_ERROR
  3205. #define OffArticleBadData(X)       (X)->status &=~ARTICLE_BAD_DATA
  3206. #define OffArticleHeadRetrieved(X) (X)->status &=~ARTICLE_HEAD_RETRIEVED
  3207. #define OffArticleBodyRetrieved(X) (X)->status &=~ARTICLE_BODY_RETRIEVED
  3208.  
  3209. #define ArticleRetrieved(X)       ((X)->status & ARTICLE_RETRIEVED)
  3210. #define SetArticleRetrieved(X)     (X)->status |= ARTICLE_RETRIEVED
  3211. #define OffArticleRetrieved(X)     (X)->status &= ~ARTICLE_RETRIEVED
  3212.  
  3213. #define ClearArticleStatus(X)      (X)->status = 0x00
  3214. #define NullArticleStatus(X)      ((X)->status == 0x00)
  3215.  
  3216. /************************* Article vector ****************************/
  3217.  
  3218. /*
  3219.  * *** IMPORTANT! *** The hack of storing a vector of VARKs (which are
  3220.  * both pointers and status bits) depends on malloc() returning storage
  3221.  * for a struct on a doubleword boundary on MVS.  This allows us to
  3222.  * treat the low-order 3 bits of the pointer as trash so that we can
  3223.  * store status bits in it.  If this is not true, then this whole
  3224.  * technique will collapse like a house of cards, or else you should
  3225.  * stick a dummy double element into the newsarticle struct to make it
  3226.  * so.
  3227.  */
  3228.  
  3229. /*
  3230.  * Each article "pointer" (VARK) looks like this:
  3231.  *
  3232.  * -------------------------------------
  3233.  * |                       |   |   |   |
  3234.  * | pointer to article    | . | . | . |
  3235.  * |                       |   |   |   |
  3236.  * -------------------------------------
  3237.  *                           ^   ^   ^
  3238.  * where pointer is one of   |   |   |
  3239.  * NULL - no article         |   |   '--- 1 = Read, 0 = Unread
  3240.  * MISSING - article missing |   |   |
  3241.  * or the actual pointer     |   '------} 1 = Eligible, 0 = Ineligible
  3242.  *                           |
  3243.  *                           '----------} 1 = I know, 0 = I don't know
  3244.  *
  3245.  *                                        10 = Ineligible (not in table)
  3246.  *                                        11 = Eligible (in table)
  3247.  *                                        00 = Don't know yet
  3248.  *                                        01 cannot occur
  3249.  *
  3250.  */
  3251.  
  3252. #define  VARK                  unsigned int
  3253.  
  3254. #define  GETVARK(X,Y)          ((X)->article_vector\
  3255.                                 [(Y)-(X)->vector_first])
  3256. #define  GETVARKFIRST(X)       ((X)->article_vector[0])
  3257. #define  GETVARKLAST(X)        ((X)->article_vector\
  3258.                                 [(X)->article_vector_len-1])
  3259.  
  3260. #define  VARK2PARTICLE(X)      (struct newsarticle *) \
  3261.                                 (((unsigned int)(X)) & 0xfffffff8)
  3262. #define  VARK2NUMBER(X,Y)      (((Y)-(X)->article_vector) \
  3263.                                 + (X)->vector_first)
  3264. #define  VARK2BITS(X)          ((unsigned int)(X) & 0x00000007)
  3265. #define  VARK2READNESS(X)      ((unsigned int)(X) & 0x00000001)
  3266. #define  VARK2ELIGIBILITY(X)   ((unsigned int)(X) & 0x00000002)
  3267. #define  VARK2KNOWLEDGE(X)     ((unsigned int)(X) & 0x00000004)
  3268.  
  3269. #define  V_READNESS(X,Y)       VARK2READNESS(GETVARK(X,Y))
  3270. #define  V_ELIGIBILITY(X,Y)    VARK2ELIGIBILITY(GETVARK(X,Y))
  3271. #define  V_KNOWLEDGE(X,Y)      VARK2KNOWLEDGE(GETVARK(X,Y))
  3272.  
  3273. #define  V_NULL_ARTICLE        (struct newsarticle *)0
  3274. #define  V_MISSING_ARTICLE     (struct newsarticle *)np
  3275. #define  VARKMISSING           (unsigned int)np
  3276. #define  VARKNULL              (unsigned int)0
  3277.  
  3278. #define  V_UNREAD_BIT          0x00000000
  3279. #define  V_READ_BIT            0x00000001
  3280. #define  V_INELIGIBLE_BIT      0x00000000
  3281. #define  V_ELIGIBLE_BIT        0x00000002
  3282. #define  V_UNKNOWN_BIT         0x00000000
  3283. #define  V_KNOWN_BIT           0x00000004
  3284.  
  3285. #define  V_KNOWN_ELIGIBLE      (V_KNOWN_BIT + V_ELIGIBLE_BIT)
  3286. #define  V_KNOWN_INELIGIBLE    (V_KNOWN_BIT + V_INELIGIBLE_BIT)
  3287.  
  3288. #define  SetUnread(X)          X &= ~V_READ_BIT
  3289. #define  SetRead(X)            X |= V_READ_BIT
  3290. #define  SetNull(X)            X = VARKNULL
  3291.  
  3292.  /* Note that whenever you set something missing, you also set it
  3293.   * ineligible for table display.
  3294.   */
  3295.  
  3296. #define  SetMissing(X)         X = (VARK)\
  3297.                                    (VARKMISSING | \
  3298.                                     VARK2READNESS(X) | \
  3299.                                     V_KNOWN_INELIGIBLE)
  3300. #define  SetMissingUnread(X)   X = (VARK)\
  3301.                                    (VARKMISSING | \
  3302.                                     V_UNREAD_BIT | \
  3303.                                     V_KNOWN_INELIGIBLE)
  3304. #define  SetMissingRead(X)     X = (VARK)\
  3305.                                    (VARKMISSING | \
  3306.                                     V_READ_BIT | \
  3307.                                     V_KNOWN_INELIGIBLE)
  3308. #define  SetEligible(X)        X |= V_ELIGIBLE_BIT
  3309. #define  SetIneligible(X)      X &= ~V_ELIGIBLE_BIT
  3310. #define  SetKnown(X)           X |= V_KNOWN_BIT
  3311. #define  SetUnknown(X)         X &= ~V_KNOWN_BIT
  3312. #define  SetKnownEligible(X)   SetKnown(X), SetEligible(X)
  3313. #define  SetKnownIneligible(X) SetKnown(X), SetIneligible(X)
  3314.  
  3315. /* to get exact readness, use: VARK2READNESS(X) == V_whatever */
  3316.  
  3317. #define  IsRead(X)            ((X) & V_READ_BIT)
  3318. #define  IsUnread(X)          (!IsRead(X))
  3319. #define  IsEligible(X)        ((X) & V_ELIGIBLE_BIT)
  3320. #define  IsIneligible(X)      (!IsEligible(X))
  3321. #define  IsKnown(X)           ((X) & V_KNOWN_BIT)
  3322. #define  IsUnknown(X)         (!IsKnown(X))
  3323. #define  IsKnownEligible(X)   ((X)&V_KNOWN_ELIGIBLE==V_KNOWN_ELIGIBLE)
  3324. #define  IsKnownIneligible(X) ((X)&V_KNOWN_ELIGIBLE==V_KNOWN_INELIGIBLE)
  3325.  
  3326. #define  IsNull(X)            (VARK2PARTICLE(X) == V_NULL_ARTICLE)
  3327. #define  IsMissing(X)         (VARK2PARTICLE(X) == V_MISSING_ARTICLE)
  3328. #define  IsPresent(X)         (!IsMissing(X))
  3329. #define  IsMissingUnread(X)   (IsMissing(X) && IsUnread(X))
  3330. #define  IsMissingRead(X)     (IsMissing(X) && IsRead(X))
  3331. #define  IsPresentUnread(X)   (IsPresent(X) && IsUnread(X))
  3332. #define  IsPresentRead(X)     (IsPresent(X) && IsRead(X))
  3333.  
  3334. #define  NOTIFY_MSG   1
  3335. #define  WARNING_MSG  2
  3336. #define  CRITICAL_MSG 3
  3337.  
  3338. #define  WARN1(X)           NNMpmsg(np,NOTIFY_MSG,NULL,X)
  3339. #define  WARN2(X,Y)         NNMpmsg(np,NOTIFY_MSG,NULL,X,Y)
  3340. #define  WARN3(X,Y,Z)       NNMpmsg(np,NOTIFY_MSG,NULL,X,Y,Z)
  3341. #define  WARN4(X,Y,Z,W)     NNMpmsg(np,NOTIFY_MSG,NULL,X,Y,Z,W)
  3342. #define  ERR1(X)            NNMpmsg(np,WARNING_MSG,NULL,X)
  3343. #define  ERR2(X,Y)          NNMpmsg(np,WARNING_MSG,NULL,X,Y)
  3344. #define  ERR3(X,Y,Z)        NNMpmsg(np,WARNING_MSG,NULL,X,Y,Z)
  3345. #define  ERR4(X,Y,Z,W)      NNMpmsg(np,WARNING_MSG,NULL,X,Y,Z,W)
  3346. #define  CRIT1(X)           NNMpmsg(np,CRITICAL_MSG,NULL,X)
  3347. #define  CRIT2(X,Y)         NNMpmsg(np,CRITICAL_MSG,NULL,X,Y)
  3348. #define  CRIT3(X,Y,Z)       NNMpmsg(np,CRITICAL_MSG,NULL,X,Y,Z)
  3349.  
  3350. #define  MSG(X)             (MSG_is_obsolete,)
  3351.  
  3352. #define  GETMAIN(Ptr,Typ,Siz,For) \
  3353.          NNMgetm(np,(char **)&(Ptr),(sizeof(Typ))*(Siz),For)
  3354.  
  3355. #define  FREEMAIN(Ptr,For)    if (Ptr) {NNMfreem(np,(char *)Ptr,For);}
  3356.  
  3357. /****** Data and structure definitions. ******************************/
  3358.  
  3359. enum scroll         {NO_SCROLL, UP, DOWN, LEFT, RIGHT, LOCATE};
  3360. enum extreq         {EXTRACT_IT, PRINT_IT};
  3361. enum data_set_type  {PDS, SEQ, UNK, JES};
  3362. enum choose_reason  {RETRIEVE, MARK_ONLY};
  3363.  
  3364. enum list_option    {LIST_ALL,
  3365.                      LIST_NEW,
  3366.                      LIST_ALL_DISCONNECT,
  3367.                      LIST_ALL_RESCAN
  3368.                     };
  3369.  
  3370. enum socket_retval  {
  3371.                      SERVER_READ_OK,
  3372.                      SERVER_READ_ERROR,
  3373.                      SERVER_BUFFER_ERROR,
  3374.                      SERVER_NO_MORE
  3375.                     };
  3376.  
  3377. enum display_retval {
  3378.                      DISPLAY_REPEAT,
  3379.                      DISPLAY_EXIT,
  3380.                      DISPLAY_ERROR,
  3381.                      DISPLAY_FAILURE
  3382.                     };
  3383.  
  3384.  
  3385.  
  3386. enum user_option    {
  3387.                      OPTION_ALL,
  3388.                      OPTION_HEADER,
  3389.                      OPTION_OTHER,
  3390.                      OPTION_VIEW
  3391.                     };
  3392.  
  3393. enum article_cookie {
  3394.                      NULL_ARTICLE_COOKIE  ,
  3395.                      UNREAD_THIS_ARTICLE  ,
  3396.                      NEXT_ARTICLE         ,
  3397.                      PREV_ARTICLE         ,
  3398.                      NEXT_TABLED_ARTICLE  ,
  3399.                      PREV_TABLED_ARTICLE  ,
  3400.                      NEXT_UNREAD_ARTICLE  ,
  3401.                      PREV_UNREAD_ARTICLE  ,
  3402.                      NEXT_THREAD_ARTICLE  ,
  3403.                      PREV_THREAD_ARTICLE  ,
  3404.                      FIRST_THREAD_ARTICLE ,
  3405.                      LAST_THREAD_ARTICLE  ,
  3406.                      NEW_THREAD_ARTICLE   ,
  3407.                      REDISPLAY_ARTICLE
  3408.                     };
  3409.  
  3410. typedef  struct   _textunit     TEXTUNIT;
  3411. typedef  unsigned int           IPADDRESS;
  3412. typedef  enum     scroll        SCROLL;
  3413. typedef  enum     extreq        EXTREQ;
  3414.  
  3415. struct textline    {
  3416.                     struct textline    *next;
  3417.                     short               text_length;
  3418.                     short               tab_expanded_text_length;
  3419.                     char               *tab_expanded_text;
  3420.                     char                text[1];  /* dummy */
  3421.                    };
  3422.  
  3423. struct texthdr     {
  3424.                     int                   text_line_count;
  3425.                     short                 text_max_length;
  3426.                     short                 text_max_tab_expanded_length;
  3427.                     struct textline      *text_body_line;
  3428.                     struct textline      *first_text_line;
  3429.                     struct textline      *current_text_line;
  3430.                     struct textline      *last_text_line;
  3431.                    };
  3432.  
  3433. /* see note on newsarticle struct under article vector stuff */
  3434.  
  3435. struct newsarticle {
  3436.                     char                 *from;
  3437.                     char                 *subject;
  3438.                     char                 *date;
  3439.                     char                 *message_id;
  3440.                     char                 *csubject;
  3441.                     int                   number;
  3442.                     char                  action;
  3443.                     char                  status;
  3444.                     struct texthdr        thdr;
  3445.                    };
  3446.  
  3447. struct newsgroup   {
  3448.                     struct newsgroup     *next;
  3449.                     struct newsgroup     *next2;
  3450.                     struct newsgroup     *next3;
  3451.                     char                 *saved_newsrc_line;
  3452.                     VARK                 *article_vector;
  3453.                     VARK                **sort_vector;
  3454.                     int                   low_number;
  3455.                     int                   high_number;
  3456.                     int                   vector_first;
  3457.                     int                   vector_last;
  3458.                     int                   article_count;
  3459.                     int                   unread_count;
  3460.                     int                   sort_count;
  3461.                     int                   article_vector_len;
  3462.                     int                   registered;
  3463.                     char                  status;
  3464.                     char                  saved_newsrc_data [12];
  3465.                     char                  name [1]; /* dummy len */
  3466.                    };
  3467.  
  3468. struct cmddesc   {
  3469.                   char    command_name[COMMANDSIZE];
  3470.                   Bool    (*command_processor)();
  3471.                  };
  3472.  
  3473. struct seldesc   {
  3474.                   char    selection_code;
  3475.                   Bool    (*selection_processor)();
  3476.                  };
  3477.  
  3478. struct tabledesc {
  3479.                   char   *command_variable;
  3480.         struct cmddesc   *first_cmddesc;
  3481.         struct seldesc   *first_seldesc;
  3482.         struct cmddesc   *next_cmddesc;
  3483.                  };
  3484.  
  3485. struct tablevector {
  3486.                     struct tabledesc *newsgroup_display_table;
  3487.                     struct tabledesc *article_display_table;
  3488.                     struct tabledesc *text_display_table;
  3489.                    };
  3490.  
  3491. struct _textunit {
  3492.                   unsigned short         key;
  3493.                   unsigned short         num;
  3494.                   struct {
  3495.                           unsigned short len;
  3496.                           char           prm[80];
  3497.                          }               ent;
  3498.                  };
  3499.  
  3500. struct extraction {
  3501.                    int                   from_article_number;
  3502.                    int                   to_article_number;
  3503.                    int                   article_count;
  3504.                    enum data_set_type    mode;
  3505.                    void                (*closer)();
  3506.                    Bool                  appending;
  3507.                    Bool                  blanking;
  3508.                    Bool                  tab_expanding;
  3509.                    Bool                  ejecting;
  3510.                    Bool                  formfeeding;
  3511.                    char                  panelname     [9];
  3512.                    char                  dsname       [65];
  3513.                    char                  separator    [81];
  3514.                    char                  member_prefix [9];
  3515.                    char                  ddname        [9];
  3516.                    char                  member        [9];
  3517.                   };
  3518.  
  3519. struct countdown  {
  3520.                    Bool                  do_update;
  3521.                    int                   done;
  3522.                    int                   to_do;
  3523.                   };
  3524.  
  3525. struct nncb {
  3526.              char    *server_buf;
  3527.              char    *client_buf;
  3528.              char    *nntp_command;
  3529.              char    *nntp_message_text;
  3530.              char    *extract_separator_line;
  3531.  struct newsgroup    *first_newsgroup;
  3532.  struct newsgroup    *current_newsgroup;
  3533.  struct newsgroup    *last_newsgroup;
  3534.  struct newsgroup    *first_newsgroup_alt;
  3535.  struct newsgroup    *last_added_newsgroup;
  3536.  struct tablevector  *display_table_vector;
  3537.  struct extraction   *extractionp;
  3538.              FILE    *debug_file;
  3539.              FILE    *newsrc_file;
  3540.              FILE    *extract_file;
  3541.              FILE    *batch_infile;
  3542.              FILE    *batch_outfile;
  3543.              void    *batch_hook;
  3544. #ifdef FETCH
  3545.               int   (*isplink_pointer)();
  3546.               int   (*ispexec_pointer)();
  3547. #endif
  3548.   struct newsarticle *article_being_viewed;
  3549.               VARK  **top_sorted_article;
  3550.               VARK  **current_sortvark;
  3551.               int     top_article;
  3552.               int     ispfrc;
  3553.               int     nntp_message_num;
  3554.               int     socknum;
  3555.               int     g_bytes_returned;
  3556.               int     g_buf_index;
  3557.               int     new_newsgroup_count;
  3558.               int     article_rows;
  3559.               int     updatefreq;      /* ddi */
  3560.               int     text_find_left_bound;
  3561.               int     text_find_right_bound;
  3562.  enum article_cookie  another_article;
  3563.    struct texthdr     thdr;
  3564.         IPADDRESS     client_ip_address;
  3565.         IPADDRESS     server_ip_address;
  3566.              time_t   lasttime;           /* ddi */
  3567.              time_t   firstime;           /* ddi */
  3568.              Bool     test_mode;
  3569.              Bool     debug_mode;
  3570.              Bool     batch_mode;
  3571.              Bool     quit;
  3572.              Bool     time_to_go_home;
  3573.              Bool     server_has_something_pending;
  3574.              Bool     server_finished_replying;
  3575.              Bool     sending_text;
  3576.              Bool     receiving_text;
  3577.              Bool     something_to_print;
  3578.              Bool     dont_read;
  3579.              Bool     connected_to_server;
  3580.              Bool     connection_broken;
  3581.              Bool     closing_connection;
  3582.              Bool     reconnect_in_progress;
  3583.              Bool     posting_allowed;
  3584.              Bool     newsgroup_selected;
  3585.              Bool     newsgroup_not_found;
  3586.              Bool     newsgroup_order_changed;
  3587.              Bool     brand_new_newsrc;
  3588.              Bool     newsgroup_criterion_changed;
  3589.              Bool     show_all_newsgroups;
  3590.              Bool     following_up;
  3591.              Bool     extract_tab_expanding;
  3592.              Bool     extract_appending;
  3593.              Bool     extract_blank_before_separator;
  3594.              Bool     extract_ejecting;
  3595.              Bool     extract_formfeeding;
  3596.              Bool     extract_write_error;
  3597.              Bool     extract_close_error;
  3598.              Bool     please_locate_group;
  3599.              Bool     please_find_group;
  3600.              Bool     repeat_find;
  3601.              Bool     article_criterion_changed;
  3602.              Bool     article_repeat_find;
  3603.              Bool     article_text_not_found;
  3604.              Bool     warn_overwrite;
  3605.              Bool     warn_append;
  3606.              Bool     dont_reissue_socket_command;
  3607.              Bool     show_all_articles;
  3608.              Bool     update_adding_newsgroups;
  3609.              Bool     update_rewriting_newsrc;
  3610.              Bool     update_retrieving_articles;
  3611.              Bool     bypass_header_retrieval;
  3612.              Bool     unread_articles_only;
  3613.              Bool     setmsg;
  3614.              Bool     newsgroup_autoscroll;
  3615.              Bool     article_autoscroll;
  3616.              Bool     sort_by_subject;
  3617.              Bool     xhdr_not_available;
  3618.              Bool     newsgroup_autocursor;
  3619.              Bool     article_autocursor;
  3620.              Bool     setcursor;
  3621.              Bool     printing;
  3622.              Bool     dont_reconnect;
  3623.              char     newsgroup_order;
  3624.              char     newsgroup_find_option;
  3625.              char     article_find_option;
  3626.              char     preselection;
  3627.              char     barchar;                /* ddi */
  3628.              char     text_dispchar;
  3629.              char     text_find_what;
  3630.              char     text_find_type;
  3631.              char     text_find_trans;
  3632.              char     newsrc_to_open          [ 12];
  3633.              char     nnrfcopt                [  2];
  3634.              char     nnrfcinc                [256];
  3635.              char     nnrfcexc                [256];
  3636.              char     maildsn                 [ 64];
  3637.              char     messageid               [128];
  3638.              char     nnregnng                [  9];
  3639.              char     nngroup                 [GROUP_NAME_SIZE+1];
  3640.              char     nnserver                [MAXHOSTNAMELEN+1];
  3641.              char     nnclient                [MAXHOSTNAMELEN+1];
  3642.              char     client_hostname         [MAXHOSTNAMELEN+1];
  3643.              char     client_ip_addrstr       [16];
  3644.              char     server_hostname         [MAXHOSTNAMELEN+1];
  3645.              char     server_ip_addrstr       [16];
  3646.              char     g_buf                   [READ_BYTES];
  3647.              char     newsgroup_locate_string [GROUP_NAME_SIZE+1];
  3648.              char     newsgroup_only_string   [GROUP_NAME_SIZE+1];
  3649.              char     newsgroup_find_string   [GROUP_NAME_SIZE+1];
  3650.              char     article_only_string     [GROUP_NAME_SIZE+1];
  3651.              char     article_find_string     [GROUP_NAME_SIZE+1];
  3652.              char     lastNGdate              [7];      /* ddi */
  3653.              char     lastNGtime              [7];      /* ddi */
  3654.              char     selsubj                 [81];     /* ddi */
  3655.              char     text_find_string        [GROUP_NAME_SIZE+1];
  3656.             };
  3657.  
  3658. #ifdef MVS
  3659. #ifndef I370
  3660. extern char                 ebcdictoascii[];
  3661. extern char                 asciitoebcdic[];
  3662. #endif
  3663. #endif
  3664.  
  3665. #ifndef FETCH
  3666. extern int                  isplink();
  3667. extern int                  ispexec();
  3668. #endif
  3669.  
  3670. /****** Procedure and function declarations. *************************/
  3671.  
  3672. extern struct newsgroup   *NNMaddng(struct nncb *, char *);
  3673. extern void                NNMadjua(struct nncb *, struct newsgroup *,
  3674.                                                         int, int, int);
  3675. extern void                NNMallav(struct nncb *, struct newsgroup *,
  3676.                                                              int, int);
  3677. extern Bool                NNMalloc(char *, char *, enum data_set_type,
  3678.                                                                   int);
  3679. extern Bool                NNMauth (struct nncb *);
  3680. extern int                 NNMbatch(struct nncb *);
  3681. extern void                NNMbtext(struct nncb *, struct texthdr *,
  3682.                                                                FILE *);
  3683. extern Bool                NNMcar  (struct nncb *,struct newsgroup *,
  3684.                                        int,VARK *,struct newsarticle **,
  3685.                                        struct countdown *,
  3686.                                        enum choose_reason);
  3687. extern void                NNMclrng(struct nncb *);
  3688. extern void                NNMclrtx(struct nncb *,struct newsarticle *);
  3689. extern void                NNMcnrf (struct nncb *, char *, Fool);
  3690. extern Bool                NNMconn (struct nncb *);
  3691. extern char               *NNMcopy (struct nncb *, char *);
  3692. extern Bool                NNMdcan (struct nncb *,struct newsgroup *,
  3693.                                                   struct newsarticle *);
  3694. extern void                NNMdfail(int,__S99parms *);
  3695. extern void                NNMdisc (struct nncb *);
  3696. extern int                 NNMdispl(struct nncb *, char *);
  3697. extern Bool                NNMdlang(struct nncb *, enum list_option);
  3698. extern void                NNMdmail(struct nncb *,struct newsgroup *,
  3699.                                                   struct newsarticle *);
  3700. extern enum display_retval NNMdmenu(struct nncb *, Bool (**)());
  3701. extern struct newsgroup   *NNMdng  (struct nncb *,
  3702.                                            struct newsgroup *, char *);
  3703. extern void                NNMdnntp(struct nncb *, char *);
  3704. extern void                NNMdoit (struct nncb *,
  3705.                                             struct newsarticle *, Fool);
  3706. extern void                NNMdpost(struct nncb *,struct newsgroup *,
  3707.                                                   struct newsarticle *);
  3708. extern void                NNMdsopt(struct nncb *,char *);
  3709. extern void                NNMdump (struct nncb *,char *, char *, int);
  3710. extern void                NNMesrvr(struct nncb *);
  3711. extern Bool                NNMestng(struct nncb *, char *);
  3712. extern void                NNMfreem(struct nncb *,char *,char *);
  3713. extern FILE               *NNMgetds(struct nncb *,struct extraction *);
  3714. extern void                NNMgetm (struct nncb *,char **,int,char *);
  3715. extern Bool                NNMgsrvl(struct nncb *, char **);
  3716. extern void                NNMierr (struct nncb *);
  3717. extern int                 NNMiget (struct nncb *, char *);
  3718. extern void                NNMimsg (struct nncb *, char *);
  3719. extern void                NNMinit (struct nncb *);
  3720. extern Bool                NNMispf (struct nncb *, char *);
  3721. extern Bool                NNMivget(struct nncb *, char *, char *,int);
  3722. extern Bool                NNMivput(struct nncb *, char *, char *,int);
  3723. extern void                NNMmarr(struct nncb *, struct newsgroup *,
  3724.                                                                 VARK *);
  3725. extern void                NNMmaru(struct nncb *, struct newsgroup *,
  3726.                                                                 VARK *);
  3727. extern void                NNMnntp (struct nncb *);
  3728. extern void                NNMonrf (struct nncb *, char *);
  3729. extern struct textline    *NNMouttx(struct nncb *, char *,
  3730.                                                   struct newsarticle *);
  3731. extern Bool                NNMpick (struct nncb *,struct newsarticle *);
  3732. extern Bool                NNMpng  (struct nncb *,struct newsgroup *,
  3733.                                                              Fool,Fool);
  3734. extern Bool                NNMqar  (struct nncb *,struct newsarticle *);
  3735. extern void                NNMqng  (struct nncb *,struct newsgroup *);
  3736. extern struct newsarticle *NNMrarh (struct nncb *,struct newsgroup *,
  3737.                                          VARK *,int,struct countdown *);
  3738. extern int                 NNMrart (struct nncb *,struct newsgroup *,
  3739.                                                              Fool,Fool);
  3740. extern void                NNMrbfm (struct nncb *);
  3741. extern Bool                NNMrecon(struct nncb *);
  3742. extern void                NNMrperr(struct nncb *);
  3743. extern Bool                NNMsave (struct nncb *,char *);
  3744. extern Bool                NNMsockt(struct nncb *);
  3745. extern void                NNMsopt (struct nncb *, enum user_option);
  3746. extern Bool                NNMsort (struct nncb *,struct newsgroup *);
  3747. extern void                NNMssrvr(struct nncb *);
  3748. extern char               *NNMstrlc(char *, char *);
  3749. extern Bool                NNMsumat(char *, char *);
  3750. extern int                 NNMtso  (char *);
  3751. extern Bool                NNMunalc(char *);
  3752. extern void                NNMupdt (struct nncb *,struct countdown *,
  3753.                                                   char *);
  3754. extern Bool                NNMvar  (struct nncb *,struct newsgroup *);
  3755. extern void                NNMview (struct nncb *,struct newsgroup *,
  3756.                                                   struct newsarticle *,
  3757.                                                   struct texthdr *,
  3758.                                                   char *);
  3759. extern Bool                NNMvng  (struct nncb *);
  3760. extern void                NNMvtx  (struct nncb *,struct newsgroup *,
  3761.                                                   struct newsarticle *);
  3762. extern Bool                NNMxartt(struct nncb *,struct newsgroup *,
  3763.                                                   enum data_set_type);
  3764. extern Bool                NNMxartx(struct nncb *,struct newsgroup *,
  3765.                                                   enum data_set_type);
  3766. extern Bool                NNMxlist(struct nncb *,enum data_set_type);
  3767. extern Bool                NNMxtx  (struct nncb *,struct newsarticle *,
  3768.                                                   Fool);
  3769.  
  3770. #ifndef SUPPRESS_V_DECLARATION
  3771. extern void                NNMpmsg (struct nncb *,int,char *,char *,
  3772.                                                                   ...);
  3773. #endif
  3774.  
  3775. #ifdef C370V2
  3776. #pragma checkout(resume)
  3777. #endif
  3778.  
  3779. ./ ADD NAME=NNBATCH
  3780.  
  3781.  /********************************************************************/
  3782.  /*                                                                  */
  3783.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  3784.  /*                                                                  */
  3785.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  3786.  /* including the implied warranties of merchantability and fitness, */
  3787.  /* are expressly denied.                                            */
  3788.  /*                                                                  */
  3789.  /* Provided this copyright notice is included, this software may    */
  3790.  /* be freely distributed and not offered for sale.                  */
  3791.  /*                                                                  */
  3792.  /* Changes or modifications may be made and used only by the maker  */
  3793.  /* of same, and not further distributed.  Such modifications should */
  3794.  /* be mailed to the author for consideration for addition to the    */
  3795.  /* software and incorporation in subsequent releases.               */
  3796.  /*                                                                  */
  3797.  /********************************************************************/
  3798.  
  3799. /* ------------------ "nnbatch.h" include member ------------------- */
  3800.  
  3801. /* Include file for NNMVS batch mode operations. */
  3802.  
  3803.  
  3804. #define FIRST_ARTICLE_IN_RANGE             (-1)
  3805. #define LAST_ARTICLE_IN_RANGE              (2147483647)
  3806.  
  3807. #define MIN_RESERVED_WORD_LENGTH 2
  3808. #define MAX_RESERVED_WORD_LENGTH 10
  3809.  
  3810. #define ANYTYPE     void *
  3811.  
  3812. #define PEEK()      (NNMbgtok(np,bp,TOKEN_PEEK) ? &bp->nextok : NULL)
  3813. #define EAT()       (void)NNMbgtok(np,bp,TOKEN_READ)
  3814.  
  3815. #define SETA(X,Y)   NNMbvput(np,bp,(X),NUMBER_SYMTYPE,(ANYTYPE)(Y))
  3816. #define SETB(X,Y)   NNMbvput(np,bp,(X),FLAG_SYMTYPE,  (ANYTYPE)(Y))
  3817. #define SETC(X,Y)   NNMbvput(np,bp,(X),STRING_SYMTYPE,(ANYTYPE)(Y))
  3818.  
  3819. #define GETA(X)     (int)   NNMbvget(np,bp,(X),NUMBER_SYMTYPE)
  3820. #define GETB(X)     (Fool)  NNMbvget(np,bp,(X),FLAG_SYMTYPE)
  3821. #define GETC(X)     (char *)NNMbvget(np,bp,(X),STRING_SYMTYPE)
  3822.  
  3823. typedef struct newscmd *(*CommandParser)   ();
  3824. typedef void            (*CommandExecutor) ();
  3825.  
  3826. enum tokentype        {NO_TOKEN,
  3827.                        EOL_TOKEN,
  3828.                        EOF_TOKEN,
  3829.                        AND_TOKEN,
  3830.                        OR_TOKEN,
  3831.                        NOT_TOKEN,
  3832.                        GT_TOKEN,
  3833.                        LT_TOKEN,
  3834.                        EQ_TOKEN,
  3835.                        NE_TOKEN,
  3836.                        GE_TOKEN,
  3837.                        LE_TOKEN,
  3838.                        LPAR_TOKEN,
  3839.                        RPAR_TOKEN,
  3840.                        PLUS_TOKEN,
  3841.                        MINUS_TOKEN,
  3842.                        TIMES_TOKEN,
  3843.                        OVER_TOKEN,
  3844.                        SEMI_TOKEN,
  3845.                        WORD_TOKEN,
  3846.                        NUMBER_TOKEN,
  3847.                        STRING_TOKEN,
  3848.                        ERROR_TOKEN
  3849.                       };
  3850.  
  3851. enum tokenfunc        {
  3852.                        TOKEN_PEEK,
  3853.                        TOKEN_READ,
  3854.                        TOKEN_FLUSH
  3855.                       };
  3856.  
  3857. enum batchmode        {
  3858.                        INITIAL_MODE,
  3859.                        PER_NEWSGROUP_MODE,
  3860.                        PER_ARTICLE_MODE,
  3861.                        TEXT_MODE,
  3862.                        ERROR_MODE,
  3863.                        ANY_MODE
  3864.                       };
  3865.  
  3866. enum marking_mode     {
  3867.                        MARKING_READ,
  3868.                        MARKING_UNREAD
  3869.                       };
  3870.  
  3871. enum extracting_mode  {
  3872.                        NO_EXTRACTING_MODE,
  3873.                        EXTRACTING_ALL,
  3874.                        EXTRACTING_READ,
  3875.                        EXTRACTING_UNREAD
  3876.                       };
  3877.  
  3878. enum which_newsgroups {
  3879.                        NO_NEWSGROUPS,
  3880.                        ALL_NEWSGROUPS,
  3881.                        REGISTERED_NEWSGROUPS,
  3882.                        UNREGISTERED_NEWSGROUPS,
  3883.                        NAMED_NEWSGROUPS,
  3884.                        MASKED_NEWSGROUPS
  3885.                       };
  3886.  
  3887. enum which_articles   {
  3888.                        NO_ARTICLES,
  3889.                        ALL_ARTICLES,
  3890.                        READ_ARTICLES,
  3891.                        UNREAD_ARTICLES,
  3892.                        RANGED_ARTICLES
  3893.                       };
  3894.  
  3895. enum symtype          {
  3896.                        NO_SYMTYPE,
  3897.                        STRING_SYMTYPE,
  3898.                        NUMBER_SYMTYPE,
  3899.                        FLAG_SYMTYPE
  3900.                       };
  3901.  
  3902. /*-------------------------------------------------------------------*
  3903.  * Define structures to handle expressions computed at run time.
  3904.  *-------------------------------------------------------------------*/
  3905.  
  3906. #include "nnptree.h"   /* Grammar to handle general expressions */
  3907.  
  3908. /*-------------------------------------------------------------------*
  3909.  * newsgroup_crit: defines criteria for selecting newsgroups.
  3910.  *                 Corresponds to xxx in:
  3911.  *                   FOR xxx WHEN (yyy) DO zzz
  3912.  *                 in top-level mode.
  3913.  *-------------------------------------------------------------------*/
  3914.  
  3915. struct newsgroup_crit {
  3916.                        enum which_newsgroups     which;
  3917.                        struct ptree             *groups;
  3918.                       };
  3919.  
  3920. /*-------------------------------------------------------------------*
  3921.  * article_crit: defines criteria for selecting articles.
  3922.  *               Corresponds to xxx in:
  3923.  *                 FOR xxx WHEN (yyy) DO zzz
  3924.  *               in per-newsgroup mode.
  3925.  *-------------------------------------------------------------------*/
  3926.  
  3927. struct article_crit {
  3928.                        enum which_articles       which;
  3929.                        struct ptree             *first;
  3930.                        struct ptree             *last;
  3931.                       };
  3932.  
  3933. /*-------------------------------------------------------------------*
  3934.  * for_newsgroups: defines what to do for each newsgroup and which
  3935.  *                 newsgroups were selected.  Corresponds to:
  3936.  *                   FOR xxx WHEN (yyy) DO zzz
  3937.  *                 in top-level mode.
  3938.  *-------------------------------------------------------------------*/
  3939.  
  3940. struct for_newsgroups {
  3941.                        struct ptree             *filter;
  3942.                        struct newsgroup_crit     crit;
  3943.                        struct cmdtree           *treep;
  3944.                       };
  3945.  
  3946. /*-------------------------------------------------------------------*
  3947.  * for_articles:   defines what to do for each article and which
  3948.  *                 articles were selected.  Corresponds to:
  3949.  *                   FOR xxx WHEN (yyy) DO zzz
  3950.  *                 in per-newsgroup mode.
  3951.  *-------------------------------------------------------------------*/
  3952.  
  3953. struct for_articles   {
  3954.                        struct ptree             *filter;
  3955.                        struct article_crit       crit;
  3956.                        struct cmdtree           *treep;
  3957.                       };
  3958.  
  3959. /*-------------------------------------------------------------------*
  3960.  * OK, here are defined the kinds of commands.
  3961.  *-------------------------------------------------------------------*/
  3962.  
  3963. struct initial_mode_cmd        {
  3964.                                 struct for_newsgroups       fors;
  3965.                                };
  3966.  
  3967. struct per_newsgroup_mode_cmd  {
  3968.                                 struct for_articles         fors;
  3969.                                };
  3970.  
  3971. struct if_cmd                  {
  3972.                                 struct ptree               *condition;
  3973.                                 struct cmdtree             *thencmds;
  3974.                                 struct cmdtree             *elsecmds;
  3975.                                };
  3976.  
  3977. struct set_cmd                 {
  3978.                                 struct ptree               *ptreep;
  3979.                                 char *                      set_symbol;
  3980.                                 enum symtype                set_type;
  3981.                                };
  3982.  
  3983. struct mark_cmd                {
  3984.                                 enum marking_mode           marking;
  3985.                                };
  3986.  
  3987. struct extract_cmd             {
  3988.                                 enum extracting_mode        extracting;
  3989.                                };
  3990.  
  3991. struct miscellaneous_cmd       {
  3992.                                 struct ptree               *ptreep;
  3993.                                };
  3994.  
  3995. union some_mode_cmd   {
  3996.                        struct initial_mode_cmd       icmd;
  3997.                        struct per_newsgroup_mode_cmd ncmd;
  3998.                        struct if_cmd                 fcmd;
  3999.                        struct set_cmd                scmd;
  4000.                        struct mark_cmd               rcmd;
  4001.                        struct extract_cmd            xcmd;
  4002.                        struct miscellaneous_cmd      mcmd;
  4003.                       };
  4004.  
  4005. /*-------------------------------------------------------------------*
  4006.  * newscmd:   defines format of operations to perform on something.
  4007.  *-------------------------------------------------------------------*/
  4008.  
  4009. struct newscmd        {
  4010.                        enum batchmode            mode;
  4011.                        CommandExecutor           proc;
  4012.                        union some_mode_cmd       cmd;
  4013.                       };
  4014.  
  4015. struct cmdtree        {
  4016.                        struct cmdtree *next;
  4017.                        struct newscmd *cmd;
  4018.                       };
  4019.  
  4020. #define MAX_SYMBOL_LENGTH      16
  4021.  
  4022. /*-------------------------------------------------------------------*
  4023.  * symtab:    defines symbol table that holds values of variables.
  4024.  *            The complete symbol table is a classic binary tree of
  4025.  *            symtab structs.
  4026.  *
  4027.  * To allocate, take length of variable value string,
  4028.  * then add that to offsetof(struct symtab,symval) to get total.
  4029.  *-------------------------------------------------------------------*/
  4030.  
  4031. struct symtab {
  4032.                char            symvar[MAX_SYMBOL_LENGTH];
  4033.                struct symtab  *left;
  4034.                struct symtab  *right;
  4035.                enum symtype    type;
  4036.                int             symnum;
  4037.                int             vallen;
  4038.                char            symval[1];      /* dummy for alloc */
  4039.               };
  4040.  
  4041. struct token {
  4042.               enum tokentype   type;
  4043.               char             string [260];
  4044.               int              number;
  4045.              };
  4046.  
  4047. struct batch {
  4048.               struct cmdtree     *treetop;
  4049.               struct cmdtree     *treebottom;
  4050.               struct symtab      *symtabp;
  4051.               struct newsgroup   *gp;
  4052.               VARK               *vp;
  4053.               struct newscmd     *ifcmd;
  4054.               char               *inchar;
  4055.               char               *reserved_words;
  4056.               char               *outfilename;
  4057.               FILE               *outfp;
  4058.               int                 input_errors;
  4059.               int                 request_errors;
  4060.               enum batchmode      mode;
  4061.               enum data_set_type  extractds_mode;
  4062.               CommandParser       endproc;
  4063.               jmp_buf             jump;
  4064.               struct token        curtok;
  4065.               struct token        nextok;
  4066.               Bool                exactcase;
  4067.               Bool                syntax_error;
  4068.               Bool                runtime_error;
  4069.               Bool                eof;
  4070.               Bool                quit;
  4071.               Bool                stop_at_newline;
  4072.               Bool                tokens_read;
  4073.               Bool                newsgroups_retrieved;
  4074.               char                inline          [260];
  4075.               char                extractds        [81];
  4076.               char                extractds_part1  [81];
  4077.               char                extractds_part2  [81];
  4078.               char                extractds_member [81];
  4079.              };
  4080.  
  4081. extern ANYTYPE         NNMbbexp(struct nncb *, struct batch *,
  4082.                                           struct ptree *,enum symtype);
  4083. extern Bool            NNMbconn(struct nncb *, struct batch *);
  4084. extern struct symtab  *NNMbdecl(struct nncb *, struct batch *, char *,
  4085.                                                 enum symtype, ANYTYPE);
  4086. extern void            NNMbflus(struct nncb *, struct batch *);
  4087. extern CommandParser   NNMbgcmd(struct nncb *, struct batch *);
  4088. extern struct cmdtree *NNMbgdo (struct nncb *, struct batch *,
  4089.                                                        enum batchmode);
  4090. extern struct ptree   *NNMbgexp(struct nncb *, struct batch *,
  4091.                                                          enum symtype);
  4092. extern Bool            NNMbgtok(struct nncb *, struct batch *,
  4093.                                                        enum tokenfunc);
  4094. extern FILE           *NNMbsout(struct nncb *, struct batch *);
  4095. extern void            NNMbsynt(struct nncb *, struct batch *,
  4096.                                                   char *, int, char *);
  4097. extern void            NNMbtras(struct nncb *, struct batch *, char *);
  4098. extern ANYTYPE         NNMbvget(struct nncb *, struct batch *, char *,
  4099.                                                          enum symtype);
  4100. extern void            NNMbvput(struct nncb *, struct batch *, char *,
  4101.                                                 enum symtype, ANYTYPE);
  4102. extern void            NNMbxfar (struct nncb *, struct batch *,
  4103.                                                       struct newscmd *);
  4104. extern void            NNMbxfng (struct nncb *, struct batch *,
  4105.                                                       struct newscmd *);
  4106.  
  4107. ./ ADD NAME=NNPTREE
  4108.  
  4109.  /********************************************************************/
  4110.  /*                                                                  */
  4111.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  4112.  /*                                                                  */
  4113.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  4114.  /* including the implied warranties of merchantability and fitness, */
  4115.  /* are expressly denied.                                            */
  4116.  /*                                                                  */
  4117.  /* Provided this copyright notice is included, this software may    */
  4118.  /* be freely distributed and not offered for sale.                  */
  4119.  /*                                                                  */
  4120.  /* Changes or modifications may be made and used only by the maker  */
  4121.  /* of same, and not further distributed.  Such modifications should */
  4122.  /* be mailed to the author for consideration for addition to the    */
  4123.  /* software and incorporation in subsequent releases.               */
  4124.  /*                                                                  */
  4125.  /********************************************************************/
  4126.  
  4127. /* ----------------- "nnptree.h" include member -------------------- */
  4128.  
  4129. #define ALLOC(X,Y)   GETMAIN(X,struct Y,1,#Y);\
  4130.                      if (!(X)) longjmp(bp->jump,ERROR_GETMAIN_FAILURE)
  4131. #define ERR(X)       (NNMbsynt(np,bp,bp->curtok.string,0,X),\
  4132.                       longjmp(bp->jump,ERROR_BAD_EXPRESSION))
  4133. #define LOSE         longjmp(bp->jump,ERROR_SCAN_ERROR)
  4134.  
  4135. #define ERROR_NONE              0
  4136. #define ERROR_TYPE_MISMATCH     1
  4137. #define ERROR_ZERODIVIDE        2
  4138. #define ERROR_GETMAIN_FAILURE   3
  4139. #define ERROR_BAD_EXPRESSION    4
  4140. #define ERROR_SCAN_ERROR        5
  4141.  
  4142. /*-------------------------------------------------------------------*
  4143.  * ptree: defines structure of expressions used by various commands,
  4144.  * including SET, PUT and NNTP.  When these commands are parsed,
  4145.  * a ptree structure is built to be interpreted when the command is
  4146.  * executed.  The structure represents one of the following:
  4147.  *
  4148.  * - a string expression (concatenated strings or string vars)
  4149.  * - a numeric expression (number, number var or arithmetic expr)
  4150.  * - a flag expression (flag, flag var or logical expr)
  4151.  *
  4152.  *-------------------------------------------------------------------*/
  4153.  
  4154. /*-------------------------------------------------------------------*
  4155.  * treetype: type of an expression tree.
  4156.  *-------------------------------------------------------------------*/
  4157.  
  4158. enum treetype   {
  4159.                  NO_TREETYPE,
  4160.                  STRING_TREETYPE,
  4161.                  NUMBER_TREETYPE,
  4162.                  FLAG_TREETYPE
  4163.                 };
  4164.  
  4165. /*-------------------------------------------------------------------*
  4166.  * rhstype:  type of an expression subtree, based on the RHS of a
  4167.  *           production.  Defines the structure of the components
  4168.  *           that make up this subtree.  Note that the types are
  4169.  *           meaningful only within a given production (LHS) type.
  4170.  *-------------------------------------------------------------------*/
  4171.  
  4172. enum rhstype    {
  4173.                  NO_RHSTYPE,
  4174.                  RHSTYPE_A,
  4175.                  RHSTYPE_B,
  4176.                  RHSTYPE_C,
  4177.                  RHSTYPE_D,
  4178.                  RHSTYPE_E
  4179.                 };
  4180.  
  4181. /*-------------------------------------------------------------------*
  4182.  * optype:  type of an operator
  4183.  *-------------------------------------------------------------------*/
  4184.  
  4185. enum optype     {
  4186.                  NO_OP,
  4187.                  AND_OP,
  4188.                  OR_OP,
  4189.                  NOT_OP,
  4190.                  IN_OP,
  4191.                  EQ_OP,
  4192.                  NE_OP,
  4193.                  GT_OP,
  4194.                  LT_OP,
  4195.                  GE_OP,
  4196.                  LE_OP,
  4197.                  ADD_OP,
  4198.                  SUB_OP,
  4199.                  MUL_OP,
  4200.                  DIV_OP
  4201.                 };
  4202.  
  4203. /*-------------------------------------------------------------------*
  4204.  * These types correspond to production LHS's.
  4205.  *-------------------------------------------------------------------*/
  4206.  
  4207. typedef struct exp        *       Exp;
  4208. typedef struct choice     *       Choice;
  4209. typedef struct relation   *       Relation;
  4210. typedef struct value      *       Value;
  4211. typedef struct quantity   *       Quantity;
  4212. typedef struct term       *       Term;
  4213. typedef struct factor     *       Factor;
  4214. typedef struct unop       *       Unop;
  4215. typedef struct addop      *       Addop;
  4216. typedef struct mulop      *       Mulop;
  4217. typedef struct logop      *       Logop;
  4218. typedef struct relop      *       Relop;
  4219. typedef struct constant   *       Constant;
  4220. typedef struct variable   *       Variable;
  4221. typedef struct number     *       Number;
  4222. typedef struct string     *       String;
  4223. typedef struct flag       *       Flag;
  4224.  
  4225. /*-------------------------------------------------------------------*
  4226.  * The following define the top-down LR(1) grammar.
  4227.  *-------------------------------------------------------------------*/
  4228.  
  4229. struct exp      {
  4230.                  enum rhstype           r;
  4231.                  enum symtype           s;
  4232.                  union {
  4233.                         struct {
  4234.                                 Choice          choice1;
  4235.                                }        a;
  4236.                         struct {
  4237.                                 /* "IF" */
  4238.                                 Exp             exp1;
  4239.                                 /* "THEN" */
  4240.                                 Exp             exp2;
  4241.                                 /* "ELSE" */
  4242.                                 Exp             exp3;
  4243.                                }        b;
  4244.                        }                u;
  4245.                 };
  4246.  
  4247. struct choice   {
  4248.                  enum rhstype           r;
  4249.                  enum symtype           s;
  4250.                  union {
  4251.                         struct {
  4252.                                 Relation        relation1;
  4253.                                }        a;
  4254.                         struct {
  4255.                                 Choice          choice1;
  4256.                                 Logop           logop2;
  4257.                                 Relation        relation3;
  4258.                                }        b;
  4259.                        }                u;
  4260.                 };
  4261.  
  4262. struct relation {
  4263.                  enum rhstype           r;
  4264.                  enum symtype           s;
  4265.                  union {
  4266.                         struct {
  4267.                                 Value           value1;
  4268.                                }        a;
  4269.                         struct {
  4270.                                 Value           value1;
  4271.                                 Relop           relop2;
  4272.                                 Value           value3;
  4273.                                }        b;
  4274.                        }                u;
  4275.                 };
  4276.  
  4277. struct value    {
  4278.                  enum rhstype           r;
  4279.                  enum symtype           s;
  4280.                  union {
  4281.                         struct {
  4282.                                 Quantity        quantity1;
  4283.                                }        a;
  4284.                         struct {
  4285.                                 Value           value1;
  4286.                                 Quantity        quantity2;
  4287.                                }        b;
  4288.                        }                u;
  4289.                 };
  4290.  
  4291. struct quantity {
  4292.                  enum rhstype           r;
  4293.                  enum symtype           s;
  4294.                  union {
  4295.                         struct {
  4296.                                 Term            term1;
  4297.                                }        a;
  4298.                         struct {
  4299.                                 Quantity        quantity1;
  4300.                                 Addop           addop2;
  4301.                                 Term            term3;
  4302.                                }        b;
  4303.                        }                u;
  4304.                 };
  4305.  
  4306. struct term     {
  4307.                  enum rhstype           r;
  4308.                  enum symtype           s;
  4309.                  union {
  4310.                         struct {
  4311.                                 Factor          factor1;
  4312.                                }        a;
  4313.                         struct {
  4314.                                 Term            term1;
  4315.                                 Mulop           mulop2;
  4316.                                 Factor          factor3;
  4317.                                }        b;
  4318.                        }                u;
  4319.                 };
  4320.  
  4321. struct factor   {
  4322.                  enum rhstype           r;
  4323.                  enum symtype           s;
  4324.                  union {
  4325.                         struct {
  4326.                                 Constant        constant1;
  4327.                                }        a;
  4328.                         struct {
  4329.                                 Variable        variable1;
  4330.                                }        b;
  4331.                         struct {
  4332.                                 Unop            unop1;
  4333.                                 Factor          factor2;
  4334.                                }        c;
  4335.                         struct {
  4336.                                 /* "(" */
  4337.                                 Exp             exp1;
  4338.                                 /* ")" */
  4339.                                }        d;
  4340.                        }                u;
  4341.                 };
  4342.  
  4343. struct constant {
  4344.                  enum rhstype           r;
  4345.                  enum symtype           s;
  4346.                  union {
  4347.                         struct {
  4348.                                 Number          number1;
  4349.                                }        a;
  4350.                         struct {
  4351.                                 String          string1;
  4352.                                }        b;
  4353.                         struct {
  4354.                                 Flag            flag1;
  4355.                                }        c;
  4356.                        }                u;
  4357.                 };
  4358.  
  4359. struct unop     {
  4360.                  enum optype            op1;    /* + - ! ^ */
  4361.                 };
  4362.  
  4363. struct addop    {
  4364.                  enum optype            op1;    /* + - */
  4365.                 };
  4366.  
  4367. struct mulop    {
  4368.                  enum optype            op1;    /* * / */
  4369.                 };
  4370.  
  4371. struct logop    {
  4372.                  enum optype            op1;    /* AND OR */
  4373.                 };
  4374.  
  4375. struct relop    {
  4376.                  enum optype            op1;    /* EQ GT LE NE IN... */
  4377.                 };
  4378.  
  4379. struct variable {
  4380.                  enum symtype           s;
  4381.                  char *                 variable1;
  4382.                 };
  4383.  
  4384. struct number   {
  4385.                  enum symtype           s;
  4386.                  int                    number1;
  4387.                 };
  4388.  
  4389. struct string   {
  4390.                  enum symtype           s;
  4391.                  char                  *string1;
  4392.                 };
  4393.  
  4394. struct flag     {
  4395.                  enum symtype           s;
  4396.                  Fool                   flag1;  /* ON OFF TRUE FALSE */
  4397.                 };
  4398.  
  4399. /*-------------------------------------------------------------------*
  4400.  * thing: describes entity to be returned from a ptree at run time
  4401.  *-------------------------------------------------------------------*/
  4402.  
  4403. struct thing    {
  4404.                  ANYTYPE                val;    /* char *, int, Fool */
  4405.                  enum symtype           typ;    /* string/number/flag*/
  4406.                 };
  4407.  
  4408. /*-------------------------------------------------------------------*
  4409.  * ptree: expression tree.  Root of string/number/flag expression
  4410.  *-------------------------------------------------------------------*/
  4411.  
  4412. struct ptree    {
  4413.                  enum symtype           type;   /* string/number/flag*/
  4414.                  Exp                    exp1;   /* actual expression */
  4415.                 };
  4416.  
  4417. ./ ADD NAME=NNSASC
  4418.  
  4419.  /********************************************************************/
  4420.  /*                                                                  */
  4421.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  4422.  /*                                                                  */
  4423.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  4424.  /*                                                                  */
  4425.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  4426.  /* including the implied warranties of merchantability and fitness, */
  4427.  /* are expressly denied.                                            */
  4428.  /*                                                                  */
  4429.  /* Provided this copyright notice is included, this software may    */
  4430.  /* be freely distributed and not offered for sale.                  */
  4431.  /*                                                                  */
  4432.  /* Changes or modifications may be made and used only by the maker  */
  4433.  /* of same, and not further distributed.  Such modifications should */
  4434.  /* be mailed to the author for consideration for addition to the    */
  4435.  /* software and incorporation in subsequent releases.               */
  4436.  /*                                                                  */
  4437.  /********************************************************************/
  4438.  
  4439. /* ------------------- "nnsasc.h" include member ------------------- */
  4440.  
  4441. #ifdef SASC
  4442.  
  4443. #define I370
  4444.  
  4445. #include <dynam.h>
  4446.  
  4447. #define FETCH
  4448.  
  4449.  __inline void (*fetch( const char *modname ))()
  4450.  {
  4451.    void (**fpp)();
  4452.  
  4453.    loadm( modname, &fpp );
  4454.    return( *fpp );
  4455.  }
  4456.  
  4457.  __inline int (*release( void (*fpp)() ))
  4458.  {
  4459.    unloadm( fpp );
  4460.    return( 0 );
  4461.  }
  4462.  
  4463.  
  4464. #ifndef __SVC99
  4465.  
  4466.   #define __SVC99  1
  4467.  
  4468.   #include <code.h>
  4469.  
  4470.   struct __S99struc
  4471.     {
  4472.       unsigned char   __S99RBLN;  /* length of request block..20      */
  4473.       unsigned char   __S99VERB;  /* verb code                        */
  4474.       unsigned short  __S99FLAG1; /* FLAGS1 field of SVC99 Req Block  */
  4475.       unsigned short  __S99ERROR; /* error code field                 */
  4476.       unsigned short  __S99INFO;  /* information reason code          */
  4477.       void           *__S99TXTPP; /* address of text unit pointer list*/
  4478.       int             __reserved; /* reserved..will always be 0       */
  4479.       unsigned int    __S99FLAG2; /* FLAGS2 field..can only be filled */
  4480.                                   /* in by APF authorized programs    */
  4481.     };
  4482.  
  4483.   typedef struct __S99struc __S99parms;
  4484.  
  4485.   __inline int svc99(__S99parms* svc99parmlist)
  4486.     { return( (_ldregs(R1, &svc99parmlist),
  4487.                _code(0, 0x9680, 0x1000),
  4488.                _code(0, 0x0a63),
  4489.                _stregs(R15) ) );
  4490.     }
  4491.  
  4492. #endif
  4493.  
  4494. #define FALSE 0
  4495. #define TRUE  1
  4496.  
  4497. #include <lcio.h>
  4498.  
  4499. #define  MAXHOSTNAMELEN     64
  4500.  
  4501. #define  __ctest(X)  fprintf(stderr,\
  4502.                      "NNMVS: CTEST is not supported by this compiler.")
  4503.  
  4504. #endif
  4505.  
  4506. ./ ADD NAME=NNUSER
  4507.  
  4508.  /********************************************************************/
  4509.  /*                                                                  */
  4510.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  4511.  /*                                                                  */
  4512.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  4513.  /* including the implied warranties of merchantability and fitness, */
  4514.  /* are expressly denied.                                            */
  4515.  /*                                                                  */
  4516.  /* Provided this copyright notice is included, this software may    */
  4517.  /* be freely distributed and not offered for sale.                  */
  4518.  /*                                                                  */
  4519.  /* Changes or modifications may be made and used only by the maker  */
  4520.  /* of same, and not further distributed.  Such modifications should */
  4521.  /* be mailed to the author for consideration for addition to the    */
  4522.  /* software and incorporation in subsequent releases.               */
  4523.  /*                                                                  */
  4524.  /********************************************************************/
  4525.  
  4526. /* ------------------- "nnuser.h" include member ------------------- */
  4527.  
  4528. /* Include file for locally customized values. */
  4529.  
  4530. /* Define levels of C/370 and TCP/IP.  This controls support for
  4531.  * fetching of non-C load modules and socket error reporting.
  4532.  */
  4533.  
  4534. /* #define  C370V1    /* define this if C/370 Version 1 */
  4535.    #define  C370V2    /* define this if C/370 Version 2 or higher */
  4536. /* #define  SASC      /* define this if SAS/C compiler */
  4537.  
  4538. /* #define  TCPIPV1   /* define this if TCP/IP Version 1 */
  4539.    #define  TCPIPV2   /* define this if TCP/IP Version 2 or higher */
  4540. /* #define  SNSTCPIP  /* define this if SNS/TCPAccess    */
  4541.  
  4542. /* #define  ISPFV2    /* define this if ISPF Version 2 or earlier */
  4543.    #define  ISPFV3    /* define this if ISPF Version 3 or later
  4544.  
  4545. /* Define the following defaults for your installation. */
  4546.  
  4547. /*
  4548.  * Specify the "user name" portion of the "Sender:" address generated
  4549.  * by posting and mailing requests.
  4550.  *
  4551.  */
  4552.  
  4553. #define NNMVS_NAME  "NNMVS"
  4554.  
  4555. /*
  4556.  * Specify the name of the authorization file used to pass AUTHINFO
  4557.  * requests to the server, if the server requires.  This file should
  4558.  * be readable only by NNMVS if possible.  See the sample authorization
  4559.  * file (AUTH) for the format.
  4560.  *
  4561.  */
  4562.  
  4563. /* #define AUTHFILE    "SYS4.NNTP.SYS"  */
  4564.    #undef  AUTHFILE
  4565.  
  4566. /*
  4567.  * Turn on for TCP-level debugging output (you probably don't want to
  4568.  * unless your TCP/IP stuff is really broken and I can't help you).
  4569.  */
  4570.  
  4571. /* #define DEBUG       */
  4572.    #undef  DEBUG
  4573.  
  4574. /*
  4575.  * Define this if you want DEST, FORMS and UCS for print requests.
  4576.  * Undefine it if you don't (you get just CLASS and COPIES).
  4577.  */
  4578.  
  4579. /* #define FULLSYSOUT  */
  4580.    #undef  FULLSYSOUT
  4581.  
  4582. /*
  4583.  * Define this if you want to be able to do automatic reconnection from
  4584.  * anywhere at any time.  The default is to be able to do automatic
  4585.  * reconnection from anywhere *except* when the list of newsgroups
  4586.  * is being built, to protect newsrc from being wiped out.
  4587.  */
  4588.  
  4589. /* #define RECONNECT_AND_MAYBE_DESTROY_NEWSRC  */
  4590.    #undef  RECONNECT_AND_MAYBE_DESTROY_NEWSRC
  4591.  
  4592. ./ ENDUP
  4593. ?!
  4594. //C        EXEC MDLOAD,BS='6160',TRK1='50',TRK2='1',TO='C'
  4595. //SYSIN    DD   DATA,DLM='?!'
  4596. ./ ADD NAME=NNMADDNG
  4597.  
  4598.  /********************************************************************/
  4599.  /*                                                                  */
  4600.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  4601.  /*                                                                  */
  4602.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  4603.  /* including the implied warranties of merchantability and fitness, */
  4604.  /* are expressly denied.                                            */
  4605.  /*                                                                  */
  4606.  /* Provided this copyright notice is included, this software may    */
  4607.  /* be freely distributed and not offered for sale.                  */
  4608.  /*                                                                  */
  4609.  /* Changes or modifications may be made and used only by the maker  */
  4610.  /* of same, and not further distributed.  Such modifications should */
  4611.  /* be mailed to the author for consideration for addition to the    */
  4612.  /* software and incorporation in subsequent releases.               */
  4613.  /*                                                                  */
  4614.  /********************************************************************/
  4615.  
  4616. #pragma  csect(code,  "NN@ADDNG")
  4617. #pragma  csect(static,"NN$ADDNG")
  4618.  
  4619. #include "nn.h"
  4620.  
  4621. #define KEEP_NEWSGROUPS_IN_ALPHABETICAL_ORDER
  4622.  
  4623. /****** Create a new newsgroup. **************************************/
  4624.  
  4625. static struct newsgroup *
  4626. new_newsgroup(np,gname)
  4627. Rstruc nncb         *np;
  4628. char                *gname;
  4629. {
  4630.  struct newsgroup   *gp;
  4631.  int                 gsize;
  4632.  char                temp [128];
  4633.  
  4634.  gsize = offsetof(struct newsgroup, name) + strlen(gname) + 1;
  4635.  
  4636.  sprintf(temp, "newsgroup %s", gname);
  4637.  GETMAIN(gp, char, gsize, temp);
  4638.  
  4639.  if (!gp) {
  4640.    ERR2("There is not enough memory to add newsgroup %s.",gname);
  4641.    return NULL;
  4642.  }
  4643.  
  4644.  memset(gp, 0, gsize);
  4645.  strcpy(gp->name, gname);
  4646.  ClearGroupStatus(gp);
  4647.  
  4648.  np->last_added_newsgroup = gp;
  4649.  
  4650.  return gp;
  4651.  
  4652. }
  4653.  
  4654. /****** Add newsgroup. ***********************************************/
  4655.  
  4656. struct newsgroup *
  4657. NNMaddng(np,gname)
  4658. Rstruc nncb         *np;
  4659. char                *gname;
  4660. {
  4661.  Rstruc newsgroup   *gp;
  4662.  struct newsgroup   *prev_gp;
  4663.  struct newsgroup   *next_gp;
  4664.  int                 s;
  4665.  
  4666.  /* If there are no newsgroups yet, make this the first one.       */
  4667.  /* If the newsgroup is currently in the newsgroup list, reuse it. */
  4668.  /* Otherwise add it. */
  4669.  
  4670.  if (np->first_newsgroup == NULL) {
  4671.    if ((gp=new_newsgroup(np,gname))) {
  4672.      np->first_newsgroup   = gp;
  4673.      np->current_newsgroup = gp;
  4674.      np->last_newsgroup    = gp;
  4675.    }
  4676.    return gp;
  4677.  }
  4678.  
  4679.  prev_gp = NULL;
  4680.  next_gp = NULL;
  4681.  
  4682.  
  4683. #ifdef KEEP_NEWSGROUPS_IN_ALPHABETICAL_ORDER
  4684.  
  4685.  /* Chances are this newsgroup will be right after the last one that
  4686.     we added.  Check there first. */
  4687.  
  4688.  gp = np->last_added_newsgroup;         /* search from last added  */
  4689.  if (!gp || strcmp(gname,gp->name) < 0) /* unless ours precedes it */
  4690.      gp = np->first_newsgroup;          /* then search from top    */
  4691.  
  4692.  for (; gp; gp = gp->next) {
  4693.    s = strcmp(gname,gp->name);
  4694.    if (s == 0)     { /* equal */
  4695.      np->current_newsgroup = gp;
  4696.      return gp;
  4697.    }
  4698.    else if (s < 0) { /* ours is less than theirs */
  4699.      next_gp = gp;
  4700.      break;
  4701.    }
  4702.    else            { /* ours is still greater */
  4703.      prev_gp = gp;
  4704.      next_gp = NULL;
  4705.    }
  4706.  }
  4707.  
  4708. #else
  4709.  
  4710.  /* keep newsgroups in NEWSRC order - not currently implemented */
  4711.  
  4712.  for (gp = np->first_newsgroup;
  4713.       gp && strcmp(gname,gp->name) != 0;
  4714.       gp = gp->next) ;
  4715.  
  4716.  if (gp) {   /* newsgroup already in list */
  4717.    np->current_newsgroup = gp;
  4718.    return gp;
  4719.  }
  4720.  
  4721.  next_gp = NULL;
  4722.  prev_gp = np->last_newsgroup;
  4723.  
  4724. #endif
  4725.  
  4726.  /* newsgroup not in list - add it now */
  4727.  
  4728.  if ((gp=new_newsgroup(np,gname))) {
  4729.  
  4730.    if (next_gp == NULL) np->last_newsgroup = gp;
  4731.    else                 gp->next = next_gp;
  4732.    if (prev_gp == NULL) np->first_newsgroup = gp;
  4733.    else                 prev_gp->next = gp;
  4734.  
  4735.    np->current_newsgroup = gp;
  4736.  }
  4737.  
  4738.  return gp;
  4739. }
  4740.  
  4741. ./ ADD NAME=NNMADJUA
  4742.  
  4743.  /********************************************************************/
  4744.  /*                                                                  */
  4745.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  4746.  /*                                                                  */
  4747.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  4748.  /* including the implied warranties of merchantability and fitness, */
  4749.  /* are expressly denied.                                            */
  4750.  /*                                                                  */
  4751.  /* Provided this copyright notice is included, this software may    */
  4752.  /* be freely distributed and not offered for sale.                  */
  4753.  /*                                                                  */
  4754.  /* Changes or modifications may be made and used only by the maker  */
  4755.  /* of same, and not further distributed.  Such modifications should */
  4756.  /* be mailed to the author for consideration for addition to the    */
  4757.  /* software and incorporation in subsequent releases.               */
  4758.  /*                                                                  */
  4759.  /********************************************************************/
  4760.  
  4761. #pragma  csect(code,  "NN@ADJUA")
  4762. #pragma  csect(static,"NN$ADJUA")
  4763. #include "nn.h"
  4764.  
  4765. /****** Adjust unread articles. **************************************/
  4766.  
  4767. void
  4768. NNMadjua(np,gp,count,first,last)
  4769. Rstruc nncb       *np;
  4770. Rstruc newsgroup  *gp;
  4771. int                count;   /* estimated article count        */
  4772. int                first;   /* estimated first article number */
  4773. int                last;    /* estimated last  article number */
  4774. {
  4775.  VARK             *vp;
  4776.  VARK             *vpfirst;
  4777.  VARK             *vplast;
  4778.  char             *nlp;
  4779.  
  4780.  /* logic:
  4781.   * case
  4782.   *   last article number went up:      increment unread count
  4783.   *                                     update high number
  4784.   *                                     no need for new vector
  4785.   * <<< but if there already is a vector, then reallocate it >>>
  4786.   * <<< (fix for rescan) >>>
  4787.   *   last article number went down:    need an article vector to
  4788.   *    see what newsrc says about which now-gone items were unread
  4789.   *
  4790.   * case
  4791.   *   first article number went up:      need an article vector to
  4792.   *    see what newsrc says about which now-gone items were unread
  4793.   *   first article number went down:    impossible, nothing to do
  4794.   *
  4795.   */
  4796.  
  4797.  /* Do not change gp->high_number.  The caller of NNMadjua does this.
  4798.     NNMallav needs to see the old value. */
  4799.  
  4800.  if (last > gp->high_number) {
  4801.    gp->unread_count += (last - gp->high_number);
  4802.    if (gp->article_vector) {        /* if already an article vector */
  4803.      NNMallav(np,gp,first,last);    /* then reallocate it */
  4804.    }
  4805.  }
  4806.  
  4807.  if (last < gp->high_number || first > gp->low_number) {
  4808.  
  4809.    /* Recent or oldest articles were cancelled or expired */
  4810.    /* Reset the count, since no GROUP request may be associated */
  4811.  
  4812.    /*
  4813.     * If NNTP LIST overriding NEWSRC spec, there is an unparsed
  4814.     * newsrc line.  If it's just of the form "<nnn" with nothing else,
  4815.     * and nnn is less than the new "low number" from LIST,
  4816.     * then bypass allocation of an article vector.  Just set the
  4817.     * unread count to the new high and low number.
  4818.     */
  4819.  
  4820.    if ((nlp=gp->saved_newsrc_line)
  4821.     && *nlp == '<'
  4822.     && !*(nlp+1 + strspn(nlp+1,"0123456789\n"))
  4823.     && atoi(nlp+1) < first) {
  4824.      gp->unread_count  = count;
  4825.    }
  4826.  
  4827.    /*
  4828.     * If the article count didn't come from the NNTP GROUP command,
  4829.     * then estimate it from the NNTP LIST or NEWSRC range, but only
  4830.     * if an article vector was allocated.
  4831.     */
  4832.  
  4833.    else {
  4834.  
  4835.      NNMallav(np,gp,first,last);    /* Allocate article vector */
  4836.  
  4837.      if (gp->article_vector && !GroupSelected(gp)) {
  4838.        gp->article_count = 0;
  4839.        vpfirst = &GETVARKFIRST(gp);
  4840.        vplast  = &GETVARKLAST(gp);
  4841.        for (vp = vpfirst; vp <= vplast; vp++) {
  4842.          if (IsPresent(*vp)) gp->article_count++;
  4843.        }
  4844.      }
  4845.    }
  4846.  }
  4847.  else {
  4848.    gp->article_count = count;
  4849.  }
  4850.  
  4851.  /* No last minute adjustment of unread count,
  4852.   * since this produces bad results later.
  4853.   * If the user doesn't like this, hack the newsgroup display, not
  4854.   * the newsgroup structure.  What about saving back to newsrc?
  4855.   */
  4856.  
  4857.  /*
  4858.   * if (gp->unread_count > gp->article_count)
  4859.   *     gp->unread_count = gp->article_count;
  4860.   */
  4861.  
  4862.  return;
  4863. }
  4864.  
  4865. ./ ADD NAME=NNMALLAV
  4866.  
  4867.  /********************************************************************/
  4868.  /*                                                                  */
  4869.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  4870.  /*                                                                  */
  4871.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  4872.  /* including the implied warranties of merchantability and fitness, */
  4873.  /* are expressly denied.                                            */
  4874.  /*                                                                  */
  4875.  /* Provided this copyright notice is included, this software may    */
  4876.  /* be freely distributed and not offered for sale.                  */
  4877.  /*                                                                  */
  4878.  /* Changes or modifications may be made and used only by the maker  */
  4879.  /* of same, and not further distributed.  Such modifications should */
  4880.  /* be mailed to the author for consideration for addition to the    */
  4881.  /* software and incorporation in subsequent releases.               */
  4882.  /*                                                                  */
  4883.  /********************************************************************/
  4884.  
  4885. #pragma  csect(code,  "NN@ALLAV")
  4886. #pragma  csect(static,"NN$ALLAV")
  4887. #include "nn.h"
  4888.  
  4889. /****** Parse NEWSRC line. *******************************************/
  4890.  
  4891. static void
  4892. parse_newsrc_line(np,gp)
  4893. Rstruc nncb         *np;
  4894. Rstruc newsgroup    *gp;
  4895. {
  4896.  register char      *nlp                  = gp->saved_newsrc_line;
  4897.  int                 newsrc_number1       = 0;
  4898.  int                 newsrc_number2       = 0;
  4899.  int                 previous_number2     = 0;
  4900.  int                 newsrc_scan_count    = 0;
  4901.  int                 i;
  4902.  int                 imin;
  4903.  int                 imax;
  4904.  
  4905.  /*
  4906.   * Reset the unread count, throwing away the "newsrc_unread" value.
  4907.   * Initially the whole article vector is unread, and we make each
  4908.   * article read if it says so in the rest of the newsrc line.
  4909.   * Anything outside of the range of the article vector is GONE,
  4910.   * so we consider it READ (i.e. not unread).
  4911.   */
  4912.  
  4913.  gp->unread_count = gp->vector_last - gp->vector_first + 1;
  4914.  
  4915.  /* If there is no newsrc line to parse, that's all.  This used to be
  4916.     first in this routine, but that caused missing articles outside of
  4917.     the vector range not to be un-unread. */
  4918.  
  4919.  if (!nlp) {
  4920.    if (np->debug_file)
  4921.       fprintf(np->debug_file,"NNMallav: no saved newsrc line for %s\n",
  4922.                              gp->name);
  4923.    return;
  4924.  }
  4925.  
  4926.  /* get next number thing */
  4927.  
  4928.  while (*nlp) {
  4929.  
  4930.    previous_number2 = newsrc_number2;
  4931.  
  4932.    while (*nlp && isspace(*nlp)) nlp++;
  4933.  
  4934.    switch (*nlp) {
  4935.      case '\0': newsrc_number1 = MAX_INT;
  4936.                 newsrc_number2 = 0;
  4937.                 break;
  4938.      case '<':  sscanf(nlp," <%d %n",    &newsrc_number2,
  4939.                                          &newsrc_scan_count);
  4940.                 newsrc_number1 = 1;
  4941.                 nlp += newsrc_scan_count;
  4942.                 break;
  4943.      case '|':  sscanf(nlp," |%d=%d %n", &newsrc_number1,
  4944.                                          &newsrc_number2,
  4945.                                          &newsrc_scan_count);
  4946.                 nlp += newsrc_scan_count;
  4947.                 break;
  4948.      case '{':  nlp = strchr(++nlp,'}');
  4949.                 if (nlp) nlp++;
  4950.                 continue;
  4951.      case '#':  nlp = strchr(++nlp,'#');
  4952.                 if (nlp) nlp++;
  4953.                 continue;
  4954.      default:   sscanf(nlp," %d %n",     &newsrc_number1,
  4955.                                          &newsrc_scan_count);
  4956.                 newsrc_number2 = newsrc_number1;
  4957.                 nlp += newsrc_scan_count;
  4958.                 break;
  4959.    }
  4960.  
  4961.    /*
  4962.     * For this range of articles marked unread, if it's in the range
  4963.     * of the article vector, we do nothing (should have been UNREAD).
  4964.     */
  4965.  
  4966.    /*
  4967.     * For this range of articles marked read, if it's in the range
  4968.     * of the article vector, we mark the status accordingly.
  4969.     * If it's outside of the range of the article vector,
  4970.     * do nothing - it's just missing somehow.
  4971.     */
  4972.  
  4973.    imax = MAX(newsrc_number1,gp->vector_first);
  4974.    imin = MIN(newsrc_number2,gp->vector_last);
  4975.    for (i = imax; i <= imin; i++) {
  4976.      SetRead(GETVARK(gp,i));
  4977.      gp->unread_count--;
  4978.    }
  4979.  
  4980.  } /* end while */
  4981.  
  4982.  /* We're finished parsing the newsrc line, so free it. */
  4983.  
  4984.  if (gp->saved_newsrc_line != gp->saved_newsrc_data) {
  4985.    FREEMAIN(gp->saved_newsrc_line,"parsed newsrc line");
  4986.  }
  4987.  
  4988.  gp->saved_newsrc_line = NULL;
  4989.  gp->saved_newsrc_data[0] = '\0';
  4990.  
  4991.  return;
  4992. }
  4993.  
  4994. /****** Allocate articles for newsgroup. *****************************/
  4995.  
  4996. void
  4997. NNMallav(np,gp,first,last)
  4998. Rstruc nncb         *np;
  4999. Rstruc newsgroup    *gp;
  5000. int                  first;
  5001. int                  last;
  5002. {
  5003.  VARK               *oldvp    = gp->article_vector;
  5004.  VARK               *newvp    = NULL;
  5005.  int                 oldfirst = gp->vector_first;
  5006.  int                 oldlast  = gp->vector_last;
  5007.  int                 newfirst = first;
  5008.  int                 newlast  = last;
  5009.  int                 oldvlen;
  5010.  int                 newvlen;
  5011.  int                 anum;
  5012.  int                 commonfirst;
  5013.  int                 commonlast;
  5014.  
  5015. /*
  5016.  * if an article vector already exists, then:
  5017.  *
  5018.  * all articles from new.first to old.first - 1 (impossible?) are
  5019.  *  set from their newsrc status, or else "unread"
  5020.  * all articles from old.first to new.first - 1 are UN-UNREAD.
  5021.  * all articles from old.last + 1 to new.last are:
  5022.  *  set to "unread" if > old.high_number
  5023.  *   (remember, we don't reset those until after the artvec hacking)
  5024.  *  set to "missing" ("read") if <= old.high_number
  5025.  *   (or unknown, or ???)
  5026.  * all articles from new.last + 1 to old.last are UN-UNREAD.
  5027.  */
  5028.  
  5029.  if (np->debug_file) {
  5030.    fprintf(np->debug_file,
  5031.            "NNMallav: asking for article vector for %s (%d, %d)\n",
  5032.            gp->name, first, last);
  5033.  }
  5034.  
  5035.  if (oldfirst == newfirst && oldlast == newlast) return;
  5036.  
  5037.  newvlen = (last == 0 ? 0 : last - first + 1);
  5038.  
  5039.  if (newvlen > 0) {
  5040.  
  5041.    GETMAIN(newvp, VARK, newvlen, "article vector");
  5042.  
  5043.    if (!newvp) {
  5044.      fprintf(stderr,"Error allocating %d-article vector for %s\n",
  5045.                     newvlen, gp->name);
  5046.      ERR1("There is not enough virtual memory available to proceed.");
  5047.      return;
  5048.    }
  5049.  
  5050.    memset(newvp, 0, newvlen * sizeof(VARK));
  5051.  
  5052.  }
  5053.  
  5054.  else {
  5055.    newfirst = 2147483647;
  5056.    newlast  = 0;
  5057.  }
  5058.  
  5059.  if (oldvp) {  /* if article vector already exists */
  5060.  
  5061.    commonfirst = MAX(oldfirst, newfirst);
  5062.    commonlast  = MIN(oldlast,  newlast);
  5063.  
  5064.   /*
  5065.    * copy the vector slots over from the old vector
  5066.    */
  5067.  
  5068.    for (anum=commonfirst; anum <= commonlast; anum++) {
  5069.      newvp[anum-newfirst] = oldvp[anum-oldfirst];
  5070.    }
  5071.  
  5072.   /*
  5073.    * all articles from new.first to old.first - 1 (impossible?) are
  5074.    *  set from their newsrc status, or else "unread"
  5075.    * Rationale: buggy newsrc didn't account for existing items
  5076.    * can't set from newsrc until NNMpnrl is executed, so set them
  5077.    * to good old missing-unread
  5078.    */
  5079.  
  5080.    for (anum = newfirst; anum <= newlast && anum < oldfirst; anum++) {
  5081.      SetMissingUnread(newvp[anum-newfirst]);
  5082.    }
  5083.  
  5084.   /*
  5085.    * all articles from old.first to new.first - 1 are UN-UNREAD.
  5086.    * Rationale: old items have expired or been cancelled.
  5087.    * Since they fall out of the vector, they don't get an explicit
  5088.    * status, but they do have to be removed from the unread count.
  5089.    */
  5090.  
  5091.    for (anum = oldfirst; anum <= oldlast && anum < newfirst; anum++) {
  5092.      if (IsUnread(oldvp[anum-oldfirst])) {
  5093.        gp->unread_count--;
  5094.      }
  5095.    }
  5096.  
  5097.   /*
  5098.    * all articles from old.last + 1 to new.last are:
  5099.    *  set to "unread" if > old.high_number
  5100.    *   Rationale: new items came in since last time we looked
  5101.    *  set to "missing" ("read") if <= old.high_number
  5102.    *   Rationale: items in range but don't exist, cancelled/expired
  5103.    */
  5104.  
  5105.    for (anum = MAX(newfirst, oldlast + 1); anum <= newlast; anum++) {
  5106.      if (anum > gp->high_number) SetUnread(newvp[anum-newfirst]);
  5107.      else                        SetMissingRead(newvp[anum-newfirst]);
  5108.    }
  5109.  
  5110.   /*
  5111.    * all articles from new.last + 1 to old.last are UN-UNREAD.
  5112.    * Rationale: old items have expired or been cancelled.
  5113.    * Since they fall out of the vector, they don't get an explicit
  5114.    * status, but they do have to be removed from the unread count.
  5115.    */
  5116.  
  5117.    for (anum = MAX(oldfirst, newlast + 1); anum <= oldlast; anum++) {
  5118.      if (IsUnread(oldvp[anum-oldfirst])) {
  5119.        gp->unread_count--;
  5120.      }
  5121.    }
  5122.  
  5123.    FREEMAIN(oldvp,"old article vector");
  5124.  
  5125.  }
  5126.  else {      /* no old article vector */
  5127.  
  5128.   /*
  5129.    * initialize the vector to all unknown and unread
  5130.    */
  5131.  
  5132.    for (anum = newfirst; anum <= newlast; anum++) {
  5133.      SetNull(newvp[anum-newfirst]);
  5134.    }
  5135.  
  5136.  }
  5137.  
  5138.  oldvlen = gp->article_vector_len;
  5139.  
  5140.  gp->article_vector     = newvp;
  5141.  gp->article_vector_len = newvlen;
  5142.  gp->vector_first       = first;
  5143.  gp->vector_last        = last;
  5144.  
  5145.  /* If this is the first time that we have allocated the article
  5146.   * vector, initialize it from the saved newsrc line if there is one.
  5147.   * i.e. if the article vector is being allocated for the first time.
  5148.   */
  5149.  
  5150.  if (oldvlen == 0) {
  5151.    parse_newsrc_line(np,gp);
  5152.  }
  5153.  
  5154.  return;
  5155.  
  5156. }
  5157.  
  5158. ./ ADD NAME=NNMALLOC
  5159.  
  5160.  /********************************************************************/
  5161.  /*                                                                  */
  5162.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  5163.  /*                                                                  */
  5164.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  5165.  /* including the implied warranties of merchantability and fitness, */
  5166.  /* are expressly denied.                                            */
  5167.  /*                                                                  */
  5168.  /* Provided this copyright notice is included, this software may    */
  5169.  /* be freely distributed and not offered for sale.                  */
  5170.  /*                                                                  */
  5171.  /* Changes or modifications may be made and used only by the maker  */
  5172.  /* of same, and not further distributed.  Such modifications should */
  5173.  /* be mailed to the author for consideration for addition to the    */
  5174.  /* software and incorporation in subsequent releases.               */
  5175.  /*                                                                  */
  5176.  /********************************************************************/
  5177.  
  5178. #pragma  csect(code,  "NN@ALLOC")
  5179. #pragma  csect(static,"NN$ALLOC")
  5180. #include "nn.h"
  5181.  
  5182. /****** Allocate a data set. *****************************************/
  5183.  
  5184. Bool
  5185. NNMalloc(dsname,ddname,type,nitems)
  5186. char                      *dsname;
  5187. char                      *ddname;
  5188. enum data_set_type         type;
  5189. int                        nitems;
  5190. {
  5191.  int          i;
  5192.  int          rc;
  5193.  Bool         try_new;
  5194.  short        primary_allocation   ;
  5195.  short        secondary_allocation ;
  5196.  short        directory_blocks     ;
  5197.  short        dsorg                ;
  5198.  __S99parms   stuff99;   /* The manual has it wrong.  No "struct". */
  5199.  TEXTUNIT    *tu [17];
  5200.  TEXTUNIT     tu_dsn;
  5201.  TEXTUNIT     tu_ddn;
  5202.  TEXTUNIT     tu_member;
  5203.  TEXTUNIT     tu_stat;
  5204.  TEXTUNIT     tu_disp;
  5205.  TEXTUNIT     tu_perm;
  5206.  TEXTUNIT     tu_rtddn;
  5207.  TEXTUNIT     tu_rtorg;
  5208.  TEXTUNIT     tu_block;
  5209.  TEXTUNIT     tu_prime;
  5210.  TEXTUNIT     tu_sec;
  5211.  TEXTUNIT     tu_dir;
  5212.  TEXTUNIT     tu_recfm;
  5213.  TEXTUNIT     tu_lrecl;
  5214.  TEXTUNIT     tu_blksz;
  5215.  TEXTUNIT     tu_dsorg;
  5216.  char        *lparp;
  5217.  char        *rparp;
  5218.  char         dsnseq [81];
  5219.  char         member [81];
  5220.  
  5221.  try_new = FALSE;
  5222.  
  5223.  memset((char *)&stuff99,0,sizeof(__S99parms));
  5224.  
  5225.  strcpy(member,"");
  5226.  strcpy(dsnseq,dsname);
  5227.  lparp = strchr(dsnseq,'(');
  5228.  rparp = strchr(dsnseq,')');
  5229.  if (lparp && rparp && (lparp < rparp) && (*(rparp+1) == '\0')) {
  5230.    *lparp = '\0';            /* makes dsnseq the seq part only */
  5231.    *rparp = '\0';            /* turns member into a string     */
  5232.    strcpy(member, lparp+1);
  5233.    type = PDS;
  5234.  }
  5235.  
  5236.  for (;;) {
  5237.  
  5238.    stuff99.__S99RBLN   = 20;
  5239.    stuff99.__S99VERB   = S99VRBAL;
  5240.    stuff99.__S99FLAG1  = S99NOCNV << 8;
  5241.    stuff99.__S99ERROR  = 0;
  5242.    stuff99.__S99INFO   = 0;
  5243.    stuff99.__S99TXTPP  = tu;
  5244.    stuff99.__S99FLAG2  = 0;
  5245.  
  5246.    i = 0;
  5247.  
  5248.    tu[i++] = &tu_dsn;
  5249.  
  5250.    tu_dsn.key        = DALDSNAM;
  5251.    tu_dsn.num        = 1;
  5252.    tu_dsn.ent.len    = strlen(dsnseq);
  5253.    copy_uppercase(tu_dsn.ent.prm,dsnseq);
  5254.  
  5255.    tu[i++] = &tu_stat;
  5256.  
  5257.    tu_stat.key      = DALSTATS;
  5258.    tu_stat.num      = 1;
  5259.    tu_stat.ent.len  = 1;
  5260.    *tu_stat.ent.prm = (try_new ? NEW : SHR);
  5261.  
  5262.    tu[i++] = &tu_disp;
  5263.  
  5264.    tu_disp.key      = DALNDISP;
  5265.    tu_disp.num      = 1;
  5266.    tu_disp.ent.len  = 1;
  5267.    *tu_disp.ent.prm = (try_new ? CATLG : KEEP);
  5268.  
  5269.    tu[i++] = &tu_rtorg;
  5270.  
  5271.    tu_rtorg.key     = DALRTORG;
  5272.    tu_rtorg.num     = 1;
  5273.    tu_rtorg.ent.len = 2;
  5274.  
  5275.    if (*member) {
  5276.  
  5277.      tu[i++] = &tu_member;
  5278.  
  5279.      tu_member.key     = DALMEMBR;
  5280.      tu_member.num     = 1;
  5281.      tu_member.ent.len = strlen(member);
  5282.      copy_uppercase(tu_member.ent.prm,member);
  5283.  
  5284.    }
  5285.  
  5286.    if (ddname && *ddname) {
  5287.  
  5288.      tu[i++] = &tu_ddn;
  5289.  
  5290.      tu_ddn.key     = DALDDNAM;
  5291.      tu_ddn.num     = 1;
  5292.      tu_ddn.ent.len = strlen(ddname);
  5293.      copy_uppercase(tu_ddn.ent.prm,ddname);
  5294.  
  5295.      tu[i++] = &tu_perm;
  5296.  
  5297.      tu_perm.key     = DALPERMA;
  5298.      tu_perm.num     = 0;
  5299.    }
  5300.    else {
  5301.  
  5302.      tu[i++] = &tu_rtddn;
  5303.  
  5304.      tu_rtddn.key     = DALRTDDN;
  5305.      tu_rtddn.num     = 1;
  5306.      tu_rtddn.ent.len = 8;
  5307.      memset(tu_rtddn.ent.prm,' ',8);
  5308.  
  5309.    }
  5310.  
  5311.    if (try_new) {
  5312.  
  5313.      switch (type) {
  5314.        case PDS:
  5315.                  primary_allocation   = (short)nitems;
  5316.                  secondary_allocation = primary_allocation;
  5317.                  directory_blocks     = (short)((nitems/(12*36)+1)*36);
  5318.                  dsorg                = DSORG_PO;
  5319.                  break;
  5320.        case SEQ:
  5321.        default:
  5322.                  primary_allocation   = (short)nitems;
  5323.                  secondary_allocation = primary_allocation;
  5324.                  directory_blocks     = 0;
  5325.                  dsorg                = DSORG_PS;
  5326.                  break;
  5327.      }
  5328.  
  5329.      tu[i++] = &tu_block;
  5330.  
  5331.      tu_block.key     = DALBLKLN;
  5332.      tu_block.num     = 1;
  5333.      tu_block.ent.len = 3;
  5334.      memset(tu_block.ent.prm,0,3);
  5335.      *(short *)(tu_block.ent.prm+1) = 6233;
  5336.  
  5337.      tu[i++] = &tu_prime;
  5338.  
  5339.      tu_prime.key     = DALPRIME;
  5340.      tu_prime.num     = 1;
  5341.      tu_prime.ent.len = 3;
  5342.      memset(tu_prime.ent.prm,0,3);
  5343.      *(short *)(tu_prime.ent.prm+1) = primary_allocation;
  5344.  
  5345.      tu[i++] = &tu_sec;
  5346.  
  5347.      tu_sec.key     = DALSECND;
  5348.      tu_sec.num     = 1;
  5349.      tu_sec.ent.len = 3;
  5350.      memset(tu_sec.ent.prm,0,3);
  5351.      *(short *)(tu_sec.ent.prm+1) = secondary_allocation;
  5352.  
  5353.      tu[i++] = &tu_dir;
  5354.  
  5355.      tu_dir.key     = DALDIR;
  5356.      tu_dir.num     = 1;
  5357.      tu_dir.ent.len = 3;
  5358.      memset(tu_dir.ent.prm,0,3);
  5359.      *(short *)(tu_dir.ent.prm+1) = directory_blocks;
  5360.  
  5361.      tu[i++] = &tu_recfm;
  5362.  
  5363.      tu_recfm.key        = DALRECFM;
  5364.      tu_recfm.num        = 1;
  5365.      tu_recfm.ent.len    = 1;
  5366.      *tu_recfm.ent.prm   = RECFM_VB;
  5367.  
  5368.      tu[i++] = &tu_lrecl;
  5369.  
  5370.      tu_lrecl.key        = DALLRECL;
  5371.      tu_lrecl.num        = 1;
  5372.      tu_lrecl.ent.len    = 2;
  5373.      *(short *)tu_lrecl.ent.prm   = 259;
  5374.  
  5375.      tu[i++] = &tu_blksz;
  5376.  
  5377.      tu_blksz.key        = DALBLKSZ;
  5378.      tu_blksz.num        = 1;
  5379.      tu_blksz.ent.len    = 2;
  5380.      *(short *)tu_blksz.ent.prm   = 6233;
  5381.  
  5382.      tu[i++] = &tu_dsorg;
  5383.  
  5384.      tu_dsorg.key        = DALDSORG;
  5385.      tu_dsorg.num        = 1;
  5386.      tu_dsorg.ent.len    = 2;
  5387.      *(short *)tu_dsorg.ent.prm   = dsorg;
  5388.  
  5389.    }
  5390.  
  5391.    tu[i] = (void *)0x80000000;
  5392.  
  5393.    rc = svc99(&stuff99);
  5394.  
  5395.    if (rc == 0) {
  5396.      if (!(ddname && *ddname)) {
  5397.        memcpy(ddname,(char *)tu_rtddn.ent.prm,8);
  5398.        *(ddname+8) = ' ';
  5399.        *(strchr(ddname,' ')) = '\0';
  5400.      }
  5401.      if (type == SEQ &&
  5402.          tu_rtorg.ent.prm[0] != 0x40) {
  5403.        fprintf(stderr,"%s: not a sequential data set\n",dsname);
  5404.        return FALSE;
  5405.      }
  5406.      if (type == PDS &&
  5407.          tu_rtorg.ent.prm[0] != 0x02) {
  5408.        fprintf(stderr,"%s: not a partitioned data set\n",dsname);
  5409.        return FALSE;
  5410.      }
  5411.      return TRUE;
  5412.    }
  5413.    else if (!try_new && nitems != 0 && stuff99.__S99ERROR == 0x1708) {
  5414.     try_new = TRUE;
  5415.     continue;
  5416.    }
  5417.    else {
  5418.      NNMdfail(rc,&stuff99);
  5419.      return FALSE;
  5420.    }
  5421.  }
  5422. }
  5423.  
  5424. ./ ADD NAME=NNMAUTH
  5425.  
  5426.  /********************************************************************/
  5427.  /*                                                                  */
  5428.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  5429.  /*                                                                  */
  5430.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  5431.  /* including the implied warranties of merchantability and fitness, */
  5432.  /* are expressly denied.                                            */
  5433.  /*                                                                  */
  5434.  /* Provided this copyright notice is included, this software may    */
  5435.  /* be freely distributed and not offered for sale.                  */
  5436.  /*                                                                  */
  5437.  /* Changes or modifications may be made and used only by the maker  */
  5438.  /* of same, and not further distributed.  Such modifications should */
  5439.  /* be mailed to the author for consideration for addition to the    */
  5440.  /* software and incorporation in subsequent releases.               */
  5441.  /*                                                                  */
  5442.  /********************************************************************/
  5443.  
  5444. #pragma  csect(code,  "NN@AUTH ")
  5445. #pragma  csect(static,"NN$AUTH ")
  5446. #include "nn.h"
  5447.  
  5448. /****** Send authorization to news server. ***************************/
  5449.  
  5450. Bool
  5451. NNMauth(np)
  5452. Rstruc nncb *np;
  5453. {
  5454.  
  5455. #ifdef AUTHFILE
  5456.  
  5457.  char              *lp;
  5458.  FILE              *fp;
  5459.  int                display_rc;
  5460.  Bool               auth_error;
  5461.  Bool               connection_probably_closed;
  5462.  char               authdd    [12];
  5463.  char               authline [260];
  5464.  char               host      [65];
  5465.  char               user      [65];
  5466.  char               pass      [65];
  5467.  
  5468.  /* Send authorization.
  5469.   *
  5470.   * NNTP numbers must be the following as defined in C News source:
  5471.   *
  5472.   * OK_AUTHSYS    280  authorization system OK
  5473.   * OK_AUTH       281  authorization OK
  5474.   * NEED_AUTHINFO 380  authorization is required
  5475.   * NEED_AUTHDATA 381  <type> authorization data required (e.g. PASS)
  5476.   * ERR_NOAUTH    480  authorization required for command
  5477.   * ERR_AUTHSYS   481  authorization system invalid
  5478.   * ERR_AUTHREJ   482  authorization data rejected
  5479.   * ERR_CMDSYN    501  command syntax error
  5480.   * ERR_COMMAND   500  command not implemented
  5481.   * ERR_ACCESS    502  access to server denied
  5482.   * ERR_AUTHBAD   580  authorization failed
  5483.   *
  5484.   * Me:     AUTHINFO USER username
  5485.   * Server: 381 PASS required
  5486.   *     or: 482 Authorization already completed
  5487.   *     or: 500 Command not recognized
  5488.   *
  5489.   * If 482, server does not accept our attempt to gain authorization.
  5490.   *
  5491.   * If 500, authorization is not needed or the server has never
  5492.   * heard of authorization.  Either way, we proceed as "authorized".
  5493.   *
  5494.   * If 381 ...
  5495.   *
  5496.   * Me:     AUTHINFO PASS password
  5497.   * Server: 281 Authorization OK
  5498.   *     or: 482 authorization data rejected
  5499.   *     or: 502 access to server denied
  5500.   *     or: 580 authorization failed
  5501.   *
  5502.   * If 502, the server has disconnected me and I should return FALSE.
  5503.   * Otherwise, everything is OK, and I should return TRUE.
  5504.   *
  5505.   */
  5506.  
  5507.  lp = "None - local system error accessing authorization file";
  5508.  
  5509.  auth_error = FALSE;
  5510.  connection_probably_closed = FALSE;
  5511.  *host   = '\0';
  5512.  *user   = '\0';
  5513.  *pass   = '\0';
  5514.  
  5515.  /* Read user and pass from auth file */
  5516.  
  5517.  strcpy(authdd,"dd:");
  5518.  
  5519.  if (!NNMalloc(AUTHFILE,authdd+3,SEQ,0)) {  /* allocate as SHR */
  5520.    auth_error = TRUE;
  5521.  }
  5522.  else {
  5523.    if (!(fp=fopen(authdd,"r"))) {
  5524.      perror(AUTHFILE);
  5525.      auth_error = TRUE;
  5526.    }
  5527.    else {
  5528.      for (;;) {
  5529.        fgets(authline,sizeof(authline),fp);
  5530.        if (feof(fp)) break;
  5531.        if (ferror(fp)) {
  5532.          fprintf(stderr,"Error reading %s\n",AUTHFILE);
  5533.          auth_error = TRUE;
  5534.          break;
  5535.        }
  5536.        if (authline[0] == '#') continue;      /* ignore comments */
  5537.        *host = '\0';
  5538.        *user = '\0';
  5539.        *pass = '\0';
  5540.        sscanf(authline,"%s %s %s", host,user,pass);
  5541.        uppercase_in_place(host);
  5542.        if (EQUAL(host,np->nnserver)) break;
  5543.      };
  5544.      fclose(fp);
  5545.    }
  5546.    (void)NNMunalc(authdd+3);
  5547.  }
  5548.  
  5549.  if (!auth_error) {
  5550.    if (*user == '\0') return TRUE;  /* Don't do auth if no username */
  5551.    sprintf(np->nntp_command,"AUTHINFO USER %s", user);
  5552.    if (!NNMsockt(np)) return FALSE; /* Send socket command to server */
  5553.    if (!NNMgsrvl(np,&lp)) return FALSE;  /* Get server line */
  5554.    switch (np->nntp_message_num) {
  5555.      case 381: /* PASS required */
  5556.                break;
  5557.      case 500: /* Command not recognized */
  5558.                /* server does not support AUTHINFO - all clients OK */
  5559.                return TRUE;
  5560.      default:  NNMrperr(np);       /* Report protocol error */
  5561.                auth_error = TRUE;
  5562.                break;
  5563.    }
  5564.  }
  5565.  
  5566.  if (!auth_error) {
  5567.    sprintf(np->nntp_command,"AUTHINFO PASS %s", pass);
  5568.    if (!NNMsockt(np)) return FALSE; /* Send socket command to server */
  5569.    if (!NNMgsrvl(np,&lp)) return FALSE;  /* Get server line */
  5570.    switch (np->nntp_message_num) {
  5571.      case 281: /* authorization OK */
  5572.                return TRUE;
  5573.      case 502: /* access to server denied */
  5574.                /* Also, we have been disconnected at this point. */
  5575.                connection_probably_closed = TRUE;
  5576.                auth_error = TRUE;
  5577.                break;
  5578.      default:  NNMrperr(np);       /* Report protocol error */
  5579.                auth_error = TRUE;
  5580.                break;
  5581.    }
  5582.  }
  5583.  
  5584.  NNMesrvr(np);                   /* End server read */
  5585.  
  5586.  if (auth_error) {
  5587.  
  5588.    if (connection_probably_closed) {
  5589.      ERR2("Authorization failed;\
  5590. The NNTP server at %s refuses to authorize you.  \
  5591. Some news operations may fail.",\
  5592.           np->nnserver);
  5593.      np->connection_broken = TRUE;
  5594.      NNMdisc(np);                  /* Complete disconnection */
  5595.      return FALSE;
  5596.    }
  5597.    else {
  5598.      if (np->batch_mode) {
  5599.        fprintf(stderr,
  5600.         "NNMVS could not obtain authorization from the NNTP server.\n");
  5601.        fprintf(stderr,
  5602.         "NNMVS will proceed, but some news operations may fail.\n");
  5603.        fprintf(stderr,
  5604.         "The response from server %s was:\n\n%s\n\n", np->nnserver,lp);
  5605.        return TRUE;
  5606.      }
  5607.      else {
  5608.        NNMivput(np,"NNSERVER ",np->nnserver,-1);
  5609.        NNMivput(np,"NNSRVRSP ",lp,          -1);
  5610.        (void)NNMispf(np,"ADDPOP ");
  5611.        (void)NNMispf(np,"DISPLAY PANEL(NNMPAUTH)");
  5612.        display_rc = np->ispfrc;
  5613.        (void)NNMispf(np,"REMPOP ");
  5614.        if (display_rc == 0) return TRUE;
  5615.        else {
  5616.          NNMdisc(np);
  5617.          return FALSE;
  5618.        }
  5619.      }
  5620.    }
  5621.  
  5622.  }
  5623.  
  5624.  else return TRUE;
  5625.  
  5626. #else
  5627.  
  5628.  return TRUE;  /* no authorization file defined */
  5629.  
  5630. #endif
  5631.  
  5632. }
  5633.  
  5634. ./ ADD NAME=NNMBATCH
  5635.  
  5636.  /********************************************************************/
  5637.  /*                                                                  */
  5638.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  5639.  /*                                                                  */
  5640.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  5641.  /* including the implied warranties of merchantability and fitness, */
  5642.  /* are expressly denied.                                            */
  5643.  /*                                                                  */
  5644.  /* Provided this copyright notice is included, this software may    */
  5645.  /* be freely distributed and not offered for sale.                  */
  5646.  /*                                                                  */
  5647.  /* Changes or modifications may be made and used only by the maker  */
  5648.  /* of same, and not further distributed.  Such modifications should */
  5649.  /* be mailed to the author for consideration for addition to the    */
  5650.  /* software and incorporation in subsequent releases.               */
  5651.  /*                                                                  */
  5652.  /********************************************************************/
  5653.  
  5654. #pragma  csect(code,  "NN@BATCH")
  5655. #pragma  csect(static,"NN$BATCH")
  5656. #include "nn.h"
  5657. #include "nnbatch.h"
  5658.  
  5659. /****** Parse command. ***********************************************/
  5660.  
  5661. static void
  5662. parse_command(np,bp,proc)
  5663. Rstruc nncb         *np;
  5664. Rstruc batch        *bp;
  5665. CommandParser        proc;
  5666. {
  5667.  Rstruc newscmd     *cmdp = NULL;
  5668.  struct cmdtree     *treep;
  5669.  
  5670.  cmdp = (proc)(np,bp);
  5671.  
  5672.  if (!cmdp) return;
  5673.  
  5674.  /* If a newscmd structure was returned, add it to the cmd tree. */
  5675.  
  5676.  GETMAIN(treep, struct cmdtree, 1, "command tree");
  5677.  if (!treep) {
  5678.    bp->input_errors++;
  5679.    return;
  5680.  }
  5681.  
  5682.  treep->next = NULL;
  5683.  treep->cmd  = cmdp;
  5684.  
  5685.  if (bp->treebottom == NULL) bp->treetop = treep;
  5686.  else               bp->treebottom->next = treep;
  5687.  bp->treebottom = treep;
  5688.  
  5689.  return;
  5690. }
  5691.  
  5692. /****** Process requests. ********************************************/
  5693.  
  5694. static void
  5695. process_requests(np,bp)
  5696. Rstruc nncb         *np;
  5697. Rstruc batch        *bp;
  5698. {
  5699.  Rstruc cmdtree     *treep;
  5700.  
  5701.  if (bp->treetop == NULL) {
  5702.    fprintf(np->batch_outfile, "There is no processing to be done.\n");
  5703.  }
  5704.  
  5705.  for (treep = bp->treetop; treep; treep = treep->next) {
  5706.    bp->runtime_error = FALSE;
  5707.    (treep->cmd->proc) (np,bp,treep->cmd);
  5708.    if (ferror(np->batch_outfile)) {
  5709.      fprintf(stderr,"*** Error writing to batch output file ***\n");
  5710.    }
  5711.    SETB("ERROR",bp->runtime_error);
  5712.  }
  5713.  
  5714.  return;
  5715.  
  5716. }
  5717.  
  5718. /****** Flag unmatched END. ******************************************/
  5719.  
  5720. static struct newscmd *
  5721. flag_unmatched_end(np,bp)
  5722. Rstruc nncb         *np;
  5723. Rstruc batch        *bp;
  5724. {
  5725.  NNMbsynt(np,bp,NULL,0,"END without matching DO seen");
  5726.  
  5727.  return NULL;
  5728. }
  5729.  
  5730. /****** Flag invalid ISPLINK call. ***********************************/
  5731.  
  5732. static int
  5733. flag_invalid_isplink_call(service,argument)
  5734. char  *service;
  5735. char  *argument;
  5736. {
  5737.  fprintf(stderr,
  5738.          "*** Attempt to call ISPLINK in batch mode:\n%8.8s %8.8s\n",
  5739.          service, argument);
  5740.  
  5741.  return 20;
  5742. }
  5743.  
  5744. /****** Flag invalid ISPEXEC call. ***********************************/
  5745.  
  5746. static int
  5747. flag_invalid_ispexec_call(lenp,buf)
  5748. int   *lenp;
  5749. char  *buf;
  5750. {
  5751.  fprintf(stderr,"*** Attempt to call ISPEXEC in batch mode:\n%*.*s\n",
  5752.                 *lenp, *lenp, buf);
  5753.  return 20;
  5754. }
  5755.  
  5756. /****** NNMVS batch mode. ********************************************/
  5757.  
  5758. int
  5759. NNMbatch(np)
  5760. Rstruc nncb         *np;
  5761. {
  5762.  struct batch       *bp;
  5763.  char               *timep;
  5764.  char               *cp;
  5765.  CommandParser       proc;
  5766.  time_t              ltime;
  5767.  struct batch        batch_struct;
  5768.  
  5769.  static char         reserved_words [] = {
  5770.  "AND       DECLARE   DEREGISTERDO        ELSE      "
  5771.  "END       EQ        EXEC      EXTRACT   FALSE     "
  5772.  "FOR       GE        GT        HELP      IF        "
  5773.  "IN        LE        LT        MARK      NE        "
  5774.  "NNTP      NO        NOT       OFF       ON        "
  5775.  "OR        PUT       QUERY     QUIT      REGISTER  "
  5776.  "SET       THEN      TO        TRUE      VARS      "
  5777.  "WHEN      YES                "                     };
  5778.  
  5779.  if (!(np->batch_infile && np->batch_outfile)) {
  5780.    fprintf(stderr,"NNMVS: Batch operation failed.  Terminated.\n");
  5781.    return 16;
  5782.  }
  5783.  
  5784. #ifdef FETCH
  5785.  
  5786.    np->isplink_pointer = (int (*) ())flag_invalid_isplink_call;
  5787.    np->ispexec_pointer = (int (*) ())flag_invalid_ispexec_call;
  5788.  
  5789. #endif
  5790.  
  5791.  time(<ime);
  5792.  timep = ctime(<ime);
  5793.  if ((cp=strchr(timep,'\n'))) *cp = '\0';
  5794.  
  5795.  fprintf(np->batch_outfile,"NNMVS news client at %s - %s\n\n",
  5796.                            np->client_hostname, timep);
  5797.  
  5798.  bp = &batch_struct;
  5799.  np->batch_hook = bp;
  5800.  memset(bp,0,sizeof(struct batch));
  5801.  bp->reserved_words = reserved_words;
  5802.  bp->mode           = INITIAL_MODE;
  5803.  bp->curtok.type    = NO_TOKEN;
  5804.  bp->nextok.type    = NO_TOKEN;
  5805.  bp->endproc        = flag_unmatched_end;
  5806.  
  5807. #undef  TRUE
  5808. #define TRUE (void *)(1)
  5809.  
  5810.  /* Declare built-in variables along with initial values. */
  5811.  
  5812.  /* globally valid */
  5813.  
  5814.  NNMbdecl(np,bp,"LOCALPATH",    STRING_SYMTYPE, np->client_hostname);
  5815.  NNMbdecl(np,bp,"DATETIME",     STRING_SYMTYPE, timep      );
  5816.  NNMbdecl(np,bp,"SERVER",       STRING_SYMTYPE, ""         );
  5817.  NNMbdecl(np,bp,"OUTFILE",      STRING_SYMTYPE, ""         );
  5818.  NNMbdecl(np,bp,"SERVERLIST",   FLAG_SYMTYPE,   TRUE       );
  5819.  NNMbdecl(np,bp,"AUTOREGISTER", FLAG_SYMTYPE,   FALSE      );
  5820.  NNMbdecl(np,bp,"AUTODELETE",   FLAG_SYMTYPE,   TRUE       );
  5821.  NNMbdecl(np,bp,"AUTOMARK",     FLAG_SYMTYPE,   TRUE       );
  5822.  NNMbdecl(np,bp,"ERROR",        FLAG_SYMTYPE,   FALSE      );
  5823.  NNMbdecl(np,bp,"EXACTCASE",    FLAG_SYMTYPE,   FALSE      );
  5824.  NNMbdecl(np,bp,"TABEXPAND",    FLAG_SYMTYPE,   TRUE       );
  5825.  NNMbdecl(np,bp,"APPEND",       FLAG_SYMTYPE,   TRUE       );
  5826.  NNMbdecl(np,bp,"SEPARATOR",    STRING_SYMTYPE, ""         );
  5827.  NNMbdecl(np,bp,"BLANKSEP",     FLAG_SYMTYPE,   FALSE      );
  5828.  NNMbdecl(np,bp,"CHECKPOINT",   FLAG_SYMTYPE,   TRUE       );
  5829.  
  5830.  /* for newsgroups only */
  5831.  
  5832.  NNMbdecl(np,bp,"GROUP",        STRING_SYMTYPE, ""         );
  5833.  NNMbdecl(np,bp,"REGISTERED",   FLAG_SYMTYPE,   FALSE      );
  5834.  NNMbdecl(np,bp,"NEWGROUP",     FLAG_SYMTYPE,   FALSE      );
  5835.  NNMbdecl(np,bp,"NOSUCHGROUP",  FLAG_SYMTYPE,   FALSE      );
  5836.  NNMbdecl(np,bp,"COUNT",        NUMBER_SYMTYPE, 0          );
  5837.  NNMbdecl(np,bp,"UNREAD",       NUMBER_SYMTYPE, 0          );
  5838.  NNMbdecl(np,bp,"FIRST",        NUMBER_SYMTYPE, 0          );
  5839.  NNMbdecl(np,bp,"LAST",         NUMBER_SYMTYPE, 0          );
  5840.  
  5841.  /* for articles only */
  5842.  
  5843.  NNMbdecl(np,bp,"NUMBER",       NUMBER_SYMTYPE, 0          );
  5844.  NNMbdecl(np,bp,"READ",         FLAG_SYMTYPE,   FALSE      );
  5845.  NNMbdecl(np,bp,"MISSING",      FLAG_SYMTYPE,   FALSE      );
  5846.  NNMbdecl(np,bp,"SUBJECT",      STRING_SYMTYPE, ""         );
  5847.  NNMbdecl(np,bp,"DATE",         STRING_SYMTYPE, ""         );
  5848.  NNMbdecl(np,bp,"FROM",         STRING_SYMTYPE, ""         );
  5849.  NNMbdecl(np,bp,"MESSAGEID",    STRING_SYMTYPE, ""         );
  5850.  
  5851.  do {
  5852.    if ((proc = NNMbgcmd(np,bp))) {
  5853.      parse_command(np,bp,proc);
  5854.    }
  5855.  } while (!bp->eof);
  5856.  
  5857.  if (bp->input_errors > 0) {
  5858.    fprintf(np->batch_outfile, "\nNo processing due to input errors.\n");
  5859.    return 12;
  5860.  }
  5861.  
  5862.  else {
  5863.  
  5864.    fprintf(np->batch_outfile, "\n\nOpening NEWSRC...\n\n");
  5865.    strcpy(np->newsrc_to_open,"DD:NNNEWSRC");
  5866.    NNMonrf(np,NULL);                             /* Open NEWSRC file */
  5867.    fprintf(np->batch_outfile, "\n\nProcessing requests...\n\n");
  5868.    process_requests(np,bp);
  5869.    fprintf(np->batch_outfile, "\n\nClosing NEWSRC...\n\n");
  5870.    NNMcnrf(np,NULL,(Fool)TRUE);                /* Close  NEWSRC file */
  5871.  
  5872.  }
  5873.  
  5874.  /* Clean up any outfile hacking that may have been done. */
  5875.  
  5876.  SETC("OUTFILE","");
  5877.  (void)NNMbsout(np,bp);     /* Set output file */
  5878.  
  5879.  np->batch_hook = NULL;
  5880.  
  5881.  return bp->request_errors;
  5882.  
  5883. }
  5884.  
  5885. ./ ADD NAME=NNMBBEXP
  5886.  
  5887.  /********************************************************************/
  5888.  /*                                                                  */
  5889.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  5890.  /*                                                                  */
  5891.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  5892.  /* including the implied warranties of merchantability and fitness, */
  5893.  /* are expressly denied.                                            */
  5894.  /*                                                                  */
  5895.  /* Provided this copyright notice is included, this software may    */
  5896.  /* be freely distributed and not offered for sale.                  */
  5897.  /*                                                                  */
  5898.  /* Changes or modifications may be made and used only by the maker  */
  5899.  /* of same, and not further distributed.  Such modifications should */
  5900.  /* be mailed to the author for consideration for addition to the    */
  5901.  /* software and incorporation in subsequent releases.               */
  5902.  /*                                                                  */
  5903.  /********************************************************************/
  5904.  
  5905. #pragma  csect(code,  "NN@BBEXP")
  5906. #pragma  csect(static,"NN$BBEXP")
  5907. #include "nn.h"
  5908. #include "nnbatch.h"
  5909.  
  5910. #define CLEAR_THING(X) memset((char *)&X, 0, sizeof(struct thing))
  5911.  
  5912. static void from_exp      ();
  5913. static void from_choice   ();
  5914. static void from_relation ();
  5915. static void from_value    ();
  5916. static void from_quantity ();
  5917. static void from_term     ();
  5918. static void from_factor   ();
  5919. static void from_unop     ();
  5920. static void from_addop    ();
  5921. static void from_mulop    ();
  5922. static void from_logop    ();
  5923. static void from_relop    ();
  5924. static void from_constant ();
  5925. static void from_variable ();
  5926. static void from_number   ();
  5927. static void from_string   ();
  5928. static void from_flag     ();
  5929.  
  5930. /****** Free old value when replacing it with a new value. ***********/
  5931.  
  5932. #define free_old_value(A,B)  /* */
  5933.  
  5934. /* Do nothing yet.  This may not have been a malloc'd value...
  5935.  *
  5936.  *  static void
  5937.  *  free_old_value(np,tp)
  5938.  *  Rstruc nncb         *np;
  5939.  *  Rstruc thing        *tp;
  5940.  *  {
  5941.  *
  5942.  * if (tp->typ == STRING_SYMTYPE) {
  5943.  * FREEMAIN((char *)tp->val,"old intermediate expression string value");
  5944.  * tp->val = NULL;
  5945.  * }
  5946.  *
  5947.  * return;
  5948.  * }
  5949.  */
  5950.  
  5951. /****** Case-insensitive string compare. *****************************/
  5952.  
  5953. static int
  5954. Ustrcmp(a,b)
  5955. register char  *a;
  5956. register char  *b;
  5957. {
  5958.  register char  A;
  5959.  register char  B;
  5960.  
  5961.  while (*a || *b) {
  5962.    A = toupper(*a++);
  5963.    B = toupper(*b++);
  5964.    if (A > B) return 1;
  5965.    if (A < B) return -1;
  5966.  }
  5967.  
  5968.  return 0;
  5969. }
  5970.  
  5971. /****** Case-insensitive string search. ******************************/
  5972.  
  5973. static char *
  5974. Ustrstr(b,a)
  5975. register char  *b;
  5976. register char  *a;
  5977. {
  5978.  register char *aa;
  5979.  register char *bb;
  5980.  
  5981.  if (!*a) return strchr(b,'\0');
  5982.  for (;;) {
  5983.    while (*b && toupper(*a) != toupper(*b)) b++;
  5984.    if (!*b) return NULL;
  5985.    aa = a;
  5986.    bb = b;
  5987.    while (*aa && *bb && toupper(*aa) == toupper(*bb)) {
  5988.      aa++;
  5989.      bb++;
  5990.    }
  5991.    if (!*aa) return a;
  5992.    b++;
  5993.  }
  5994. }
  5995.  
  5996. /****** Concatenate string values. ***********************************/
  5997.  
  5998. static void
  5999. cat(np,bp,tp,tp1,tp2)
  6000. Rstruc nncb         *np;
  6001. Rstruc batch        *bp;
  6002. Rstruc thing        *tp;
  6003. Rstruc thing        *tp1;
  6004. Rstruc thing        *tp2;
  6005. {
  6006.  char               *strdata1;
  6007.  char               *strdata2;
  6008.  char               *newstr;
  6009.  int                 newlen;
  6010.  
  6011.  /* for now, just do a lot of getmains and freemains */
  6012.  
  6013.  free_old_value(np,tp);
  6014.  
  6015.  strdata1 = (char *)tp1->val;
  6016.  strdata2 = (char *)tp2->val;
  6017.  
  6018.  if (*strdata1 == '\0') {
  6019.    tp->val = (ANYTYPE)tp2->val;
  6020.  }
  6021.  else if (*strdata2 == '\0') {
  6022.    tp->val = (ANYTYPE)tp1->val;
  6023.  }
  6024.  else {
  6025.  
  6026.    newlen = strlen(strdata1) + strlen(strdata2) + 1;
  6027.  
  6028.    GETMAIN(newstr, 1, newlen, "new concatenated string");
  6029.  
  6030.    if (!newstr) {
  6031.      fprintf(np->batch_outfile,
  6032.       "Error, no storage to concatenate strings: %s, %s\n",
  6033.              tp1->val, tp2->val);
  6034.      longjmp(bp->jump,ERROR_GETMAIN_FAILURE);
  6035.    }
  6036.  
  6037.    strcpy(newstr,(char *)tp1->val);
  6038.    strcat(newstr,(char *)tp2->val);
  6039.  
  6040.    tp->val = (ANYTYPE)newstr;
  6041.  
  6042.  }
  6043.  
  6044.  tp->typ = STRING_SYMTYPE;
  6045.  free_old_value(np,tp1);
  6046.  free_old_value(np,tp2);
  6047.  return;
  6048. }
  6049.  
  6050. /*-------------------------------------------------------------------*/
  6051.  
  6052. static void
  6053. convert_to_string(np,bp,tp)
  6054. Rstruc nncb         *np;
  6055. Rstruc batch        *bp;
  6056. Rstruc thing        *tp;
  6057. {
  6058.  Fool                tempflag;
  6059.  char                tempstr[17];
  6060.  
  6061.  switch (tp->typ) {
  6062.    case STRING_SYMTYPE: return;
  6063.    case NUMBER_SYMTYPE:
  6064.                         sprintf(tempstr, "%d", (int)tp->val);
  6065.                         tp->val = (ANYTYPE)NNMcopy(np,tempstr);
  6066.                         tp->typ = STRING_SYMTYPE;
  6067.                         return;
  6068.    case FLAG_SYMTYPE:
  6069.                         tempflag = (Fool)tp->val;
  6070.                         tp->val = tempflag ? (ANYTYPE)"TRUE"
  6071.                                            : (ANYTYPE)"FALSE";
  6072.                         tp->typ = STRING_SYMTYPE;
  6073.                         return;
  6074.  }
  6075. }
  6076.  
  6077. /*-------------------------------------------------------------------*/
  6078.  
  6079. static void
  6080. convert_to_number(np,bp,tp)
  6081. Rstruc nncb         *np;
  6082. Rstruc batch        *bp;
  6083. Rstruc thing        *tp;
  6084. {
  6085.  Fool                tempflag;
  6086.  
  6087.  switch (tp->typ) {
  6088.    case NUMBER_SYMTYPE: return;
  6089.    case FLAG_SYMTYPE:
  6090.                         tempflag = (Fool)tp->val;
  6091.                         tp->val = tempflag ? (ANYTYPE)1
  6092.                                            : (ANYTYPE)0;
  6093.                         tp->typ = NUMBER_SYMTYPE;
  6094.                         return;
  6095.    case STRING_SYMTYPE:
  6096.    /* Note: This should be permitted if the string is all numerics,
  6097.     *       but for now it is always an error.
  6098.     * If permitted, call free_old_value before altering.
  6099.     */
  6100.                         fprintf(np->batch_outfile,
  6101.              "Type mismatch, cannot convert string to number: %s\n",
  6102.                                 tp->val);
  6103.                         longjmp(bp->jump,ERROR_TYPE_MISMATCH);
  6104.  }
  6105. }
  6106.  
  6107. /*-------------------------------------------------------------------*/
  6108.  
  6109. static void
  6110. convert_to_flag(np,bp,tp)
  6111. Rstruc nncb         *np;
  6112. Rstruc batch        *bp;
  6113. Rstruc thing        *tp;
  6114. {
  6115.  
  6116.  switch (tp->typ) {
  6117.    case FLAG_SYMTYPE:   return;
  6118.    case NUMBER_SYMTYPE:
  6119.    /* Note: This should be permitted if the number is 0 or 1,
  6120.     *       but for now it is always an error.
  6121.     */
  6122.                         fprintf(np->batch_outfile,
  6123.              "Type mismatch, cannot convert number to flag: %d\n",
  6124.                                 tp->val);
  6125.                         longjmp(bp->jump,ERROR_TYPE_MISMATCH);
  6126.    case STRING_SYMTYPE:
  6127.    /* Note: This should be permitted if the string is "0", "1",
  6128.     *       "TRUE", "FALSE", "ON", "OFF", "YES", or "NO",
  6129.     *       but for now it is always an error.
  6130.     * If permitted, call free_old_value before altering.
  6131.     */
  6132.                         fprintf(np->batch_outfile,
  6133.              "Type mismatch, cannot convert string to flag: %s\n",
  6134.                                 tp->val);
  6135.                         longjmp(bp->jump,ERROR_TYPE_MISMATCH);
  6136.  }
  6137. }
  6138.  
  6139. /*-------------------------------------------------------------------*/
  6140.  
  6141. static void
  6142. from_number(np,bp,tp,p)
  6143. Rstruc nncb         *np;
  6144. Rstruc batch        *bp;
  6145. Rstruc thing        *tp;
  6146. Number               p;
  6147. {
  6148.  
  6149.  tp->val = (ANYTYPE)p->number1;
  6150.  tp->typ = NUMBER_SYMTYPE;
  6151.  return;
  6152. }
  6153.  
  6154. /*-------------------------------------------------------------------*/
  6155.  
  6156. static void
  6157. from_string(np,bp,tp,p)
  6158. Rstruc nncb         *np;
  6159. Rstruc batch        *bp;
  6160. Rstruc thing        *tp;
  6161. String               p;
  6162. {
  6163.  
  6164.  tp->val = (ANYTYPE)p->string1;
  6165.  tp->typ = STRING_SYMTYPE;
  6166.  return;
  6167. }
  6168.  
  6169. /*-------------------------------------------------------------------*/
  6170.  
  6171. static void
  6172. from_flag(np,bp,tp,p)
  6173. Rstruc nncb         *np;
  6174. Rstruc batch        *bp;
  6175. Rstruc thing        *tp;
  6176. Flag                 p;
  6177. {
  6178.  
  6179.  tp->val = (ANYTYPE)p->flag1;
  6180.  tp->typ = FLAG_SYMTYPE;
  6181.  return;
  6182. }
  6183.  
  6184. /*-------------------------------------------------------------------*/
  6185.  
  6186. static void
  6187. from_variable(np,bp,tp,p)
  6188. Rstruc nncb         *np;
  6189. Rstruc batch        *bp;
  6190. Rstruc thing        *tp;
  6191. Variable             p;
  6192. {
  6193.  enum symtype        type;
  6194.  
  6195.  type = p->s;
  6196.  
  6197.  tp->val = (ANYTYPE)NNMbvget(np,bp,p->variable1,type);
  6198.  tp->typ = type;
  6199.  return;
  6200. }
  6201.  
  6202. /*-------------------------------------------------------------------*/
  6203.  
  6204. static void
  6205. from_constant(np,bp,tp,p)
  6206. Rstruc nncb         *np;
  6207. Rstruc batch        *bp;
  6208. Rstruc thing        *tp;
  6209. Constant             p;
  6210. {
  6211.  
  6212.  switch (p->r) {
  6213.    case RHSTYPE_A: from_number(np,bp,tp,p->u.a.number1); break;
  6214.    case RHSTYPE_B: from_string(np,bp,tp,p->u.b.string1); break;
  6215.    case RHSTYPE_C: from_flag  (np,bp,tp,p->u.c.flag1  ); break;
  6216.  }
  6217.  
  6218.  return;
  6219. }
  6220.  
  6221. /*-------------------------------------------------------------------*/
  6222.  
  6223. static void
  6224. from_factor(np,bp,tp,p)
  6225. Rstruc nncb         *np;
  6226. Rstruc batch        *bp;
  6227. Rstruc thing        *tp;
  6228. Factor               p;
  6229. {
  6230.  struct thing        t1;
  6231.  
  6232.  switch (p->r) {
  6233.    case RHSTYPE_A: from_constant(np,bp,tp,p->u.a.constant1); break;
  6234.    case RHSTYPE_B: from_variable(np,bp,tp,p->u.b.variable1); break;
  6235.    case RHSTYPE_C:
  6236.                    CLEAR_THING(t1);
  6237.                    from_factor(np,bp,&t1,p->u.c.factor2);
  6238.                    switch (p->u.c.unop1->op1) {
  6239.                      case ADD_OP:
  6240.                                   convert_to_number(np,bp,&t1);
  6241.                                   tp->val = t1.val;
  6242.                                   tp->typ = NUMBER_SYMTYPE;
  6243.                                   break;
  6244.                      case SUB_OP:
  6245.                                   convert_to_number(np,bp,&t1);
  6246.                                   tp->val = (ANYTYPE)
  6247.                                             (-((int)t1.val));
  6248.                                   tp->typ = NUMBER_SYMTYPE;
  6249.                                   break;
  6250.                      case NOT_OP:
  6251.                                   convert_to_flag(np,bp,&t1);
  6252.                                   tp->val = (ANYTYPE)
  6253.                                             (!((Fool)t1.val));
  6254.                                   tp->typ = FLAG_SYMTYPE;
  6255.                                   break;
  6256.                    }
  6257.                    break;
  6258.    case RHSTYPE_D: from_exp(np,bp,tp,p->u.d.exp1); break;
  6259.  }
  6260.  
  6261.  return;
  6262. }
  6263.  
  6264. /*-------------------------------------------------------------------*/
  6265.  
  6266. static void
  6267. from_term(np,bp,tp,p)
  6268. Rstruc nncb         *np;
  6269. Rstruc batch        *bp;
  6270. Rstruc thing        *tp;
  6271. Term                 p;
  6272. {
  6273.  struct thing        t1;
  6274.  struct thing        t3;
  6275.  
  6276.  switch (p->r) {
  6277.    case RHSTYPE_A: from_factor(np,bp,tp,p->u.a.factor1); break;
  6278.    case RHSTYPE_B:
  6279.                    CLEAR_THING(t1);
  6280.                    CLEAR_THING(t3);
  6281.                    from_term  (np,bp,&t1,p->u.b.term1  );
  6282.                    from_factor(np,bp,&t3,p->u.b.factor3);
  6283.                    convert_to_number(np,bp,&t1);
  6284.                    convert_to_number(np,bp,&t3);
  6285.                    switch (p->u.b.mulop2->op1) {
  6286.                      case MUL_OP:
  6287.                                   /* how to detect overflow? */
  6288.                                   tp->val = (ANYTYPE)
  6289.                                             ((int)t1.val * (int)t3.val);
  6290.                                   break;
  6291.                      case DIV_OP:
  6292.                                   if ((int)t3.val == 0) {
  6293.                                     fprintf(np->batch_outfile,
  6294.                                "Arithmetic error, division by zero\n");
  6295.                                     longjmp(bp->jump,ERROR_ZERODIVIDE);
  6296.                                   }
  6297.                                   tp->val = (ANYTYPE)
  6298.                                             ((int)t1.val / (int)t3.val);
  6299.                                   break;
  6300.                    }
  6301.                    tp->typ = NUMBER_SYMTYPE;
  6302.                    break;
  6303.  }
  6304.  
  6305.  return;
  6306. }
  6307.  
  6308. /*-------------------------------------------------------------------*/
  6309.  
  6310. static void
  6311. from_quantity(np,bp,tp,p)
  6312. Rstruc nncb         *np;
  6313. Rstruc batch        *bp;
  6314. Rstruc thing        *tp;
  6315. Quantity             p;
  6316. {
  6317.  struct thing        t1;
  6318.  struct thing        t3;
  6319.  
  6320.  switch (p->r) {
  6321.    case RHSTYPE_A: from_term(np,bp,tp,p->u.a.term1); break;
  6322.    case RHSTYPE_B:
  6323.                    CLEAR_THING(t1);
  6324.                    CLEAR_THING(t3);
  6325.                    from_quantity(np,bp,&t1,p->u.b.quantity1);
  6326.                    from_term    (np,bp,&t3,p->u.b.term3);
  6327.                    convert_to_number(np,bp,&t1);
  6328.                    convert_to_number(np,bp,&t3);
  6329.                    switch (p->u.b.addop2->op1) {
  6330.                      case ADD_OP:
  6331.                                   /* how to detect overflow? */
  6332.                                   tp->val = (ANYTYPE)
  6333.                                             ((int)t1.val + (int)t3.val);
  6334.                                   break;
  6335.                      case SUB_OP:
  6336.                                   /* how to detect overflow? */
  6337.                                   tp->val = (ANYTYPE)
  6338.                                             ((int)t1.val - (int)t3.val);
  6339.                                   break;
  6340.                    }
  6341.                    tp->typ = NUMBER_SYMTYPE;
  6342.                    break;
  6343.  }
  6344.  
  6345.  return;
  6346. }
  6347.  
  6348. /*-------------------------------------------------------------------*/
  6349.  
  6350. static void
  6351. from_value(np,bp,tp,p)
  6352. Rstruc nncb         *np;
  6353. Rstruc batch        *bp;
  6354. Rstruc thing        *tp;
  6355. Value                p;
  6356. {
  6357.  struct thing        t1;
  6358.  struct thing        t2;
  6359.  
  6360.  switch (p->r) {
  6361.    case RHSTYPE_A: from_quantity(np,bp,tp,p->u.a.quantity1); break;
  6362.    case RHSTYPE_B:
  6363.                    CLEAR_THING(t1);
  6364.                    CLEAR_THING(t2);
  6365.                    from_value   (np,bp,&t1,p->u.b.value1);
  6366.                    from_quantity(np,bp,&t2,p->u.b.quantity2);
  6367.                    convert_to_string(np,bp,&t1);
  6368.                    convert_to_string(np,bp,&t2);
  6369.                    cat(np,bp,tp,&t1,&t2);
  6370.                    break;
  6371.  }
  6372.  
  6373.  return;
  6374. }
  6375.  
  6376. /*-------------------------------------------------------------------*/
  6377.  
  6378. static void
  6379. from_relation(np,bp,tp,p)
  6380. Rstruc nncb         *np;
  6381. Rstruc batch        *bp;
  6382. Rstruc thing        *tp;
  6383. Relation             p;
  6384. {
  6385.  enum optype         op;
  6386.  struct thing        t1;
  6387.  struct thing        t3;
  6388.  
  6389.  switch (p->r) {
  6390.    case RHSTYPE_A: from_value(np,bp,tp,p->u.a.value1); break;
  6391.    case RHSTYPE_B:
  6392.         CLEAR_THING(t1);
  6393.         CLEAR_THING(t3);
  6394.         from_value(np,bp,&t1,p->u.b.value1);
  6395.         from_value(np,bp,&t3,p->u.b.value3);
  6396.         /* If either value is a string,
  6397.          * or operation is "IN", do string compare.
  6398.          * Otherwise do numeric compare.
  6399.          * Note: Currently we are case sensitive.
  6400.          *       This possibly should be changed, but
  6401.          *       not now...
  6402.          */
  6403.         op = p->u.b.relop2->op1;
  6404.         if (op == IN_OP
  6405.          || t1.typ == STRING_SYMTYPE
  6406.          || t3.typ == STRING_SYMTYPE) {
  6407.           convert_to_string(np,bp,&t1);
  6408.           convert_to_string(np,bp,&t3);
  6409.           if (bp->exactcase) {
  6410.             switch (op) {
  6411.               case EQ_OP: tp->val = (ANYTYPE)
  6412.                           (strcmp((char *)t1.val,(char *)t3.val) == 0);
  6413.                           break;
  6414.               case NE_OP: tp->val = (ANYTYPE)
  6415.                           (strcmp((char *)t1.val,(char *)t3.val) != 0);
  6416.                           break;
  6417.               case GT_OP: tp->val = (ANYTYPE)
  6418.                           (strcmp((char *)t1.val,(char *)t3.val) >  0);
  6419.                           break;
  6420.               case LT_OP: tp->val = (ANYTYPE)
  6421.                           (strcmp((char *)t1.val,(char *)t3.val) <  0);
  6422.                           break;
  6423.               case GE_OP: tp->val = (ANYTYPE)
  6424.                           (strcmp((char *)t1.val,(char *)t3.val) >= 0);
  6425.                           break;
  6426.               case LE_OP: tp->val = (ANYTYPE)
  6427.                           (strcmp((char *)t1.val,(char *)t3.val) <= 0);
  6428.                           break;
  6429.               case IN_OP: tp->val = (ANYTYPE)
  6430.                           (strstr((char *)t3.val,(char *)t1.val)!=NULL);
  6431.                           break;
  6432.             }
  6433.           }
  6434.           else {
  6435.             switch (op) {
  6436.               case EQ_OP: tp->val = (ANYTYPE)
  6437.                          (Ustrcmp((char *)t1.val,(char *)t3.val) == 0);
  6438.                           break;
  6439.               case NE_OP: tp->val = (ANYTYPE)
  6440.                          (Ustrcmp((char *)t1.val,(char *)t3.val) != 0);
  6441.                           break;
  6442.               case GT_OP: tp->val = (ANYTYPE)
  6443.                          (Ustrcmp((char *)t1.val,(char *)t3.val) >  0);
  6444.                           break;
  6445.               case LT_OP: tp->val = (ANYTYPE)
  6446.                          (Ustrcmp((char *)t1.val,(char *)t3.val) <  0);
  6447.                           break;
  6448.               case GE_OP: tp->val = (ANYTYPE)
  6449.                          (Ustrcmp((char *)t1.val,(char *)t3.val) >= 0);
  6450.                           break;
  6451.               case LE_OP: tp->val = (ANYTYPE)
  6452.                          (Ustrcmp((char *)t1.val,(char *)t3.val) <= 0);
  6453.                           break;
  6454.               case IN_OP: tp->val = (ANYTYPE)
  6455.                          (Ustrstr((char *)t3.val,(char *)t1.val)!=NULL);
  6456.                           break;
  6457.             }
  6458.           }
  6459.         }
  6460.         else {
  6461.           convert_to_number(np,bp,&t1);
  6462.           convert_to_number(np,bp,&t3);
  6463.           switch (op) {
  6464.             case EQ_OP: tp->val = (ANYTYPE)((int)t1.val == (int)t3.val);
  6465.                         break;
  6466.             case NE_OP: tp->val = (ANYTYPE)((int)t1.val != (int)t3.val);
  6467.                         break;
  6468.             case GT_OP: tp->val = (ANYTYPE)((int)t1.val >  (int)t3.val);
  6469.                         break;
  6470.             case LT_OP: tp->val = (ANYTYPE)((int)t1.val <  (int)t3.val);
  6471.                         break;
  6472.             case GE_OP: tp->val = (ANYTYPE)((int)t1.val >= (int)t3.val);
  6473.                         break;
  6474.             case LE_OP: tp->val = (ANYTYPE)((int)t1.val <= (int)t3.val);
  6475.                         break;
  6476.           }
  6477.         }
  6478.         tp->typ = FLAG_SYMTYPE;
  6479.         break;
  6480.  }
  6481.  
  6482.  return;
  6483. }
  6484.  
  6485. /*-------------------------------------------------------------------*/
  6486.  
  6487. static void
  6488. from_choice(np,bp,tp,p)
  6489. Rstruc nncb         *np;
  6490. Rstruc batch        *bp;
  6491. Rstruc thing        *tp;
  6492. Choice               p;
  6493. {
  6494.  struct thing        t1;
  6495.  struct thing        t3;
  6496.  
  6497.  switch (p->r) {
  6498.    case RHSTYPE_A: from_relation(np,bp,tp,p->u.a.relation1); break;
  6499.    case RHSTYPE_B:
  6500.         CLEAR_THING(t1);
  6501.         CLEAR_THING(t3);
  6502.         from_choice  (np,bp,&t1,p->u.b.choice1);
  6503.         from_relation(np,bp,&t3,p->u.b.relation3);
  6504.         convert_to_flag(np,bp,&t1);
  6505.         convert_to_flag(np,bp,&t3);
  6506.         switch (p->u.b.logop2->op1) {
  6507.           case AND_OP:
  6508.                        tp->val = (ANYTYPE)
  6509.                                  ((Fool)t1.val && (Fool)t3.val);
  6510.                        break;
  6511.           case OR_OP:
  6512.                        tp->val = (ANYTYPE)
  6513.                                  ((Fool)t1.val || (Fool)t3.val);
  6514.                        break;
  6515.         }
  6516.         tp->typ = FLAG_SYMTYPE;
  6517.         break;
  6518.  }
  6519.  
  6520.  return;
  6521. }
  6522.  
  6523. /*-------------------------------------------------------------------*/
  6524.  
  6525. static void
  6526. from_exp(np,bp,tp,p)
  6527. Rstruc nncb         *np;
  6528. Rstruc batch        *bp;
  6529. Rstruc thing        *tp;
  6530. Exp                  p;
  6531. {
  6532.  struct thing        t1;
  6533.  struct thing        t2;
  6534.  struct thing        t3;
  6535.  
  6536.  switch (p->r) {
  6537.    case RHSTYPE_A: from_choice(np,bp,tp,p->u.a.choice1); break;
  6538.    case RHSTYPE_B:
  6539.         CLEAR_THING(t1);
  6540.         CLEAR_THING(t2);
  6541.         CLEAR_THING(t3);
  6542.         from_exp(np,bp,&t1,p->u.b.exp1);
  6543.         from_exp(np,bp,&t2,p->u.b.exp2);
  6544.         from_exp(np,bp,&t3,p->u.b.exp3);
  6545.         convert_to_flag(np,bp,&t1);
  6546.         if ((Fool)t1.val) {
  6547.           tp->val = t2.val;
  6548.           tp->typ = t2.typ;
  6549.         }
  6550.         else {
  6551.           tp->val = t3.val;
  6552.           tp->typ = t3.typ;
  6553.         }
  6554.         break;
  6555.  }
  6556.  
  6557.  return;
  6558. }
  6559.  
  6560. /****** Build object from ptree to return as run-time value. *********/
  6561.  
  6562. ANYTYPE
  6563. NNMbbexp(np,bp,treep,type)
  6564. Rstruc nncb         *np;
  6565. Rstruc batch        *bp;
  6566. Rstruc ptree        *treep;
  6567. enum symtype         type;
  6568. {
  6569.  struct thing        it;
  6570.  
  6571.  CLEAR_THING(it);
  6572.  
  6573.  bp->exactcase = GETB("EXACTCASE");
  6574.  
  6575.  /* Define return point for run-time errors during evaluation. */
  6576.  
  6577.  if (setjmp(bp->jump) != 0) {
  6578.    bp->request_errors++;
  6579.    bp->runtime_error = TRUE;
  6580.    return NULL;
  6581.  }
  6582.  
  6583.  /* Get the value, whatever type it turns out to be. */
  6584.  
  6585.  from_exp(np,bp,&it,treep->exp1);
  6586.  
  6587.  /* Try to make the value match the requested type. */
  6588.  
  6589.  switch (type) {
  6590.  
  6591.    case STRING_SYMTYPE: convert_to_string(np,bp,&it); break;
  6592.    case NUMBER_SYMTYPE: convert_to_number(np,bp,&it); break;
  6593.    case   FLAG_SYMTYPE: convert_to_flag  (np,bp,&it); break;
  6594.  
  6595.  }
  6596.  
  6597.  /* Return the value. */
  6598.  
  6599.  return it.val;
  6600.  
  6601. }
  6602.  
  6603. ./ ADD NAME=NNMBCONN
  6604.  
  6605.  /********************************************************************/
  6606.  /*                                                                  */
  6607.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  6608.  /*                                                                  */
  6609.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  6610.  /* including the implied warranties of merchantability and fitness, */
  6611.  /* are expressly denied.                                            */
  6612.  /*                                                                  */
  6613.  /* Provided this copyright notice is included, this software may    */
  6614.  /* be freely distributed and not offered for sale.                  */
  6615.  /*                                                                  */
  6616.  /* Changes or modifications may be made and used only by the maker  */
  6617.  /* of same, and not further distributed.  Such modifications should */
  6618.  /* be mailed to the author for consideration for addition to the    */
  6619.  /* software and incorporation in subsequent releases.               */
  6620.  /*                                                                  */
  6621.  /********************************************************************/
  6622.  
  6623. #pragma  csect(code,  "NN@BCONN")
  6624. #pragma  csect(static,"NN$BCONN")
  6625. #include "nn.h"
  6626. #include "nnbatch.h"
  6627.  
  6628. /****** Insure server name. ******************************************/
  6629.  
  6630. static void
  6631. insure_server_name(np,bp)
  6632. Rstruc nncb         *np;
  6633. Rstruc batch        *bp;
  6634. {
  6635.  char               *servername;
  6636.  
  6637.  if (!*np->nnserver) {
  6638.    servername = GETC("SERVER");
  6639.    if (servername) {
  6640.      strncpy(np->nnserver,servername,sizeof(np->nnserver));
  6641.    }
  6642.  }
  6643.  
  6644.  return;
  6645. }
  6646.  
  6647. /****** Connect to server in batch mode. *****************************/
  6648.  
  6649. Bool
  6650. NNMbconn(np,bp)
  6651. Rstruc nncb         *np;
  6652. Rstruc batch        *bp;
  6653. {
  6654.  
  6655.  if (!np->connected_to_server) {
  6656.    insure_server_name(np,bp);
  6657.    if (!NNMconn(np)) {              /* Connect to server */
  6658.      fprintf(np->batch_outfile,"Server connection failed.\n");
  6659.      return FALSE;
  6660.    }
  6661.  }
  6662.  
  6663.  return np->connected_to_server;
  6664. }
  6665.  
  6666. ./ ADD NAME=NNMBDECL
  6667.  
  6668.  /********************************************************************/
  6669.  /*                                                                  */
  6670.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  6671.  /*                                                                  */
  6672.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  6673.  /* including the implied warranties of merchantability and fitness, */
  6674.  /* are expressly denied.                                            */
  6675.  /*                                                                  */
  6676.  /* Provided this copyright notice is included, this software may    */
  6677.  /* be freely distributed and not offered for sale.                  */
  6678.  /*                                                                  */
  6679.  /* Changes or modifications may be made and used only by the maker  */
  6680.  /* of same, and not further distributed.  Such modifications should */
  6681.  /* be mailed to the author for consideration for addition to the    */
  6682.  /* software and incorporation in subsequent releases.               */
  6683.  /*                                                                  */
  6684.  /********************************************************************/
  6685.  
  6686. #pragma  csect(code,  "NN@BDECL")
  6687. #pragma  csect(static,"NN$BDECL")
  6688. #include "nn.h"
  6689. #include "nnbatch.h"
  6690.  
  6691. /****** Validate a variable name. ************************************/
  6692.  
  6693. static Bool
  6694. validate(np,bp,var)
  6695. Rstruc nncb         *np;
  6696. Rstruc batch        *bp;
  6697. char                *var;
  6698. {
  6699.  int                 varlen;
  6700.  char               *cp;
  6701.  char                vartest[MAX_RESERVED_WORD_LENGTH];
  6702.  
  6703.  varlen = strlen(var);
  6704.  if (varlen < 1 || varlen > MAX_SYMBOL_LENGTH) {
  6705.    ERR2(
  6706.     "A variable name must be between 1 and %d characters in length.",
  6707.         MAX_SYMBOL_LENGTH);
  6708.    return FALSE;
  6709.  }
  6710.  
  6711.  if (varlen >= MIN_RESERVED_WORD_LENGTH
  6712.   && varlen <= MAX_RESERVED_WORD_LENGTH) {
  6713.  
  6714.    memset(vartest,' ',MAX_RESERVED_WORD_LENGTH);
  6715.    memcpy(vartest,var,strlen(var));
  6716.  
  6717.    for (cp = bp->reserved_words; *cp != ' '; cp += 10) {
  6718.      if (memcmp(vartest,cp,MAX_RESERVED_WORD_LENGTH) == 0) {
  6719.        ERR2(
  6720.     "The name %s is reserved and cannot be used as a variable name.",
  6721.             var);
  6722.        return FALSE;
  6723.      }
  6724.    }
  6725.  }
  6726.  
  6727.  return TRUE;
  6728. }
  6729.  
  6730. /****** Declare a variable symbol. ***********************************/
  6731.  
  6732. struct symtab *
  6733. NNMbdecl(np,bp,var,type,val)
  6734. Rstruc nncb         *np;
  6735. Rstruc batch        *bp;
  6736. char                *var;
  6737. enum symtype         type;
  6738. ANYTYPE              val;
  6739. {
  6740.  Rstruc symtab      *symp;
  6741.  Rstruc symtab     **sympref;
  6742.  struct symtab      *sympnew;
  6743.  struct symtab      *sympleft;
  6744.  struct symtab      *sympright;
  6745.  int                 minimum_value_length;
  6746.  int                 getlen;
  6747.  int                 comp;
  6748.  char                vartest[MAX_SYMBOL_LENGTH];
  6749.  
  6750.  if (!validate(np,bp,var)) {
  6751.    NNMbsynt(np,bp,var,0,"Variable name cannot be declared");
  6752.    return NULL;
  6753.  }
  6754.  memset(vartest,'\0',MAX_SYMBOL_LENGTH);
  6755.  memcpy(vartest,var,strlen(var));
  6756.  
  6757.  switch (type) {
  6758.    case STRING_SYMTYPE: minimum_value_length = strlen((char *)val) + 1;
  6759.                         break;
  6760.    case NUMBER_SYMTYPE: minimum_value_length = 12;
  6761.                         break;
  6762.    case FLAG_SYMTYPE:   minimum_value_length = 6;
  6763.                         break;
  6764.  }
  6765.  
  6766.  sympleft  = NULL;
  6767.  sympright = NULL;
  6768.  sympref   = &bp->symtabp;
  6769.  
  6770.  while ((symp=*sympref)) {
  6771.    switch ((comp=memcmp(vartest, symp->symvar, MAX_SYMBOL_LENGTH))) {
  6772.      case 0:   /* equal   */
  6773.                NNMbsynt(np,bp,var,0,
  6774.                         "Variable being declared already exists");
  6775.                return NULL;
  6776.      case 1:   /* greater */
  6777.                sympref = &symp->right;
  6778.                continue;
  6779.      default:  /* less    */
  6780.                sympref = &symp->left;
  6781.                continue;
  6782.    }
  6783.  }
  6784.  
  6785.  /* Allocate a new symbol table entry for this new symbol and
  6786.   * add it to the tree.
  6787.   */
  6788.  
  6789.  getlen = offsetof(struct symtab, symval) + minimum_value_length;
  6790.  
  6791.  GETMAIN(sympnew, char, getlen, "new symbol table entry");
  6792.  if (!sympnew) {
  6793.    NNMbsynt(np,bp,var,0,"Not enough storage to declare symbol");
  6794.    return NULL;
  6795.  }
  6796.  
  6797.  memcpy(sympnew->symvar, vartest, MAX_SYMBOL_LENGTH);
  6798.  sympnew->left   = sympleft;
  6799.  sympnew->right  = sympright;
  6800.  sympnew->vallen = minimum_value_length;
  6801.  *sympref        = sympnew;
  6802.  
  6803.  sympnew->type = type;
  6804.  
  6805.  switch (type) {
  6806.    case STRING_SYMTYPE:
  6807.                         strcpy(sympnew->symval,(char *)val);
  6808.                         if (np->debug_file)
  6809.                            fprintf(np->debug_file,
  6810.                                    "NNMbdecl: %s set to '%s'\n",
  6811.                                    sympnew->symvar, sympnew->symval);
  6812.                         break;
  6813.    case NUMBER_SYMTYPE:
  6814.                         sympnew->symnum = (int)val;
  6815.                         if (np->debug_file)
  6816.                            fprintf(np->debug_file,
  6817.                                    "NNMbdecl: %s set to %d\n",
  6818.                                    sympnew->symvar, sympnew->symnum);
  6819.                         break;
  6820.    case FLAG_SYMTYPE:
  6821.                         sympnew->symnum = (int)val ? 1 : 0;
  6822.                         if (np->debug_file)
  6823.                            fprintf(np->debug_file,
  6824.                                    "NNMbdecl: %s set to %s\n",
  6825.                                    sympnew->symvar,
  6826.                                    sympnew->symnum ? "TRUE" : "FALSE");
  6827.                         break;
  6828.  }
  6829.  
  6830.  
  6831.  return sympnew;
  6832.  
  6833. }
  6834.  
  6835. ./ ADD NAME=NNMBFLUS
  6836.  
  6837.  /********************************************************************/
  6838.  /*                                                                  */
  6839.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  6840.  /*                                                                  */
  6841.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  6842.  /* including the implied warranties of merchantability and fitness, */
  6843.  /* are expressly denied.                                            */
  6844.  /*                                                                  */
  6845.  /* Provided this copyright notice is included, this software may    */
  6846.  /* be freely distributed and not offered for sale.                  */
  6847.  /*                                                                  */
  6848.  /* Changes or modifications may be made and used only by the maker  */
  6849.  /* of same, and not further distributed.  Such modifications should */
  6850.  /* be mailed to the author for consideration for addition to the    */
  6851.  /* software and incorporation in subsequent releases.               */
  6852.  /*                                                                  */
  6853.  /********************************************************************/
  6854.  
  6855. #pragma  csect(code,  "NN@BFLUS")
  6856. #pragma  csect(static,"NN$BFLUS")
  6857. #include "nn.h"
  6858. #include "nnbatch.h"
  6859.  
  6860. /****** Flush input line. ********************************************/
  6861.  
  6862. void
  6863. NNMbflus(np,bp)
  6864. Rstruc nncb         *np;
  6865. Rstruc batch        *bp;
  6866. {
  6867.  
  6868.  /* This routine eats tokens, ignoring them, until it sees a
  6869.     semicolon or a new line. */
  6870.  
  6871.  if (np->debug_file) {
  6872.    fprintf(np->debug_file,"Flushing rest of input line.\n");
  6873.  }
  6874.  
  6875.  bp->stop_at_newline = TRUE;
  6876.  
  6877.  for (;;) {
  6878.    if (!NNMbgtok(np,bp,TOKEN_FLUSH)) break;  /* get token */
  6879.    switch (bp->curtok.type) {
  6880.      case EOF_TOKEN:
  6881.      case EOL_TOKEN:
  6882.      case SEMI_TOKEN:  break;
  6883.      default:
  6884.                        if (np->debug_file) {
  6885.                          fprintf(np->debug_file,"Ignoring token.\n");
  6886.                        }
  6887.                        continue;
  6888.    }
  6889.    break;
  6890.  }
  6891.  
  6892.  bp->stop_at_newline = FALSE;
  6893.  
  6894.  return;
  6895. }
  6896.  
  6897. ./ ADD NAME=NNMBGCMD
  6898.  
  6899.  /********************************************************************/
  6900.  /*                                                                  */
  6901.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  6902.  /*                                                                  */
  6903.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  6904.  /* including the implied warranties of merchantability and fitness, */
  6905.  /* are expressly denied.                                            */
  6906.  /*                                                                  */
  6907.  /* Provided this copyright notice is included, this software may    */
  6908.  /* be freely distributed and not offered for sale.                  */
  6909.  /*                                                                  */
  6910.  /* Changes or modifications may be made and used only by the maker  */
  6911.  /* of same, and not further distributed.  Such modifications should */
  6912.  /* be mailed to the author for consideration for addition to the    */
  6913.  /* software and incorporation in subsequent releases.               */
  6914.  /*                                                                  */
  6915.  /********************************************************************/
  6916.  
  6917. #pragma  csect(code,  "NN@BGCMD")
  6918. #pragma  csect(static,"NN$BGCMD")
  6919. #include "nn.h"
  6920. #include "nnbatch.h"
  6921.  
  6922. #define BATCHPARSER(X)   extern struct newscmd * \
  6923.                                      X (struct nncb *, struct batch *)
  6924.  
  6925. BATCHPARSER (NNMbphel);       /* Parse batch HELP         command     */
  6926. BATCHPARSER (NNMbpfor);       /* Parse batch FOR          command     */
  6927. BATCHPARSER (NNMbpif );       /* Parse batch IF           command     */
  6928. BATCHPARSER (NNMbpels);       /* Parse batch ELSE         command     */
  6929. BATCHPARSER (NNMbpque);       /* Parse batch QUERY        command     */
  6930. BATCHPARSER (NNMbpreg);       /* Parse batch REGISTER     command     */
  6931. BATCHPARSER (NNMbpder);       /* Parse batch DEREGISTER   command     */
  6932. BATCHPARSER (NNMbpset);       /* Parse batch SET          command     */
  6933. BATCHPARSER (NNMbpput);       /* Parse batch PUT          command     */
  6934. BATCHPARSER (NNMbpexe);       /* Parse batch EXEC         command     */
  6935. BATCHPARSER (NNMbpqui);       /* Parse batch QUIT         command     */
  6936. BATCHPARSER (NNMbpnnt);       /* Parse batch NNTP         command     */
  6937. BATCHPARSER (NNMbplis);       /* Parse batch LIST         command     */
  6938. BATCHPARSER (NNMbpmar);       /* Parse batch MARK         command     */
  6939. BATCHPARSER (NNMbpext);       /* Parse batch EXTRACT      command     */
  6940. BATCHPARSER (NNMbpvar);       /* Parse batch VARS         command     */
  6941. BATCHPARSER (NNMbpdec);       /* Parse batch DECLARE      command     */
  6942.  
  6943. /****** Get command. *************************************************/
  6944.  
  6945. CommandParser
  6946. NNMbgcmd(np,bp)
  6947. Rstruc nncb         *np;
  6948. Rstruc batch        *bp;
  6949. {
  6950.  char               *cp;
  6951.  struct token       *tp;
  6952.  CommandParser       cproc;
  6953.  Bool                command_not_gotten = FALSE;
  6954.  Bool                assumed_set        = FALSE;
  6955.  
  6956.  for (;;) {
  6957.  
  6958.    bp->stop_at_newline = FALSE;  /* read lines until token found */
  6959.  
  6960.    if (!(tp = PEEK())) {                          /* peek token */
  6961.       command_not_gotten = TRUE;
  6962.    }
  6963.    else switch (tp->type) {
  6964.      case EOF_TOKEN:
  6965.             EAT();
  6966.             return FALSE; /* OK, no more commands to process */
  6967.      case WORD_TOKEN:
  6968.             break;        /* good, what a command should look like */
  6969.      case EOL_TOKEN:
  6970.      case SEMI_TOKEN:
  6971.             EAT();
  6972.             continue;     /* keep looping */
  6973.      case STRING_TOKEN:
  6974.             EAT();
  6975.             NNMbsynt(np,bp,NULL,0,
  6976.                      "Quoted string where command name expected");
  6977.             command_not_gotten = TRUE;
  6978.             break;
  6979.      default:
  6980.             EAT();
  6981.             NNMbsynt(np,bp,tp->string,0,
  6982.                      "Invalid token where command name expected");
  6983.             command_not_gotten = TRUE;
  6984.             break;
  6985.    }
  6986.    break; /* continue only when ';' found */
  6987.  }
  6988.  
  6989.  /* Determine what the command is.  If the command is not recognized,
  6990.   * but it is the name of a declared variable, then assume it is SET
  6991.   * and don't eat the token - let SET see it.
  6992.   */
  6993.  
  6994.  if (!command_not_gotten) {
  6995.   cp = tp->string;
  6996.   if      (EQUAL(cp,"HELP"        )) cproc = NNMbphel;
  6997.   else if (EQUAL(cp,"FOR"         )) cproc = NNMbpfor;
  6998.   else if (EQUAL(cp,"IF"          )) cproc = NNMbpif ;
  6999.   else if (EQUAL(cp,"ELSE"        )) cproc = NNMbpels;
  7000.   else if (EQUAL(cp,"QUERY"       )) cproc = NNMbpque;
  7001.   else if (EQUAL(cp,"REGISTER"    )) cproc = NNMbpreg;
  7002.   else if (EQUAL(cp,"DEREGISTER"  )) cproc = NNMbpder;
  7003.   else if (EQUAL(cp,"SET"         )) cproc = NNMbpset;
  7004.   else if (EQUAL(cp,"PUT"         )) cproc = NNMbpput;
  7005.   else if (EQUAL(cp,"EXEC"        )) cproc = NNMbpexe;
  7006.   else if (EQUAL(cp,"QUIT"        )) cproc = NNMbpqui;
  7007.   else if (EQUAL(cp,"NNTP"        )) cproc = NNMbpnnt;
  7008.   else if (EQUAL(cp,"LIST"        )) cproc = NNMbplis;
  7009.   else if (EQUAL(cp,"MARK"        )) cproc = NNMbpmar;
  7010.   else if (EQUAL(cp,"EXTRACT"     )) cproc = NNMbpext;
  7011.   else if (EQUAL(cp,"VARS"        )) cproc = NNMbpvar;
  7012.   else if (EQUAL(cp,"DECLARE"     )) cproc = NNMbpdec;
  7013.   else if (EQUAL(cp,"END"         )) cproc = bp->endproc;
  7014.  
  7015.   else if (NNMbvget(np,bp,cp,NO_SYMTYPE)) { /* if declared var name */
  7016.     assumed_set = TRUE;
  7017.     cproc = NNMbpset;
  7018.   }
  7019.   else {
  7020.     NNMbsynt(np,bp,cp,0, "Command or variable name unknown");
  7021.     command_not_gotten = TRUE;
  7022.   }
  7023.  }
  7024.  
  7025.  if (!(EQUAL(cp,"ELSE"))) bp->ifcmd = NULL; /*Disallow unmatched ELSE*/
  7026.  
  7027.  if (!assumed_set) EAT();  /* Swallow the command name if 'twas real */
  7028.  
  7029.  if (command_not_gotten) {
  7030.    fprintf(np->batch_outfile, "Rest of input line ignored.\n");
  7031.    NNMbflus(np,bp);       /* Flush rest of tokens on input line */
  7032.    return FALSE;
  7033.  }
  7034.  
  7035.  return cproc;
  7036.  
  7037. }
  7038.  
  7039. ./ ADD NAME=NNMBGDO
  7040.  
  7041.  /********************************************************************/
  7042.  /*                                                                  */
  7043.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  7044.  /*                                                                  */
  7045.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  7046.  /* including the implied warranties of merchantability and fitness, */
  7047.  /* are expressly denied.                                            */
  7048.  /*                                                                  */
  7049.  /* Provided this copyright notice is included, this software may    */
  7050.  /* be freely distributed and not offered for sale.                  */
  7051.  /*                                                                  */
  7052.  /* Changes or modifications may be made and used only by the maker  */
  7053.  /* of same, and not further distributed.  Such modifications should */
  7054.  /* be mailed to the author for consideration for addition to the    */
  7055.  /* software and incorporation in subsequent releases.               */
  7056.  /*                                                                  */
  7057.  /********************************************************************/
  7058.  
  7059. #pragma  csect(code,  "NN@BGDO ")
  7060. #pragma  csect(static,"NN$BGDO ")
  7061. #include "nn.h"
  7062. #include "nnbatch.h"
  7063.  
  7064. #define MAGIC_END_COOKIE    (void *)(1)
  7065.  
  7066. /****** Handle END command. ******************************************/
  7067.  
  7068. static struct newscmd *
  7069. handle_end(np,bp)
  7070. Rstruc nncb         *np;
  7071. Rstruc batch        *bp;
  7072. {
  7073.  
  7074.  NNMbflus(np,bp);  /* flush all tokens following END */
  7075.  
  7076.  return MAGIC_END_COOKIE;
  7077. }
  7078.  
  7079. /****** Get commands, parse them and add to command tree. ************/
  7080.  
  7081. static struct cmdtree *
  7082. get_multiple_commands(np,bp,mode)
  7083. Rstruc nncb         *np;
  7084. Rstruc batch        *bp;
  7085. enum batchmode       mode;
  7086. {
  7087.  Rstruc newscmd     *cmdp        = NULL;
  7088.  struct cmdtree     *treep       = NULL;
  7089.  struct cmdtree     *treetop     = NULL;
  7090.  struct cmdtree     *treebottom  = NULL;
  7091.  CommandParser       proc;
  7092.  CommandParser       save_endproc;
  7093.  enum batchmode      save_mode;
  7094.  Bool                bad_command = FALSE;
  7095.  Bool                end_found   = FALSE;
  7096.  
  7097.  save_mode    = bp->mode;
  7098.  bp->mode     = mode;
  7099.  
  7100.  save_endproc = bp->endproc;
  7101.  bp->endproc  = handle_end;
  7102.  
  7103.  while (!bp->eof) {
  7104.  
  7105.    proc = NNMbgcmd(np,bp);   /* Get next command */
  7106.    if (!proc) {              /* If invalid command, continue */
  7107.      bad_command = TRUE;
  7108.      continue;
  7109.    }
  7110.  
  7111.    cmdp = (proc)(np,bp);     /* Parse it returning command tree */
  7112.    if (!cmdp) {              /* If syntax error, continue */
  7113.      bad_command = TRUE;
  7114.      continue;
  7115.    }
  7116.  
  7117.    if (cmdp == MAGIC_END_COOKIE) {  /* if END seen */
  7118.      end_found = TRUE;
  7119.      break;
  7120.    }
  7121.  
  7122.    /* If a newscmd structure was returned, add it to the cmd tree. */
  7123.  
  7124.    GETMAIN(treep, struct cmdtree, 1, "DO command tree");
  7125.    if (!treep) {
  7126.      bp->input_errors++;
  7127.      bad_command = TRUE;
  7128.      continue;
  7129.    }
  7130.  
  7131.    treep->next = NULL;
  7132.    treep->cmd  = cmdp;
  7133.  
  7134.    if (treebottom == NULL) treetop = treep;
  7135.    else                    treebottom->next = treep;
  7136.    treebottom = treep;
  7137.  
  7138.  }
  7139.  
  7140.  bp->endproc = save_endproc;
  7141.  bp->mode    = save_mode;
  7142.  
  7143.  if (!end_found) {
  7144.    NNMbsynt(np,bp,NULL,0,"No END found to match DO");
  7145.  }
  7146.  
  7147.  return treetop;
  7148. }
  7149.  
  7150. /****** Get a single command, parse it and make command tree. ********/
  7151.  
  7152. static struct cmdtree *
  7153. get_single_command(np,bp,mode)
  7154. Rstruc nncb         *np;
  7155. Rstruc batch        *bp;
  7156. enum batchmode       mode;
  7157. {
  7158.  Rstruc newscmd     *cmdp        = NULL;
  7159.  struct cmdtree     *treep       = NULL;
  7160.  struct token       *tp;
  7161.  CommandParser       proc;
  7162.  enum batchmode      save_mode;
  7163.  
  7164.  save_mode    = bp->mode;
  7165.  bp->mode     = mode;
  7166.  
  7167.  if (!(tp = PEEK())) return NULL;
  7168.  
  7169.  /* Handle null command (e.g. IF x THEN; ELSE; ) */
  7170.  
  7171.  if (tp->type == SEMI_TOKEN) return NULL;
  7172.  
  7173.  proc = NNMbgcmd(np,bp);   /* Get next command */
  7174.  if (!proc) return NULL;   /* If invalid command, error */
  7175.  
  7176.  cmdp = (proc)(np,bp);     /* Parse it returning command tree */
  7177.  if (!cmdp) return NULL;   /* If syntax error, error */
  7178.  
  7179.  bp->mode = save_mode;
  7180.  
  7181.  /* If a newscmd structure was returned, add it to the cmd tree. */
  7182.  
  7183.  GETMAIN(treep, struct cmdtree, 1, "DO command tree");
  7184.  if (!treep) {
  7185.    bp->input_errors++;
  7186.    return NULL;
  7187.  }
  7188.  
  7189.  treep->next = NULL;
  7190.  treep->cmd  = cmdp;
  7191.  
  7192.  return treep;
  7193. }
  7194.  
  7195. /****** Get keyword. *************************************************/
  7196.  
  7197. static Bool
  7198. get_keyword(np,bp,key)
  7199. Rstruc nncb                 *np;
  7200. Rstruc batch                *bp;
  7201. char                        *key;
  7202. {
  7203.  struct token               *tp;
  7204.  
  7205.  if ((tp = PEEK()) && tp->type == WORD_TOKEN && EQUAL(tp->string,key)) {
  7206.    EAT();
  7207.    return TRUE;
  7208.  }
  7209.  
  7210.  else return FALSE;
  7211.  
  7212. }
  7213.  
  7214. /****** Get a DO-END command group. **********************************/
  7215.  
  7216. struct cmdtree *
  7217. NNMbgdo(np,bp,mode)
  7218. Rstruc nncb         *np;
  7219. Rstruc batch        *bp;
  7220. enum batchmode       mode;
  7221. {
  7222.  
  7223.  /* Look for DO (required).  When found, get commands until END seen.*/
  7224.  
  7225.  if (get_keyword(np,bp,"DO")) {
  7226.    NNMbtras(np,bp,"DO");
  7227.    return get_multiple_commands(np,bp,mode);
  7228.  }
  7229.  else return get_single_command(np,bp,mode);
  7230.  
  7231. }
  7232.  
  7233. ./ ADD NAME=NNMBGEXP
  7234.  
  7235.  /********************************************************************/
  7236.  /*                                                                  */
  7237.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  7238.  /*                                                                  */
  7239.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  7240.  /* including the implied warranties of merchantability and fitness, */
  7241.  /* are expressly denied.                                            */
  7242.  /*                                                                  */
  7243.  /* Provided this copyright notice is included, this software may    */
  7244.  /* be freely distributed and not offered for sale.                  */
  7245.  /*                                                                  */
  7246.  /* Changes or modifications may be made and used only by the maker  */
  7247.  /* of same, and not further distributed.  Such modifications should */
  7248.  /* be mailed to the author for consideration for addition to the    */
  7249.  /* software and incorporation in subsequent releases.               */
  7250.  /*                                                                  */
  7251.  /********************************************************************/
  7252.  
  7253. #pragma  csect(code,  "NN@BGEXP")
  7254. #pragma  csect(static,"NN$BGEXP")
  7255. #include "nn.h"
  7256. #include "nnbatch.h"
  7257.  
  7258. static Exp              get_exp();
  7259. static Choice           get_choice();
  7260. static Relation         get_relation();
  7261. static Value            get_value();
  7262. static Quantity         get_quantity();
  7263. static Term             get_term();
  7264. static Factor           get_factor();
  7265. static Unop             get_unop();
  7266. static Addop            get_addop();
  7267. static Mulop            get_mulop();
  7268. static Logop            get_logop();
  7269. static Relop            get_relop();
  7270. static Constant         get_constant();
  7271. static Variable         get_variable();
  7272. static Number           get_number();
  7273. static String           get_string();
  7274. static Flag             get_flag();
  7275.  
  7276. static Exp              make_exp();
  7277. static Choice           make_choice();
  7278. static Relation         make_relation();
  7279. static Value            make_value();
  7280. static Quantity         make_quantity();
  7281. static Term             make_term();
  7282. static Factor           make_factor();
  7283. static Unop             make_unop();
  7284. static Addop            make_addop();
  7285. static Mulop            make_mulop();
  7286. static Logop            make_logop();
  7287. static Relop            make_relop();
  7288. static Constant         make_constant();
  7289. static Variable         make_variable();
  7290. static Number           make_number();
  7291. static String           make_string();
  7292. static Flag             make_flag();
  7293.  
  7294. /*-------------------------------------------------------------------*/
  7295.  
  7296. static Bool
  7297. is_reserved(bp,var)
  7298. Rstruc batch    *bp;
  7299. char            *var;
  7300. {
  7301.  char          *cp;
  7302.  int            varlen = strlen(var);
  7303.  char           vartest[MAX_RESERVED_WORD_LENGTH];
  7304.  
  7305.  if (varlen >= MIN_RESERVED_WORD_LENGTH
  7306.   && varlen <= MAX_RESERVED_WORD_LENGTH) {
  7307.  
  7308.    memset(vartest,' ',MAX_RESERVED_WORD_LENGTH);
  7309.    memcpy(vartest,var,varlen);
  7310.  
  7311.    for (cp = bp->reserved_words; *cp != ' '; cp += 10) {
  7312.      if (memcmp(vartest,cp,MAX_RESERVED_WORD_LENGTH) == 0) {
  7313.        return TRUE;
  7314.      }
  7315.    }
  7316.  }
  7317.  return FALSE;
  7318. }
  7319.  
  7320. /*-------------------------------------------------------------------*/
  7321.  
  7322. static Flag
  7323. make_flag(np,bp,type,v)
  7324. Rstruc nncb     *np;
  7325. Rstruc batch    *bp;
  7326. enum symtype     type;
  7327. Fool             v;
  7328. {
  7329.  Flag            p;
  7330.  
  7331.  ALLOC(p,flag);
  7332.  p->s     = type;
  7333.  p->flag1 = v;
  7334.  return p;
  7335.  
  7336. }
  7337.  
  7338. /*-------------------------------------------------------------------*/
  7339.  
  7340. static String
  7341. make_string(np,bp,type,v)
  7342. Rstruc nncb     *np;
  7343. Rstruc batch    *bp;
  7344. enum symtype     type;
  7345. char            *v;
  7346. {
  7347.  String          p;
  7348.  
  7349.  ALLOC(p,string);
  7350.  p->s       = type;
  7351.  p->string1 = NNMcopy(np,v);
  7352.  return p;
  7353.  
  7354. }
  7355.  
  7356. /*-------------------------------------------------------------------*/
  7357.  
  7358. static Number
  7359. make_number(np,bp,type,v)
  7360. Rstruc nncb     *np;
  7361. Rstruc batch    *bp;
  7362. enum symtype     type;
  7363. int              v;
  7364. {
  7365.  Number          p;
  7366.  
  7367.  ALLOC(p,number);
  7368.  p->s       = type;
  7369.  p->number1 = v;
  7370.  return p;
  7371.  
  7372. }
  7373.  
  7374. /*-------------------------------------------------------------------*/
  7375.  
  7376. static Variable
  7377. make_variable(np,bp,type,v)
  7378. Rstruc nncb     *np;
  7379. Rstruc batch    *bp;
  7380. enum symtype     type;
  7381. char            *v;
  7382. {
  7383.  Variable        p;
  7384.  
  7385.  ALLOC(p,variable);
  7386.  p->s         = type;
  7387.  p->variable1 = NNMcopy(np,v);
  7388.  return p;
  7389. }
  7390.  
  7391. /*-------------------------------------------------------------------*/
  7392.  
  7393. static Relop
  7394. make_relop(np,bp,t)
  7395. Rstruc nncb     *np;
  7396. Rstruc batch    *bp;
  7397. enum optype      t;
  7398. {
  7399.  Relop           p;
  7400.  
  7401.  ALLOC(p,relop);
  7402.  p->op1 = t;
  7403.  return p;
  7404. }
  7405.  
  7406. /*-------------------------------------------------------------------*/
  7407.  
  7408. static Logop
  7409. make_logop(np,bp,t)
  7410. Rstruc nncb     *np;
  7411. Rstruc batch    *bp;
  7412. enum optype      t;
  7413. {
  7414.  Logop           p;
  7415.  
  7416.  ALLOC(p,logop);
  7417.  p->op1 = t;
  7418.  return p;
  7419. }
  7420.  
  7421. /*-------------------------------------------------------------------*/
  7422.  
  7423. static Mulop
  7424. make_mulop(np,bp,t)
  7425. Rstruc nncb     *np;
  7426. Rstruc batch    *bp;
  7427. enum optype      t;
  7428. {
  7429.  Mulop           p;
  7430.  
  7431.  ALLOC(p,mulop);
  7432.  p->op1 = t;
  7433.  return p;
  7434. }
  7435.  
  7436. /*-------------------------------------------------------------------*/
  7437.  
  7438. static Addop
  7439. make_addop(np,bp,t)
  7440. Rstruc nncb     *np;
  7441. Rstruc batch    *bp;
  7442. enum optype      t;
  7443. {
  7444.  Addop           p;
  7445.  
  7446.  ALLOC(p,addop);
  7447.  p->op1 = t;
  7448.  return p;
  7449. }
  7450.  
  7451. /*-------------------------------------------------------------------*/
  7452.  
  7453. static Unop
  7454. make_unop(np,bp,t)
  7455. Rstruc nncb     *np;
  7456. Rstruc batch    *bp;
  7457. enum optype      t;
  7458. {
  7459.  Unop            p;
  7460.  
  7461.  ALLOC(p,unop);
  7462.  p->op1 = t;
  7463.  return p;
  7464. }
  7465.  
  7466. /*-------------------------------------------------------------------*/
  7467.  
  7468. static Constant
  7469. make_constant_a(np,bp,type,p1)
  7470. Rstruc nncb     *np;
  7471. Rstruc batch    *bp;
  7472. enum symtype     type;
  7473. Number           p1;
  7474. {
  7475.  Constant        p;
  7476.  
  7477.  ALLOC(p,constant);
  7478.  p->r           = RHSTYPE_A;
  7479.  p->s           = type;
  7480.  p->u.a.number1 = p1;
  7481.  return p;
  7482. }
  7483.  
  7484. /*-------------------------------------------------------------------*/
  7485.  
  7486. static Constant
  7487. make_constant_b(np,bp,type,p1)
  7488. Rstruc nncb     *np;
  7489. Rstruc batch    *bp;
  7490. enum symtype     type;
  7491. String           p1;
  7492. {
  7493.  Constant        p;
  7494.  
  7495.  ALLOC(p,constant);
  7496.  p->r           = RHSTYPE_B;
  7497.  p->s           = type;
  7498.  p->u.b.string1 = p1;
  7499.  return p;
  7500. }
  7501.  
  7502. /*-------------------------------------------------------------------*/
  7503.  
  7504. static Constant
  7505. make_constant_c(np,bp,type,p1)
  7506. Rstruc nncb     *np;
  7507. Rstruc batch    *bp;
  7508. enum symtype     type;
  7509. Flag             p1;
  7510. {
  7511.  Constant        p;
  7512.  
  7513.  ALLOC(p,constant);
  7514.  p->r         = RHSTYPE_C;
  7515.  p->s         = type;
  7516.  p->u.c.flag1 = p1;
  7517.  return p;
  7518. }
  7519.  
  7520. /*-------------------------------------------------------------------*/
  7521.  
  7522. static Factor
  7523. make_factor_a(np,bp,type,p1)
  7524. Rstruc nncb    *np;
  7525. Rstruc batch    *bp;
  7526. enum symtype    type;
  7527. Constant        p1;
  7528. {
  7529.  Factor         p;
  7530.  
  7531.  ALLOC(p,factor);
  7532.  p->r             = RHSTYPE_A;
  7533.  p->s             = type;
  7534.  p->u.a.constant1 = p1;
  7535.  return p;
  7536. }
  7537.  
  7538. /*-------------------------------------------------------------------*/
  7539.  
  7540. static Factor
  7541. make_factor_b(np,bp,type,p1)
  7542. Rstruc nncb    *np;
  7543. Rstruc batch    *bp;
  7544. enum symtype    type;
  7545. Variable        p1;
  7546. {
  7547.  Factor         p;
  7548.  
  7549.  ALLOC(p,factor);
  7550.  p->r             = RHSTYPE_B;
  7551.  p->s             = type;
  7552.  p->u.b.variable1 = p1;
  7553.  return p;
  7554. }
  7555.  
  7556. /*-------------------------------------------------------------------*/
  7557.  
  7558. static Factor
  7559. make_factor_c(np,bp,type,p1,p2)
  7560. Rstruc nncb    *np;
  7561. Rstruc batch    *bp;
  7562. enum symtype    type;
  7563. Unop            p1;
  7564. Factor          p2;
  7565. {
  7566.  Factor         p;
  7567.  
  7568.  ALLOC(p,factor);
  7569.  p->r             = RHSTYPE_C;
  7570.  p->s             = type;
  7571.  p->u.c.unop1     = p1;
  7572.  p->u.c.factor2   = p2;
  7573.  return p;
  7574. }
  7575.  
  7576. /*-------------------------------------------------------------------*/
  7577.  
  7578. static Factor
  7579. make_factor_d(np,bp,type,p1)
  7580. Rstruc nncb    *np;
  7581. Rstruc batch    *bp;
  7582. enum symtype    type;
  7583. Exp             p1;
  7584. {
  7585.  Factor         p;
  7586.  
  7587.  ALLOC(p,factor);
  7588.  p->r        = RHSTYPE_D;
  7589.  p->s        = type;
  7590.  p->u.d.exp1 = p1;
  7591.  return p;
  7592. }
  7593.  
  7594. /*-------------------------------------------------------------------*/
  7595.  
  7596. static Term
  7597. make_term_a(np,bp,type,p1)
  7598. Rstruc nncb    *np;
  7599. Rstruc batch    *bp;
  7600. enum symtype    type;
  7601. Factor          p1;
  7602. {
  7603.  Term           p;
  7604.  
  7605.  ALLOC(p,term);
  7606.  p->r           = RHSTYPE_A;
  7607.  p->s           = type;
  7608.  p->u.a.factor1 = p1;
  7609.  return p;
  7610. }
  7611.  
  7612. /*-------------------------------------------------------------------*/
  7613.  
  7614. static Term
  7615. make_term_b(np,bp,type,p1,p2,p3)
  7616. Rstruc nncb    *np;
  7617. Rstruc batch    *bp;
  7618. enum symtype    type;
  7619. Term            p1;
  7620. Mulop           p2;
  7621. Factor          p3;
  7622. {
  7623.  Term           p;
  7624.  
  7625.  ALLOC(p,term);
  7626.  p->r           = RHSTYPE_B;
  7627.  p->s           = type;
  7628.  p->u.b.term1   = p1;
  7629.  p->u.b.mulop2  = p2;
  7630.  p->u.b.factor3 = p3;
  7631.  return p;
  7632. }
  7633.  
  7634. /*-------------------------------------------------------------------*/
  7635.  
  7636. static Quantity
  7637. make_quantity_a(np,bp,type,p1)
  7638. Rstruc nncb    *np;
  7639. Rstruc batch    *bp;
  7640. enum symtype    type;
  7641. Term            p1;
  7642. {
  7643.  Quantity       p;
  7644.  
  7645.  ALLOC(p,quantity);
  7646.  p->r           = RHSTYPE_A;
  7647.  p->s           = type;
  7648.  p->u.a.term1   = p1;
  7649.  return p;
  7650. }
  7651.  
  7652. /*-------------------------------------------------------------------*/
  7653.  
  7654. static Quantity
  7655. make_quantity_b(np,bp,type,p1,p2,p3)
  7656. Rstruc nncb    *np;
  7657. Rstruc batch    *bp;
  7658. enum symtype    type;
  7659. Quantity        p1;
  7660. Addop           p2;
  7661. Term            p3;
  7662. {
  7663.  Quantity       p;
  7664.  
  7665.  ALLOC(p,quantity);
  7666.  p->r             = RHSTYPE_B;
  7667.  p->s             = type;
  7668.  p->u.b.quantity1 = p1;
  7669.  p->u.b.addop2    = p2;
  7670.  p->u.b.term3     = p3;
  7671.  return p;
  7672. }
  7673.  
  7674. /*-------------------------------------------------------------------*/
  7675.  
  7676. static Value
  7677. make_value_a(np,bp,type,p1)
  7678. Rstruc nncb    *np;
  7679. Rstruc batch    *bp;
  7680. enum symtype    type;
  7681. Quantity        p1;
  7682. {
  7683.  Value           p;
  7684.  
  7685.  ALLOC(p,value);
  7686.  p->r             = RHSTYPE_A;
  7687.  p->s             = type;
  7688.  p->u.a.quantity1 = p1;
  7689.  return p;
  7690. }
  7691.  
  7692. /*-------------------------------------------------------------------*/
  7693.  
  7694. static Value
  7695. make_value_b(np,bp,type,p1,p2)
  7696. Rstruc nncb    *np;
  7697. Rstruc batch    *bp;
  7698. enum symtype    type;
  7699. Value           p1;
  7700. Quantity        p2;
  7701. {
  7702.  Value          p;
  7703.  
  7704.  ALLOC(p,value);
  7705.  p->r             = RHSTYPE_B;
  7706.  p->s             = type;
  7707.  p->u.b.value1    = p1;
  7708.  p->u.b.quantity2 = p2;
  7709.  return p;
  7710. }
  7711.  
  7712. /*-------------------------------------------------------------------*/
  7713.  
  7714. static Relation
  7715. make_relation_a(np,bp,type,p1)
  7716. Rstruc nncb    *np;
  7717. Rstruc batch    *bp;
  7718. enum symtype    type;
  7719. Value           p1;
  7720. {
  7721.  Relation       p;
  7722.  
  7723.  ALLOC(p,relation);
  7724.  p->r           = RHSTYPE_A;
  7725.  p->s           = type;
  7726.  p->u.a.value1  = p1;
  7727.  return p;
  7728. }
  7729.  
  7730. /*-------------------------------------------------------------------*/
  7731.  
  7732. static Relation
  7733. make_relation_b(np,bp,type,p1,p2,p3)
  7734. Rstruc nncb    *np;
  7735. Rstruc batch    *bp;
  7736. enum symtype    type;
  7737. Value           p1;
  7738. Relop           p2;
  7739. Value           p3;
  7740. {
  7741.  Relation       p;
  7742.  
  7743.  ALLOC(p,relation);
  7744.  p->r             = RHSTYPE_B;
  7745.  p->s             = type;
  7746.  p->u.b.value1    = p1;
  7747.  p->u.b.relop2    = p2;
  7748.  p->u.b.value3    = p3;
  7749.  return p;
  7750. }
  7751.  
  7752. /*-------------------------------------------------------------------*/
  7753.  
  7754. static Choice
  7755. make_choice_a(np,bp,type,p1)
  7756. Rstruc nncb    *np;
  7757. Rstruc batch    *bp;
  7758. enum symtype    type;
  7759. Relation        p1;
  7760. {
  7761.  Choice         p;
  7762.  
  7763.  ALLOC(p,choice);
  7764.  p->r             = RHSTYPE_A;
  7765.  p->s             = type;
  7766.  p->u.a.relation1 = p1;
  7767.  return p;
  7768. }
  7769.  
  7770. /*-------------------------------------------------------------------*/
  7771.  
  7772. static Choice
  7773. make_choice_b(np,bp,type,p1,p2,p3)
  7774. Rstruc nncb    *np;
  7775. Rstruc batch    *bp;
  7776. enum symtype    type;
  7777. Choice          p1;
  7778. Logop           p2;
  7779. Relation        p3;
  7780. {
  7781.  Choice         p;
  7782.  
  7783.  ALLOC(p,choice);
  7784.  p->r             = RHSTYPE_B;
  7785.  p->s             = type;
  7786.  p->u.b.choice1   = p1;
  7787.  p->u.b.logop2    = p2;
  7788.  p->u.b.relation3 = p3;
  7789.  return p;
  7790. }
  7791.  
  7792. /*-------------------------------------------------------------------*/
  7793.  
  7794. static Exp
  7795. make_exp_a(np,bp,type,p1)
  7796. Rstruc nncb    *np;
  7797. Rstruc batch    *bp;
  7798. enum symtype    type;
  7799. Choice          p1;
  7800. {
  7801.  Exp            p;
  7802.  
  7803.  ALLOC(p,exp);
  7804.  p->r           = RHSTYPE_A;
  7805.  p->s           = type;
  7806.  p->u.a.choice1 = p1;
  7807.  return p;
  7808. }
  7809.  
  7810. /*-------------------------------------------------------------------*/
  7811.  
  7812. static Exp
  7813. make_exp_b(np,bp,type,p1,p2,p3)
  7814. Rstruc nncb    *np;
  7815. Rstruc batch    *bp;
  7816. enum symtype    type;
  7817. Exp             p1;
  7818. Exp             p2;
  7819. Exp             p3;
  7820. {
  7821.  Exp            p;
  7822.  
  7823.  ALLOC(p,exp);
  7824.  p->r        = RHSTYPE_B;
  7825.  p->s        = type;
  7826.  p->u.b.exp1 = p1;
  7827.  p->u.b.exp2 = p2;
  7828.  p->u.b.exp3 = p3;
  7829.  return p;
  7830. }
  7831.  
  7832. /*===================================================================*/
  7833.  
  7834. static Flag
  7835. get_flag(np,bp)
  7836. Rstruc nncb         *np;
  7837. Rstruc batch        *bp;
  7838. {
  7839.  struct token       *tp;
  7840.  
  7841.  if (!(tp = PEEK())) LOSE;
  7842.  switch (tp->type) {
  7843.    case WORD_TOKEN:
  7844.      if (EQUAL(tp->string,"FALSE") ||
  7845.          EQUAL(tp->string,"NO"   ) ||
  7846.          EQUAL(tp->string,"OFF"  )) {
  7847.        EAT();
  7848.        return make_flag(np,bp,FLAG_SYMTYPE,FALSE);
  7849.      }
  7850.      else
  7851.      if (EQUAL(tp->string,"TRUE" ) ||
  7852.          EQUAL(tp->string,"YES"  ) ||
  7853.          EQUAL(tp->string,"ON"   )) {
  7854.        EAT();
  7855.        return make_flag(np,bp,FLAG_SYMTYPE,TRUE);
  7856.      }
  7857.    default:        return NULL;
  7858.  }
  7859. }
  7860.  
  7861. /*-------------------------------------------------------------------*/
  7862.  
  7863. static String
  7864. get_string(np,bp)
  7865. Rstruc nncb         *np;
  7866. Rstruc batch        *bp;
  7867. {
  7868.  struct token       *tp;
  7869.  
  7870.  if (!(tp = PEEK())) LOSE;
  7871.  switch (tp->type) {
  7872.    case STRING_TOKEN:
  7873.             EAT();
  7874.             return make_string(np,bp,STRING_SYMTYPE,tp->string);
  7875.    default: return NULL;
  7876.  }
  7877. }
  7878.  
  7879. /*-------------------------------------------------------------------*/
  7880.  
  7881. static Number
  7882. get_number(np,bp)
  7883. Rstruc nncb         *np;
  7884. Rstruc batch        *bp;
  7885. {
  7886.  struct token       *tp;
  7887.  
  7888.  if (!(tp = PEEK())) LOSE;
  7889.  switch (tp->type) {
  7890.    case NUMBER_TOKEN:
  7891.             EAT();
  7892.             return make_number(np,bp,NUMBER_SYMTYPE,tp->number);
  7893.    default: return NULL;
  7894.  }
  7895. }
  7896.  
  7897. /*-------------------------------------------------------------------*/
  7898.  
  7899. static Variable
  7900. get_variable(np,bp)
  7901. Rstruc nncb         *np;
  7902. Rstruc batch        *bp;
  7903. {
  7904.  struct token       *tp;
  7905.  enum symtype        type;
  7906.  
  7907.  if (!(tp = PEEK())) LOSE;
  7908.  switch (tp->type) {
  7909.    case WORD_TOKEN:
  7910.             if (is_reserved(bp,tp->string)) return NULL;
  7911.             EAT();
  7912.             type = (enum symtype)NNMbvget(np,bp,tp->string,NO_SYMTYPE);
  7913.             if (type == NO_SYMTYPE) ERR("variable not declared");
  7914.             return make_variable(np,bp,type,tp->string);
  7915.    default: return NULL;
  7916.  }
  7917. }
  7918.  
  7919. /*-------------------------------------------------------------------*/
  7920.  
  7921. static Constant
  7922. get_constant(np,bp)
  7923. Rstruc nncb         *np;
  7924. Rstruc batch        *bp;
  7925. {
  7926.  Number              a1;
  7927.  String              b1;
  7928.  Flag                c1;
  7929.  
  7930.  if ((a1 = get_number(np,bp)))
  7931.     return make_constant_a(np,bp,NUMBER_SYMTYPE,a1);
  7932.  if ((b1 = get_string(np,bp)))
  7933.     return make_constant_b(np,bp,STRING_SYMTYPE,b1);
  7934.  if ((c1 = get_flag(np,bp)))
  7935.     return make_constant_c(np,bp,FLAG_SYMTYPE,c1);
  7936.  return NULL;
  7937. }
  7938.  
  7939. /*-------------------------------------------------------------------*/
  7940.  
  7941. static Addop
  7942. get_addop(np,bp)
  7943. Rstruc nncb         *np;
  7944. Rstruc batch        *bp;
  7945. {
  7946.  struct token       *tp;
  7947.  
  7948.  if (!(tp = PEEK())) LOSE;
  7949.  switch (tp->type) {
  7950.    case PLUS_TOKEN:  EAT(); return make_addop(np,bp,ADD_OP);
  7951.    case MINUS_TOKEN: EAT(); return make_addop(np,bp,SUB_OP);
  7952.    default:          return NULL;
  7953.  }
  7954. }
  7955.  
  7956. /*-------------------------------------------------------------------*/
  7957.  
  7958. static Mulop
  7959. get_mulop(np,bp)
  7960. Rstruc nncb         *np;
  7961. Rstruc batch        *bp;
  7962. {
  7963.  struct token       *tp;
  7964.  
  7965.  if (!(tp = PEEK())) LOSE;
  7966.  switch (tp->type) {
  7967.    case TIMES_TOKEN:  EAT(); return make_mulop(np,bp,MUL_OP);
  7968.    case OVER_TOKEN:   EAT(); return make_mulop(np,bp,DIV_OP);
  7969.    default:           return NULL;
  7970.  }
  7971. }
  7972.  
  7973. /*-------------------------------------------------------------------*/
  7974.  
  7975. static Logop
  7976. get_logop(np,bp)
  7977. Rstruc nncb         *np;
  7978. Rstruc batch        *bp;
  7979. {
  7980.  struct token       *tp;
  7981.  
  7982.  if (!(tp = PEEK())) LOSE;
  7983.  switch (tp->type) {
  7984.    case AND_TOKEN:  EAT(); return make_logop(np,bp,AND_OP);
  7985.    case OR_TOKEN:   EAT(); return make_logop(np,bp,OR_OP);
  7986.    case WORD_TOKEN:
  7987.      if (EQUAL(tp->string,"AND")) {
  7988.        EAT();
  7989.        return make_logop(np,bp,AND_OP);
  7990.      }
  7991.      if (EQUAL(tp->string,"OR"))  {
  7992.        EAT();
  7993.        return make_logop(np,bp,OR_OP);
  7994.      }
  7995.      return NULL;
  7996.    default:             return NULL;
  7997.  }
  7998. }
  7999.  
  8000. /*-------------------------------------------------------------------*/
  8001.  
  8002. static Relop
  8003. get_relop(np,bp)
  8004. Rstruc nncb         *np;
  8005. Rstruc batch        *bp;
  8006. {
  8007.  struct token       *tp;
  8008.  
  8009.  if (!(tp = PEEK())) LOSE;
  8010.  switch (tp->type) {
  8011.    case EQ_TOKEN:  EAT(); return make_relop(np,bp,EQ_OP);
  8012.    case NE_TOKEN:  EAT(); return make_relop(np,bp,NE_OP);
  8013.    case GT_TOKEN:  EAT(); return make_relop(np,bp,GT_OP);
  8014.    case LT_TOKEN:  EAT(); return make_relop(np,bp,LT_OP);
  8015.    case GE_TOKEN:  EAT(); return make_relop(np,bp,GE_OP);
  8016.    case LE_TOKEN:  EAT(); return make_relop(np,bp,LE_OP);
  8017.    case WORD_TOKEN:
  8018.      if (EQUAL(tp->string,"IN")) {EAT();
  8019.                                   return make_relop(np,bp,IN_OP);}
  8020.      if (EQUAL(tp->string,"EQ")) {EAT();
  8021.                                   return make_relop(np,bp,EQ_OP);}
  8022.      if (EQUAL(tp->string,"NE")) {EAT();
  8023.                                   return make_relop(np,bp,NE_OP);}
  8024.      if (EQUAL(tp->string,"GT")) {EAT();
  8025.                                   return make_relop(np,bp,GT_OP);}
  8026.      if (EQUAL(tp->string,"LT")) {EAT();
  8027.                                   return make_relop(np,bp,LT_OP);}
  8028.      if (EQUAL(tp->string,"GE")) {EAT();
  8029.                                   return make_relop(np,bp,GE_OP);}
  8030.      if (EQUAL(tp->string,"LE")) {EAT();
  8031.                                   return make_relop(np,bp,LE_OP);}
  8032.      return NULL;
  8033.    default:       return NULL;
  8034.  }
  8035. }
  8036.  
  8037. /*-------------------------------------------------------------------*/
  8038.  
  8039. static Unop
  8040. get_unop(np,bp)
  8041. Rstruc nncb         *np;
  8042. Rstruc batch        *bp;
  8043. {
  8044.  struct token       *tp;
  8045.  
  8046.  if (!(tp = PEEK())) LOSE;
  8047.  switch (tp->type) {
  8048.    case MINUS_TOKEN: EAT(); return make_unop(np,bp,SUB_OP);
  8049.    case PLUS_TOKEN:  EAT(); return make_unop(np,bp,ADD_OP);
  8050.    case NOT_TOKEN:   EAT(); return make_unop(np,bp,NOT_OP);
  8051.    case WORD_TOKEN:
  8052.      if (EQUAL(tp->string,"NOT")) {EAT();
  8053.                                    return make_unop(np,bp,NOT_OP);}
  8054.      return NULL;
  8055.    default:          return NULL;
  8056.  }
  8057. }
  8058.  
  8059. /*-------------------------------------------------------------------*/
  8060.  
  8061. static Bool
  8062. get_word(np,bp,word)
  8063. Rstruc nncb         *np;
  8064. Rstruc batch        *bp;
  8065. char                *word;
  8066. {
  8067.  struct token       *tp;
  8068.  
  8069.  if (!(tp = PEEK())) LOSE;
  8070.  switch (tp->type) {
  8071.    case WORD_TOKEN:
  8072.                     if (EQUAL(tp->string,word)) {EAT(); return TRUE;}
  8073.                     else return FALSE;
  8074.    default:         return FALSE;
  8075.  }
  8076. }
  8077.  
  8078. /*-------------------------------------------------------------------*/
  8079.  
  8080. static Bool
  8081. get_lpar(np,bp)
  8082. Rstruc nncb         *np;
  8083. Rstruc batch        *bp;
  8084. {
  8085.  struct token       *tp;
  8086.  
  8087.  if (!(tp = PEEK())) LOSE;
  8088.  switch (tp->type) {
  8089.    case LPAR_TOKEN: EAT(); return TRUE;
  8090.    default: return FALSE;
  8091.  }
  8092. }
  8093.  
  8094. /*-------------------------------------------------------------------*/
  8095.  
  8096. static Bool
  8097. get_rpar(np,bp)
  8098. Rstruc nncb         *np;
  8099. Rstruc batch        *bp;
  8100. {
  8101.  struct token       *tp;
  8102.  
  8103.  if (!(tp = PEEK())) LOSE;
  8104.  switch (tp->type) {
  8105.    case RPAR_TOKEN: EAT(); return TRUE;
  8106.    default: return FALSE;
  8107.  }
  8108. }
  8109.  
  8110. /*-------------------------------------------------------------------*/
  8111.  
  8112. static Factor
  8113. get_factor(np,bp)
  8114. Rstruc nncb     *np;
  8115. Rstruc batch    *bp;
  8116. {
  8117.  Constant        a1;
  8118.  Variable        b1;
  8119.  Unop            c1;
  8120.  Factor          c2;
  8121.  Exp             d1;
  8122.  enum symtype    type;
  8123.  enum symtype    type2;
  8124.  
  8125.  /* a:  factor -> constant */
  8126.  
  8127.  if (a1 = get_constant(np,bp)) {
  8128.    type = a1->s;
  8129.    return make_factor_a(np,bp,type,a1);
  8130.  }
  8131.  
  8132.  /* b:  factor -> variable */
  8133.  
  8134.  if ((b1 = get_variable(np,bp))) {
  8135.    type = b1->s;
  8136.    return make_factor_b(np,bp,type,b1);
  8137.  }
  8138.  
  8139.  /* c:  factor -> unop factor */
  8140.  
  8141.  if ((c1 = get_unop(np,bp))) {
  8142.    if (!(c2 = get_factor(np,bp))) ERR("expecting factor");
  8143.    type2 = c2->s;
  8144.    switch (c1->op1) {
  8145.      case SUB_OP:
  8146.           if (type2 != NUMBER_SYMTYPE) ERR("not number expression");
  8147.           type = NUMBER_SYMTYPE;
  8148.           break;
  8149.      case ADD_OP:
  8150.           if (type2 != NUMBER_SYMTYPE) ERR("not number expression");
  8151.           type = NUMBER_SYMTYPE;
  8152.           break;
  8153.      case NOT_OP:
  8154.           if (type2 != FLAG_SYMTYPE)   ERR("not flag expression");
  8155.           type = FLAG_SYMTYPE;
  8156.           break;
  8157.    }
  8158.    return make_factor_c(np,bp,type2,c1,c2);
  8159.  }
  8160.  
  8161.  /* d:  factor -> "(" exp ")" */
  8162.  
  8163.  if (get_lpar(np,bp)) {
  8164.    if (!(d1 = get_exp(np,bp))) ERR("expecting numeric expression");
  8165.    if (!get_rpar(np,bp))       ERR("expecting right parenthesis");
  8166.    type = d1->s;
  8167.    return make_factor_d(np,bp,type,d1);
  8168.  }
  8169.  
  8170.  return NULL;
  8171.  
  8172. }
  8173.  
  8174. /*-------------------------------------------------------------------*/
  8175.  
  8176. static Term
  8177. get_term(np,bp)
  8178. Rstruc nncb     *np;
  8179. Rstruc batch    *bp;
  8180. {
  8181.  Term            p;
  8182.  Factor          a1;
  8183.  Mulop           b2;
  8184.  Factor          b3;
  8185.  enum symtype    type;
  8186.  enum symtype    type1;
  8187.  enum symtype    type3;
  8188.  
  8189.  /* a:  term -> factor */
  8190.  
  8191.  if (!(a1 = get_factor(np,bp))) return NULL;
  8192.  
  8193.  type = a1->s;
  8194.  p = make_term_a(np,bp,type,a1);
  8195.  
  8196.  /* b:  term -> term mulop factor */
  8197.  
  8198.  for (;;) {
  8199.  
  8200.    if (!(b2 = get_mulop(np,bp))) break;
  8201.    if (!(b3 = get_factor(np,bp))) ERR("expecting numeric factor");
  8202.    type1 = p->s;
  8203.    type3 = b3->s;
  8204.    if (type1!=NUMBER_SYMTYPE) ERR("operand 1 not number expression");
  8205.    if (type3!=NUMBER_SYMTYPE) ERR("operand 2 not number expression");
  8206.    type = NUMBER_SYMTYPE;
  8207.    p = make_term_b(np,bp,type,p,b2,b3);
  8208.  }
  8209.  
  8210.  return p;
  8211.  
  8212. }
  8213.  
  8214. /*-------------------------------------------------------------------*/
  8215.  
  8216. static Quantity
  8217. get_quantity(np,bp)
  8218. Rstruc nncb     *np;
  8219. Rstruc batch    *bp;
  8220. {
  8221.  Quantity        p;
  8222.  Term            a1;
  8223.  Addop           b2;
  8224.  Term            b3;
  8225.  enum symtype    type;
  8226.  enum symtype    type1;
  8227.  enum symtype    type3;
  8228.  
  8229.  /* a:  quantity -> term */
  8230.  
  8231.  if (!(a1 = get_term(np,bp))) return NULL;
  8232.  
  8233.  type = a1->s;
  8234.  p = make_quantity_a(np,bp,type,a1);
  8235.  
  8236.  /* b:  quantity -> quantity addop term */
  8237.  
  8238.  for (;;) {
  8239.  
  8240.    if (!(b2 = get_addop(np,bp))) break;
  8241.    if (!(b3 = get_term(np,bp))) ERR("expecting numeric term");
  8242.    type1 = p->s;
  8243.    type3 = b3->s;
  8244.    if (type1!=NUMBER_SYMTYPE) ERR("operand 1 not number expression");
  8245.    if (type3!=NUMBER_SYMTYPE) ERR("operand 2 not number expression");
  8246.    type = NUMBER_SYMTYPE;
  8247.    p = make_quantity_b(np,bp,type,p,b2,b3);
  8248.  }
  8249.  
  8250.  return p;
  8251.  
  8252. }
  8253.  
  8254. /*-------------------------------------------------------------------*/
  8255.  
  8256. static Value
  8257. get_value(np,bp)
  8258. Rstruc nncb     *np;
  8259. Rstruc batch    *bp;
  8260. {
  8261.  Value           p;
  8262.  Quantity        a1;
  8263.  Quantity        b2;
  8264.  enum symtype    type;
  8265.  enum symtype    type1;
  8266.  enum symtype    type2;
  8267.  
  8268.  /* a:  value -> quantity */
  8269.  
  8270.  if (!(a1 = get_quantity(np,bp))) return NULL;
  8271.  
  8272.  type = a1->s;
  8273.  p = make_value_a(np,bp,type,a1);
  8274.  
  8275.  /* b:  value -> value quantity */
  8276.  
  8277.  for (;;) {
  8278.  
  8279.    if (!(b2 = get_quantity(np,bp))) break;
  8280.    type1 = p->s;
  8281.    type2 = p->s;
  8282.    type = STRING_SYMTYPE;
  8283.    p = make_value_b(np,bp,type,p,b2);
  8284.  }
  8285.  
  8286.  return p;
  8287.  
  8288. }
  8289.  
  8290. /*-------------------------------------------------------------------*/
  8291.  
  8292. static Relation
  8293. get_relation(np,bp)
  8294. Rstruc nncb     *np;
  8295. Rstruc batch    *bp;
  8296. {
  8297.  Relation        p;
  8298.  Value           a1;
  8299.  Relop           b2;
  8300.  Value           b3;
  8301.  enum symtype    type;
  8302.  enum symtype    type1;
  8303.  enum symtype    type3;
  8304.  
  8305.  /* a:  relation -> value */
  8306.  
  8307.  if (!(a1 = get_value(np,bp))) return NULL;
  8308.  
  8309.  type = a1->s;
  8310.  p = make_relation_a(np,bp,type,a1);
  8311.  
  8312.  /* b:  relation -> value relop value */
  8313.  
  8314.  if (!(b2 = get_relop(np,bp))) return p;
  8315.  if (!(b3 = get_value(np,bp)))
  8316.     ERR("expecting string or numeric value");
  8317.  type1 = a1->s;
  8318.  type3 = b3->s;
  8319.  switch (b2->op1) {
  8320.    case IN_OP:
  8321.      if (type1 != STRING_SYMTYPE)
  8322.         ERR("operand 1 not string expression");
  8323.      if (type3 != STRING_SYMTYPE)
  8324.         ERR("operand 3 not string expression");
  8325.      break;
  8326.    case EQ_OP:
  8327.    case NE_OP:
  8328.      if (!((type1 == NUMBER_SYMTYPE && type3 == NUMBER_SYMTYPE)
  8329.         || (type1 == STRING_SYMTYPE && type3 == STRING_SYMTYPE)
  8330.         || (type1 == FLAG_SYMTYPE   && type3 == FLAG_SYMTYPE)))
  8331.       ERR("operands are not both of the same type");
  8332.      break;
  8333.    default:
  8334.      if (!((type1 == NUMBER_SYMTYPE && type3 == NUMBER_SYMTYPE)
  8335.         || (type1 == STRING_SYMTYPE && type3 == STRING_SYMTYPE)))
  8336.       ERR("operands are not both numeric or both string expressions");
  8337.      break;
  8338.  }
  8339.  type = FLAG_SYMTYPE;
  8340.  p = make_relation_b(np,bp,type,a1,b2,b3);
  8341.  
  8342.  return p;
  8343.  
  8344. }
  8345.  
  8346. /*-------------------------------------------------------------------*/
  8347.  
  8348. static Choice
  8349. get_choice(np,bp)
  8350. Rstruc nncb     *np;
  8351. Rstruc batch    *bp;
  8352. {
  8353.  Choice          p;
  8354.  Relation        a1;
  8355.  Logop           b2;
  8356.  Relation        b3;
  8357.  enum symtype    type;
  8358.  enum symtype    type1;
  8359.  enum symtype    type3;
  8360.  
  8361.  /* a:  choice -> relation */
  8362.  
  8363.  if (!(a1 = get_relation(np,bp))) return NULL;
  8364.  
  8365.  type = a1->s;
  8366.  p = make_choice_a(np,bp,type,a1);
  8367.  
  8368.  /* b:  choice -> choice logop relation */
  8369.  
  8370.  for (;;) {
  8371.  
  8372.    if (!(b2 = get_logop(np,bp))) break;
  8373.    if (!(b3 = get_relation(np,bp)))
  8374.       ERR("expecting logical expression");
  8375.    type1 = p->s;
  8376.    type3 = b3->s;
  8377.    if (type1 != FLAG_SYMTYPE) ERR("operand 1 not logical expression");
  8378.    if (type3 != FLAG_SYMTYPE) ERR("operand 2 not logical expression");
  8379.    type = FLAG_SYMTYPE;
  8380.    p = make_choice_b(np,bp,type,p,b2,b3);
  8381.  }
  8382.  
  8383.  return p;
  8384.  
  8385. }
  8386.  
  8387. /*-------------------------------------------------------------------*/
  8388.  
  8389. static Exp
  8390. get_exp(np,bp)
  8391. Rstruc nncb     *np;
  8392. Rstruc batch    *bp;
  8393. {
  8394.  Choice          a1;
  8395.  Exp             b1;
  8396.  Exp             b2;
  8397.  Exp             b3;
  8398.  enum symtype    type;
  8399.  enum symtype    type1;
  8400.  enum symtype    type2;
  8401.  enum symtype    type3;
  8402.  
  8403.  /* b:  exp -> "IF" exp "THEN" exp "ELSE" exp */
  8404.  
  8405.  if (get_word(np,bp,"IF")) {
  8406.    if (!(b1 = get_exp(np,bp)))    ERR("expecting expression");
  8407.    if (!(get_word(np,bp,"THEN"))) ERR("expecting THEN");
  8408.    if (!(b2 = get_exp(np,bp)))    ERR("expecting expression");
  8409.    if (!(get_word(np,bp,"ELSE"))) ERR("expecting ELSE");
  8410.    if (!(b3 = get_exp(np,bp)))    ERR("expecting expression");
  8411.    type1 = b1->s;
  8412.    type2 = b2->s;
  8413.    type3 = b3->s;
  8414.    if (type1 != FLAG_SYMTYPE) ERR("operand 1 not logical expression");
  8415.    type = type2;
  8416.    return make_exp_b(np,bp,type,b1,b2,b3);
  8417.  }
  8418.  
  8419.  /* a:  exp -> choice */
  8420.  
  8421.  if (!(a1 = get_choice(np,bp))) ERR("expecting IF or expression");
  8422.  type = a1->s;
  8423.  return make_exp_a(np,bp,type,a1);
  8424.  
  8425. }
  8426.  
  8427. /*-------------------------------------------------------------------*/
  8428.  
  8429. static Exp
  8430. get_strtree(np,bp)
  8431. Rstruc nncb     *np;
  8432. Rstruc batch    *bp;
  8433. {
  8434.  Exp             p;
  8435.  
  8436.  p = get_exp(np,bp);
  8437.  if (!p) {
  8438.   NNMbsynt(np,bp,NULL,0,"no expression found");
  8439.   return NULL;
  8440.  }
  8441.  
  8442.  return p;
  8443. }
  8444.  
  8445. /*-------------------------------------------------------------------*/
  8446.  
  8447. static Exp
  8448. get_numtree(np,bp)
  8449. Rstruc nncb     *np;
  8450. Rstruc batch    *bp;
  8451. {
  8452.  Exp             p;
  8453.  
  8454.  p = get_exp(np,bp);
  8455.  if (!p) {
  8456.    NNMbsynt(np,bp,NULL,0,"no expression found");
  8457.    return NULL;
  8458.  }
  8459.  switch (p->s) {
  8460.    case STRING_SYMTYPE:
  8461.         NNMbsynt(np,bp,NULL,0,"numeric expression required");
  8462.         return NULL;
  8463.    case NUMBER_SYMTYPE:
  8464.    case FLAG_SYMTYPE:
  8465.    default:             return p;
  8466.  }
  8467. }
  8468.  
  8469. /*-------------------------------------------------------------------*/
  8470.  
  8471. static Exp
  8472. get_flagtree(np,bp)
  8473. Rstruc nncb     *np;
  8474. Rstruc batch    *bp;
  8475. {
  8476.  Exp             p;
  8477.  
  8478.  p = get_exp(np,bp);
  8479.  if (!p) {
  8480.    NNMbsynt(np,bp,NULL,0,"no expression found");
  8481.    return NULL;
  8482.  }
  8483.  switch (p->s) {
  8484.    case FLAG_SYMTYPE:  return p;
  8485.    default:
  8486.             NNMbsynt(np,bp,NULL,0,"logical expression required");
  8487.             return NULL;
  8488.  }
  8489. }
  8490.  
  8491. /****** Get expression and build an expression tree. *****************/
  8492.  
  8493. struct ptree *
  8494. NNMbgexp(np,bp,type)
  8495. Rstruc nncb         *np;
  8496. Rstruc batch        *bp;
  8497. enum symtype         type;
  8498. {
  8499.  struct ptree       *treep      = NULL;
  8500.  
  8501.  /* Define return point for syntax errors during parse. */
  8502.  
  8503.  switch (setjmp(bp->jump)) {
  8504.    case ERROR_NONE:
  8505.         break;
  8506.    case ERROR_GETMAIN_FAILURE:
  8507.         NNMbsynt(np,bp,NULL,0,"Not enough memory to parse expression");
  8508.         return NULL;
  8509.    default:
  8510.         bp->syntax_error = TRUE;
  8511.         return NULL;
  8512.  }
  8513.  
  8514.  switch (type) {
  8515.    case STRING_SYMTYPE:
  8516.                         GETMAIN(treep,struct ptree,1,"string ptree");
  8517.                         if (treep) {
  8518.                           treep->type = STRING_TREETYPE;
  8519.                           treep->exp1 = get_strtree(np,bp);
  8520.                         }
  8521.                         break;
  8522.    case NUMBER_SYMTYPE:
  8523.                         GETMAIN(treep,struct ptree,1,"number ptree");
  8524.                         if (treep) {
  8525.                           treep->type = NUMBER_TREETYPE;
  8526.                           treep->exp1 = get_numtree(np,bp);
  8527.                         }
  8528.                         break;
  8529.    case FLAG_SYMTYPE:
  8530.                         GETMAIN(treep,struct ptree,1,"flag ptree");
  8531.                         if (treep) {
  8532.                           treep->type       = FLAG_TREETYPE;
  8533.                           treep->exp1 = get_flagtree(np,bp);
  8534.                         }
  8535.                         break;
  8536.    default: NNMbsynt(np,bp,NULL,0,"Invalid type passed to NNMbgexp");
  8537.             return NULL;
  8538.  }
  8539.  
  8540.  if (!treep) {
  8541.    NNMbsynt(np,bp,NULL,0,"No storage available to build expression");
  8542.    return NULL;
  8543.  }
  8544.  
  8545.  return treep;
  8546. }
  8547.  
  8548. ./ ADD NAME=NNMBGTOK
  8549.  
  8550.  /********************************************************************/
  8551.  /*                                                                  */
  8552.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  8553.  /*                                                                  */
  8554.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  8555.  /* including the implied warranties of merchantability and fitness, */
  8556.  /* are expressly denied.                                            */
  8557.  /*                                                                  */
  8558.  /* Provided this copyright notice is included, this software may    */
  8559.  /* be freely distributed and not offered for sale.                  */
  8560.  /*                                                                  */
  8561.  /* Changes or modifications may be made and used only by the maker  */
  8562.  /* of same, and not further distributed.  Such modifications should */
  8563.  /* be mailed to the author for consideration for addition to the    */
  8564.  /* software and incorporation in subsequent releases.               */
  8565.  /*                                                                  */
  8566.  /********************************************************************/
  8567.  
  8568. #pragma  csect(code,  "NN@BGTOK")
  8569. #pragma  csect(static,"NN$BGTOK")
  8570. #include "nn.h"
  8571. #include "nnbatch.h"
  8572.  
  8573. /****** Get input line. **********************************************/
  8574.  
  8575. static char *
  8576. get_input_line(np,bp)
  8577. Rstruc nncb         *np;
  8578. Rstruc batch        *bp;
  8579. {
  8580.  char               *cp;
  8581.  
  8582.  for (;;) {
  8583.    cp = fgets(bp->inline, sizeof(bp->inline), np->batch_infile);
  8584.    if (!cp) {
  8585.      if (ferror(np->batch_infile)) {
  8586.        fprintf(stderr,"\n*** Error reading batch input file ***\n");
  8587.        abort();
  8588.      }
  8589.      bp->eof = TRUE;
  8590.      return NULL;
  8591.    }
  8592.    else if ((cp=strchr(cp,'\n'))) *cp = '\0';
  8593.  
  8594.    /* Hack to allow standard entry of EOF from the terminal. */
  8595.  
  8596.    if (EQUAL(bp->inline,"/*")) {
  8597.      fprintf(np->batch_outfile, "EOF (/*) signalled in input.\n");
  8598.      bp->eof = TRUE;
  8599.      return NULL;
  8600.    }
  8601.    fprintf(np->batch_outfile, "%s\n", bp->inline);
  8602.    if (bp->inline[0] != '#') break;
  8603.  }
  8604.  return bp->inline;
  8605. }
  8606.  
  8607. /****** Show token, for debugging only. ******************************/
  8608.  
  8609. static char *
  8610. token_description(tokp)
  8611. struct token     *tokp;
  8612. {
  8613.  char            *c;
  8614.  
  8615.  switch (tokp->type) {
  8616.                      case NO_TOKEN:       c = "no token"; break;
  8617.                      case EOL_TOKEN:      c = "EOL";      break;
  8618.                      case EOF_TOKEN:      c = "EOF";      break;
  8619.                      case AND_TOKEN:      c = "AND";      break;
  8620.                      case OR_TOKEN:       c = "OR";       break;
  8621.                      case NOT_TOKEN:      c = "NOT";      break;
  8622.                      case GT_TOKEN:       c = "GT";       break;
  8623.                      case LT_TOKEN:       c = "LT";       break;
  8624.                      case EQ_TOKEN:       c = "EQ";       break;
  8625.                      case NE_TOKEN:       c = "NE";       break;
  8626.                      case GE_TOKEN:       c = "GE";       break;
  8627.                      case LE_TOKEN:       c = "LE";       break;
  8628.                      case LPAR_TOKEN:     c = "LPAR";     break;
  8629.                      case RPAR_TOKEN:     c = "RPAR";     break;
  8630.                      case PLUS_TOKEN:     c = "PLUS";     break;
  8631.                      case MINUS_TOKEN:    c = "MINUS";    break;
  8632.                      case TIMES_TOKEN:    c = "TIMES";    break;
  8633.                      case OVER_TOKEN:     c = "OVER";     break;
  8634.                      case SEMI_TOKEN:     c = "SEMI";     break;
  8635.                      case WORD_TOKEN:     c = "WORD";     break;
  8636.                      case NUMBER_TOKEN:   c = "NUMBER";   break;
  8637.                      case STRING_TOKEN:   c = "STRING";   break;
  8638.                      case ERROR_TOKEN:    c = "ERROR";    break;
  8639.                      default:             c = "?";        break;
  8640.                 }
  8641.  return c;
  8642. }
  8643.  
  8644. /****** Get token. ***************************************************/
  8645.  
  8646. static Bool
  8647. get_token(np,bp,tokp,flushing)
  8648. Rstruc nncb         *np;
  8649. Rstruc batch        *bp;
  8650. struct token        *tokp;
  8651. Fool                 flushing;
  8652. {
  8653.  char               *cp;
  8654.  char               *dp;
  8655.  char               *ep;
  8656.  int                 len;
  8657.  Bool                inquote;
  8658.  Bool                badtoken;
  8659.  
  8660.  /* If reached end of current line, get a line */
  8661.  
  8662.  do {
  8663.    while (*bp->inchar == '\0') {
  8664.      if (bp->stop_at_newline) {
  8665.        tokp->type = EOL_TOKEN;
  8666.        strcpy(tokp->string,"<**End Of Line**>");
  8667.        return TRUE;
  8668.      }
  8669.      bp->inchar = get_input_line(np,bp);
  8670.      if (bp->inchar == NULL) {
  8671.        tokp->type = EOF_TOKEN;
  8672.        strcpy(tokp->string,"<**End Of File**>");
  8673.        return TRUE;
  8674.      }
  8675.    }
  8676.    while (isspace(*bp->inchar)) bp->inchar++;
  8677.    if (*bp->inchar == '#') *bp->inchar = '\0';
  8678.  } while (*bp->inchar == '\0');
  8679.  
  8680.  memset(tokp->string, 0, sizeof(tokp->string));
  8681.  tokp->number = 0;
  8682.  bp->syntax_error = FALSE;
  8683.  badtoken = FALSE;
  8684.  
  8685.  cp = bp->inchar;
  8686.  if (isdigit(*cp)) {
  8687.    ep = cp + strspn(cp,"0123456789");
  8688.    len = ep - cp;
  8689.    bp->inchar = ep;
  8690.    if (len > 10) {
  8691.      badtoken = TRUE;
  8692.      if (flushing) tokp->type = ERROR_TOKEN;
  8693.      else NNMbsynt(np,bp,cp,len,"Number too long");
  8694.    }
  8695.    else {
  8696.      tokp->type = NUMBER_TOKEN;
  8697.      memcpy(tokp->string, cp, len);
  8698.      tokp->number = atoi(tokp->string);
  8699.    }
  8700.  }
  8701.  else if (isalpha(*cp)) {
  8702.    dp = tokp->string;
  8703.    ep = dp + sizeof(tokp->string) - 1;
  8704.    while (isalnum(*cp)) {
  8705.      if (dp > ep) {
  8706.        if (!badtoken) {
  8707.          badtoken = TRUE;
  8708.          if (flushing) tokp->type = ERROR_TOKEN;
  8709.          else NNMbsynt(np,bp,cp,ep-cp, "Word too long");
  8710.        }
  8711.      }
  8712.      else {
  8713.        *(dp++) = toupper(*(cp++));
  8714.      }
  8715.    }
  8716.    *dp = '\0';
  8717.    bp->inchar = cp;
  8718.    tokp->type = badtoken ? ERROR_TOKEN : WORD_TOKEN;
  8719.  }
  8720.  else if (*cp == '"') {
  8721.    bp->inchar++;
  8722.    cp = bp->inchar;
  8723.    dp = tokp->string;
  8724.    ep = tokp->string + sizeof(tokp->string) - 1;
  8725.    inquote = TRUE;
  8726.    while (inquote) {
  8727.      switch (*cp) {
  8728.        case '\0': NNMbsynt(np,bp,NULL,0,"Missing end quote");
  8729.                   inquote = FALSE;
  8730.                   bp->inchar = cp;
  8731.                   break;
  8732.        case '"' : inquote = FALSE;
  8733.                   bp->inchar = cp+1;
  8734.                   break;
  8735.        case '\\': cp++;
  8736.                   /* fall through */
  8737.        default  : if (dp > ep) {
  8738.                     if (!badtoken) {
  8739.                       badtoken = TRUE;
  8740.                       if (flushing) tokp->type = ERROR_TOKEN;
  8741.                       else
  8742.                        NNMbsynt(np,bp,NULL,0,"Quoted string too long");
  8743.                     }
  8744.                   }
  8745.                   else *(dp++) = *(cp++);
  8746.                   break;
  8747.      }
  8748.    }
  8749.    *dp = '\0';
  8750.    tokp->type = badtoken ? ERROR_TOKEN : STRING_TOKEN;
  8751.  }
  8752.  else {
  8753.    switch (*cp) {
  8754.      case ';': bp->inchar++; tokp->type = SEMI_TOKEN;  break;
  8755.      case '(': bp->inchar++; tokp->type = LPAR_TOKEN;  break;
  8756.      case ')': bp->inchar++; tokp->type = RPAR_TOKEN;  break;
  8757.      case '+': bp->inchar++; tokp->type = PLUS_TOKEN;  break;
  8758.      case '-': bp->inchar++; tokp->type = MINUS_TOKEN; break;
  8759.      case '*': bp->inchar++; tokp->type = TIMES_TOKEN; break;
  8760.      case '/': bp->inchar++; tokp->type = OVER_TOKEN;  break;
  8761.      case '&': bp->inchar++; tokp->type = AND_TOKEN;   break;
  8762.      case '|': bp->inchar++; tokp->type = OR_TOKEN;    break;
  8763.      case '>': bp->inchar++;
  8764.                switch (*bp->inchar) {
  8765.                  case '=': bp->inchar++; tokp->type = GE_TOKEN; break;
  8766.                  default:                tokp->type = GT_TOKEN; break;
  8767.                }
  8768.                break;
  8769.      case '<': bp->inchar++;
  8770.                switch (*bp->inchar) {
  8771.                  case '=': bp->inchar++; tokp->type = LE_TOKEN; break;
  8772.                  case '>': bp->inchar++; tokp->type = NE_TOKEN; break;
  8773.                  default:                tokp->type = LT_TOKEN; break;
  8774.                }
  8775.                break;
  8776.      case '=': bp->inchar++;
  8777.                switch (*bp->inchar) {
  8778.                  case '=': bp->inchar++; tokp->type = EQ_TOKEN; break;
  8779.                  default:                tokp->type = EQ_TOKEN; break;
  8780.                }
  8781.                break;
  8782.      case '^':
  8783.      case '!': bp->inchar++;
  8784.                switch (*bp->inchar) {
  8785.                  case '=': bp->inchar++; tokp->type = NE_TOKEN; break;
  8786.                  case '<': bp->inchar++; tokp->type = GT_TOKEN; break;
  8787.                  case '>': bp->inchar++; tokp->type = LT_TOKEN; break;
  8788.                  default:                tokp->type = NOT_TOKEN; break;
  8789.                }
  8790.                break;
  8791.      default:  if (flushing) tokp->type = ERROR_TOKEN;
  8792.                else NNMbsynt(np,bp,cp,1,
  8793.                              "Invalid character, cannot scan");
  8794.                bp->inchar++;
  8795.                break;
  8796.    }
  8797.    memcpy(tokp->string, cp, bp->inchar - cp); /* just in case */
  8798.  }
  8799.  
  8800.  if (np->debug_file) {
  8801.    fprintf(np->debug_file,"token = %s", token_description(tokp));
  8802.    switch (tokp->type) {
  8803.      case NUMBER_TOKEN:
  8804.               fprintf(np->debug_file, "(%d,'%s')\n",
  8805.                                       tokp->number, tokp->string);
  8806.               break;
  8807.      case WORD_TOKEN:
  8808.      case STRING_TOKEN:
  8809.      default:
  8810.               fprintf(np->debug_file, "(%s)\n", tokp->string);
  8811.               break;
  8812.    }
  8813.  }
  8814.  
  8815.  return TRUE;
  8816.  
  8817. }
  8818.  
  8819. /****** Get token. ***************************************************/
  8820.  
  8821. Bool
  8822. NNMbgtok(np,bp,func)
  8823. Rstruc nncb         *np;
  8824. Rstruc batch        *bp;
  8825. enum tokenfunc       func;
  8826. {
  8827.  
  8828.  if (!bp->tokens_read) {
  8829.    bp->inchar = get_input_line(np,bp);
  8830.    bp->tokens_read = TRUE;
  8831.    if (bp->inchar == NULL) { /* no input at all? */
  8832.      bp->curtok.type = EOF_TOKEN;
  8833.      bp->nextok.type = EOF_TOKEN;
  8834.      return TRUE;
  8835.    }
  8836.  }
  8837.  if (bp->curtok.type == EOF_TOKEN) {
  8838.    NNMbsynt(np,bp,NULL,0, "Attempt to read token past end of file");
  8839.    return FALSE;
  8840.  }
  8841.  
  8842.  switch (func) {
  8843.    case TOKEN_PEEK:
  8844.                      if (bp->nextok.type == NO_TOKEN) {
  8845.                        return get_token(np,bp,&bp->nextok,FALSE);
  8846.                      }
  8847.                      else { /* token already peeked at */
  8848.                        return TRUE;
  8849.                      }
  8850.    case TOKEN_READ:
  8851.                      if (bp->nextok.type == NO_TOKEN) {
  8852.                        return get_token(np,bp,&bp->curtok,FALSE);
  8853.                      }
  8854.                      else { /* token already peeked at */
  8855.                        memcpy((char *)&bp->curtok,
  8856.                               (char *)&bp->nextok,
  8857.                               sizeof(struct token));
  8858.                        bp->nextok.type = NO_TOKEN;
  8859.                        return TRUE;
  8860.                      }
  8861.    case TOKEN_FLUSH:
  8862.                      if (bp->nextok.type == NO_TOKEN) {
  8863.                        return get_token(np,bp,&bp->curtok,TRUE);
  8864.                      }
  8865.                      else { /* token already peeked at */
  8866.                        memcpy((char *)&bp->curtok,
  8867.                               (char *)&bp->nextok,
  8868.                               sizeof(struct token));
  8869.                        bp->nextok.type = NO_TOKEN;
  8870.                        return TRUE;
  8871.                      }
  8872.  }
  8873.  
  8874. }
  8875.  
  8876. ./ ADD NAME=NNMBPDEC
  8877.  
  8878.  /********************************************************************/
  8879.  /*                                                                  */
  8880.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  8881.  /*                                                                  */
  8882.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  8883.  /* including the implied warranties of merchantability and fitness, */
  8884.  /* are expressly denied.                                            */
  8885.  /*                                                                  */
  8886.  /* Provided this copyright notice is included, this software may    */
  8887.  /* be freely distributed and not offered for sale.                  */
  8888.  /*                                                                  */
  8889.  /* Changes or modifications may be made and used only by the maker  */
  8890.  /* of same, and not further distributed.  Such modifications should */
  8891.  /* be mailed to the author for consideration for addition to the    */
  8892.  /* software and incorporation in subsequent releases.               */
  8893.  /*                                                                  */
  8894.  /********************************************************************/
  8895.  
  8896. /*=====================================================================
  8897.  *
  8898.  * Command: DECLARE
  8899.  *
  8900.  * Syntax:  DECLARE variablename {STRING | NUMBER | FLAG}
  8901.  *
  8902.  * Mode:    any
  8903.  *
  8904.  * Function: Declares a variable that can be referenced later.
  8905.  *           Its type is specified as well.  The type can be:
  8906.  *
  8907.  *           * STRING - character string
  8908.  *           * NUMBER - integer
  8909.  *           * FLAG   - 1 or 0, TRUE or FALSE, ON or OFF, YES or NO
  8910.  *
  8911.  * Note: This command is processed at parse time only.  It is not an
  8912.  *       executable command.  No matter where it appears in the input
  8913.  *       command environment, it will be processed.  The only caveat
  8914.  *       is that a variable must be referenced by DECLARE prior to
  8915.  *       any appearance of it in the input stream.
  8916.  *
  8917.  * Examples:  DECLARE FOO STRING
  8918.  *            DECLARE BAR NUMBER
  8919.  *            DECLARE BAZ FLAG
  8920.  *
  8921.  *====================================================================*/
  8922.  
  8923. #pragma  csect(code,  "NN@BPDEC")
  8924. #pragma  csect(static,"NN$BPDEC")
  8925. #include "nn.h"
  8926. #include "nnbatch.h"
  8927.  
  8928. /****** Parse batch DECLARE      command. ****************************/
  8929.  
  8930. struct newscmd *
  8931. NNMbpdec(np,bp)
  8932. Rstruc nncb         *np;
  8933. Rstruc batch        *bp;
  8934. {
  8935.  char               *var;
  8936.  enum symtype        type;
  8937.  ANYTYPE             val;
  8938.  
  8939.  /* Next token must be variable name.  */
  8940.  
  8941.  (void)NNMbgtok(np,bp,TOKEN_READ);          /* get token */
  8942.  if (bp->curtok.type != WORD_TOKEN) {
  8943.    NNMbsynt(np,bp,NULL,0, "Expected DECLARE variable name not seen");
  8944.    NNMbflus(np,bp);                         /* flush input tokens */
  8945.    return NULL;
  8946.  }
  8947.  
  8948.  var = NNMcopy(np,bp->curtok.string);
  8949.  
  8950.  /* Next token must be one of the words STRING, NUMBER or FLAG.  */
  8951.  
  8952.  (void)NNMbgtok(np,bp,TOKEN_READ);          /* get token */
  8953.  if (bp->curtok.type != WORD_TOKEN) {
  8954.    NNMbsynt(np,bp,NULL,0, "Expected DECLARE type name not seen");
  8955.    NNMbflus(np,bp);                         /* flush input tokens */
  8956.    return NULL;
  8957.  }
  8958.  
  8959.  if      (EQUAL(bp->curtok.string,"STRING")) {
  8960.    type = STRING_SYMTYPE;
  8961.    val  = (ANYTYPE)"";
  8962.  }
  8963.  else if (EQUAL(bp->curtok.string,"NUMBER")) {
  8964.    type = NUMBER_SYMTYPE;
  8965.    val  = (ANYTYPE)0;
  8966.  }
  8967.  else if (EQUAL(bp->curtok.string,"FLAG")) {
  8968.    type = FLAG_SYMTYPE;
  8969.    val  = (ANYTYPE)0;
  8970.  }
  8971.  else {
  8972.   NNMbsynt(np,bp,bp->curtok.string,0,
  8973.            "DECLARE type not one of STRING, NUMBER or FLAG");
  8974.   return NULL;
  8975.  }
  8976.  
  8977.  if (!NNMbdecl(np,bp,var,type,val)) {
  8978.   NNMbsynt(np,bp,var,0, "Declaration failed");
  8979.   return NULL;
  8980.  }
  8981.  
  8982.  return NULL;
  8983. }
  8984.  
  8985. ./ ADD NAME=NNMBPDER
  8986.  
  8987.  /********************************************************************/
  8988.  /*                                                                  */
  8989.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  8990.  /*                                                                  */
  8991.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  8992.  /* including the implied warranties of merchantability and fitness, */
  8993.  /* are expressly denied.                                            */
  8994.  /*                                                                  */
  8995.  /* Provided this copyright notice is included, this software may    */
  8996.  /* be freely distributed and not offered for sale.                  */
  8997.  /*                                                                  */
  8998.  /* Changes or modifications may be made and used only by the maker  */
  8999.  /* of same, and not further distributed.  Such modifications should */
  9000.  /* be mailed to the author for consideration for addition to the    */
  9001.  /* software and incorporation in subsequent releases.               */
  9002.  /*                                                                  */
  9003.  /********************************************************************/
  9004.  
  9005. /*=====================================================================
  9006.  *
  9007.  * Command: DEREGISTER
  9008.  *
  9009.  * Syntax:  DEREGISTER
  9010.  *
  9011.  * Mode:    per_newsgroup
  9012.  *
  9013.  * Function: Deregisters the current newsgroup.
  9014.  *
  9015.  * Note: Arguments are not permitted.  If they are given, the
  9016.  *       function will not be performed.
  9017.  *
  9018.  * Examples:  DEREGISTER
  9019.  *
  9020.  *====================================================================*/
  9021.  
  9022. #pragma  csect(code,  "NN@BPDER")
  9023. #pragma  csect(static,"NN$BPDER")
  9024. #include "nn.h"
  9025. #include "nnbatch.h"
  9026.  
  9027. /****** Execute batch DEREGISTER command. ****************************/
  9028.  
  9029. static void
  9030. NNMbxder(np,bp,cmdp)
  9031. Rstruc nncb         *np;
  9032. Rstruc batch        *bp;
  9033. Rstruc newscmd      *cmdp;
  9034. {
  9035.  Rstruc newsgroup   *gp = bp->gp;
  9036.  
  9037.  gp->registered = 0;
  9038.  fprintf(np->batch_outfile,"Newsgroup %s deregistered.\n",gp->name);
  9039.  NNMsave(np,NULL);    /* Checkpoint NEWSRC file */
  9040.  return;
  9041.  
  9042. }
  9043.  
  9044. /****** Parse batch DEREGISTER command. ****************************/
  9045.  
  9046. struct newscmd *
  9047. NNMbpder(np,bp)
  9048. Rstruc nncb         *np;
  9049. Rstruc batch        *bp;
  9050. {
  9051.  struct newscmd     *cmdp;
  9052.  
  9053.  bp->stop_at_newline = TRUE;
  9054.  NNMbtras(np,bp,"DEREGISTER");   /* Trash extraneous parameters */
  9055.  if (bp->syntax_error) return NULL;
  9056.  if (bp->mode != PER_NEWSGROUP_MODE) {
  9057.    NNMbsynt(np,bp,NULL,0,
  9058.             "DEREGISTER is invalid outside of per-newsgroup mode");
  9059.    return NULL;
  9060.  }
  9061.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for DEREGISTER command");
  9062.  if (cmdp) {
  9063.    cmdp->mode = PER_NEWSGROUP_MODE;
  9064.    cmdp->proc = NNMbxder;
  9065.  }
  9066.  return cmdp;
  9067. }
  9068.  
  9069. ./ ADD NAME=NNMBPELS
  9070.  
  9071.  /********************************************************************/
  9072.  /*                                                                  */
  9073.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  9074.  /*                                                                  */
  9075.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  9076.  /* including the implied warranties of merchantability and fitness, */
  9077.  /* are expressly denied.                                            */
  9078.  /*                                                                  */
  9079.  /* Provided this copyright notice is included, this software may    */
  9080.  /* be freely distributed and not offered for sale.                  */
  9081.  /*                                                                  */
  9082.  /* Changes or modifications may be made and used only by the maker  */
  9083.  /* of same, and not further distributed.  Such modifications should */
  9084.  /* be mailed to the author for consideration for addition to the    */
  9085.  /* software and incorporation in subsequent releases.               */
  9086.  /*                                                                  */
  9087.  /********************************************************************/
  9088.  
  9089. #pragma  csect(code,  "NN@BPELS")
  9090. #pragma  csect(static,"NN$BPELS")
  9091. #include "nn.h"
  9092. #include "nnbatch.h"
  9093.  
  9094. /****** Parse batch ELSE         command. ****************************/
  9095.  
  9096. struct newscmd *
  9097. NNMbpels(np,bp)
  9098. Rstruc nncb         *np;
  9099. Rstruc batch        *bp;
  9100. {
  9101.  struct newscmd             *cmdp       = NULL;
  9102.  struct cmdtree             *elsecmds   = NULL;
  9103.  
  9104.  cmdp = bp->ifcmd;
  9105.  bp->ifcmd = NULL;
  9106.  
  9107.  if (!cmdp) {
  9108.    NNMbsynt(np,bp,NULL,0,"ELSE without matching IF found");
  9109.  }
  9110.  
  9111.  /* Get DO-END command group.  */
  9112.  
  9113.  elsecmds = NNMbgdo(np,bp,bp->mode);
  9114.  
  9115.  if (bp->syntax_error) return NULL;
  9116.  
  9117.  if (cmdp) cmdp->cmd.fcmd.elsecmds = elsecmds;
  9118.  
  9119.  return NULL;  /* cmdp was already returned by IF */
  9120.  
  9121. }
  9122.  
  9123. ./ ADD NAME=NNMBPEXE
  9124.  
  9125.  /********************************************************************/
  9126.  /*                                                                  */
  9127.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  9128.  /*                                                                  */
  9129.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  9130.  /* including the implied warranties of merchantability and fitness, */
  9131.  /* are expressly denied.                                            */
  9132.  /*                                                                  */
  9133.  /* Provided this copyright notice is included, this software may    */
  9134.  /* be freely distributed and not offered for sale.                  */
  9135.  /*                                                                  */
  9136.  /* Changes or modifications may be made and used only by the maker  */
  9137.  /* of same, and not further distributed.  Such modifications should */
  9138.  /* be mailed to the author for consideration for addition to the    */
  9139.  /* software and incorporation in subsequent releases.               */
  9140.  /*                                                                  */
  9141.  /********************************************************************/
  9142.  
  9143. /*=====================================================================
  9144.  *
  9145.  * Command: EXEC
  9146.  *
  9147.  * Syntax:  EXEC {datum}* ;
  9148.  *
  9149.  * Mode:    any (but see note)
  9150.  *
  9151.  * Function: Executes the TSO command built from the specified
  9152.  *           data items.  Items can be:
  9153.  *
  9154.  *           * text strings
  9155.  *           * integers
  9156.  *           * words representing variables that have values
  9157.  *
  9158.  * Note: When words are used, the values they represent must be
  9159.  *       valid for the mode in which the EXEC is executed.
  9160.  *
  9161.  * Note: Since the command can span input lines and the number of
  9162.  *       arguments is variable, the arguments MUST be terminated
  9163.  *       by a semicolon or end of file.
  9164.  *
  9165.  * Examples:  EXEC "time";
  9166.  *            EXEC "SE 'I have " UNREAD " new items' USER(JRL)";
  9167.  *
  9168.  *====================================================================*/
  9169.  
  9170. #pragma  csect(code,  "NN@BPEXE")
  9171. #pragma  csect(static,"NN$BPEXE")
  9172. #include "nn.h"
  9173. #include "nnbatch.h"
  9174.  
  9175. /****** Execute batch EXEC       command. ****************************/
  9176.  
  9177. static void
  9178. NNMbxexe(np,bp,cmdp)
  9179. Rstruc nncb         *np;
  9180. Rstruc batch        *bp;
  9181. Rstruc newscmd      *cmdp;
  9182. {
  9183.  char               *string;
  9184.  int                 rc;
  9185.  
  9186.  string = NNMbbexp(np,bp,cmdp->cmd.mcmd.ptreep,STRING_SYMTYPE);
  9187.  if (bp->runtime_error) {
  9188.    fprintf(np->batch_outfile,
  9189.            "Command not executed due to errors building argument\n");
  9190.  }
  9191.  else {
  9192.    fprintf(np->batch_outfile, "Executing command:\n%s\n\n", string);
  9193.    rc = NNMtso(string);
  9194.    fprintf(np->batch_outfile, "\nReturn code: %d\n",rc);
  9195.  }
  9196.  
  9197.  return;
  9198. }
  9199.  
  9200. /****** Parse batch EXEC         command. ****************************/
  9201.  
  9202. struct newscmd *
  9203. NNMbpexe(np,bp)
  9204. Rstruc nncb         *np;
  9205. Rstruc batch        *bp;
  9206. {
  9207.  struct newscmd     *cmdp       = NULL;
  9208.  struct ptree       *treep      = NULL;
  9209.  
  9210.  treep = NNMbgexp(np,bp,STRING_SYMTYPE); /* Get data string struct */
  9211.  
  9212.  if (!treep) {
  9213.    NNMbsynt(np,bp,NULL,0,"Error in arguments to EXEC");
  9214.    return NULL;
  9215.  }
  9216.  
  9217.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for EXEC command");
  9218.  
  9219.  if (cmdp) {
  9220.    cmdp->mode = ANY_MODE;
  9221.    cmdp->proc = NNMbxexe;
  9222.    cmdp->cmd.mcmd.ptreep = treep;
  9223.  }
  9224.  
  9225.  return cmdp;
  9226. }
  9227.  
  9228. ./ ADD NAME=NNMBPEXT
  9229.  
  9230.  /********************************************************************/
  9231.  /*                                                                  */
  9232.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  9233.  /*                                                                  */
  9234.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  9235.  /* including the implied warranties of merchantability and fitness, */
  9236.  /* are expressly denied.                                            */
  9237.  /*                                                                  */
  9238.  /* Provided this copyright notice is included, this software may    */
  9239.  /* be freely distributed and not offered for sale.                  */
  9240.  /*                                                                  */
  9241.  /* Changes or modifications may be made and used only by the maker  */
  9242.  /* of same, and not further distributed.  Such modifications should */
  9243.  /* be mailed to the author for consideration for addition to the    */
  9244.  /* software and incorporation in subsequent releases.               */
  9245.  /*                                                                  */
  9246.  /********************************************************************/
  9247.  
  9248. /*=====================================================================
  9249.  *
  9250.  * Command: EXTRACT
  9251.  *
  9252.  * Syntax:  In per-newsgroup mode: EXTRACT ALL / READ / UNREAD
  9253.  *          In per-article   mode: EXTRACT
  9254.  *
  9255.  * Mode:    per-newsgroup or per-article
  9256.  *
  9257.  * Function: EXTRACTs all, read, or unread articles in the current
  9258.  *           newsgroup; extracts the current article.
  9259.  *
  9260.  * Note:     The file into which the article(s) are extracted is
  9261.  *           specified by the contents of file DD:NNEXTTAB, which
  9262.  *           is a listing of newsgroups and filenames.  The filenames
  9263.  *           are expected to contain a wildcard asterisk, which is
  9264.  *           substituted with the article number.
  9265.  *
  9266.  * Examples:  EXTRACT
  9267.  *            EXTRACT ALL
  9268.  *            EXTRACT READ
  9269.  *            EXTRACT UNREAD
  9270.  *
  9271.  *====================================================================*/
  9272.  
  9273. #pragma  csect(code,  "NN@BPEXT")
  9274. #pragma  csect(static,"NN$BPEXT")
  9275. #include "nn.h"
  9276. #include "nnbatch.h"
  9277.  
  9278. /********** Extract this article. ************************************/
  9279.  
  9280. static int
  9281. extract_this_article(np,bp,gp,vp)
  9282. Rstruc nncb            *np;
  9283. Rstruc batch           *bp;
  9284. Rstruc newsgroup       *gp;
  9285. VARK                   *vp;
  9286. {
  9287.  Rstruc newsarticle    *ap;
  9288.  FILE                  *xfp;
  9289.  char                  *cp1;
  9290.  char                  *cp2;
  9291.  char                   ddname  [9];
  9292.  char                   exdsn  [81];
  9293.  char                   expds  [81];
  9294.  char                   member [81];
  9295.  char                   thing_to_open [81];
  9296.  Bool                   automark;
  9297.  
  9298.  ap = VARK2PARTICLE(*vp);
  9299.  
  9300.  *member = '\0';
  9301.  *ddname = '\0';
  9302.  
  9303.  if (*bp->extractds_member) {
  9304.  
  9305.    sprintf(member,"%8.8d",ap->number);
  9306.    for (cp1=member,   cp2=bp->extractds_member;
  9307.        *cp1=='0'  && *cp2;
  9308.         cp1++,        cp2++) {
  9309.      *cp1 = *cp2;
  9310.    }
  9311.  
  9312.    sprintf(exdsn, "%s%s%s", bp->extractds_part1, member,
  9313.                             bp->extractds_part2);
  9314.  }
  9315.  else strcpy(exdsn,bp->extractds);
  9316.  
  9317.  automark = GETB("AUTOMARK");
  9318.  
  9319.  np->extract_tab_expanding          = GETB("TABEXPAND");
  9320.  np->extract_appending              = bp->extractds_mode == PDS
  9321.                                       ? FALSE
  9322.                                       : GETB("APPEND");
  9323.  np->extract_blank_before_separator = GETB("BLANKSEP");
  9324.  np->extract_separator_line         = GETC("SEPARATOR");
  9325.  np->extract_write_error            = FALSE;
  9326.  np->extract_close_error            = FALSE;
  9327.  
  9328.  /* Preallocate the data set so that we don't run out of space
  9329.   * and so that brain-damaged C/370 doesn't barf on hyphens.
  9330.   * If it already exists, use the existing one.
  9331.   */
  9332.  
  9333.  if (bp->extractds_mode == PDS) {
  9334.  
  9335.    strcpy(expds,exdsn);
  9336.    cp1 = strchr(expds,'(');
  9337.    *cp1 = '\0';
  9338.    cp2 = strchr(cp1+1,')');
  9339.    *cp2 = '\0';
  9340.  
  9341.    strcpy(member,cp1+1);
  9342.  
  9343.    if (!NNMalloc(expds,ddname,PDS,gp->article_count)) {
  9344.      fprintf(np->batch_outfile,
  9345.              "Could not allocate %s for extract.\n",expds);
  9346.      bp->runtime_error = TRUE;
  9347.      return 0;
  9348.    }
  9349.  
  9350.    sprintf(thing_to_open, "dd:%s(%s)", ddname, member);
  9351.    sprintf(exdsn, "%s(%s)", expds, member);
  9352.  
  9353.  }
  9354.  else {
  9355.    if (!NNMalloc(exdsn,ddname,SEQ,gp->article_count)) {
  9356.      fprintf(np->batch_outfile,
  9357.              "Could not allocate %s for extract.\n",exdsn);
  9358.      bp->runtime_error = TRUE;
  9359.      return 0;
  9360.    }
  9361.  
  9362.    sprintf(thing_to_open, "dd:%s", ddname);
  9363.  
  9364.  }
  9365.  
  9366.  xfp = OPEN_TEXT_FILE_FOR_WRITE_OR_APPEND(thing_to_open,
  9367.                                           np->extract_appending);
  9368.  
  9369.  if (!xfp) {
  9370.    perror(exdsn);
  9371.    fprintf(np->batch_outfile,"Could not open %s for extract.\n",exdsn);
  9372.    bp->runtime_error = TRUE;
  9373.    return 0;
  9374.  }
  9375.  
  9376.  if (!NNMpick(np,ap)) {             /* Pick article */
  9377.    fprintf(np->batch_outfile,
  9378.            "Error accessing article %d of %s.\n",ap->number,gp->name);
  9379.    fprintf(np->batch_outfile,
  9380.            "Extraction into %s was not done.\n",exdsn);
  9381.    bp->runtime_error = TRUE;
  9382.  }
  9383.  else {
  9384.    NNMbtext(np,&ap->thdr,xfp);      /* Print text   */
  9385.  }
  9386.  
  9387.  if (fclose(xfp) < 0) {
  9388.    fprintf(np->batch_outfile,
  9389.            "Error closing %s.\n", exdsn);
  9390.    bp->runtime_error = TRUE;
  9391.  }
  9392.  
  9393.  (void)NNMunalc(ddname);
  9394.  
  9395.  if (bp->runtime_error ||
  9396.      np->extract_write_error || np->extract_close_error) {
  9397.    fprintf(np->batch_outfile,
  9398.            "Error extracting article %d of %s into %s.\n",
  9399.            ap->number, gp->name, exdsn);
  9400.    bp->runtime_error = TRUE;
  9401.  }
  9402.  else {
  9403.    if (automark && IsUnread(*vp)) {
  9404.      NNMmarr(np,gp,vp);
  9405.      fprintf(np->batch_outfile,
  9406.              "Article %d of %s extracted into %s and marked read.\n",
  9407.              ap->number, gp->name, exdsn);
  9408.      NNMsave(np,NULL);   /* Checkpoint NEWSRC file */
  9409.    }
  9410.    else {
  9411.      fprintf(np->batch_outfile,
  9412.              "Article %d of %s extracted into %s.\n",
  9413.              ap->number, gp->name, exdsn);
  9414.    }
  9415.  }
  9416.  
  9417.  return (bp->runtime_error ? 0 : 1);
  9418. }
  9419.  
  9420. /********** Extract articles. ****************************************/
  9421.  
  9422. static int
  9423. extract_articles(np,bp,gp,extracting)
  9424. Rstruc nncb            *np;
  9425. Rstruc batch           *bp;
  9426. Rstruc newsgroup       *gp;
  9427. enum extracting_mode    extracting;
  9428. {
  9429.  VARK                  *vp;
  9430.  VARK                  *vpfirst;
  9431.  VARK                  *vplast;
  9432.  int                    count;
  9433.  
  9434.  np->current_newsgroup   = gp;
  9435.  np->newsgroup_selected  = FALSE;
  9436.  np->show_all_articles   = TRUE;
  9437.  
  9438.  if (!GroupSelected(gp)) gp = NNMdng(np,gp,NULL);
  9439.  if (!gp) return 0;
  9440.  
  9441.  bp->gp = gp;
  9442.  count = 0;
  9443.  if (gp->article_vector) {
  9444.    vpfirst = &GETVARKFIRST(gp);
  9445.    vplast  = &GETVARKLAST(gp);
  9446.    for (vp = vpfirst; vp <= vplast; vp++) {
  9447.      int Number = VARK2NUMBER(gp,vp);
  9448.      if ((extracting == EXTRACTING_ALL)
  9449.       || (extracting == EXTRACTING_READ   && IsRead(*vp))
  9450.       || (extracting == EXTRACTING_UNREAD && IsUnread(*vp))) {
  9451.        if (NNMrarh(np,gp,vp,0,NULL)) { /* retrieve article hdr */
  9452.          count += extract_this_article(np,bp,gp,vp);
  9453.        }
  9454.      }
  9455.    }
  9456.  }
  9457.  
  9458.  return count;
  9459. }
  9460.  
  9461. /********** Get extract file. ****************************************/
  9462.  
  9463. static Bool
  9464. get_extract_file(np,bp,gp)
  9465. Rstruc nncb            *np;
  9466. Rstruc batch           *bp;
  9467. Rstruc newsgroup       *gp;
  9468. {
  9469.  FILE                  *tabfp;
  9470.  char                  *asp;
  9471.  char                  *cp;
  9472.  char                  *cp1;
  9473.  char                  *cp2;
  9474.  char                  *lp;
  9475.  char                  *rp;
  9476.  int                    len;
  9477.  enum data_set_type     mode;
  9478.  Bool                   found_extract;
  9479.  char                   line    [260];
  9480.  char                   tabname [260];
  9481.  char                   tabds   [260];
  9482.  
  9483.  strcpy(bp->extractds,"");
  9484.  
  9485.  /* Open the extract table. */
  9486.  
  9487.  if (!(tabfp = fopen("DD:NNEXTTAB","r"))) {
  9488.    perror("extract table (ddname NNEXTTAB)");
  9489.    fprintf(np->batch_outfile,"Could not open extract table.\n");
  9490.    bp->runtime_error = TRUE;
  9491.    return FALSE;
  9492.  }
  9493.  
  9494.  /* Search the extract table for a line that matches this newsgroup. */
  9495.  
  9496.  found_extract = FALSE;
  9497.  
  9498.  do {
  9499.    fgets(line, sizeof line, tabfp);
  9500.    if (feof(tabfp)) break;
  9501.    if (ferror(tabfp)) {
  9502.      fprintf(np->batch_outfile,
  9503.              "Error reading extract table (ddname NNEXTTAB)");
  9504.      break;
  9505.    }
  9506.    strcpy(tabname,"");
  9507.    strcpy(tabds  ,"");
  9508.    sscanf(line,"%s %s",tabname, tabds);
  9509.    if (!*tabname) continue;
  9510.    lowercase_in_place(tabname);
  9511.    if (UNEQUAL(tabname, gp->name)) continue;
  9512.    found_extract = TRUE;
  9513.    if (!*tabds) {
  9514.      fprintf(np->batch_outfile,
  9515.      "Extract table entry for group %s has no file name specified.\n",
  9516.              gp->name);
  9517.      break;
  9518.    }
  9519.  } while (!found_extract);
  9520.  
  9521.  if (!found_extract) {
  9522.    fprintf(np->batch_outfile,
  9523.     "Extract terminated for group %s, no entry in extract table.\n",
  9524.      gp->name);
  9525.    return FALSE;
  9526.  }
  9527.  
  9528.  if (fclose(tabfp) < 0) {
  9529.    fprintf(stderr,"Error closing extract table (ddname NNEXTTAB)");
  9530.    fprintf(np->batch_outfile,"Could not close extract table\n");
  9531.    bp->runtime_error = TRUE;
  9532.    return FALSE;
  9533.  }
  9534.  
  9535.  if (*tabds == '!') {
  9536.    fprintf(np->batch_outfile,
  9537.            "Extract suppressed for group %s ('!' in extract table).\n",
  9538.            gp->name);
  9539.    return FALSE;
  9540.  }
  9541.  
  9542.  /* Copy table dsn to extract dsn, upcasing and stripping all quotes */
  9543.  
  9544.  for (cp1 = tabds, cp2 = bp->extractds; *cp1; cp1++) {
  9545.    if (*cp1 != '\'') *cp2++ = toupper(*cp1);
  9546.  }
  9547.  *cp2 = '\0';
  9548.  
  9549.  lp  = strchr(bp->extractds,'(');
  9550.  rp  = strchr(bp->extractds,')');
  9551.  asp = strchr(bp->extractds,'*');
  9552.  
  9553.  if (lp && rp) {
  9554.    if (*(rp+1) != '\0') {
  9555.      fprintf(np->batch_outfile,
  9556.              "Misuse of parentheses in extract file template %s\n",
  9557.              bp->extractds);
  9558.      bp->runtime_error = TRUE;
  9559.      return FALSE;
  9560.    }
  9561.    if (!asp) {
  9562.      fprintf(np->batch_outfile,
  9563.              "Parentheses without '*' in extract file template %s\n",
  9564.              bp->extractds);
  9565.      fprintf(np->batch_outfile,
  9566.              "(cannot append multiple articles to same PDS member)\n");
  9567.      bp->runtime_error = TRUE;
  9568.      return FALSE;
  9569.    }
  9570.    mode = PDS;
  9571.  }
  9572.  else {
  9573.    if (lp || rp) {
  9574.      fprintf(np->batch_outfile,
  9575.              "Misuse of parentheses in extract file template %s\n",
  9576.              bp->extractds);
  9577.      bp->runtime_error = TRUE;
  9578.      return FALSE;
  9579.    }
  9580.    mode = SEQ;
  9581.  }
  9582.  
  9583.  if (strchr(asp+1,'*')) {
  9584.    fprintf(np->batch_outfile,
  9585.            "Too many '*' in extract file template %s\n",
  9586.            bp->extractds);
  9587.    bp->runtime_error = TRUE;
  9588.    return FALSE;
  9589.  }
  9590.  
  9591.  if (asp) {
  9592.    switch (*(asp+1)) {
  9593.      case '\0':
  9594.      case ')':
  9595.      case '(':
  9596.      case '.':  break;
  9597.      default:
  9598.             fprintf(np->batch_outfile,
  9599.                     "Invalid use of '*' in extract file template %s\n",
  9600.                     bp->extractds);
  9601.             fprintf(np->batch_outfile,
  9602.                     "(must be followed by '.', ')' or end of name)\n");
  9603.             bp->runtime_error = TRUE;
  9604.             return FALSE;
  9605.    }
  9606.    for (cp = asp-1;
  9607.         cp >= bp->extractds && (*cp != '(' && *cp != '.');
  9608.         cp--);
  9609.    cp++;
  9610.    if (cp == asp) {
  9611.      fprintf(np->batch_outfile,
  9612.              "Invalid use of '*' in extract file template %s\n",
  9613.              bp->extractds);
  9614.      fprintf(np->batch_outfile,
  9615.              "(must be preceded by an alphanumeric dsname char)\n");
  9616.      bp->runtime_error = TRUE;
  9617.      return FALSE;
  9618.    }
  9619.    len = cp - bp->extractds;
  9620.    memcpy(bp->extractds_part1,  bp->extractds, len);
  9621.    *(bp->extractds_part1 + len) = '\0';
  9622.    len = asp - cp;
  9623.    memcpy(bp->extractds_member, cp, len);
  9624.    *(bp->extractds_member + len) = '\0';
  9625.    strcpy(bp->extractds_part2,  asp+1);
  9626.  }
  9627.  else {
  9628.    strcpy(bp->extractds_part1, bp->extractds);
  9629.    strcpy(bp->extractds_part2, "");
  9630.    strcpy(bp->extractds_member,"");
  9631.  }
  9632.  
  9633.  bp->extractds_mode = mode;
  9634.  
  9635.  return TRUE;
  9636. }
  9637.  
  9638. /********** Execute batch EXTRACT command. ***************************/
  9639.  
  9640. static void
  9641. NNMbxext(np,bp,cmdp)
  9642. Rstruc nncb            *np;
  9643. Rstruc batch           *bp;
  9644. Rstruc newscmd         *cmdp;
  9645. {
  9646.  struct newsgroup      *gp    = bp->gp;
  9647.  int                    count = 0;
  9648.  enum extracting_mode   extracting;
  9649.  
  9650.  extracting = cmdp->cmd.xcmd.extracting;
  9651.  
  9652.  if (get_extract_file(np,bp,gp)) {
  9653.    if (extracting == NO_EXTRACTING_MODE) {
  9654.      count = extract_this_article(np,bp,gp,bp->vp);
  9655.    }
  9656.    else {
  9657.      count = extract_articles(np,bp,gp,extracting);
  9658.    }
  9659.  }
  9660.  if (bp->runtime_error) {
  9661.    fprintf(np->batch_outfile, "Extraction failed for %s.\n",
  9662.                               gp->name);
  9663.  }
  9664.  else {
  9665.    fprintf(np->batch_outfile, "%d article%s extracted for %s.\n",
  9666.                               count, count==1 ? "" : "s", gp->name);
  9667.  }
  9668.  
  9669.  return;
  9670.  
  9671. }
  9672.  
  9673. /****** Per-newsgroup mode EXTRACT. **********************************/
  9674.  
  9675. static struct newscmd *
  9676. parse_newsgroup_extract(np,bp)
  9677. Rstruc nncb            *np;
  9678. Rstruc batch           *bp;
  9679. {
  9680.  struct newscmd        *cmdp       = NULL;
  9681.  enum extracting_mode   extracting = NO_EXTRACTING_MODE;
  9682.  
  9683.  /*
  9684.   * Next token must be ALL, READ or UNREAD.
  9685.   */
  9686.  
  9687.  if (NNMbgtok(np,bp,TOKEN_READ)) {  /* get token */
  9688.    switch (bp->curtok.type) {
  9689.      case WORD_TOKEN:
  9690.                       if (EQUAL(bp->curtok.string,"ALL")) {
  9691.                         extracting = EXTRACTING_ALL;
  9692.                       }
  9693.                       if (EQUAL(bp->curtok.string,"READ")) {
  9694.                         extracting = EXTRACTING_READ;
  9695.                       }
  9696.                       else if (EQUAL(bp->curtok.string,"UNREAD")) {
  9697.                         extracting = EXTRACTING_UNREAD;
  9698.                       }
  9699.                       break;
  9700.      default:
  9701.                       break;
  9702.    }
  9703.  }
  9704.  
  9705.  if (extracting == NO_EXTRACTING_MODE) {
  9706.    NNMbsynt(np,bp,bp->curtok.string,0,
  9707.          "EXTRACT in per-newsgroup mode requires ALL, READ or UNREAD");
  9708.  }
  9709.  
  9710.  bp->stop_at_newline = TRUE;
  9711.  
  9712.  NNMbtras(np,bp,"EXTRACT"); /* Trash extraneous parameters */
  9713.  
  9714.  if (bp->syntax_error) return NULL;
  9715.  
  9716.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for EXTRACT command");
  9717.  
  9718.  if (cmdp) {
  9719.    cmdp->mode = PER_NEWSGROUP_MODE;
  9720.    cmdp->proc = NNMbxext;
  9721.    cmdp->cmd.xcmd.extracting = extracting;
  9722.  }
  9723.  
  9724.  return cmdp;
  9725. }
  9726.  
  9727. /****** Per-article mode EXTRACT. ************************************/
  9728.  
  9729. static struct newscmd *
  9730. parse_article_extract(np,bp)
  9731. Rstruc nncb            *np;
  9732. Rstruc batch           *bp;
  9733. {
  9734.  struct newscmd        *cmdp       = NULL;
  9735.  bp->stop_at_newline = TRUE;
  9736.  
  9737.  NNMbtras(np,bp,"EXTRACT"); /* Trash extraneous parameters */
  9738.  
  9739.  if (bp->syntax_error) return NULL;
  9740.  
  9741.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for EXTRACT command");
  9742.  
  9743.  if (cmdp) {
  9744.    cmdp->mode = PER_ARTICLE_MODE;
  9745.    cmdp->proc = NNMbxext;
  9746.    cmdp->cmd.xcmd.extracting = NO_EXTRACTING_MODE;
  9747.  }
  9748.  
  9749.  return cmdp;
  9750. }
  9751.  
  9752. /****** Parse batch EXTRACT      command. ****************************/
  9753.  
  9754. struct newscmd *
  9755. NNMbpext(np,bp)
  9756. Rstruc nncb         *np;
  9757. Rstruc batch        *bp;
  9758. {
  9759.  
  9760.  switch (bp->mode) {
  9761.    case PER_NEWSGROUP_MODE: return parse_newsgroup_extract (np,bp);
  9762.    case PER_ARTICLE_MODE:   return parse_article_extract   (np,bp);
  9763.    default:
  9764.         NNMbsynt(np,bp,NULL,0,
  9765.         "EXTRACT belongs in per-newsgroup mode or per-article mode");
  9766.    return NULL;
  9767.  }
  9768.  
  9769. }
  9770.  
  9771. ./ ADD NAME=NNMBPFOR
  9772.  
  9773.  /********************************************************************/
  9774.  /*                                                                  */
  9775.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  9776.  /*                                                                  */
  9777.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  9778.  /* including the implied warranties of merchantability and fitness, */
  9779.  /* are expressly denied.                                            */
  9780.  /*                                                                  */
  9781.  /* Provided this copyright notice is included, this software may    */
  9782.  /* be freely distributed and not offered for sale.                  */
  9783.  /*                                                                  */
  9784.  /* Changes or modifications may be made and used only by the maker  */
  9785.  /* of same, and not further distributed.  Such modifications should */
  9786.  /* be mailed to the author for consideration for addition to the    */
  9787.  /* software and incorporation in subsequent releases.               */
  9788.  /*                                                                  */
  9789.  /********************************************************************/
  9790.  
  9791. /*=====================================================================
  9792.  *
  9793.  * Command: FOR
  9794.  *
  9795.  * Syntax:  (1) in top-level mode...
  9796.  *
  9797.  *          FOR criterion {WHEN filter} DO;
  9798.  *          command(s);
  9799.  *          END;
  9800.  *
  9801.  *          where
  9802.  *
  9803.  *          criterion is one of: ALL
  9804.  *                               REGISTERED
  9805.  *                               UNREGISTERED
  9806.  *           * not implemented:  "groupmask"  (e.g. "comp*")
  9807.  *           * not implemented:  {NEWS}GROUP{S} "groupnames"
  9808.  *
  9809.  *          filter is any flag expression
  9810.  *
  9811.  *          commands are any commands for the appropriate mode
  9812.  *
  9813.  * Examples:
  9814.  *
  9815.  *   FOR ALL                  DO ... { per-newsgroup commands }
  9816.  *   FOR REGISTERED           DO ...
  9817.  *   FOR ... WHEN (READ = nn) DO ...
  9818.  *   FOR ... WHEN (UNREAD > nn) DO ...
  9819.  *   FOR ... WHEN (COUNT < nn) DO ...
  9820.  *   the following are not implemented:
  9821.  *   FOR "comp.*"             DO ...
  9822.  *   FOR GROUPS "a.b.c d.e.f" DO ...
  9823.  *   FOR NEWSGROUP "a.b.c" DO ...
  9824.  *
  9825.  * Syntax:  (2) in per-newsgroup mode...
  9826.  *
  9827.  *          FOR criterion {WHEN filter} DO;
  9828.  *          command(s);
  9829.  *          END;
  9830.  *
  9831.  *          where
  9832.  *
  9833.  *          criterion is one of: ALL
  9834.  *                               READ
  9835.  *                               UNREAD
  9836.  *                               i TO j  (i = number or FIRST,
  9837.  *                                       (j = number or LAST)
  9838.  *
  9839.  *          filter is any flag expression
  9840.  *
  9841.  *          commands are any commands for the appropriate mode
  9842.  *
  9843.  * Examples:
  9844.  *
  9845.  * FOR ALL WHEN "foo" IN SUBJECT DO ...
  9846.  * FOR UNREAD DO ...
  9847.  * FOR FIRST TO 10 DO ...
  9848.  *
  9849.  * Mode:    (1) top-level     (picking newsgroups)
  9850.  *          (2) per-newsgroup (picking articles)
  9851.  *
  9852.  * For (1), the commands between DO and END are in per-newsgroup mode.
  9853.  * For (2), the commands between DO and END are in per-article mode.
  9854.  *
  9855.  * Function: Defines operations to be performed on each newsgroup
  9856.  *           in a list of newsgroups (1), or on each article in a
  9857.  *           list of articles (2).
  9858.  *
  9859.  *
  9860.  *====================================================================*/
  9861.  
  9862. #pragma  csect(code,  "NN@BPFOR")
  9863. #pragma  csect(static,"NN$BPFOR")
  9864. #include "nn.h"
  9865. #include "nnbatch.h"
  9866.  
  9867. /****** Get keyword. *************************************************/
  9868.  
  9869. static Bool
  9870. get_keyword(np,bp,key)
  9871. Rstruc nncb                 *np;
  9872. Rstruc batch                *bp;
  9873. char                        *key;
  9874. {
  9875.  struct token               *tp;
  9876.  
  9877.  if ((tp = PEEK()) && tp->type == WORD_TOKEN && EQUAL(tp->string,key)) {
  9878.    EAT();
  9879.    return TRUE;
  9880.  }
  9881.  
  9882.  else return FALSE;
  9883.  
  9884. }
  9885.  
  9886. /****** Parse initial-mode FOR for newsgroups. ***********************/
  9887.  
  9888. static struct newscmd *
  9889. parse_for_newsgroups(np,bp)
  9890. Rstruc nncb                 *np;
  9891. Rstruc batch                *bp;
  9892. {
  9893.  struct token               *tp;
  9894.  struct newscmd             *cmdp       = NULL;
  9895.  struct ptree               *filter     = NULL;
  9896.  struct cmdtree             *treep      = NULL;
  9897.  struct ptree               *groups     = NULL;
  9898.  enum which_newsgroups       which      = NO_NEWSGROUPS;
  9899.  
  9900.  /* Look for criterion, one of:
  9901.   *                              ALL
  9902.   *                              REGISTERED
  9903.   *                              UNREGISTERED
  9904.   *  (not implemented)           GROUPMASK group-mask-expression
  9905.   *                              {NEWS}GROUP{S} group-name-expression
  9906.   */
  9907.  
  9908.  if ((tp = PEEK())) {
  9909.    switch (tp->type) {
  9910.      case WORD_TOKEN:
  9911.                          if      (EQUAL(tp->string,"ALL")) {
  9912.                            EAT();
  9913.                            which = ALL_NEWSGROUPS;
  9914.                          }
  9915.                          else if (EQUAL(tp->string,"REGISTERED")) {
  9916.                            EAT();
  9917.                            which = REGISTERED_NEWSGROUPS;
  9918.                          }
  9919.                          else if (EQUAL(tp->string,"UNREGISTERED")) {
  9920.                            EAT();
  9921.                            which = UNREGISTERED_NEWSGROUPS;
  9922.                          }
  9923.                          else if (EQUAL(tp->string,"GROUP")
  9924.                                || EQUAL(tp->string,"GROUPS")
  9925.                                || EQUAL(tp->string,"NEWSGROUP")
  9926.                                || EQUAL(tp->string,"NEWSGROUPS")) {
  9927.                            EAT();
  9928.                            which = NAMED_NEWSGROUPS;
  9929.                          }
  9930.                          else if (EQUAL(tp->string,"GROUPMASK")
  9931.                                || EQUAL(tp->string,"NEWSGROUPMASK")) {
  9932.                            EAT();
  9933.                            which = MASKED_NEWSGROUPS;
  9934.                          }
  9935.                          break;
  9936.      case STRING_TOKEN:  if (strchr(tp->string,'*'))
  9937.                               which = MASKED_NEWSGROUPS;
  9938.                          else which = NAMED_NEWSGROUPS;
  9939.                          break;
  9940.      default:
  9941.                          break;
  9942.    }
  9943.  }
  9944.  
  9945.  switch (which) {
  9946.    case NO_NEWSGROUPS:
  9947.                            NNMbsynt(np,bp,NULL,0,
  9948.   "Missing FOR criterion - ALL, REGISTERED, UNREGISTERED, NEWSGROUPS");
  9949.                            break;
  9950.    case NAMED_NEWSGROUPS:
  9951.                            groups = NNMbgexp(np,bp,STRING_SYMTYPE);
  9952.                            if (!groups) NNMbsynt(np,bp,NULL,0,
  9953.                                       "No valid group list specified");
  9954.                            break;
  9955.    case MASKED_NEWSGROUPS:
  9956.                            groups = NNMbgexp(np,bp,STRING_SYMTYPE);
  9957.                            if (!groups) NNMbsynt(np,bp,NULL,0,
  9958.                                       "No valid group mask specified");
  9959.                            break;
  9960.    default: break;
  9961.  }
  9962.  
  9963.  /* Look for WHEN.  If found, then look for filter, a flag expression.
  9964.   */
  9965.  
  9966.  if (get_keyword(np,bp,"WHEN")) {
  9967.    filter = NNMbgexp(np,bp,FLAG_SYMTYPE);
  9968.    if (!filter) {
  9969.      NNMbsynt(np,bp,NULL,0,"No valid filter expression specified");
  9970.    }
  9971.  }
  9972.  
  9973.  /* Get DO-END command group.  */
  9974.  
  9975.  treep = NNMbgdo(np,bp,PER_NEWSGROUP_MODE);
  9976.  
  9977.  if (bp->syntax_error) return NULL;
  9978.  
  9979.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for FOR command");
  9980.  
  9981.  if (cmdp) {
  9982.    cmdp->mode = INITIAL_MODE;
  9983.    cmdp->proc = NNMbxfng;
  9984.    cmdp->cmd.icmd.fors.filter          = filter;
  9985.    cmdp->cmd.icmd.fors.treep           = treep;
  9986.    cmdp->cmd.icmd.fors.crit.which      = which;
  9987.    cmdp->cmd.icmd.fors.crit.groups     = groups;
  9988.  }
  9989.  
  9990.  return cmdp;
  9991.  
  9992. }
  9993.  
  9994. /****** Parse per-newsgroup-mode FOR for articles. *******************/
  9995.  
  9996. static struct newscmd *
  9997. parse_for_articles(np,bp)
  9998. Rstruc nncb                 *np;
  9999. Rstruc batch                *bp;
  10000. {
  10001.  struct token               *tp;
  10002.  struct newscmd             *cmdp        = NULL;
  10003.  struct ptree               *filter      = NULL;
  10004.  struct cmdtree             *treep       = NULL;
  10005.  struct ptree               *first       = NULL;
  10006.  struct ptree               *last        = NULL;
  10007.  enum which_articles         which       = NO_ARTICLES;
  10008.  
  10009.  /* Look for criterion, one of:
  10010.   *                              ALL
  10011.   *                              READ
  10012.   *                              UNREAD
  10013.   *                              i/FIRST to j/LAST
  10014.   *
  10015.   * Note: FIRST and LAST will be variables at run time, making it
  10016.   *       easier to handle them.  That way you can say things like
  10017.   *       FIRST + 1 TO LAST - 3.
  10018.   */
  10019.  
  10020.  if ((tp = PEEK())) {
  10021.    switch (tp->type) {
  10022.      case WORD_TOKEN:
  10023.                          if      (EQUAL(tp->string,"ALL")) {
  10024.                            EAT();
  10025.                            which = ALL_ARTICLES;
  10026.                          }
  10027.                          else if (EQUAL(tp->string,"READ")) {
  10028.                            EAT();
  10029.                            which = READ_ARTICLES;
  10030.                          }
  10031.                          else if (EQUAL(tp->string,"UNREAD")) {
  10032.                            EAT();
  10033.                            which = UNREAD_ARTICLES;
  10034.                          }
  10035.                          else which = RANGED_ARTICLES;
  10036.                          break;
  10037.      default:            which = RANGED_ARTICLES;
  10038.                          break;
  10039.    }
  10040.  }
  10041.  
  10042.  switch (which) {
  10043.    case NO_ARTICLES:
  10044.                          NNMbsynt(np,bp,NULL,0,
  10045.   "Missing FOR criterion - ALL, READ, UNREAD, or n/FIRST to n/LAST");
  10046.                          break;
  10047.    case RANGED_ARTICLES:
  10048.                          first = NNMbgexp(np,bp,NUMBER_SYMTYPE);
  10049.                          if (!first) NNMbsynt(np,bp,NULL,0,
  10050.                                      "No valid range start given");
  10051.                          if (get_keyword(np,bp,"TO")) {
  10052.                            last = NNMbgexp(np,bp,NUMBER_SYMTYPE);
  10053.                            if (!last) NNMbsynt(np,bp,NULL,0,
  10054.                                       "No valid range end given");
  10055.                          }
  10056.                          else last = NULL;
  10057.                          break;
  10058.    default: break;
  10059.  }
  10060.  
  10061.  /* Look for WHEN.  If found, then look for filter, a flag expression.*/
  10062.  
  10063.  if (get_keyword(np,bp,"WHEN")) {
  10064.    filter = NNMbgexp(np,bp,FLAG_SYMTYPE);
  10065.    if (!filter) {
  10066.      NNMbsynt(np,bp,NULL,0,"No valid filter expression specified");
  10067.    }
  10068.  }
  10069.  
  10070.  /* Get DO-END command group.  */
  10071.  
  10072.  treep = NNMbgdo(np,bp,PER_ARTICLE_MODE);
  10073.  
  10074.  if (bp->syntax_error) return NULL;
  10075.  
  10076.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for FOR command");
  10077.  
  10078.  if (cmdp) {
  10079.    cmdp->mode = PER_NEWSGROUP_MODE;
  10080.    cmdp->proc = NNMbxfar;
  10081.    cmdp->cmd.ncmd.fors.filter     = filter;
  10082.    cmdp->cmd.ncmd.fors.treep      = treep;
  10083.    cmdp->cmd.ncmd.fors.crit.which = which;
  10084.    cmdp->cmd.ncmd.fors.crit.first = first;
  10085.    cmdp->cmd.ncmd.fors.crit.last  = last;
  10086.  }
  10087.  
  10088.  return cmdp;
  10089.  
  10090. }
  10091.  
  10092. /****** Parse batch FOR          command. ****************************/
  10093.  
  10094. struct newscmd *
  10095. NNMbpfor(np,bp)
  10096. Rstruc nncb         *np;
  10097. Rstruc batch        *bp;
  10098. {
  10099.  
  10100.  switch (bp->mode) {
  10101.    case INITIAL_MODE:       return parse_for_newsgroups(np,bp);
  10102.    case PER_NEWSGROUP_MODE: return parse_for_articles  (np,bp);
  10103.    default: NNMbsynt(np,bp,NULL,0,
  10104.                  "FOR belongs in initial mode or per-newsgroup mode");
  10105.             return NULL;
  10106.  }
  10107.  
  10108. }
  10109.  
  10110. ./ ADD NAME=NNMBPHEL
  10111.  
  10112.  /********************************************************************/
  10113.  /*                                                                  */
  10114.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  10115.  /*                                                                  */
  10116.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  10117.  /* including the implied warranties of merchantability and fitness, */
  10118.  /* are expressly denied.                                            */
  10119.  /*                                                                  */
  10120.  /* Provided this copyright notice is included, this software may    */
  10121.  /* be freely distributed and not offered for sale.                  */
  10122.  /*                                                                  */
  10123.  /* Changes or modifications may be made and used only by the maker  */
  10124.  /* of same, and not further distributed.  Such modifications should */
  10125.  /* be mailed to the author for consideration for addition to the    */
  10126.  /* software and incorporation in subsequent releases.               */
  10127.  /*                                                                  */
  10128.  /********************************************************************/
  10129.  
  10130. /*=====================================================================
  10131.  *
  10132.  * Command: HELP
  10133.  *
  10134.  * Syntax:  HELP {word}*
  10135.  *
  10136.  * Mode:    any
  10137.  *
  10138.  * Function: Writes help information to the output file.
  10139.  *
  10140.  * Note: Words may be specified, but are currently ignored.  All
  10141.  *       arguments are flushed until a new line or ';' is seen.
  10142.  *
  10143.  * Examples:  HELP
  10144.  *            HELP FOR
  10145.  *            HELP "anything" (at all), it doesn't matter!
  10146.  *
  10147.  *====================================================================*/
  10148.  
  10149. #pragma  csect(code,  "NN@BPHEL")
  10150. #pragma  csect(static,"NN$BPHEL")
  10151. #include "nn.h"
  10152. #include "nnbatch.h"
  10153.  
  10154. /****** Execute batch HELP       command. ****************************/
  10155.  
  10156. static void
  10157. NNMbxhel(np,bp,cmdp)
  10158. Rstruc nncb         *np;
  10159. Rstruc batch        *bp;
  10160. Rstruc newscmd      *cmdp;
  10161. {
  10162.  FILE               *helpfp;
  10163.  char                helpline[257];
  10164.  
  10165.  if (!(helpfp = fopen("DD:NNBATHLP","r"))) {
  10166.    perror("ddname NNBATHLP");
  10167.    fprintf(np->batch_outfile,
  10168.      "\n\n*** Help not available - cannot open batch help file. ***\n");
  10169.    return;
  10170.  }
  10171.  for (;;) {
  10172.    fgets(helpline, sizeof(helpline), helpfp);
  10173.    if (feof(helpfp))  break;
  10174.    if (ferror(helpfp)) {
  10175.      fprintf(np->batch_outfile,
  10176.            "\n\n*** Help terminated - error reading help file. ***\n");
  10177.      break;
  10178.    }
  10179.    fprintf(np->batch_outfile,"%s",helpline);
  10180.  }
  10181.  fprintf(np->batch_outfile,"\n");
  10182.  fclose(helpfp);
  10183.  
  10184.  return;
  10185. }
  10186.  
  10187. /****** Parse batch HELP         command. ****************************/
  10188.  
  10189. struct newscmd *
  10190. NNMbphel(np,bp)
  10191. Rstruc nncb         *np;
  10192. Rstruc batch        *bp;
  10193. {
  10194.  struct newscmd     *cmdp;
  10195.  
  10196.  bp->stop_at_newline = TRUE;
  10197.  
  10198.  while (NNMbgtok(np,bp,TOKEN_READ)) { /* Get token */
  10199.    switch (bp->curtok.type) {
  10200.      case EOF_TOKEN:
  10201.      case EOL_TOKEN:
  10202.      case SEMI_TOKEN: break;
  10203.      default:         NNMbsynt(np,bp,bp->curtok.string,0,
  10204.                                "Extraneous parameter for HELP");
  10205.                       continue;
  10206.    }
  10207.    break;
  10208.  }
  10209.  
  10210.  if (bp->syntax_error) return NULL;
  10211.  
  10212.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for HELP command");
  10213.  
  10214.  if (cmdp) {
  10215.    cmdp->mode = ANY_MODE;
  10216.    cmdp->proc = NNMbxhel;
  10217.  }
  10218.  
  10219.  return cmdp;
  10220.  
  10221. }
  10222.  
  10223. ./ ADD NAME=NNMBPIF
  10224.  
  10225.  /********************************************************************/
  10226.  /*                                                                  */
  10227.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  10228.  /*                                                                  */
  10229.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  10230.  /* including the implied warranties of merchantability and fitness, */
  10231.  /* are expressly denied.                                            */
  10232.  /*                                                                  */
  10233.  /* Provided this copyright notice is included, this software may    */
  10234.  /* be freely distributed and not offered for sale.                  */
  10235.  /*                                                                  */
  10236.  /* Changes or modifications may be made and used only by the maker  */
  10237.  /* of same, and not further distributed.  Such modifications should */
  10238.  /* be mailed to the author for consideration for addition to the    */
  10239.  /* software and incorporation in subsequent releases.               */
  10240.  /*                                                                  */
  10241.  /********************************************************************/
  10242.  
  10243. /*=====================================================================
  10244.  *
  10245.  * Command: IF
  10246.  *
  10247.  * Syntax:  IF condition THEN DO;
  10248.  *          command(s);
  10249.  *          END;
  10250.  *          ELSE DO;
  10251.  *          command(s);
  10252.  *          END;
  10253.  *
  10254.  *          where
  10255.  *
  10256.  *          condition is any flag expression
  10257.  *
  10258.  *          commands are any commands for the appropriate mode
  10259.  *
  10260.  * Examples:
  10261.  *
  10262.  *   IF AUTOREGISTER THEN DO ...
  10263.  *   IF SERVER != "" THEN DO ...
  10264.  *   IF (A = 1 | B = 2)  THEN DO ...
  10265.  *
  10266.  * Mode:    any (but see note)
  10267.  *
  10268.  * The commands between DO and END, for the THEN and ELSE groups,
  10269.  * must be in the appropriate mode.
  10270.  *
  10271.  * Function: If condition is true, executes commands in the first
  10272.  *           command group; otherwise executes commands in the second
  10273.  *           command group.
  10274.  *
  10275.  *====================================================================*/
  10276.  
  10277. #pragma  csect(code,  "NN@BPIF ")
  10278. #pragma  csect(static,"NN$BPIF ")
  10279. #include "nn.h"
  10280. #include "nnbatch.h"
  10281.  
  10282. /****** Execute commands. ********************************************/
  10283.  
  10284. static void
  10285. execute_commands(np,bp,treep)
  10286. Rstruc nncb                 *np;
  10287. Rstruc batch                *bp;
  10288. struct cmdtree              *treep;
  10289. {
  10290.  
  10291.  for (; treep; treep = treep->next) {
  10292.    bp->runtime_error = FALSE;
  10293.    (treep->cmd->proc) (np,bp,treep->cmd);
  10294.    SETB("ERROR",bp->runtime_error);
  10295.  }
  10296.  
  10297.  return;
  10298. }
  10299.  
  10300. /****** Execute batch IF command. ************************************/
  10301.  
  10302. static void
  10303. NNMbxif(np,bp,cmdp)
  10304. Rstruc nncb                 *np;
  10305. Rstruc batch                *bp;
  10306. Rstruc newscmd              *cmdp;
  10307. {
  10308.  struct ptree               *condition;
  10309.  struct cmdtree             *thencmds;
  10310.  struct cmdtree             *elsecmds;
  10311.  Fool                        condval;
  10312.  
  10313.  condition = cmdp->cmd.fcmd.condition;
  10314.  thencmds  = cmdp->cmd.fcmd.thencmds;
  10315.  elsecmds  = cmdp->cmd.fcmd.elsecmds;
  10316.  
  10317.  condval = (Fool) NNMbbexp(np,bp,condition,FLAG_SYMTYPE);
  10318.  if (bp->runtime_error) return;
  10319.  
  10320.  if (condval) execute_commands(np,bp,thencmds);
  10321.  else         execute_commands(np,bp,elsecmds);
  10322.  
  10323.  return;
  10324. }
  10325.  
  10326. /****** Get keyword. *************************************************/
  10327.  
  10328. static Bool
  10329. get_keyword(np,bp,key)
  10330. Rstruc nncb                 *np;
  10331. Rstruc batch                *bp;
  10332. char                        *key;
  10333. {
  10334.  struct token               *tp;
  10335.  
  10336.  if ((tp = PEEK())
  10337.   && tp->type == WORD_TOKEN
  10338.   && EQUAL(tp->string,key)) {
  10339.    EAT();
  10340.    return TRUE;
  10341.  }
  10342.  
  10343.  else return FALSE;
  10344.  
  10345. }
  10346.  
  10347. /****** Parse batch IF           command. ****************************/
  10348.  
  10349. struct newscmd *
  10350. NNMbpif(np,bp)
  10351. Rstruc nncb         *np;
  10352. Rstruc batch        *bp;
  10353. {
  10354.  struct newscmd             *cmdp       = NULL;
  10355.  struct ptree               *condition  = NULL;
  10356.  struct cmdtree             *thencmds   = NULL;
  10357.  
  10358.  /* Look for condition */
  10359.  
  10360.  condition = NNMbgexp(np,bp,FLAG_SYMTYPE);
  10361.  
  10362.  if (condition == NULL) {
  10363.    NNMbsynt(np,bp,NULL,0,"Missing IF condition");
  10364.    return NULL;
  10365.  }
  10366.  
  10367.  /* Look for THEN (required).  */
  10368.  
  10369.  if (!(get_keyword(np,bp,"THEN"))) {
  10370.    NNMbsynt(np,bp,NULL,0,"Missing THEN keyword");
  10371.    return NULL;
  10372.  }
  10373.  
  10374.  /* Get DO-END command group.
  10375.   */
  10376.  
  10377.  thencmds = NNMbgdo(np,bp,bp->mode);
  10378.  
  10379.  if (bp->syntax_error) return NULL;
  10380.  
  10381.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for IF command");
  10382.  
  10383.  if (cmdp) {
  10384.    cmdp->mode = bp->mode;
  10385.    cmdp->proc = NNMbxif;
  10386.    cmdp->cmd.fcmd.condition  = condition;
  10387.    cmdp->cmd.fcmd.thencmds   = thencmds;
  10388.    cmdp->cmd.fcmd.elsecmds   = NULL;
  10389.  }
  10390.  
  10391.  /* Make sure any following ELSE is properly handled. */
  10392.  
  10393.  bp->ifcmd = cmdp;
  10394.  
  10395.  return cmdp;
  10396.  
  10397. }
  10398.  
  10399. ./ ADD NAME=NNMBPLIS
  10400.  
  10401.  /********************************************************************/
  10402.  /*                                                                  */
  10403.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  10404.  /*                                                                  */
  10405.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  10406.  /* including the implied warranties of merchantability and fitness, */
  10407.  /* are expressly denied.                                            */
  10408.  /*                                                                  */
  10409.  /* Provided this copyright notice is included, this software may    */
  10410.  /* be freely distributed and not offered for sale.                  */
  10411.  /*                                                                  */
  10412.  /* Changes or modifications may be made and used only by the maker  */
  10413.  /* of same, and not further distributed.  Such modifications should */
  10414.  /* be mailed to the author for consideration for addition to the    */
  10415.  /* software and incorporation in subsequent releases.               */
  10416.  /*                                                                  */
  10417.  /********************************************************************/
  10418.  
  10419. /*=====================================================================
  10420.  *
  10421.  * Command: LIST
  10422.  *
  10423.  * Syntax:  LIST
  10424.  *
  10425.  * Mode:    per_article
  10426.  *
  10427.  * Function: Lists the contents of the current news article.
  10428.  *
  10429.  * Note: Arguments are not permitted.  If they are given, the
  10430.  *       function will not be performed.
  10431.  *
  10432.  * Examples:  LIST
  10433.  *
  10434.  *====================================================================*/
  10435.  
  10436. #pragma  csect(code,  "NN@BPLIS")
  10437. #pragma  csect(static,"NN$BPLIS")
  10438. #include "nn.h"
  10439. #include "nnbatch.h"
  10440.  
  10441. /********** Execute batch LIST command. ******************************/
  10442.  
  10443. static void
  10444. NNMbxlis(np,bp,cmdp)
  10445. Rstruc nncb         *np;
  10446. Rstruc batch        *bp;
  10447. Rstruc newscmd      *cmdp;
  10448. {
  10449.  Rstruc newsarticle *ap = VARK2PARTICLE(*bp->vp);
  10450.  
  10451.  NNMpick(np,ap);                  /* Pick article */
  10452.  
  10453.  NNMbtext(np,&ap->thdr,NULL);     /* Print text */
  10454.  
  10455.  return;
  10456.  
  10457. }
  10458.  
  10459. /****** Parse batch LIST command. ************************************/
  10460.  
  10461. struct newscmd *
  10462. NNMbplis(np,bp)
  10463. Rstruc nncb         *np;
  10464. Rstruc batch        *bp;
  10465. {
  10466.  struct newscmd     *cmdp;
  10467.  
  10468.  bp->stop_at_newline = TRUE;
  10469.  
  10470.  NNMbtras(np,bp,"LIST");   /* Trash extraneous parameters */
  10471.  
  10472.  if (bp->syntax_error) return NULL;
  10473.  
  10474.  if (bp->mode != PER_ARTICLE_MODE) {
  10475.    NNMbsynt(np,bp,NULL,0,"LIST is invalid outside of per-article mode");
  10476.    return NULL;
  10477.  }
  10478.  
  10479.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for LIST command");
  10480.  
  10481.  if (cmdp) {
  10482.    cmdp->mode = PER_ARTICLE_MODE;
  10483.    cmdp->proc = NNMbxlis;
  10484.  }
  10485.  
  10486.  return cmdp;
  10487.  
  10488. }
  10489.  
  10490. ./ ADD NAME=NNMBPMAR
  10491.  
  10492.  /********************************************************************/
  10493.  /*                                                                  */
  10494.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  10495.  /*                                                                  */
  10496.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  10497.  /* including the implied warranties of merchantability and fitness, */
  10498.  /* are expressly denied.                                            */
  10499.  /*                                                                  */
  10500.  /* Provided this copyright notice is included, this software may    */
  10501.  /* be freely distributed and not offered for sale.                  */
  10502.  /*                                                                  */
  10503.  /* Changes or modifications may be made and used only by the maker  */
  10504.  /* of same, and not further distributed.  Such modifications should */
  10505.  /* be mailed to the author for consideration for addition to the    */
  10506.  /* software and incorporation in subsequent releases.               */
  10507.  /*                                                                  */
  10508.  /********************************************************************/
  10509.  
  10510. /*=====================================================================
  10511.  *
  10512.  * Command: MARK
  10513.  *
  10514.  * Syntax:  MARK { READ / UNREAD }
  10515.  *
  10516.  * Default: MARK READ
  10517.  *
  10518.  * Mode:    per-article
  10519.  *
  10520.  * Function: Marks the article read or unread.
  10521.  *
  10522.  * Examples:  MARK
  10523.  *            MARK READ
  10524.  *            MARK UNREAD
  10525.  *
  10526.  *====================================================================*/
  10527.  
  10528. #pragma  csect(code,  "NN@BPMAR")
  10529. #pragma  csect(static,"NN$BPMAR")
  10530. #include "nn.h"
  10531. #include "nnbatch.h"
  10532.  
  10533. /********** Execute batch MARK command. ******************************/
  10534.  
  10535. static void
  10536. NNMbxmar(np,bp,cmdp)
  10537. Rstruc nncb         *np;
  10538. Rstruc batch        *bp;
  10539. Rstruc newscmd      *cmdp;
  10540. {
  10541.  struct newsgroup   *gp   = bp->gp;
  10542.  VARK               *vp   = bp->vp;
  10543.  char               *what = "not";
  10544.  
  10545.  switch (cmdp->cmd.rcmd.marking) {
  10546.    case MARKING_READ:   NNMmarr(np,gp,vp);
  10547.                         what = "read";
  10548.                         break;
  10549.    case MARKING_UNREAD: NNMmaru(np,gp,vp);
  10550.                         what = "unread";
  10551.                         break;
  10552.  }
  10553.  
  10554.  fprintf(np->batch_outfile, "Article %d of %s marked %s.\n",
  10555.                             VARK2NUMBER(gp,vp), gp->name, what);
  10556.  
  10557.  NNMsave(np,NULL);   /* Checkpoint NEWSRC file */
  10558.  
  10559.  return;
  10560.  
  10561. }
  10562.  
  10563. /****** Parse batch MARK         command. ****************************/
  10564.  
  10565. struct newscmd *
  10566. NNMbpmar(np,bp)
  10567. Rstruc nncb         *np;
  10568. Rstruc batch        *bp;
  10569. {
  10570.  struct newscmd     *cmdp       = NULL;
  10571.  enum marking_mode   marking    = MARKING_READ;
  10572.  
  10573.  /* Next token, if present, must be READ or UNREAD.  */
  10574.  
  10575.  if (NNMbgtok(np,bp,TOKEN_READ)) {  /* get token */
  10576.    switch (bp->curtok.type) {
  10577.      case EOL_TOKEN:
  10578.      case EOF_TOKEN:
  10579.      case SEMI_TOKEN: marking = MARKING_READ;
  10580.                       break;
  10581.      case WORD_TOKEN: if (EQUAL(bp->curtok.string,"READ")) {
  10582.                         marking = MARKING_READ;
  10583.                       }
  10584.                       else if (EQUAL(bp->curtok.string,"UNREAD")) {
  10585.                         marking = MARKING_UNREAD;
  10586.                       }
  10587.                       else {
  10588.                         NNMbsynt(np,bp,bp->curtok.string,0,
  10589.                                  "MARK operand must be READ or UNREAD");
  10590.                       }
  10591.                       break;
  10592.      default:         NNMbsynt(np,bp,bp->curtok.string,0,
  10593.                                "MARK operand must be READ or UNREAD");
  10594.                       break;
  10595.    }
  10596.  }
  10597.  
  10598.  bp->stop_at_newline = TRUE;
  10599.  
  10600.  NNMbtras(np,bp,"MARK");   /* Trash extraneous parameters */
  10601.  
  10602.  if (bp->syntax_error) return NULL;
  10603.  
  10604.  if (bp->mode != PER_ARTICLE_MODE) {
  10605.    NNMbsynt(np,bp,NULL,0,"MARK is invalid outside of per-article mode");
  10606.    return NULL;
  10607.  }
  10608.  
  10609.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for MARK command");
  10610.  
  10611.  if (cmdp) {
  10612.    cmdp->mode = PER_ARTICLE_MODE;
  10613.    cmdp->proc = NNMbxmar;
  10614.    cmdp->cmd.rcmd.marking = marking;
  10615.  }
  10616.  
  10617.  return cmdp;
  10618. }
  10619.  
  10620. ./ ADD NAME=NNMBPNNT
  10621.  
  10622.  /********************************************************************/
  10623.  /*                                                                  */
  10624.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  10625.  /*                                                                  */
  10626.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  10627.  /* including the implied warranties of merchantability and fitness, */
  10628.  /* are expressly denied.                                            */
  10629.  /*                                                                  */
  10630.  /* Provided this copyright notice is included, this software may    */
  10631.  /* be freely distributed and not offered for sale.                  */
  10632.  /*                                                                  */
  10633.  /* Changes or modifications may be made and used only by the maker  */
  10634.  /* of same, and not further distributed.  Such modifications should */
  10635.  /* be mailed to the author for consideration for addition to the    */
  10636.  /* software and incorporation in subsequent releases.               */
  10637.  /*                                                                  */
  10638.  /********************************************************************/
  10639.  
  10640. /*=====================================================================
  10641.  *
  10642.  * Command: NNTP
  10643.  *
  10644.  * Syntax:  NNTP {datum}* ;
  10645.  *
  10646.  * Mode:    any (but see notes)
  10647.  *
  10648.  * Function: Sends an NNTP protocol command to the server as built
  10649.  *           from the specified data items.  Items can be:
  10650.  *
  10651.  *           * text strings
  10652.  *           * integers
  10653.  *           * words representing variables that have values
  10654.  *
  10655.  * Note: When words are used, the values they represent must be
  10656.  *       valid for the mode in which the EXEC is executed.
  10657.  *
  10658.  * Note: The NNTP request must be appropriate for the mode active
  10659.  *       at the time the request is executed.
  10660.  *
  10661.  * Note: Since the command can span input lines and the number of
  10662.  *       arguments is variable, the arguments MUST be terminated
  10663.  *       by a semicolon or end of file.
  10664.  *
  10665.  * Examples:  NNTP "HELP";
  10666.  *            NNTP "ARTICLE " NUMBER;
  10667.  *
  10668.  *====================================================================*/
  10669.  
  10670. #pragma  csect(code,  "NN@BPNNT")
  10671. #pragma  csect(static,"NN$BPNNT")
  10672. #include "nn.h"
  10673. #include "nnbatch.h"
  10674.  
  10675. /****** Execute batch NNTP       command. ****************************/
  10676.  
  10677. static void
  10678. NNMbxnnt(np,bp,cmdp)
  10679. Rstruc nncb         *np;
  10680. Rstruc batch        *bp;
  10681. Rstruc newscmd      *cmdp;
  10682. {
  10683.  char               *string;
  10684.  
  10685.  string = NNMbbexp(np,bp,cmdp->cmd.mcmd.ptreep,STRING_SYMTYPE);
  10686.  if (bp->runtime_error) {
  10687.    fprintf(np->batch_outfile,
  10688.            "NNTP command not sent due to errors building argument\n");
  10689.    return;
  10690.  }
  10691.  
  10692.  if (!NNMbconn(np,bp)) {  /* Insure server name and connect to server */
  10693.    fprintf(np->batch_outfile,"NNTP command not executed:\n%s\n\n",
  10694.                              string);
  10695.    return;
  10696.  }
  10697.  
  10698.  fprintf(np->batch_outfile, "NNTP command:\n%s\n\n", string);
  10699.  
  10700.  if (*string || np->receiving_text) {
  10701.    if (strlen(string) > CLIENT_BUF_MSGSIZE) {
  10702.      ERR1(
  10703.    "Requested NNTP command is longer than NNMVS is prepared to handle."
  10704.          );
  10705.    }
  10706.    else {
  10707.      strcpy(np->nntp_command,string);
  10708.      NNMnntp(np);                       /* execute NNTP commands */
  10709.    }
  10710.  }
  10711.  
  10712.  return;
  10713.  
  10714. }
  10715.  
  10716. /****** Parse batch NNTP         command. ****************************/
  10717.  
  10718. struct newscmd *
  10719. NNMbpnnt(np,bp)
  10720. Rstruc nncb         *np;
  10721. Rstruc batch        *bp;
  10722. {
  10723.  struct newscmd     *cmdp       = NULL;
  10724.  struct ptree       *treep      = NULL;
  10725.  
  10726.  treep = NNMbgexp(np,bp,STRING_SYMTYPE); /* Get data string struct */
  10727.  
  10728.  if (!treep) {
  10729.    NNMbsynt(np,bp,NULL,0,"Error in arguments to NNTP");
  10730.    return NULL;
  10731.  }
  10732.  
  10733.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for NNTP command");
  10734.  
  10735.  if (cmdp) {
  10736.    cmdp->mode = ANY_MODE;
  10737.    cmdp->proc = NNMbxnnt;
  10738.    cmdp->cmd.mcmd.ptreep = treep;
  10739.  }
  10740.  
  10741.  return cmdp;
  10742. }
  10743.  
  10744. ./ ADD NAME=NNMBPPUT
  10745.  
  10746.  /********************************************************************/
  10747.  /*                                                                  */
  10748.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  10749.  /*                                                                  */
  10750.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  10751.  /* including the implied warranties of merchantability and fitness, */
  10752.  /* are expressly denied.                                            */
  10753.  /*                                                                  */
  10754.  /* Provided this copyright notice is included, this software may    */
  10755.  /* be freely distributed and not offered for sale.                  */
  10756.  /*                                                                  */
  10757.  /* Changes or modifications may be made and used only by the maker  */
  10758.  /* of same, and not further distributed.  Such modifications should */
  10759.  /* be mailed to the author for consideration for addition to the    */
  10760.  /* software and incorporation in subsequent releases.               */
  10761.  /*                                                                  */
  10762.  /********************************************************************/
  10763.  
  10764. /*=====================================================================
  10765.  *
  10766.  * Command: PUT
  10767.  *
  10768.  * Syntax:  PUT {datum}* ;
  10769.  *
  10770.  * Mode:    any (but see note)
  10771.  *
  10772.  * Function: Writes zero or more items of data to the output file,
  10773.  *           followed by a newline.  Items can be:
  10774.  *
  10775.  *           * text strings
  10776.  *           * integers
  10777.  *           * words representing variables that have values
  10778.  *
  10779.  * Note: When words are used, the values they represent must be
  10780.  *       valid for the mode in which the PUT is executed.
  10781.  *
  10782.  * Note: Since the command can span input lines and the number of
  10783.  *       arguments is variable, the arguments MUST be terminated
  10784.  *       by a semicolon or end of file.
  10785.  *
  10786.  * Examples:  PUT;
  10787.  *            PUT "Hello, world";
  10788.  *            PUT 666 " is the number of the Beast.";
  10789.  *            PUT "I have " UNREAD " new items from server " server ".";
  10790.  *
  10791.  *====================================================================*/
  10792.  
  10793. #pragma  csect(code,  "NN@BPPUT")
  10794. #pragma  csect(static,"NN$BPPUT")
  10795. #include "nn.h"
  10796. #include "nnbatch.h"
  10797.  
  10798. /****** Print text line. *********************************************/
  10799.  
  10800. static Bool
  10801. print_text_line(fp,string)
  10802. FILE           *fp;
  10803. char           *string;
  10804. {
  10805.  char          *cp;
  10806.  int            l;
  10807.  
  10808.  for (cp = string, l = strlen(string); l > 0; cp += 251, l -= 251) {
  10809.   fwrite(cp,(l>251 ? 251 : l),1,fp);
  10810.   if (ferror(fp))            return FALSE;
  10811.   if (fputc('\n',fp) == EOF) return FALSE;
  10812.  }
  10813.  
  10814.  return TRUE;
  10815. }
  10816.  
  10817. /****** Execute batch PUT        command. ****************************/
  10818.  
  10819. static void
  10820. NNMbxput(np,bp,cmdp)
  10821. Rstruc nncb         *np;
  10822. Rstruc batch        *bp;
  10823. Rstruc newscmd      *cmdp;
  10824. {
  10825.  struct ptree       *treep;
  10826.  char               *string;
  10827.  FILE               *fp;
  10828.  Bool                print_error;
  10829.  
  10830.  treep = cmdp->cmd.mcmd.ptreep;
  10831.  
  10832.  print_error = FALSE;
  10833.  
  10834.  if (!treep) {
  10835.    fp = NNMbsout(np,bp);  /* Set output file */
  10836.    fprintf(fp,"\n");
  10837.    if (ferror(fp)) print_error = TRUE;
  10838.  }
  10839.  else {
  10840.    string = NNMbbexp(np,bp,treep,STRING_SYMTYPE);
  10841.    if (bp->runtime_error) {
  10842.      fprintf(np->batch_outfile,
  10843.              "\n<<Put failed, error building argument>>\n");
  10844.    }
  10845.    else {
  10846.      fp = NNMbsout(np,bp);  /* Set output file */
  10847.      if (!print_text_line(fp,string)) print_error = TRUE;
  10848.    }
  10849.  }
  10850.  
  10851.  if (print_error) {
  10852.    fprintf(stderr,"Error writing to outfile\n");
  10853.    bp->runtime_error = TRUE;
  10854.  }
  10855.  
  10856.  return;
  10857.  
  10858. }
  10859.  
  10860. /****** Parse batch PUT          command. ****************************/
  10861.  
  10862. struct newscmd *
  10863. NNMbpput(np,bp)
  10864. Rstruc nncb         *np;
  10865. Rstruc batch        *bp;
  10866. {
  10867.  struct newscmd     *cmdp       = NULL;
  10868.  struct ptree       *treep      = NULL;
  10869.  
  10870.  /*
  10871.   * Special case for PUT without arguments
  10872.   *
  10873.   */
  10874.  
  10875.  if (NNMbgtok(np,bp,TOKEN_PEEK)) {  /* Peek next token */
  10876.    switch (bp->nextok.type) {
  10877.      case EOF_TOKEN:
  10878.      case EOL_TOKEN:
  10879.      case SEMI_TOKEN:  treep = NULL;
  10880.                        break;
  10881.      default:
  10882.                        treep = NNMbgexp(np,bp,STRING_SYMTYPE);
  10883.                        if (!treep) {
  10884.                          NNMbsynt(np,bp,NULL,0,
  10885.                                   "Error in arguments to PUT");
  10886.                          return NULL;
  10887.                        }
  10888.                        break;
  10889.    }
  10890.  }
  10891.  
  10892.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for PUT command");
  10893.  
  10894.  if (cmdp) {
  10895.    cmdp->mode = ANY_MODE;
  10896.    cmdp->proc = NNMbxput;
  10897.    cmdp->cmd.mcmd.ptreep = treep;
  10898.  }
  10899.  
  10900.  return cmdp;
  10901. }
  10902.  
  10903. ./ ADD NAME=NNMBPQUE
  10904.  
  10905.  /********************************************************************/
  10906.  /*                                                                  */
  10907.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  10908.  /*                                                                  */
  10909.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  10910.  /* including the implied warranties of merchantability and fitness, */
  10911.  /* are expressly denied.                                            */
  10912.  /*                                                                  */
  10913.  /* Provided this copyright notice is included, this software may    */
  10914.  /* be freely distributed and not offered for sale.                  */
  10915.  /*                                                                  */
  10916.  /* Changes or modifications may be made and used only by the maker  */
  10917.  /* of same, and not further distributed.  Such modifications should */
  10918.  /* be mailed to the author for consideration for addition to the    */
  10919.  /* software and incorporation in subsequent releases.               */
  10920.  /*                                                                  */
  10921.  /********************************************************************/
  10922.  
  10923. /*=====================================================================
  10924.  *
  10925.  * Command: QUERY
  10926.  *
  10927.  * Syntax:  QUERY
  10928.  *
  10929.  * Mode:    per_newsgroup or per_article
  10930.  *
  10931.  * Function: Dumps the status of the current newsgroup or article.
  10932.  *
  10933.  * Examples:  QUERY
  10934.  *
  10935.  *====================================================================*/
  10936.  
  10937. #pragma  csect(code,  "NN@BPQUE")
  10938. #pragma  csect(static,"NN$BPQUE")
  10939. #include "nn.h"
  10940. #include "nnbatch.h"
  10941.  
  10942. /****** Execute batch QUERY      command. ****************************/
  10943.  
  10944. static void
  10945. NNMbxque(np,bp,cmdp)
  10946. Rstruc nncb         *np;
  10947. Rstruc batch        *bp;
  10948. Rstruc newscmd      *cmdp;
  10949. {
  10950.  
  10951.  switch (cmdp->mode) {
  10952.    case PER_NEWSGROUP_MODE:  NNMqng(np,bp->gp);                 break;
  10953.    case PER_ARTICLE_MODE:    NNMqar(np,VARK2PARTICLE(*bp->vp)); break;
  10954.  }
  10955.  
  10956.  return;
  10957. }
  10958.  
  10959. /****** Parse batch QUERY        command. ****************************/
  10960.  
  10961. struct newscmd *
  10962. NNMbpque(np,bp)
  10963. Rstruc nncb         *np;
  10964. Rstruc batch        *bp;
  10965. {
  10966.  struct newscmd     *cmdp;
  10967.  
  10968.  bp->stop_at_newline = TRUE;
  10969.  
  10970.  NNMbtras(np,bp,"QUERY");        /* Trash extraneous parameters */
  10971.  
  10972.  if (bp->syntax_error) return NULL;
  10973.  
  10974.  switch (bp->mode) {
  10975.    case PER_NEWSGROUP_MODE:
  10976.    case PER_ARTICLE_MODE:
  10977.         break;
  10978.    default:
  10979.         NNMbsynt(np,bp,NULL,0,
  10980.             "QUERY is valid only in per-newsgroup or per-article mode");
  10981.    return NULL;
  10982.  }
  10983.  
  10984.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for QUERY command");
  10985.  
  10986.  if (cmdp) {
  10987.    cmdp->mode = bp->mode;
  10988.    cmdp->proc = NNMbxque;
  10989.  }
  10990.  
  10991.  return cmdp;
  10992.  
  10993. }
  10994.  
  10995. ./ ADD NAME=NNMBPQUI
  10996.  
  10997.  /********************************************************************/
  10998.  /*                                                                  */
  10999.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  11000.  /*                                                                  */
  11001.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  11002.  /* including the implied warranties of merchantability and fitness, */
  11003.  /* are expressly denied.                                            */
  11004.  /*                                                                  */
  11005.  /* Provided this copyright notice is included, this software may    */
  11006.  /* be freely distributed and not offered for sale.                  */
  11007.  /*                                                                  */
  11008.  /* Changes or modifications may be made and used only by the maker  */
  11009.  /* of same, and not further distributed.  Such modifications should */
  11010.  /* be mailed to the author for consideration for addition to the    */
  11011.  /* software and incorporation in subsequent releases.               */
  11012.  /*                                                                  */
  11013.  /********************************************************************/
  11014.  
  11015. /*=====================================================================
  11016.  *
  11017.  * Command: QUIT
  11018.  *
  11019.  * Syntax:  QUIT
  11020.  *
  11021.  * Mode:    any
  11022.  *
  11023.  * Function: Terminates processing when it is seen.
  11024.  *
  11025.  * Note: Arguments are not permitted.  If they are given, the QUIT
  11026.  *       function will not be performed.
  11027.  *
  11028.  * Examples:  QUIT
  11029.  *
  11030.  *====================================================================*/
  11031.  
  11032. #pragma  csect(code,  "NN@BPQUI")
  11033. #pragma  csect(static,"NN$BPQUI")
  11034. #include "nn.h"
  11035. #include "nnbatch.h"
  11036.  
  11037. /****** Execute batch QUIT       command. ****************************/
  11038.  
  11039. static void
  11040. NNMbxqui(np,bp,cmdp)
  11041. Rstruc nncb         *np;
  11042. Rstruc batch        *bp;
  11043. Rstruc newscmd      *cmdp;
  11044. {
  11045.  
  11046.  bp->quit = TRUE;
  11047.  
  11048.  fprintf(np->batch_outfile,"\nQUIT signalled.  Processing ended.\n");
  11049.  
  11050.  return;
  11051.  
  11052. }
  11053.  
  11054. /****** Parse batch QUIT         command. ****************************/
  11055.  
  11056. struct newscmd *
  11057. NNMbpqui(np,bp)
  11058. Rstruc nncb         *np;
  11059. Rstruc batch        *bp;
  11060. {
  11061.  struct newscmd     *cmdp;
  11062.  
  11063.  bp->stop_at_newline = TRUE;
  11064.  
  11065.  NNMbtras(np,bp,"QUIT");   /* Trash extraneous parameters */
  11066.  
  11067.  if (bp->syntax_error) return NULL;
  11068.  
  11069.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for QUIT command");
  11070.  
  11071.  if (cmdp) {
  11072.    cmdp->mode = ANY_MODE;
  11073.    cmdp->proc = NNMbxqui;
  11074.  }
  11075.  
  11076.  return cmdp;
  11077.  
  11078. }
  11079.  
  11080. ./ ADD NAME=NNMBPREG
  11081.  
  11082.  /********************************************************************/
  11083.  /*                                                                  */
  11084.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  11085.  /*                                                                  */
  11086.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  11087.  /* including the implied warranties of merchantability and fitness, */
  11088.  /* are expressly denied.                                            */
  11089.  /*                                                                  */
  11090.  /* Provided this copyright notice is included, this software may    */
  11091.  /* be freely distributed and not offered for sale.                  */
  11092.  /*                                                                  */
  11093.  /* Changes or modifications may be made and used only by the maker  */
  11094.  /* of same, and not further distributed.  Such modifications should */
  11095.  /* be mailed to the author for consideration for addition to the    */
  11096.  /* software and incorporation in subsequent releases.               */
  11097.  /*                                                                  */
  11098.  /********************************************************************/
  11099.  
  11100. /*=====================================================================
  11101.  *
  11102.  * Command: REGISTER
  11103.  *
  11104.  * Syntax:  REGISTER
  11105.  *
  11106.  * Mode:    per_newsgroup
  11107.  *
  11108.  * Function: Registers the current newsgroup.
  11109.  *
  11110.  * Note: Arguments are not permitted.  If they are given, the
  11111.  *       function will not be performed.
  11112.  *
  11113.  * Examples:  REGISTER
  11114.  *
  11115.  *====================================================================*/
  11116.  
  11117. #pragma  csect(code,  "NN@BPREG")
  11118. #pragma  csect(static,"NN$BPREG")
  11119. #include "nn.h"
  11120. #include "nnbatch.h"
  11121.  
  11122. /****** Execute batch REGISTER command. ******************************/
  11123.  
  11124. static void
  11125. NNMbxreg(np,bp,cmdp)
  11126. Rstruc nncb         *np;
  11127. Rstruc batch        *bp;
  11128. Rstruc newscmd      *cmdp;
  11129. {
  11130.  Rstruc newsgroup   *gp = bp->gp;
  11131.  
  11132.  gp->registered = 1;
  11133.  
  11134.  fprintf(np->batch_outfile,"Newsgroup %s registered.\n",gp->name);
  11135.  
  11136.  NNMsave(np,NULL);   /* Checkpoint NEWSRC file */
  11137.  
  11138.  return;
  11139.  
  11140. }
  11141.  
  11142. /****** Parse batch REGISTER command. ********************************/
  11143.  
  11144. struct newscmd *
  11145. NNMbpreg(np,bp)
  11146. Rstruc nncb         *np;
  11147. Rstruc batch        *bp;
  11148. {
  11149.  struct newscmd     *cmdp;
  11150.  
  11151.  bp->stop_at_newline = TRUE;
  11152.  
  11153.  NNMbtras(np,bp,"REGISTER");   /* Trash extraneous parameters */
  11154.  
  11155.  if (bp->syntax_error) return NULL;
  11156.  
  11157.  if (bp->mode != PER_NEWSGROUP_MODE) {
  11158.    NNMbsynt(np,bp,NULL,0,
  11159.             "REGISTER is invalid outside of per-newsgroup mode");
  11160.    return NULL;
  11161.  }
  11162.  
  11163.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for REGISTER command");
  11164.  
  11165.  if (cmdp) {
  11166.    cmdp->mode = PER_NEWSGROUP_MODE;
  11167.    cmdp->proc = NNMbxreg;
  11168.  }
  11169.  
  11170.  return cmdp;
  11171.  
  11172. }
  11173.  
  11174. ./ ADD NAME=NNMBPSET
  11175.  
  11176.  /********************************************************************/
  11177.  /*                                                                  */
  11178.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  11179.  /*                                                                  */
  11180.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  11181.  /* including the implied warranties of merchantability and fitness, */
  11182.  /* are expressly denied.                                            */
  11183.  /*                                                                  */
  11184.  /* Provided this copyright notice is included, this software may    */
  11185.  /* be freely distributed and not offered for sale.                  */
  11186.  /*                                                                  */
  11187.  /* Changes or modifications may be made and used only by the maker  */
  11188.  /* of same, and not further distributed.  Such modifications should */
  11189.  /* be mailed to the author for consideration for addition to the    */
  11190.  /* software and incorporation in subsequent releases.               */
  11191.  /*                                                                  */
  11192.  /********************************************************************/
  11193.  
  11194. /*=====================================================================
  11195.  *
  11196.  * Command: SET
  11197.  *
  11198.  * Syntax:  SET variablename {=} {value-datum}*
  11199.  *
  11200.  * Mode:    any (but see note)
  11201.  *
  11202.  * Function: Assigns a value to the specified variablename so
  11203.  *           that it can be referenced in later PUT statements or
  11204.  *           condition queries.  Value can be made up of:
  11205.  *
  11206.  *           * text strings
  11207.  *           * integers
  11208.  *           * words representing other variables that have values
  11209.  *
  11210.  * Note: When words are used, the values they represent must be
  11211.  *       valid for the mode in which the SET is executed.
  11212.  *
  11213.  * Note: Since the command can span input lines and the number of
  11214.  *       arguments is variable, the arguments MUST be terminated
  11215.  *       by a semicolon or end of file.
  11216.  *
  11217.  * Note: The type of the value is determined by the declared type
  11218.  *       of the variable being set.
  11219.  *
  11220.  * Examples:  SET SERVER "foo.news.com"
  11221.  *            SET COUNT = 1
  11222.  *            SET MESSAGE = "There are " UNREAD "new items."
  11223.  *
  11224.  *====================================================================*/
  11225.  
  11226. #pragma  csect(code,  "NN@BPSET")
  11227. #pragma  csect(static,"NN$BPSET")
  11228. #include "nn.h"
  11229. #include "nnbatch.h"
  11230.  
  11231. /****** Execute batch SET        command. ****************************/
  11232.  
  11233. static void
  11234. NNMbxset(np,bp,cmdp)
  11235. Rstruc nncb         *np;
  11236. Rstruc batch        *bp;
  11237. Rstruc newscmd      *cmdp;
  11238. {
  11239.  char               *string;
  11240.  int                 number;
  11241.  Fool                flag;
  11242.  char               *var;
  11243.  
  11244.  var = cmdp->cmd.scmd.set_symbol;
  11245.  
  11246.  switch (cmdp->cmd.scmd.set_type) {
  11247.    case STRING_SYMTYPE:
  11248.         string = (char *)
  11249.                  NNMbbexp(np,bp,cmdp->cmd.scmd.ptreep,STRING_SYMTYPE);
  11250.         if (!bp->runtime_error) {
  11251.           SETC(var,string);
  11252.         }
  11253.         break;
  11254.    case NUMBER_SYMTYPE:
  11255.         number = (int)
  11256.                  NNMbbexp(np,bp,cmdp->cmd.scmd.ptreep,NUMBER_SYMTYPE);
  11257.         if (!bp->runtime_error) {
  11258.           SETA(var,number);
  11259.         }
  11260.         break;
  11261.    case FLAG_SYMTYPE:
  11262.         flag   = (Fool)
  11263.                  NNMbbexp(np,bp,cmdp->cmd.scmd.ptreep,FLAG_SYMTYPE);
  11264.         if (!bp->runtime_error) {
  11265.           SETB(var,flag);
  11266.         }
  11267.         break;
  11268.    default:
  11269.         fprintf(np->batch_outfile,
  11270.                 "Set of %s failed due to unrecognized var type\n", var);
  11271.  }
  11272.  if (bp->runtime_error) {
  11273.    fprintf(np->batch_outfile,
  11274.            "Set of %s failed due to errors building value\n", var);
  11275.  }
  11276.  
  11277.  return;
  11278. }
  11279.  
  11280. /****** Parse batch SET          command. ****************************/
  11281.  
  11282. struct newscmd *
  11283. NNMbpset(np,bp)
  11284. Rstruc nncb         *np;
  11285. Rstruc batch        *bp;
  11286. {
  11287.  struct newscmd     *cmdp       = NULL;
  11288.  struct ptree       *treep      = NULL;
  11289.  char               *var        = NULL;
  11290.  enum symtype        type;
  11291.  
  11292.  /* Next token must be variable name.  */
  11293.  
  11294.  if (!NNMbgtok(np,bp,TOKEN_READ)) return NULL;   /* get token */
  11295.  if (bp->curtok.type != WORD_TOKEN) {
  11296.    NNMbsynt(np,bp,NULL,0, "Expected SET variable name not seen");
  11297.    NNMbflus(np,bp);                         /* flush input tokens */
  11298.    return NULL;
  11299.  }
  11300.  
  11301.  var = NNMcopy(np,bp->curtok.string);
  11302.  
  11303.  /* Variable must have been declared, else it is not valid.  */
  11304.  
  11305.  if (!(type = (enum symtype)NNMbvget(np,bp,var,NO_SYMTYPE))) {
  11306.    NNMbsynt(np,bp,var,0,"Variable has not been declared");
  11307.    NNMbflus(np,bp);                         /* flush input tokens */
  11308.    return NULL;
  11309.  }
  11310.  
  11311.  /*
  11312.   * Next token must be either an equal sign or the first of a series
  11313.   * of "datums".  If the latter, assume the former was present.
  11314.   */
  11315.  
  11316.  if (!NNMbgtok(np,bp,TOKEN_PEEK)) return NULL;   /* Peek next token */
  11317.  if (bp->nextok.type == EQ_TOKEN) {
  11318.    (void)NNMbgtok(np,bp,TOKEN_FLUSH);            /* Eat the '=' */
  11319.  }
  11320.  
  11321.  /*
  11322.   * Rest of tokens define the string to which the variable must be set.
  11323.   * Note that the type (returned by NNMbvget) is the type of the
  11324.   * variable in question, defining the type of its value.
  11325.   */
  11326.  
  11327.  treep = NNMbgexp(np,bp,type);  /* Get structure describing data */
  11328.  
  11329.  if (!treep) {
  11330.    NNMbsynt(np,bp,NULL,0,"Bad arguments to SET, need '=' or data");
  11331.    return NULL;
  11332.  }
  11333.  
  11334.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for SET command");
  11335.  
  11336.  if (cmdp) {
  11337.    cmdp->mode = ANY_MODE;
  11338.    cmdp->proc = NNMbxset;
  11339.    cmdp->cmd.scmd.ptreep     = treep;
  11340.    cmdp->cmd.scmd.set_symbol = var;
  11341.    cmdp->cmd.scmd.set_type   = type;
  11342.  }
  11343.  
  11344.  return cmdp;
  11345. }
  11346.  
  11347. ./ ADD NAME=NNMBPVAR
  11348.  
  11349.  /********************************************************************/
  11350.  /*                                                                  */
  11351.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  11352.  /*                                                                  */
  11353.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  11354.  /* including the implied warranties of merchantability and fitness, */
  11355.  /* are expressly denied.                                            */
  11356.  /*                                                                  */
  11357.  /* Provided this copyright notice is included, this software may    */
  11358.  /* be freely distributed and not offered for sale.                  */
  11359.  /*                                                                  */
  11360.  /* Changes or modifications may be made and used only by the maker  */
  11361.  /* of same, and not further distributed.  Such modifications should */
  11362.  /* be mailed to the author for consideration for addition to the    */
  11363.  /* software and incorporation in subsequent releases.               */
  11364.  /*                                                                  */
  11365.  /********************************************************************/
  11366.  
  11367. /*=====================================================================
  11368.  *
  11369.  * Command: VARS
  11370.  *
  11371.  * Syntax:  VARS
  11372.  *
  11373.  * Mode:    any
  11374.  *
  11375.  * Function: Displays all defined variables and their types and values.
  11376.  *
  11377.  * Examples:  VARS
  11378.  *
  11379.  *====================================================================*/
  11380.  
  11381. #pragma  csect(code,  "NN@BPVAR")
  11382. #pragma  csect(static,"NN$BPVAR")
  11383. #include "nn.h"
  11384. #include "nnbatch.h"
  11385.  
  11386. /****** Dump variable name, type and value. **************************/
  11387.  
  11388. static void
  11389. dump_variable(np,bp,symp)
  11390. Rstruc nncb         *np;
  11391. Rstruc batch        *bp;
  11392. Rstruc symtab       *symp;
  11393. {
  11394.  
  11395.  if (!symp) return;
  11396.  
  11397.  fprintf(np->batch_outfile, " %-16.16s  ", symp->symvar);
  11398.  
  11399.  switch (symp->type) {
  11400.    case STRING_SYMTYPE:
  11401.         fprintf(np->batch_outfile, "STRING  %s\n", symp->symval);
  11402.         break;
  11403.    case NUMBER_SYMTYPE:
  11404.         fprintf(np->batch_outfile, "NUMBER  %d\n", symp->symnum);
  11405.         break;
  11406.    case FLAG_SYMTYPE:
  11407.         fprintf(np->batch_outfile, "FLAG    %s\n",
  11408.                 symp->symnum ? "TRUE" : "FALSE");
  11409.         break;
  11410.  }
  11411.  
  11412.  return;
  11413. }
  11414.  
  11415. /****** Display variable. ********************************************/
  11416.  
  11417. static void
  11418. display_variable(np,bp,symp)
  11419. Rstruc nncb         *np;
  11420. Rstruc batch        *bp;
  11421. Rstruc symtab       *symp;
  11422. {
  11423.  
  11424.  if (!symp) return;
  11425.  
  11426.  if (symp->left) display_variable(np,bp,symp->left);
  11427.  dump_variable(np,bp,symp);
  11428.  if (symp->right) display_variable(np,bp,symp->right);
  11429.  
  11430.  return;
  11431. }
  11432.  
  11433. /****** Execute batch VARS       command. ****************************/
  11434.  
  11435. static void
  11436. NNMbxvar(np,bp,cmdp)
  11437. Rstruc nncb         *np;
  11438. Rstruc batch        *bp;
  11439. Rstruc newscmd      *cmdp;
  11440. {
  11441.  
  11442.  fprintf(np->batch_outfile, "Current variables follow\n\n");
  11443.  display_variable(np,bp,bp->symtabp);
  11444.  fprintf(np->batch_outfile, "\nEnd variable display\n");
  11445.  
  11446.  return;
  11447.  
  11448. }
  11449.  
  11450. /****** Parse batch VARS         command. ****************************/
  11451.  
  11452. struct newscmd *
  11453. NNMbpvar(np,bp)
  11454. Rstruc nncb         *np;
  11455. Rstruc batch        *bp;
  11456. {
  11457.  struct newscmd     *cmdp;
  11458.  
  11459.  bp->stop_at_newline = TRUE;
  11460.  
  11461.  NNMbtras(np,bp,"VARS");   /* Trash extraneous parameters */
  11462.  
  11463.  if (bp->syntax_error) return NULL;
  11464.  
  11465.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for VARS command");
  11466.  
  11467.  if (cmdp) {
  11468.    cmdp->mode = ANY_MODE;
  11469.    cmdp->proc = NNMbxvar;
  11470.  }
  11471.  
  11472.  return cmdp;
  11473.  
  11474. }
  11475.  
  11476. ./ ADD NAME=NNMBSOUT
  11477.  
  11478.  /********************************************************************/
  11479.  /*                                                                  */
  11480.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  11481.  /*                                                                  */
  11482.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  11483.  /* including the implied warranties of merchantability and fitness, */
  11484.  /* are expressly denied.                                            */
  11485.  /*                                                                  */
  11486.  /* Provided this copyright notice is included, this software may    */
  11487.  /* be freely distributed and not offered for sale.                  */
  11488.  /*                                                                  */
  11489.  /* Changes or modifications may be made and used only by the maker  */
  11490.  /* of same, and not further distributed.  Such modifications should */
  11491.  /* be mailed to the author for consideration for addition to the    */
  11492.  /* software and incorporation in subsequent releases.               */
  11493.  /*                                                                  */
  11494.  /********************************************************************/
  11495.  
  11496. #pragma  csect(code,  "NN@BSOUT")
  11497. #pragma  csect(static,"NN$BSOUT")
  11498. #include "nn.h"
  11499. #include "nnbatch.h"
  11500.  
  11501. /****** Set the output file from the OUTFILE variable. ***************/
  11502.  
  11503. FILE *
  11504. NNMbsout(np,bp)
  11505. Rstruc nncb         *np;
  11506. Rstruc batch        *bp;
  11507. {
  11508.  char               *outfile;
  11509.  FILE               *outfp = NULL;
  11510.  FILE               *infp  = NULL;
  11511.  Bool                appending;
  11512.  
  11513.  outfile = GETC("OUTFILE");
  11514.  if (!outfile) outfile = "";
  11515.  if (bp->outfilename && EQUAL(bp->outfilename,outfile)) {
  11516.    if (!bp->outfp) outfp = np->batch_outfile;
  11517.    else outfp = bp->outfp;
  11518.  }
  11519.  else {
  11520.    if (bp->outfp) {
  11521.      if (fclose(bp->outfp) < 0) {
  11522.        fprintf(stderr,"Error closing outfile\n");
  11523.        bp->runtime_error = TRUE;
  11524.      }
  11525.      fprintf(np->batch_outfile,"Ending output to %s\n",bp->outfilename);
  11526.      bp->outfp = NULL;
  11527.      bp->outfilename = NULL;
  11528.    }
  11529.    if (*outfile) {
  11530.      if (TEST_IF_FILE_EXISTS(infp,outfile)) {
  11531.        CLEANUP_IF_FILE_EXISTS(infp);
  11532.        appending = TRUE;
  11533.      }
  11534.      else {
  11535.        appending = FALSE;
  11536.      }
  11537.      outfp = OPEN_OUTPUT_FILE_FOR_WRITE_OR_APPEND(outfile,appending);
  11538.      if (!outfp) {
  11539.        perror(outfile);
  11540.        fprintf(np->batch_outfile,"Error: OUTFILE %s is not usable.\n",
  11541.                                  outfile);
  11542.        bp->runtime_error = TRUE;
  11543.      }
  11544.      else {
  11545.        bp->outfp = outfp;
  11546.        bp->outfilename = NNMcopy(np,outfile);
  11547.        fprintf(np->batch_outfile,"Beginning output to %s\n", outfile);
  11548.      }
  11549.    }
  11550.    else {
  11551.      outfp = np->batch_outfile;
  11552.      bp->outfp = NULL;
  11553.      bp->outfilename = NULL;
  11554.    }
  11555.  }
  11556.  
  11557.  return outfp;
  11558. }
  11559.  
  11560. ./ ADD NAME=NNMBSYNT
  11561.  
  11562.  /********************************************************************/
  11563.  /*                                                                  */
  11564.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  11565.  /*                                                                  */
  11566.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  11567.  /* including the implied warranties of merchantability and fitness, */
  11568.  /* are expressly denied.                                            */
  11569.  /*                                                                  */
  11570.  /* Provided this copyright notice is included, this software may    */
  11571.  /* be freely distributed and not offered for sale.                  */
  11572.  /*                                                                  */
  11573.  /* Changes or modifications may be made and used only by the maker  */
  11574.  /* of same, and not further distributed.  Such modifications should */
  11575.  /* be mailed to the author for consideration for addition to the    */
  11576.  /* software and incorporation in subsequent releases.               */
  11577.  /*                                                                  */
  11578.  /********************************************************************/
  11579.  
  11580. #pragma  csect(code,  "NN@BSYNT")
  11581. #pragma  csect(static,"NN$BSYNT")
  11582. #include "nn.h"
  11583. #include "nnbatch.h"
  11584.  
  11585. /****** Syntax error. ************************************************/
  11586.  
  11587. void
  11588. NNMbsynt(np,bp,cp,len,msg)
  11589. Rstruc nncb         *np;
  11590. Rstruc batch        *bp;
  11591. char                *cp;
  11592. int                  len;
  11593. char                *msg;
  11594. {
  11595.  
  11596.  if (cp && len == 0) len = strlen(cp);
  11597.  if (!cp) {
  11598.    fprintf(np->batch_outfile, "Syntax error: %s.\n", msg);
  11599.  }
  11600.  else {
  11601.    fprintf(np->batch_outfile, "Syntax error: %s.  Token: %*.*s\n",
  11602.                               msg, len, len, cp);
  11603.  }
  11604.  
  11605.  bp->syntax_error = TRUE;
  11606.  bp->curtok.type  = ERROR_TOKEN;
  11607.  bp->nextok.type  = NO_TOKEN;
  11608.  bp->input_errors++;
  11609.  
  11610.  return;
  11611. }
  11612.  
  11613. ./ ADD NAME=NNMBTEXT
  11614.  
  11615.  /********************************************************************/
  11616.  /*                                                                  */
  11617.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  11618.  /*                                                                  */
  11619.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  11620.  /* including the implied warranties of merchantability and fitness, */
  11621.  /* are expressly denied.                                            */
  11622.  /*                                                                  */
  11623.  /* Provided this copyright notice is included, this software may    */
  11624.  /* be freely distributed and not offered for sale.                  */
  11625.  /*                                                                  */
  11626.  /* Changes or modifications may be made and used only by the maker  */
  11627.  /* of same, and not further distributed.  Such modifications should */
  11628.  /* be mailed to the author for consideration for addition to the    */
  11629.  /* software and incorporation in subsequent releases.               */
  11630.  /*                                                                  */
  11631.  /********************************************************************/
  11632.  
  11633. #pragma  csect(code,  "NN@BTEXT")
  11634. #pragma  csect(static,"NN$BTEXT")
  11635. #include "nn.h"
  11636. #include "nnbatch.h"
  11637.  
  11638. /****** Print text lines. ********************************************/
  11639.  
  11640. static int
  11641. print_text_lines(np,bp,fp,textp,linep,extracting)
  11642. Rstruc nncb         *np;
  11643. Rstruc batch        *bp;
  11644. FILE                *fp;
  11645. struct textline     *textp;
  11646. char               **linep;
  11647. Fool                 extracting;
  11648. {
  11649.  struct textline    *tp;
  11650.  char               *cp;
  11651.  int                 l;
  11652.  int                 write_error;
  11653.  Bool                tab_expanding;
  11654.  Bool                appending;
  11655.  Bool                blank_before_separator;
  11656.  char               *separator_line;
  11657.  
  11658.  if (!fp) return TRUE;
  11659.  
  11660.  if (extracting) {
  11661.    tab_expanding           = np->extract_tab_expanding;
  11662.    appending               = np->extract_appending;
  11663.    blank_before_separator  = np->extract_blank_before_separator;
  11664.    separator_line          = np->extract_separator_line;
  11665.  }
  11666.  else {
  11667.    tab_expanding           = TRUE;
  11668.    appending               = FALSE;
  11669.    blank_before_separator  = FALSE;
  11670.    separator_line          = "";
  11671.  }
  11672.  
  11673.  tab_expanding = extracting ? np->extract_tab_expanding
  11674.                             : GETB("TABEXPAND");
  11675.  write_error   = 0;
  11676.  
  11677.  /* If append mode, and a separator line was specified, use it. */
  11678.  
  11679.  while (appending && separator_line && *separator_line) {
  11680.    if (fprintf(fp,"%s\n",separator_line) < 0) {
  11681.      *linep = separator_line;
  11682.      write_error = 1;
  11683.      break;
  11684.    }
  11685.    if (blank_before_separator) {
  11686.      if (fprintf(fp,"\n") < 0) {
  11687.        *linep = "<blank before separator>";
  11688.        write_error = 2;
  11689.        break;
  11690.      }
  11691.    }
  11692.    break;
  11693.  }
  11694.  
  11695.  for (tp=textp; tp && !write_error; tp=tp->next) {
  11696.    if (tp->text_length == 0) {
  11697.      if (fputc('\n',fp) == EOF) {
  11698.        *linep = "<single newline character>";
  11699.        write_error = 3;
  11700.        break;
  11701.      }
  11702.    }
  11703.    else if (tp->text_length > 0) {
  11704.      if (tab_expanding) {
  11705.        cp = tp->tab_expanded_text;
  11706.        l  = tp->tab_expanded_text_length;
  11707.      }
  11708.      else {
  11709.        cp = tp->text;
  11710.        l  = tp->text_length;
  11711.      }
  11712.      for (; l > 0; cp += 251, l -= 251) {
  11713.        fwrite(cp,(l>251 ? 251 : l),1,fp);
  11714.        if (ferror(fp)) {
  11715.          *linep = cp;
  11716.          write_error = 4;
  11717.          break;
  11718.        }
  11719.        if (fputc('\n',fp) == EOF) {
  11720.          *linep = "<single newline character>";
  11721.          write_error = 5;
  11722.          break;
  11723.        }
  11724.      }
  11725.    }
  11726.  }
  11727.  
  11728.  if (write_error) return write_error;
  11729.  if (ferror(fp)) {
  11730.    *linep = "<ferror occurred>";
  11731.    return -1;
  11732.  }
  11733.  else return 0;
  11734. }
  11735.  
  11736. /****** Process the lines of text retrieved from server. *************/
  11737.  
  11738. void
  11739. NNMbtext(np,thp,fp)
  11740. Rstruc nncb         *np;
  11741. struct texthdr      *thp;
  11742. FILE                *fp;
  11743. {
  11744.  Rstruc batch       *bp = np->batch_hook;
  11745.  int                 rc;
  11746.  char               *line;
  11747.  Fool                extracting;
  11748.  
  11749.  if (fp) {  /* file pointer passed :: called from EXTRACT command */
  11750.    extracting = TRUE;
  11751.  }
  11752.  else {
  11753.    fp = NNMbsout(np,bp);    /* set output file */
  11754.    extracting = FALSE;
  11755.  }
  11756.  
  11757.  rc = print_text_lines(np,bp,fp,thp->first_text_line,&line,extracting);
  11758.  if (rc != 0) {
  11759.    fprintf(stderr,"Error %d writing text to outfile\n",rc);
  11760.    fprintf(stderr,"Line: %s\n",line);
  11761.    bp->runtime_error = TRUE;
  11762.  }
  11763.  
  11764.  return;
  11765.  
  11766. }
  11767.  
  11768. ./ ADD NAME=NNMBTRAS
  11769.  
  11770.  /********************************************************************/
  11771.  /*                                                                  */
  11772.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  11773.  /*                                                                  */
  11774.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  11775.  /* including the implied warranties of merchantability and fitness, */
  11776.  /* are expressly denied.                                            */
  11777.  /*                                                                  */
  11778.  /* Provided this copyright notice is included, this software may    */
  11779.  /* be freely distributed and not offered for sale.                  */
  11780.  /*                                                                  */
  11781.  /* Changes or modifications may be made and used only by the maker  */
  11782.  /* of same, and not further distributed.  Such modifications should */
  11783.  /* be mailed to the author for consideration for addition to the    */
  11784.  /* software and incorporation in subsequent releases.               */
  11785.  /*                                                                  */
  11786.  /********************************************************************/
  11787.  
  11788. #pragma  csect(code,  "NN@BTRAS")
  11789. #pragma  csect(static,"NN$BTRAS")
  11790. #include "nn.h"
  11791. #include "nnbatch.h"
  11792.  
  11793. /****** Trash extraneous data in command line. ***********************/
  11794.  
  11795. void
  11796. NNMbtras(np,bp,name)
  11797. Rstruc nncb         *np;
  11798. Rstruc batch        *bp;
  11799. char                *name;
  11800. {
  11801.  struct token       *tp;
  11802.  Bool                finished = FALSE;
  11803.  char                tmp[81];
  11804.  
  11805.  /*
  11806.   * Pull tokens until semicolon or EOF.  Note that EOL will not be
  11807.   * considered the end of the datum stream, because the user may wish
  11808.   * to specify a long list that takes several lines.  Therefore, an
  11809.   * explicit semicolon is required to terminate the list.
  11810.   */
  11811.  
  11812.  while (!finished && (tp = PEEK())) {
  11813.    switch (tp->type) {
  11814.      case EOL_TOKEN:
  11815.      case EOF_TOKEN:
  11816.      case SEMI_TOKEN: EAT();
  11817.                       finished = TRUE;
  11818.                       break;
  11819.      default:         EAT();
  11820.                       sprintf(tmp,"Extraneous data in %s command",name);
  11821.                       NNMbsynt(np,bp,tp->string,0,tmp);
  11822.                       break;
  11823.    }
  11824.  }
  11825.  
  11826.  return;
  11827. }
  11828.  
  11829. ./ ADD NAME=NNMBVGET
  11830.  
  11831.  /********************************************************************/
  11832.  /*                                                                  */
  11833.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  11834.  /*                                                                  */
  11835.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  11836.  /* including the implied warranties of merchantability and fitness, */
  11837.  /* are expressly denied.                                            */
  11838.  /*                                                                  */
  11839.  /* Provided this copyright notice is included, this software may    */
  11840.  /* be freely distributed and not offered for sale.                  */
  11841.  /*                                                                  */
  11842.  /* Changes or modifications may be made and used only by the maker  */
  11843.  /* of same, and not further distributed.  Such modifications should */
  11844.  /* be mailed to the author for consideration for addition to the    */
  11845.  /* software and incorporation in subsequent releases.               */
  11846.  /*                                                                  */
  11847.  /********************************************************************/
  11848.  
  11849. #pragma  csect(code,  "NN@BVGET")
  11850. #pragma  csect(static,"NN$BVGET")
  11851. #include "nn.h"
  11852. #include "nnbatch.h"
  11853.  
  11854. /****** Report type mismatch error. **********************************/
  11855.  
  11856. static void
  11857. type_error(np,var,type1,type2)
  11858. Rstruc nncb     *np;
  11859. char            *var;
  11860. char            *type1;
  11861. char            *type2;
  11862. {
  11863.  
  11864.  ERR4("Type mismatch: \
  11865. Cannot retrieve a value of type %s from %s variable %s.",
  11866.       type1,type2,var);
  11867.  
  11868.  return;
  11869.  
  11870. }
  11871.  
  11872. /****** Get a value from the symbol table. ***************************/
  11873.  
  11874. ANYTYPE
  11875. NNMbvget(np,bp,var,type)
  11876. Rstruc nncb         *np;
  11877. Rstruc batch        *bp;
  11878. char                *var;
  11879. enum symtype         type;
  11880. {
  11881.  Rstruc symtab      *symp;
  11882.  int                 varlen;
  11883.  char                vartest[MAX_SYMBOL_LENGTH];
  11884.  
  11885.  varlen = strlen(var);
  11886.  if (varlen < 1 || varlen > MAX_SYMBOL_LENGTH) {
  11887.    ERR2(
  11888.     "A variable name must be between 1 and %d characters in length.",
  11889.         MAX_SYMBOL_LENGTH);
  11890.    return FALSE;
  11891.  }
  11892.  
  11893.  memset(vartest,'\0',MAX_SYMBOL_LENGTH);
  11894.  memcpy(vartest,var,varlen);
  11895.  
  11896.  symp = bp->symtabp;
  11897.  
  11898.  while (symp) {
  11899.    switch (memcmp(vartest, symp->symvar, MAX_SYMBOL_LENGTH)) {
  11900.      case 0:   /* equal   */
  11901.                break;
  11902.      case 1:   /* greater */
  11903.                symp = symp->right;
  11904.                continue;
  11905.      default:  /* less    */
  11906.                symp = symp->left;
  11907.                continue;
  11908.    }
  11909.    break;
  11910.  }
  11911.  
  11912.  /* Special case, just to see if the variable exists or not. */
  11913.  
  11914.  if (type == NO_SYMTYPE)
  11915.     return (symp ? (ANYTYPE)symp->type : (ANYTYPE)NO_SYMTYPE);
  11916.  
  11917.  if (!symp) {
  11918.    ERR2("The variable %s has not been declared or set to a value.",var);
  11919.    return NULL;
  11920.  }
  11921.  
  11922.  /*------------------------------------------------------------------*
  11923.   *                                                                  *
  11924.   * Table of allowable type-to-type settings:                        *
  11925.   *                                                                  *
  11926.   * symp->type |   type      | result                                *
  11927.   *____________|_____________|_________________________________      *
  11928.   * STRING     |   STRING    | OK                                    *
  11929.   *            |   NUMBER    | error                                 *
  11930.   *            |   FLAG      | error                                 *
  11931.   *____________|_____________|_________________________________      *
  11932.   * NUMBER     |   STRING    | convert to string via sprintf %d      *
  11933.   *            |   NUMBER    | OK                                    *
  11934.   *            |   FLAG      | interpret as nonzero or zero          *
  11935.   *____________|_____________|_________________________________      *
  11936.   * FLAG       |   STRING    | convert to "1" or "0"                 *
  11937.   *            |   NUMBER    | convert to 1 or 0                     *
  11938.   *            |   FLAG      | OK                                    *
  11939.   *            |             |                                       *
  11940.   *------------------------------------------------------------------*/
  11941.  
  11942.  switch (symp->type) {
  11943.    case STRING_SYMTYPE:
  11944.         switch (type) {
  11945.           case STRING_SYMTYPE: return (ANYTYPE)symp->symval;
  11946.  
  11947.           case NUMBER_SYMTYPE: type_error(np,var,"NUMBER","STRING");
  11948.                                break;
  11949.           case FLAG_SYMTYPE:   type_error(np,var,"FLAG","STRING");
  11950.                                break;
  11951.         }
  11952.         break;
  11953.    case NUMBER_SYMTYPE:
  11954.         switch (type) {
  11955.           case STRING_SYMTYPE: sprintf(symp->symval,"%d",symp->symnum);
  11956.                                return (ANYTYPE)symp->symval;
  11957.  
  11958.           case NUMBER_SYMTYPE: return (ANYTYPE)symp->symnum;
  11959.  
  11960.           case FLAG_SYMTYPE:   return (symp->symnum
  11961.                                        ? (ANYTYPE)1 : (ANYTYPE)0);
  11962.  
  11963.         }
  11964.         break;
  11965.    case FLAG_SYMTYPE:
  11966.         switch (type) {
  11967.           case STRING_SYMTYPE: return (symp->symnum
  11968.                                        ? (ANYTYPE)"1" : (ANYTYPE)"0");
  11969.  
  11970.           case NUMBER_SYMTYPE: return (symp->symnum
  11971.                                        ? (ANYTYPE)1 : (ANYTYPE)0);
  11972.  
  11973.           case FLAG_SYMTYPE:   return (symp->symnum
  11974.                                        ? (ANYTYPE)1 : (ANYTYPE)0);
  11975.  
  11976.         }
  11977.         break;
  11978.  }
  11979.  
  11980.  return NULL;
  11981. }
  11982.  
  11983. ./ ADD NAME=NNMBVPUT
  11984.  
  11985.  /********************************************************************/
  11986.  /*                                                                  */
  11987.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  11988.  /*                                                                  */
  11989.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  11990.  /* including the implied warranties of merchantability and fitness, */
  11991.  /* are expressly denied.                                            */
  11992.  /*                                                                  */
  11993.  /* Provided this copyright notice is included, this software may    */
  11994.  /* be freely distributed and not offered for sale.                  */
  11995.  /*                                                                  */
  11996.  /* Changes or modifications may be made and used only by the maker  */
  11997.  /* of same, and not further distributed.  Such modifications should */
  11998.  /* be mailed to the author for consideration for addition to the    */
  11999.  /* software and incorporation in subsequent releases.               */
  12000.  /*                                                                  */
  12001.  /********************************************************************/
  12002.  
  12003. #pragma  csect(code,  "NN@BVPUT")
  12004. #pragma  csect(static,"NN$BVPUT")
  12005. #include "nn.h"
  12006. #include "nnbatch.h"
  12007.  
  12008. /****** Report type mismatch error. **********************************/
  12009.  
  12010. static void
  12011. type_error(np,var,type1,type2)
  12012. Rstruc nncb     *np;
  12013. char            *var;
  12014. char            *type1;
  12015. char            *type2;
  12016. {
  12017.  
  12018.  ERR4("Type mismatch: \
  12019. Cannot assign a value of type %s to %s variable %s.",
  12020.       type1,type2,var);
  12021.  
  12022.  return;
  12023.  
  12024. }
  12025.  
  12026. /****** Set value of symbol table entry. *****************************/
  12027.  
  12028. static void
  12029. set_value(np,sp,var,val,type)
  12030. Rstruc nncb     *np;
  12031. struct symtab   *sp;
  12032. char            *var;
  12033. ANYTYPE          val;
  12034. enum symtype     type;
  12035. {
  12036.  
  12037.  /*------------------------------------------------------------------*
  12038.   *                                                                  *
  12039.   * Table of allowable type-to-type settings:                        *
  12040.   *                                                                  *
  12041.   * sp->type   |   type      | result                                *
  12042.   *____________|_____________|_________________________________      *
  12043.   * STRING     |   STRING    | OK                                    *
  12044.   *            |   NUMBER    | convert to string via sprintf %d      *
  12045.   *            |   FLAG      | error                                 *
  12046.   *____________|_____________|_________________________________      *
  12047.   * NUMBER     |   STRING    | error                                 *
  12048.   *            |   NUMBER    | OK                                    *
  12049.   *            |   FLAG      | convert to 1 or 0                     *
  12050.   *____________|_____________|_________________________________      *
  12051.   * FLAG       |   STRING    | error                                 *
  12052.   *            |   NUMBER    | interpret as nonzero or zero          *
  12053.   *            |   FLAG      | OK                                    *
  12054.   *            |             |                                       *
  12055.   *------------------------------------------------------------------*/
  12056.  
  12057.  switch (sp->type) {
  12058.    case STRING_SYMTYPE:
  12059.         switch (type) {
  12060.           case STRING_SYMTYPE: strcpy(sp->symval,(char *)val);
  12061.                                break;
  12062.           case NUMBER_SYMTYPE: sprintf(sp->symval,"%d",(int)val);
  12063.                                break;
  12064.           case FLAG_SYMTYPE:   type_error(np,var,"FLAG","STRING");
  12065.                                break;
  12066.         }
  12067.         break;
  12068.    case NUMBER_SYMTYPE:
  12069.         switch (type) {
  12070.           case STRING_SYMTYPE: type_error(np,var,"STRING","NUMBER");
  12071.                                break;
  12072.           case NUMBER_SYMTYPE: sp->symnum = (int)val;
  12073.                                break;
  12074.           case FLAG_SYMTYPE:   sp->symnum = (Fool)val ? 1 : 0;
  12075.                                break;
  12076.         }
  12077.         break;
  12078.    case FLAG_SYMTYPE:
  12079.         switch (type) {
  12080.           case STRING_SYMTYPE: type_error(np,var,"STRING","FLAG");
  12081.                                break;
  12082.           case NUMBER_SYMTYPE: sp->symnum = (int)val ? 1 : 0;
  12083.                                break;
  12084.           case FLAG_SYMTYPE:   sp->symnum = (Fool)val ? 1 : 0;
  12085.                                break;
  12086.         }
  12087.         break;
  12088.  }
  12089.  
  12090.  if (np->debug_file) {
  12091.    switch (sp->type) {
  12092.      case STRING_SYMTYPE:  fprintf(np->debug_file,
  12093.                                    "NNMbvput: %s set to '%s'\n",
  12094.                                    sp->symvar, sp->symval);
  12095.                            break;
  12096.      case NUMBER_SYMTYPE:  fprintf(np->debug_file,
  12097.                                    "NNMbvput: %s set to %d\n",
  12098.                                    sp->symvar, sp->symnum);
  12099.                            break;
  12100.      case FLAG_SYMTYPE:    fprintf(np->debug_file,
  12101.                                    "NNMbvput: %s set to %s\n",
  12102.                                    sp->symvar,
  12103.                                    sp->symnum ? "TRUE" : "FALSE");
  12104.                            break;
  12105.    }
  12106.  }
  12107.  
  12108.  return;
  12109. }
  12110.  
  12111. /****** Put a value into the symbol table. ***************************/
  12112.  
  12113. void
  12114. NNMbvput(np,bp,var,type,val)
  12115. Rstruc nncb         *np;
  12116. Rstruc batch        *bp;
  12117. char                *var;
  12118. enum symtype         type;
  12119. ANYTYPE              val;
  12120. {
  12121.  Rstruc symtab      *symp;
  12122.  Rstruc symtab     **sympref;
  12123.  struct symtab      *sympnew;
  12124.  struct symtab      *sympleft;
  12125.  struct symtab      *sympright;
  12126.  enum symtype        symptype;
  12127.  int                 varlen;
  12128.  int                 minimum_value_length;
  12129.  int                 getlen;
  12130.  int                 comp;
  12131.  Bool                symbol_found;
  12132.  char                vartest[MAX_SYMBOL_LENGTH];
  12133.  
  12134.  varlen = strlen(var);
  12135.  if (varlen < 1 || varlen > MAX_SYMBOL_LENGTH) {
  12136.    ERR2(
  12137.     "A variable name must be between 1 and %d characters in length.",
  12138.         MAX_SYMBOL_LENGTH);
  12139.    return;
  12140.  }
  12141.  
  12142.  memset(vartest,'\0',MAX_SYMBOL_LENGTH);
  12143.  memcpy(vartest,var,varlen);
  12144.  
  12145.  switch (type) {
  12146.    case STRING_SYMTYPE: minimum_value_length = strlen((char *)val) + 1;
  12147.                         break;
  12148.    case NUMBER_SYMTYPE: minimum_value_length = 12;
  12149.                         break;
  12150.    case FLAG_SYMTYPE:   minimum_value_length = 6;
  12151.                         break;
  12152.  }
  12153.  
  12154.  symbol_found = FALSE;
  12155.  
  12156.  sympleft  = NULL;
  12157.  sympright = NULL;
  12158.  sympref   = &bp->symtabp;
  12159.  
  12160.  while ((symp=*sympref)) {
  12161.    switch ((comp=memcmp(vartest, symp->symvar, MAX_SYMBOL_LENGTH))) {
  12162.      case 0:   /* equal   */
  12163.                symbol_found = TRUE;
  12164.                /* free this entry and allocate a new one if this one
  12165.                   is too small to hold the requested value */
  12166.                if (minimum_value_length > symp->vallen) {
  12167.                  symptype  = symp->type;
  12168.                  sympleft  = symp->left;
  12169.                  sympright = symp->right;
  12170.                  FREEMAIN(*sympref,"old symbol table entry");
  12171.                  *sympref = NULL;
  12172.                  break;
  12173.                }
  12174.                else {
  12175.                  set_value(np,symp,var,val,type);
  12176.                  return;
  12177.                }
  12178.      case 1:   /* greater */
  12179.                sympref = &symp->right;
  12180.                continue;
  12181.      default:  /* less    */
  12182.                sympref = &symp->left;
  12183.                continue;
  12184.    }
  12185.  }
  12186.  
  12187.  /* Symbol not found - not allowed, means variable not declared */
  12188.  
  12189.  if (!symbol_found) {
  12190.    ERR2("The variable %s has not been declared or set to a value.",var);
  12191.    return;
  12192.  }
  12193.  
  12194.  getlen = offsetof(struct symtab, symval) + minimum_value_length;
  12195.  
  12196.  GETMAIN(sympnew, char, getlen, "new symbol table entry");
  12197.  if (!sympnew) {
  12198.    ERR2("Cannot set variable: \
  12199. Unable to allocate storage to hold value for variable %s.",
  12200.         var);
  12201.    return;
  12202.  }
  12203.  
  12204.  memcpy(sympnew->symvar, vartest, MAX_SYMBOL_LENGTH);
  12205.  sympnew->left   = sympleft;
  12206.  sympnew->right  = sympright;
  12207.  sympnew->vallen = minimum_value_length;
  12208.  sympnew->type   = symptype;
  12209.  *sympref        = sympnew;
  12210.  
  12211.  set_value(np,sympnew,var,val,type);
  12212.  
  12213.  return;
  12214.  
  12215. }
  12216.  
  12217. ./ ADD NAME=NNMBXFAR
  12218.  
  12219.  /********************************************************************/
  12220.  /*                                                                  */
  12221.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  12222.  /*                                                                  */
  12223.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  12224.  /* including the implied warranties of merchantability and fitness, */
  12225.  /* are expressly denied.                                            */
  12226.  /*                                                                  */
  12227.  /* Provided this copyright notice is included, this software may    */
  12228.  /* be freely distributed and not offered for sale.                  */
  12229.  /*                                                                  */
  12230.  /* Changes or modifications may be made and used only by the maker  */
  12231.  /* of same, and not further distributed.  Such modifications should */
  12232.  /* be mailed to the author for consideration for addition to the    */
  12233.  /* software and incorporation in subsequent releases.               */
  12234.  /*                                                                  */
  12235.  /********************************************************************/
  12236.  
  12237. #pragma  csect(code,  "NN@BXFAR")
  12238. #pragma  csect(static,"NN$BXFAR")
  12239. #include "nn.h"
  12240. #include "nnbatch.h"
  12241.  
  12242. /****** Execute batch FOR articles command. **************************/
  12243.  
  12244. struct variablesave {
  12245.                      int        number;
  12246.                      Bool       read;
  12247.                      Bool       missing;
  12248.                      char      *subject;
  12249.                      char      *date;
  12250.                      char      *from;
  12251.                      char      *messageid;
  12252.                     };
  12253.  
  12254. /****** Set article variables. ***************************************/
  12255.  
  12256. static void
  12257. set_article_variables(np,bp,vp,anum,vsp)
  12258. Rstruc nncb                 *np;
  12259. Rstruc batch                *bp;
  12260. VARK                        *vp;
  12261. int                          anum;
  12262. struct variablesave         *vsp;
  12263. {
  12264.  Rstruc newsarticle         *ap = VARK2PARTICLE(*vp);
  12265.  
  12266.  vsp->number     = GETA("NUMBER");
  12267.  vsp->read       = GETB("READ");
  12268.  vsp->missing    = GETB("MISSING");
  12269.  vsp->subject    = NNMcopy(np,GETC("SUBJECT"));
  12270.  vsp->date       = NNMcopy(np,GETC("DATE"));
  12271.  vsp->from       = NNMcopy(np,GETC("FROM"));
  12272.  vsp->messageid  = NNMcopy(np,GETC("MESSAGEID"));
  12273.  
  12274.  SETA("NUMBER",       anum);
  12275.  SETB("READ",         IsRead(*vp));
  12276.  if (IsMissing(*vp)) {
  12277.    SETB("MISSING",    TRUE);
  12278.    SETC("SUBJECT",    "");
  12279.    SETC("DATE",       "");
  12280.    SETC("FROM",       "");
  12281.    SETC("MESSAGEID",  "");
  12282.  }
  12283.  else {
  12284.    SETB("MISSING",    FALSE);
  12285.    SETC("SUBJECT",    ap->subject);
  12286.    SETC("DATE",       ap->date);
  12287.    SETC("FROM",       ap->from);
  12288.    SETC("MESSAGEID",  ap->message_id);
  12289.  }
  12290.  
  12291.  return ;
  12292. }
  12293.  
  12294. /****** Unset article variables. *************************************/
  12295.  
  12296. static void
  12297. unset_article_variables(np,bp,vsp)
  12298. Rstruc nncb                 *np;
  12299. Rstruc batch                *bp;
  12300. struct variablesave         *vsp;
  12301. {
  12302.  
  12303.  SETA("NUMBER",    vsp->number);
  12304.  SETB("READ",      vsp->read);
  12305.  SETB("MISSING",   vsp->missing);
  12306.  SETC("SUBJECT",   vsp->subject);
  12307.  SETC("DATE",      vsp->date);
  12308.  SETC("FROM",      vsp->from);
  12309.  SETC("MESSAGEID", vsp->messageid);
  12310.  
  12311.  FREEMAIN(vsp->subject,   "saved copy of SUBJECT");
  12312.  FREEMAIN(vsp->date,      "saved copy of DATE");
  12313.  FREEMAIN(vsp->from,      "saved copy of FROM");
  12314.  FREEMAIN(vsp->messageid, "saved copy of MESSAGEID");
  12315.  
  12316.  return;
  12317. }
  12318.  
  12319. /****** Reset newsgroup variables. ***********************************/
  12320.  
  12321. static void
  12322. reset_newsgroup_variables(np,bp,gp)
  12323. Rstruc nncb                 *np;
  12324. Rstruc batch                *bp;
  12325. Rstruc newsgroup            *gp;
  12326. {
  12327.  
  12328.  SETA("COUNT"      ,gp->article_count);
  12329.  SETA("UNREAD"     ,gp->unread_count);
  12330.  SETA("FIRST"      ,gp->low_number);
  12331.  SETA("LAST"       ,gp->high_number);
  12332.  
  12333.  return ;
  12334. }
  12335.  
  12336. /****** Execute article commands. ************************************/
  12337.  
  12338. static void
  12339. execute_article_commands(np,bp,vp,treep)
  12340. Rstruc nncb                 *np;
  12341. Rstruc batch                *bp;
  12342. VARK                        *vp;
  12343. struct cmdtree              *treep;
  12344. {
  12345.  VARK                       *savevp;
  12346.  
  12347.  for (; treep; treep = treep->next) {
  12348.    bp->runtime_error = FALSE;
  12349.    savevp = bp->vp;
  12350.    bp->vp = vp;
  12351.    (treep->cmd->proc) (np,bp,treep->cmd);
  12352.    bp->vp = savevp;
  12353.    SETB("ERROR",bp->runtime_error);
  12354.  }
  12355.  
  12356.  return;
  12357. }
  12358.  
  12359. /****** Test if article passes filter. *****************************/
  12360.  
  12361. static Bool
  12362. pass_filter(np,bp,filter)
  12363. Rstruc nncb                 *np;
  12364. Rstruc batch                *bp;
  12365. struct ptree                *filter;
  12366. {
  12367.  Bool                        passes_filter;
  12368.  
  12369.  if (filter) {
  12370.    passes_filter = (Fool)NNMbbexp(np,bp,filter,FLAG_SYMTYPE);
  12371.    if (bp->runtime_error) {
  12372.      bp->request_errors++;
  12373.      passes_filter = FALSE;
  12374.    }
  12375.  }
  12376.  else passes_filter = TRUE;
  12377.  
  12378.  return passes_filter;
  12379. }
  12380.  
  12381. /****** Test if article passes criterion. ****************************/
  12382.  
  12383. static Bool
  12384. pass_criterion(np,bp,vp,anum,which,first,last)
  12385. Rstruc nncb                 *np;
  12386. Rstruc batch                *bp;
  12387. VARK                        *vp;
  12388. int                          anum;
  12389. enum which_articles          which;
  12390. struct ptree                *first;
  12391. struct ptree                *last;
  12392. {
  12393.  int                         firstnum;
  12394.  int                         lastnum;
  12395.  
  12396.  switch (which) {
  12397.    case ALL_ARTICLES:
  12398.             return TRUE;
  12399.    case READ_ARTICLES:
  12400.             return (IsRead(*vp));
  12401.    case UNREAD_ARTICLES:
  12402.             return (IsUnread(*vp));
  12403.    case RANGED_ARTICLES:
  12404.             if (first)
  12405.                  firstnum = (int)NNMbbexp(np,bp,first,NUMBER_SYMTYPE);
  12406.             else firstnum = FIRST_ARTICLE_IN_RANGE;
  12407.             if (last)
  12408.                  lastnum  = (int)NNMbbexp(np,bp,last, NUMBER_SYMTYPE);
  12409.             else lastnum  = firstnum;
  12410.             return (anum >= firstnum && anum <= lastnum);
  12411.    case NO_ARTICLES:
  12412.             return FALSE;
  12413.    default:
  12414.             return FALSE;
  12415.  }
  12416.  
  12417. }
  12418.  
  12419. /****** Execute batch FOR articles command. **************************/
  12420.  
  12421. void
  12422. NNMbxfar(np,bp,cmdp)
  12423. Rstruc nncb                 *np;
  12424. Rstruc batch                *bp;
  12425. Rstruc newscmd              *cmdp;
  12426. {
  12427.  Rstruc newsgroup           *gp;
  12428.  Rstruc newsarticle         *ap;
  12429.  VARK                       *vp;
  12430.  struct ptree               *filter;
  12431.  struct cmdtree             *treep;
  12432.  struct ptree               *first;
  12433.  struct ptree               *last;
  12434.  int                         anum;
  12435.  enum which_articles         which;
  12436.  struct variablesave         varsave;
  12437.  
  12438.  filter = cmdp->cmd.ncmd.fors.filter;
  12439.  treep  = cmdp->cmd.ncmd.fors.treep;
  12440.  which  = cmdp->cmd.ncmd.fors.crit.which;
  12441.  first  = cmdp->cmd.ncmd.fors.crit.first;
  12442.  last   = cmdp->cmd.ncmd.fors.crit.last;
  12443.  
  12444.  gp = bp->gp;
  12445.  
  12446.  /* Logic:  (1) apply "which" criteria
  12447.   *         (2) set variables for articles remaining
  12448.   *         (3) apply filters
  12449.   * Rationale:  Variables must be set before filters can use them.
  12450.   *             But criteria can be used to reduce the load.
  12451.   */
  12452.  
  12453.  np->current_newsgroup   = gp;
  12454.  np->newsgroup_selected  = FALSE;
  12455.  
  12456.  if (!GroupSelected(gp)) gp = NNMdng(np,gp,NULL);
  12457.  if (!gp) return;
  12458.  
  12459.  bp->gp = gp;
  12460.  reset_newsgroup_variables(np,bp,gp);
  12461.  if (gp->article_vector) {
  12462.    for (anum = gp->vector_first; anum <= gp->vector_last; anum++) {
  12463.      vp = &GETVARK(gp,anum);
  12464.      if (pass_criterion(np,bp,vp,anum,which,first,last)) {
  12465.        if (NNMrarh(np,gp,vp,anum,NULL)) { /* retrieve article hdr */
  12466.          set_article_variables(np,bp,vp,anum,&varsave);
  12467.          if (pass_filter(np,bp,filter)) {
  12468.            execute_article_commands(np,bp,vp,treep);
  12469.          }
  12470.          unset_article_variables(np,bp,&varsave);
  12471.        }
  12472.      }
  12473.    }
  12474.  }
  12475.  
  12476.  np->current_newsgroup  = NULL;
  12477.  np->newsgroup_selected = FALSE;
  12478.  
  12479.  return;
  12480. }
  12481.  
  12482. ./ ADD NAME=NNMBXFNG
  12483.  
  12484.  /********************************************************************/
  12485.  /*                                                                  */
  12486.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  12487.  /*                                                                  */
  12488.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  12489.  /* including the implied warranties of merchantability and fitness, */
  12490.  /* are expressly denied.                                            */
  12491.  /*                                                                  */
  12492.  /* Provided this copyright notice is included, this software may    */
  12493.  /* be freely distributed and not offered for sale.                  */
  12494.  /*                                                                  */
  12495.  /* Changes or modifications may be made and used only by the maker  */
  12496.  /* of same, and not further distributed.  Such modifications should */
  12497.  /* be mailed to the author for consideration for addition to the    */
  12498.  /* software and incorporation in subsequent releases.               */
  12499.  /*                                                                  */
  12500.  /********************************************************************/
  12501.  
  12502. #pragma  csect(code,  "NN@BXFNG")
  12503. #pragma  csect(static,"NN$BXFNG")
  12504. #include "nn.h"
  12505. #include "nnbatch.h"
  12506.  
  12507. struct variablesave {
  12508.                      char      *group;
  12509.                      Bool       registered;
  12510.                      Bool       newgroup;
  12511.                      Bool       nosuchgroup;
  12512.                      int        count;
  12513.                      int        unread;
  12514.                      int        first;
  12515.                      int        last;
  12516.                     };
  12517.  
  12518. /****** Set newsgroup variables. *************************************/
  12519.  
  12520. static void
  12521. set_newsgroup_variables(np,bp,gp,vsp)
  12522. Rstruc nncb                 *np;
  12523. Rstruc batch                *bp;
  12524. Rstruc newsgroup            *gp;
  12525. struct variablesave         *vsp;
  12526. {
  12527.  
  12528.  vsp->group       = NNMcopy(np,GETC("GROUP"));
  12529.  vsp->registered  = GETB("REGISTERED");
  12530.  vsp->newgroup    = GETB("NEWGROUP");
  12531.  vsp->nosuchgroup = GETB("NOSUCHGROUP");
  12532.  vsp->count       = GETA("COUNT");
  12533.  vsp->unread      = GETA("UNREAD");
  12534.  vsp->first       = GETA("FIRST");
  12535.  vsp->last        = GETA("LAST");
  12536.  
  12537.  SETC("GROUP"      ,gp->name);
  12538.  SETA("COUNT"      ,gp->article_count);
  12539.  SETA("UNREAD"     ,gp->unread_count);
  12540.  SETA("FIRST"      ,gp->low_number);
  12541.  SETA("LAST"       ,gp->high_number);
  12542.  SETB("REGISTERED" ,(gp->registered > 0) ? TRUE : FALSE);
  12543.  
  12544.  if (NewGroup(gp)) {  /* if new newsgroup */
  12545.    fprintf(np->batch_outfile,"New newsgroup: %s (%d articles)\n",
  12546.                              gp->name, gp->article_count);
  12547.    gp->registered = -1;
  12548.    SETB("NEWGROUP",TRUE);
  12549.  }
  12550.  else if (gp->registered == -1) {  /* old way: if new newsgroup */
  12551.    fprintf(np->batch_outfile,"New newsgroup: %s (%d articles)\n",
  12552.                              gp->name, gp->article_count);
  12553.    SetNewGroup(gp);
  12554.    SETB("NEWGROUP",TRUE);
  12555.  }
  12556.  else {
  12557.    OffNewGroup(gp);
  12558.    SETB("NEWGROUP",FALSE);
  12559.  }
  12560.  
  12561.  if (BogusGroup(gp)) {
  12562.    fprintf(np->batch_outfile,"Nonexistent newsgroup: %s\n", gp->name);
  12563.    SetNoSuchGroup(gp);
  12564.    SETB("NOSUCHGROUP",TRUE);
  12565.  }
  12566.  else {
  12567.    SETB("NOSUCHGROUP",FALSE);
  12568.  }
  12569.  
  12570.  return ;
  12571. }
  12572.  
  12573. /****** Unset newsgroup variables. **********************************/
  12574.  
  12575. static void
  12576. unset_newsgroup_variables(np,bp,gp,vsp)
  12577. Rstruc nncb                 *np;
  12578. Rstruc batch                *bp;
  12579. Rstruc newsgroup            *gp;
  12580. struct variablesave         *vsp;
  12581. {
  12582.  
  12583.  SETC("GROUP"       ,vsp->group);
  12584.  SETB("REGISTERED"  ,vsp->registered);
  12585.  SETB("NEWGROUP"    ,vsp->newgroup);
  12586.  SETB("NOSUCHGROUP" ,vsp->nosuchgroup);
  12587.  SETA("COUNT"       ,vsp->count);
  12588.  SETA("UNREAD"      ,vsp->unread);
  12589.  SETA("FIRST"       ,vsp->first);
  12590.  SETA("LAST"        ,vsp->last);
  12591.  
  12592.  FREEMAIN(vsp->group,"saved copy of GROUP");
  12593.  
  12594.  return ;
  12595. }
  12596.  
  12597. /****** See if new newsgroup. ****************************************/
  12598.  
  12599. static void
  12600. see_if_new_newsgroup(np,bp,gp)
  12601. Rstruc nncb                 *np;
  12602. Rstruc batch                *bp;
  12603. Rstruc newsgroup            *gp;
  12604. {
  12605.  
  12606.  if (NewGroup(gp)) {  /* if new newsgroup */
  12607.  
  12608.    if (GETB("AUTOREGISTER")) {
  12609.      gp->registered = 1;
  12610.      SETB("REGISTERED",TRUE);
  12611.      fprintf(np->batch_outfile,
  12612.             "Added newsgroup %s as REGISTERED\n", gp->name);
  12613.    }
  12614.    else {
  12615.      gp->registered = 0;
  12616.      SETB("REGISTERED",FALSE);
  12617.      fprintf(np->batch_outfile,
  12618.             "Added newsgroup %s as UNREGISTERED\n", gp->name);
  12619.    }
  12620.  }
  12621.  
  12622.  return;
  12623. }
  12624.  
  12625. /****** See if bogus newsgroup. **************************************/
  12626.  
  12627. static void
  12628. see_if_bogus_newsgroup(np,bp,gp)
  12629. Rstruc nncb                 *np;
  12630. Rstruc batch                *bp;
  12631. Rstruc newsgroup            *gp;
  12632. {
  12633.  
  12634.  if (BogusGroup(gp)) {
  12635.  
  12636.    if (GETB("AUTODELETE")) {
  12637.      SetNoSuchGroup(gp);
  12638.      OffGroupListed(gp);
  12639.      fprintf(np->batch_outfile, "Deleted newsgroup %s\n", gp->name);
  12640.    }
  12641.    else {
  12642.      SetGroupListed(gp);
  12643.      fprintf(np->batch_outfile, "Kept newsgroup %s\n", gp->name);
  12644.    }
  12645.  }
  12646.  
  12647.  return;
  12648. }
  12649.  
  12650. /****** Execute newsgroup commands. **********************************/
  12651.  
  12652. static void
  12653. execute_newsgroup_commands(np,bp,gp,treep)
  12654. Rstruc nncb                 *np;
  12655. Rstruc batch                *bp;
  12656. Rstruc newsgroup            *gp;
  12657. struct cmdtree              *treep;
  12658. {
  12659.  struct newsgroup           *savegp;
  12660.  
  12661.  for (; treep; treep = treep->next) {
  12662.    bp->runtime_error = FALSE;
  12663.    savegp = bp->gp;
  12664.    bp->gp = gp;
  12665.    (treep->cmd->proc) (np,bp,treep->cmd);
  12666.    bp->gp = savegp;
  12667.    SETB("ERROR",bp->runtime_error);
  12668.  }
  12669.  
  12670.  return;
  12671. }
  12672.  
  12673. /****** Test if newsgroup passes filter. *****************************/
  12674.  
  12675. static Bool
  12676. pass_filter(np,bp,gp,filter)
  12677. Rstruc nncb                 *np;
  12678. Rstruc batch                *bp;
  12679. Rstruc newsgroup            *gp;
  12680. struct ptree                *filter;
  12681. {
  12682.  Bool                        passes_filter;
  12683.  
  12684.  if (filter) {
  12685.    passes_filter = (Fool)NNMbbexp(np,bp,filter,FLAG_SYMTYPE);
  12686.    if (bp->runtime_error) {
  12687.      bp->request_errors++;
  12688.      passes_filter = FALSE;
  12689.    }
  12690.  }
  12691.  else passes_filter = TRUE;
  12692.  
  12693.  return passes_filter;
  12694.  
  12695. }
  12696.  
  12697. /****** Match group name against group string. ***********************/
  12698.  
  12699. static Bool
  12700. match(name,string)
  12701. char    *name;
  12702. char    *string;
  12703. {
  12704.  
  12705.  return FALSE;
  12706. }
  12707.  
  12708. /****** See if group name is in group string. ************************/
  12709.  
  12710. static Bool
  12711. in(name,string)
  12712. char    *name;
  12713. char    *string;
  12714. {
  12715.  char   *s;
  12716.  char   *cp1;
  12717.  char   *cp2;
  12718.  char   *cp3;
  12719.  
  12720.  s = string;
  12721.  for (;;) {
  12722.    cp1 = strstr(s,name);
  12723.    if (!cp1) return FALSE;
  12724.    cp2 = cp1-1;
  12725.    if (cp2 < string || *cp2 == ' ' || *cp2 == '\t' || *cp2 == ',') {
  12726.      cp3 = cp1+strlen(name);
  12727.      if (*cp3 == '\0' || *cp3 == ' ' || *cp3 == '\t' || *cp3 == ',') {
  12728.        return TRUE;
  12729.      }
  12730.    }
  12731.    s = cp1 + 1;
  12732.    continue;
  12733.  }
  12734. }
  12735.  
  12736. /****** Test if newsgroup passes criterion. **************************/
  12737.  
  12738. static Bool
  12739. pass_criterion(np,bp,gp,which,groups)
  12740. Rstruc nncb                 *np;
  12741. Rstruc batch                *bp;
  12742. Rstruc newsgroup            *gp;
  12743. enum which_newsgroups        which;
  12744. struct ptree                *groups;
  12745. {
  12746.  char                       *groupstring;
  12747.  
  12748.  if (groups) {
  12749.    groupstring = NNMbbexp(np,bp,groups,STRING_SYMTYPE);
  12750.    lowercase_in_place(groupstring);
  12751.  }
  12752.  
  12753.  switch (which) {
  12754.    case ALL_NEWSGROUPS:           return TRUE;
  12755.    case REGISTERED_NEWSGROUPS:    return (gp->registered >  0);
  12756.    case UNREGISTERED_NEWSGROUPS:  return (gp->registered == 0);
  12757.    case NAMED_NEWSGROUPS:         return in(gp->name,groupstring);
  12758.    case MASKED_NEWSGROUPS:
  12759.  fprintf(np->batch_outfile,"Sorry, cannot handle MASKED_NEWSGROUPS.\n");
  12760.                                   return match(gp->name,groupstring);
  12761.    case NO_NEWSGROUPS:            return FALSE;
  12762.    default:                       return FALSE;
  12763.  }
  12764.  
  12765. }
  12766.  
  12767. /****** Execute batch FOR newsgroups command. ************************/
  12768.  
  12769. void
  12770. NNMbxfng(np,bp,cmdp)
  12771. Rstruc nncb                 *np;
  12772. Rstruc batch                *bp;
  12773. Rstruc newscmd              *cmdp;
  12774. {
  12775.  Rstruc newsgroup           *gp;
  12776.  struct ptree               *filter;
  12777.  struct cmdtree             *treep;
  12778.  struct ptree               *groups;
  12779.  enum which_newsgroups       which;
  12780.  struct variablesave         varsave;
  12781.  Bool                        serverlist;
  12782.  
  12783.  filter = cmdp->cmd.icmd.fors.filter;
  12784.  treep  = cmdp->cmd.icmd.fors.treep;
  12785.  which  = cmdp->cmd.icmd.fors.crit.which;
  12786.  groups = cmdp->cmd.icmd.fors.crit.groups;
  12787.  
  12788.  /* Connect to server. */
  12789.  
  12790.  if (!NNMbconn(np,bp)) {
  12791.    fprintf(np->batch_outfile,"No newsgroup commands executed.\n");
  12792.    bp->request_errors++;
  12793.    return;
  12794.  }
  12795.  
  12796.  /* Determine source of newsgroups - SERVER or NEWSRC. */
  12797.  /* If SERVERLIST is true, do an NNTP list.  Otherwise */
  12798.  /* use NEWSRC and do individual group requests...     */
  12799.  
  12800.  /* If we do get the newsgroups via LIST, do it only once. */
  12801.  
  12802.  serverlist = GETB("SERVERLIST");
  12803.  
  12804.  if (serverlist) {
  12805.    if (!bp->newsgroups_retrieved) {
  12806.      if (!NNMdlang(np,LIST_ALL)) { /* get list of all grps fr server */
  12807.        fprintf(np->batch_outfile,"No newsgroups processed.\n");
  12808.        bp->request_errors++;
  12809.        return;
  12810.      }
  12811.      bp->newsgroups_retrieved = TRUE;
  12812.    }
  12813.  }
  12814.  
  12815.  /* Logic:  (1) apply "which" criteria
  12816.   *         (2) set variables for groups remaining
  12817.   *         (3) apply filters
  12818.   * Rationale:  Variables must be set before filters can use them.
  12819.   *             But criteria can be used to reduce the load.
  12820.   */
  12821.  
  12822.  /* The list of newsgroups has already been built from newsrc at this
  12823.   * point.  Now, if the source is the server, then ask NNTP to get
  12824.   * the current list of newsgroups and process it against the list
  12825.   * from NEWSRC.  If the source is NEWSRC, then get the current status
  12826.   * of each newsgroup via the NNTP "group" command (slow).
  12827.   */
  12828.  
  12829.  /* Note that the position of see_if_new_newsgroup determines if new
  12830.   * newsgroups are to be registered depending on AUTOREGISTER *after*
  12831.   * the filtering or *before*.  If *after*, then all groups that are
  12832.   * not handled get autoregistered as DEREGISTERED.
  12833.   */
  12834.  
  12835.  for (gp = np->first_newsgroup; gp; gp = gp->next) {
  12836.    if (pass_criterion(np,bp,gp,which,groups)) {
  12837.      if (!serverlist) {
  12838.        NNMdng(np,gp,NULL);             /* do newsgroup by address */
  12839.        if (np->newsgroup_not_found) {
  12840.          SetNoSuchGroup(gp);
  12841.          gp->article_count = 0;
  12842.          gp->unread_count  = 0;
  12843.        }
  12844.      }
  12845.      set_newsgroup_variables(np,bp,gp,&varsave);
  12846.      if (pass_filter(np,bp,gp,filter)) {
  12847.        see_if_new_newsgroup(np,bp,gp);
  12848.        see_if_bogus_newsgroup(np,bp,gp);
  12849.        if (!NoSuchGroup(gp)) {
  12850.          execute_newsgroup_commands(np,bp,gp,treep);
  12851.        }
  12852.      }
  12853.      unset_newsgroup_variables(np,bp,gp,&varsave);
  12854.    }
  12855.  }
  12856.  
  12857.  return;
  12858. }
  12859.  
  12860. ./ ADD NAME=NNMCAR
  12861.  
  12862.  /********************************************************************/
  12863.  /*                                                                  */
  12864.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  12865.  /*                                                                  */
  12866.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  12867.  /*                                                                  */
  12868.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  12869.  /* including the implied warranties of merchantability and fitness, */
  12870.  /* are expressly denied.                                            */
  12871.  /*                                                                  */
  12872.  /* Provided this copyright notice is included, this software may    */
  12873.  /* be freely distributed and not offered for sale.                  */
  12874.  /*                                                                  */
  12875.  /* Changes or modifications may be made and used only by the maker  */
  12876.  /* of same, and not further distributed.  Such modifications should */
  12877.  /* be mailed to the author for consideration for addition to the    */
  12878.  /* software and incorporation in subsequent releases.               */
  12879.  /*                                                                  */
  12880.  /********************************************************************/
  12881.  
  12882. #pragma  csect(code,  "NN@CAR  ")
  12883. #pragma  csect(static,"NN$CAR  ")
  12884. #include "nn.h"
  12885.  
  12886. /****** Choose article (Determine if it is eligible for display) *****/
  12887.  
  12888. Bool
  12889. NNMcar(np,gp,anum,vp,app,cdp,carfun)
  12890. Rstruc nncb           *np;
  12891. Rstruc newsgroup      *gp;
  12892. int                    anum;
  12893. VARK                  *vp;
  12894. struct newsarticle   **app;
  12895. struct countdown      *cdp;
  12896. enum choose_reason     carfun;
  12897. {
  12898.  Rstruc newsarticle   *ap = NULL;
  12899.  Bool                  rc = FALSE;
  12900.  
  12901.  /* If vp is null, anum must be nonzero.
  12902.   * If vp is provided, anum may be zero, in which case NNMrarh will
  12903.   * figure out what it is if it needs to.  Not to worry here.
  12904.   */
  12905.  
  12906.  if (!vp) vp = &GETVARK(gp,anum);
  12907.  
  12908.  if (IsUnknown(*vp)) {
  12909.    if (np->show_all_articles        /* if "A"ll requested           */
  12910.     || IsUnread(*vp)                /* or "S" and article not read  */
  12911.     || (!np->unread_articles_only   /* or article already in table  */
  12912.         && IsPresent(*vp)
  12913.         && (ap=VARK2PARTICLE(*vp)) && ArticleRetrieved(ap))) {
  12914.      if (*np->article_only_string) {
  12915.        SetKnownIneligible(*vp);
  12916.        if (!ap) ap = NNMrarh(np,gp,vp,anum,cdp);
  12917.        if (ap && IsPresent(*vp)) {
  12918.          if (NNMstrlc(ap->subject,np->article_only_string)) {
  12919.            SetKnownEligible(*vp);
  12920.            rc = TRUE;
  12921.          }
  12922.        }
  12923.      }
  12924.      else {                      /* no ONLY string */
  12925.        if (carfun != MARK_ONLY) {
  12926.          SetKnownIneligible(*vp);
  12927.          if (!ap) ap = NNMrarh(np,gp,vp,anum,cdp);
  12928.          if (ap && IsPresent(*vp)) {
  12929.            SetKnownEligible(*vp);
  12930.            rc = TRUE;
  12931.          }
  12932.        }
  12933.        else {
  12934.          ap = VARK2PARTICLE(*vp);
  12935.          if (ap != V_NULL_ARTICLE && ap != V_MISSING_ARTICLE) {
  12936.            rc = TRUE;  /* just return for marking, don't set up etc. */
  12937.          }
  12938.        }
  12939.      }
  12940.    }
  12941.    else SetKnownIneligible(*vp);
  12942.  }
  12943.  
  12944.  if (IsEligible(*vp)) {
  12945.    rc = TRUE;
  12946.    if (!ap) ap = VARK2PARTICLE(*vp);
  12947.  }
  12948.  
  12949.  if (rc && app) *app = ap;
  12950.  return rc;
  12951. }
  12952.  
  12953. ./ ADD NAME=NNMCLRNG
  12954.  
  12955.  /********************************************************************/
  12956.  /*                                                                  */
  12957.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  12958.  /*                                                                  */
  12959.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  12960.  /* including the implied warranties of merchantability and fitness, */
  12961.  /* are expressly denied.                                            */
  12962.  /*                                                                  */
  12963.  /* Provided this copyright notice is included, this software may    */
  12964.  /* be freely distributed and not offered for sale.                  */
  12965.  /*                                                                  */
  12966.  /* Changes or modifications may be made and used only by the maker  */
  12967.  /* of same, and not further distributed.  Such modifications should */
  12968.  /* be mailed to the author for consideration for addition to the    */
  12969.  /* software and incorporation in subsequent releases.               */
  12970.  /*                                                                  */
  12971.  /********************************************************************/
  12972.  
  12973. #pragma  csect(code,  "NN@CLRNG")
  12974. #pragma  csect(static,"NN$CLRNG")
  12975. #include "nn.h"
  12976.  
  12977. /****** Clear newsgroups. ********************************************/
  12978.  
  12979. void
  12980. NNMclrng(np)
  12981. Rstruc nncb           *np;
  12982. {
  12983.  Rstruc newsgroup     *gp1;
  12984.  Rstruc newsgroup     *gp2;
  12985.  VARK                 *vp;
  12986.  VARK                 *vpfirst;
  12987.  VARK                 *vplast;
  12988.  
  12989.  np->newsgroup_selected = FALSE;
  12990.  np->new_newsgroup_count = 0;
  12991.  
  12992.  gp1 = np->first_newsgroup;
  12993.  while (gp1) {
  12994.   gp2 = gp1->next;
  12995.   if (gp1->article_vector) {
  12996.     vpfirst = &GETVARKFIRST(gp1);
  12997.     vplast  = &GETVARKLAST(gp1);
  12998.     for (vp = vpfirst; vp <= vplast; vp++) {
  12999.       if (IsPresent(*vp)) {
  13000.         NNMclrtx(np,VARK2PARTICLE(*vp));
  13001.       }
  13002.     }
  13003.   }
  13004.   FREEMAIN(gp1->sort_vector,        "newsgroup sort vector");
  13005.   FREEMAIN(gp1->article_vector,     "newsgroup article vector");
  13006.   if (gp1->saved_newsrc_line != gp1->saved_newsrc_data) {
  13007.     FREEMAIN(gp1->saved_newsrc_line,"newsgroup newsrc line");
  13008.   }
  13009.   FREEMAIN(gp1,                     "newsgroup");
  13010.   gp1 = gp2;
  13011.  }
  13012.  
  13013.  np->first_newsgroup      = NULL;
  13014.  np->first_newsgroup_alt  = NULL;
  13015.  np->current_newsgroup    = NULL;
  13016.  np->last_newsgroup       = NULL;
  13017.  np->last_added_newsgroup = NULL;
  13018.  
  13019.  return;
  13020. }
  13021.  
  13022. ./ ADD NAME=NNMCLRTX
  13023.  
  13024.  /********************************************************************/
  13025.  /*                                                                  */
  13026.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  13027.  /*                                                                  */
  13028.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  13029.  /* including the implied warranties of merchantability and fitness, */
  13030.  /* are expressly denied.                                            */
  13031.  /*                                                                  */
  13032.  /* Provided this copyright notice is included, this software may    */
  13033.  /* be freely distributed and not offered for sale.                  */
  13034.  /*                                                                  */
  13035.  /* Changes or modifications may be made and used only by the maker  */
  13036.  /* of same, and not further distributed.  Such modifications should */
  13037.  /* be mailed to the author for consideration for addition to the    */
  13038.  /* software and incorporation in subsequent releases.               */
  13039.  /*                                                                  */
  13040.  /********************************************************************/
  13041.  
  13042. #pragma  csect(code,  "NN@CLRTX")
  13043. #pragma  csect(static,"NN$CLRTX")
  13044. #include "nn.h"
  13045.  
  13046. /****** Clear text. **************************************************/
  13047.  
  13048. void
  13049. NNMclrtx(np,ap)
  13050. Rstruc nncb           *np;
  13051. Rstruc newsarticle    *ap;
  13052.  
  13053. {
  13054.  Rstruc texthdr       *thp;
  13055.  Rstruc textline      *tp1;
  13056.  Rstruc textline      *tp2;
  13057.  
  13058.  /* If article is not specified, use main nncb, else article's text */
  13059.  
  13060.  thp = (ap ? &ap->thdr : &np->thdr);
  13061.  
  13062.  tp1 = thp->first_text_line;
  13063.  while (tp1) {
  13064.   tp2 = tp1->next;
  13065.   FREEMAIN(tp1,"text line");
  13066.   tp1 = tp2;
  13067.  }
  13068.  
  13069.  thp->text_body_line    = NULL;
  13070.  thp->first_text_line   = NULL;
  13071.  thp->current_text_line = NULL;
  13072.  thp->last_text_line    = NULL;
  13073.  thp->text_line_count   = 0;
  13074.  thp->text_max_length   = 0;
  13075.  thp->text_max_tab_expanded_length   = 0;
  13076.  
  13077.  return;
  13078.  
  13079. }
  13080.  
  13081. ./ ADD NAME=NNMCNRF
  13082.  
  13083.  /********************************************************************/
  13084.  /*                                                                  */
  13085.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  13086.  /*                                                                  */
  13087.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  13088.  /*                                                                  */
  13089.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  13090.  /* including the implied warranties of merchantability and fitness, */
  13091.  /* are expressly denied.                                            */
  13092.  /*                                                                  */
  13093.  /* Provided this copyright notice is included, this software may    */
  13094.  /* be freely distributed and not offered for sale.                  */
  13095.  /*                                                                  */
  13096.  /* Changes or modifications may be made and used only by the maker  */
  13097.  /* of same, and not further distributed.  Such modifications should */
  13098.  /* be mailed to the author for consideration for addition to the    */
  13099.  /* software and incorporation in subsequent releases.               */
  13100.  /*                                                                  */
  13101.  /********************************************************************/
  13102.  
  13103. #pragma  csect(code,  "NN@CNRF ")
  13104. #pragma  csect(static,"NN$CNRF ")
  13105. #include "nn.h"
  13106.  
  13107. /*** Write to newsrc file. *******************************************/
  13108.  
  13109. static Bool
  13110. write_to_newsrc(np,newsrc_line,thing)
  13111. Rstruc nncb        *np;
  13112. char               *newsrc_line;
  13113. char               *thing;
  13114. {
  13115.  char              *newlinep;
  13116.  Bool               write_ok = TRUE;
  13117.  
  13118.  if (!*thing) return TRUE;
  13119.  
  13120.  newlinep = strchr(thing,'\n');
  13121.  if (newlinep) {
  13122.    while (newlinep) {
  13123.      strncat(newsrc_line,thing,newlinep-thing);
  13124.      if (fprintf(np->newsrc_file,"%s\n",newsrc_line) < 0)
  13125.          write_ok = FALSE;
  13126.      strcpy(newsrc_line,"");
  13127.      thing = newlinep + 1;
  13128.      newlinep = strchr(thing,'\n');
  13129.    }
  13130.    strcat(newsrc_line,thing);
  13131.    return write_ok;
  13132.  }
  13133.  
  13134.  if (strlen(newsrc_line) + strlen(thing) > 250) {
  13135.    if (fprintf(np->newsrc_file,"%s\n",newsrc_line) < 0)
  13136.        write_ok = FALSE;
  13137.    strcpy(newsrc_line," ");
  13138.  }
  13139.  strcat(newsrc_line,thing);
  13140.  return write_ok;
  13141. }
  13142.  
  13143. /****** Close NEWSRC file. *******************************************/
  13144.  
  13145. void
  13146. NNMcnrf(np,what_to_open,updating)
  13147. Rstruc nncb         *np;
  13148. char                *what_to_open;
  13149. Fool                 updating;
  13150. {
  13151.  Rstruc newsgroup   *gp1;
  13152.  int                 newsrc_unread;
  13153.  int                 newsrc_topnum;
  13154.  int                 newsrc_count;
  13155.  register int        iv;
  13156.  int                 read0;
  13157.  int                 read1;
  13158.  int                 read2;
  13159.  int                 read3;
  13160.  Bool                write_ok;
  13161.  char                newsrc_line[257];
  13162.  char                newsrc_numb[32];
  13163.  
  13164.  write_ok = TRUE;
  13165.  
  13166.  /* If the file is currently open for input, close it first. */
  13167.  
  13168.  if (np->newsrc_file) {
  13169.    if (fclose(np->newsrc_file) < 0) {
  13170.      fprintf(stderr,"%s: Error closing NEWSRC file\n",what_to_open);
  13171.    }
  13172.    np->newsrc_file = NULL;
  13173.  }
  13174.  
  13175.  if (!updating) return;
  13176.  
  13177.  /* Open the file for output.  This will empty it at first. */
  13178.  
  13179.  if (!what_to_open) what_to_open = np->newsrc_to_open;
  13180.  
  13181.  np->newsrc_file = fopen(what_to_open,"w");
  13182.  if (np->newsrc_file == NULL) {
  13183.    perror("Cannot open NEWSRC file");
  13184.    return;
  13185.  }
  13186.  
  13187.  if (np->update_rewriting_newsrc) {
  13188.    if (!np->batch_mode) {
  13189.      (void)NNMispf(np,"CONTROL DISPLAY LOCK");
  13190.      (void)NNMispf(np,"DISPLAY PANEL(NNMLUNRC)");
  13191.    }
  13192.  }
  13193.  
  13194.  /* Write current status into the file. */
  13195.  
  13196.  /********************************************************************/
  13197.  /*                                                                  */
  13198.  /* Note:  The format used here is designed to be compatible with    */
  13199.  /*        the format used by ANU-NEWS.  This is not an attempt to   */
  13200.  /*        duplicate the "look and feel" of ANU-NEWS - it is just    */
  13201.  /*        to be compatible with the saved state of VAX NEWS users.  */
  13202.  /*                                                                  */
  13203.  /********************************************************************/
  13204.  
  13205.  /* First record: time of last update in hex, current newsgroup, blah */
  13206.  
  13207.  if (fprintf(np->newsrc_file,"%.6s %.6s %s\n",
  13208.             np->lastNGdate, np->lastNGtime,
  13209.             np->current_newsgroup ? np->current_newsgroup->name : " ")
  13210.      < 0) write_ok = FALSE;
  13211.  
  13212.  for (gp1=np->first_newsgroup; gp1; gp1=gp1->next) {
  13213.  
  13214.    if (!NoSuchGroup(gp1)) { /* Skip groups that don't really exist */
  13215.  
  13216.     /* for each newsgroup, the following data...
  13217.      * newsgroupname: (registration) [unread,topnum] read-items
  13218.      *
  13219.      * if extended format, topnum = low_number":"high_number
  13220.      * otherwise topnum = high_number
  13221.      */
  13222.  
  13223.      /*    write out gp1->low_number somewhere too? */
  13224.  
  13225.      newsrc_unread = MAX(gp1->unread_count,0);
  13226.      newsrc_topnum = gp1->high_number;
  13227.      newsrc_count  = gp1->article_count;
  13228.  
  13229.      /* The following is a hack for "new newsgroups" */
  13230.      if (gp1->registered < 0) gp1->registered = 0;
  13231.  
  13232.      sprintf(newsrc_line,"%s: (%d) [%d,%d]",
  13233.           /* groupname */    gp1->name,
  13234.           /* reg/prio  */    gp1->registered,
  13235.           /* unread    */    newsrc_unread,
  13236.           /* topnum    */    newsrc_topnum);
  13237.  
  13238.  /*
  13239.   * All articles from 1 to low_number - 1 are "read" (expired, etc.)
  13240.   * If there is an article vector,
  13241.   *  All articles from 1 to vector_first - 1 are "read"
  13242.   *  All articles from vector_last + 1 to high_number are "read"
  13243.   * end
  13244.   */
  13245.  
  13246.      if (gp1->article_vector == NULL
  13247.       && gp1->saved_newsrc_line != NULL) {
  13248.        strcat(newsrc_line," ");
  13249.        if (!write_to_newsrc(np,newsrc_line,gp1->saved_newsrc_line))
  13250.            write_ok = FALSE;
  13251.      }
  13252.      else
  13253.      if (gp1->article_vector == NULL
  13254.    /* || newsrc_unread == newsrc_count */
  13255.       || newsrc_unread == (gp1->vector_last - gp1->vector_first + 1)) {
  13256.        sprintf(newsrc_numb, " <%d", gp1->low_number - 1);
  13257.        strcat(newsrc_line, newsrc_numb);
  13258.      }
  13259.      else {
  13260.        read0 = MAX(gp1->vector_first, gp1->low_number);
  13261.        read1 = 0;
  13262.        read2 = 0;
  13263.        read3 = gp1->vector_last;
  13264.        iv = read0;
  13265.        if (IsUnread(GETVARK(gp1,iv))) {
  13266.          sprintf(newsrc_numb, " <%d", read0 - 1);
  13267.          strcat(newsrc_line, newsrc_numb);
  13268.        }
  13269.        while (iv <= read3) {
  13270.          /* look for the first of a series of read articles */
  13271.          while (iv <= read3 && IsUnread(GETVARK(gp1,iv))) iv++;
  13272.          read1 = iv;
  13273.          /* look for the last of a series of read articles */
  13274.          while (iv <= read3 && IsRead(GETVARK(gp1,iv))) iv++;
  13275.          read2 = iv-1;
  13276.          if (read2 == read3) read2 = gp1->high_number;
  13277.          if (read1 == read0)         sprintf(newsrc_numb," <%d",read2);
  13278.          else if (read1 >  read2)    *newsrc_numb = '\0';
  13279.          else if (read1 == read2)    sprintf(newsrc_numb," %d" ,read2);
  13280.          else if (read1 == read2-1)
  13281.                             sprintf(newsrc_numb," %d %d", read1,read2);
  13282.          else               sprintf(newsrc_numb," |%d=%d",read1,read2);
  13283.          if (!write_to_newsrc(np,newsrc_line,newsrc_numb))
  13284.              write_ok = FALSE;
  13285.        }
  13286.      }
  13287.      if (*newsrc_line) {
  13288.        if (fprintf(np->newsrc_file,"%s\n",newsrc_line) < 0)
  13289.            write_ok = FALSE;
  13290.      }
  13291.    }
  13292.  }
  13293.  
  13294.  /* Close the file, saving the contents. */
  13295.  
  13296.  if (!write_ok || ferror(np->newsrc_file)) {
  13297.    fprintf(stderr,
  13298.            "%s: Error writing NEWSRC file.  Contents may be invalid.\n",
  13299.            what_to_open);
  13300.  }
  13301.  
  13302.  if (fclose(np->newsrc_file) < 0) {
  13303.    fprintf(stderr,
  13304.            "%s: Error closing NEWSRC file.  Contents may be invalid.\n",
  13305.            what_to_open);
  13306.  }
  13307.  np->newsrc_file = NULL;
  13308.  
  13309.  return;
  13310. }
  13311.  
  13312. ./ ADD NAME=NNMCONN
  13313.  
  13314.  /********************************************************************/
  13315.  /*                                                                  */
  13316.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  13317.  /*                                                                  */
  13318.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  13319.  /* including the implied warranties of merchantability and fitness, */
  13320.  /* are expressly denied.                                            */
  13321.  /*                                                                  */
  13322.  /* Provided this copyright notice is included, this software may    */
  13323.  /* be freely distributed and not offered for sale.                  */
  13324.  /*                                                                  */
  13325.  /* Changes or modifications may be made and used only by the maker  */
  13326.  /* of same, and not further distributed.  Such modifications should */
  13327.  /* be mailed to the author for consideration for addition to the    */
  13328.  /* software and incorporation in subsequent releases.               */
  13329.  /*                                                                  */
  13330.  /********************************************************************/
  13331.  
  13332. #pragma  csect(code,  "NN@CONN ")
  13333. #pragma  csect(static,"NN$CONN ")
  13334. #include "nn.h"
  13335.  
  13336. /****** Internet address formatter. **********************************/
  13337.  
  13338. static void
  13339. format_ip_address(ia,is)
  13340. IPADDRESS   ia;
  13341. char       *is;
  13342. {
  13343.  char *cp = (char *)&ia;
  13344.  
  13345.  sprintf(is,"%d.%d.%d.%d",*cp,*(cp+1),*(cp+2),*(cp+3));
  13346.  return;
  13347. }
  13348.  
  13349. /****** Connect to news server. **************************************/
  13350.  
  13351. Bool
  13352. NNMconn(np)
  13353. Rstruc nncb *np;
  13354. {
  13355.  char              *lp;
  13356.  struct hostent    *server_hp;
  13357.  struct sockaddr_in bindsock;       /* socket used by bind           */
  13358.  struct sockaddr_in consock;        /* socket used by connect        */
  13359.  int                bindsocklen;    /* size of bind socket           */
  13360.  int                consocklen;     /* size of connect socket        */
  13361.  int                bindrc;         /* the return code from bind     */
  13362.  int                connrc;         /* the return code from connect  */
  13363.  int                ip_part_1;
  13364.  int                ip_part_2;
  13365.  int                ip_part_3;
  13366.  int                ip_part_4;
  13367.  
  13368.  if (np->connected_to_server) {
  13369.    NNMdisc(np);                /* Disconnect from news server */
  13370.  }
  13371.  
  13372.  np->closing_connection = FALSE;
  13373.  
  13374.  if (!*np->nnserver) {
  13375.    ERR1("Server not defined;\
  13376. An NNTP server name must be defined before a connection can be made."
  13377.        );
  13378.    return FALSE;
  13379.  }
  13380.  
  13381.  uppercase_in_place(np->nnserver);
  13382.  
  13383.  /* Get server name and address.
  13384.   * The client name and address were gotten in NNMmain.
  13385.   */
  13386.  
  13387.  if (strchr(np->nnserver,'.') &&
  13388.      np->nnserver[strspn(np->nnserver,".0123456789")] == '\0') {
  13389.    ip_part_1 = ip_part_2 = ip_part_3 = ip_part_4 = 32767;
  13390.    strcpy(np->server_hostname, np->nnserver);
  13391.    sscanf(np->nnserver,"%d.%d.%d.%d",&ip_part_1,
  13392.                                      &ip_part_2,
  13393.                                      &ip_part_3,
  13394.                                      &ip_part_4);
  13395.    if (ip_part_1 > 255 ||
  13396.        ip_part_2 > 255 ||
  13397.        ip_part_3 > 255 ||
  13398.        ip_part_4 > 255) {
  13399.      ERR2("Syntax error in server network address: %s", np->nnserver);
  13400.      return FALSE;
  13401.    }
  13402.    np->server_ip_address = (IPADDRESS) ((ip_part_1 << 24) +
  13403.                                         (ip_part_2 << 16) +
  13404.                                         (ip_part_3 <<  8) +
  13405.                                         (ip_part_4      ));
  13406.  }
  13407.  else {
  13408.    server_hp = gethostbyname(np->nnserver);
  13409.    if (!server_hp) {
  13410.      ERR2(
  13411. "Unknown host %s - gethostbyname() could not resolve the server name.",
  13412.           np->nnserver);
  13413.      return FALSE;
  13414.    }
  13415.    strcpy(np->server_hostname, server_hp->h_name);
  13416.    np->server_ip_address = *(IPADDRESS *)server_hp->h_addr;
  13417.  }
  13418.  
  13419.  format_ip_address(np->server_ip_address, np->server_ip_addrstr);
  13420.  format_ip_address(np->client_ip_address, np->client_ip_addrstr);
  13421.  
  13422.  if (!np->batch_mode) {
  13423.    (void)NNMivput(np,"NNSERVER ",np->nnserver,-1);
  13424.    (void)NNMivput(np,"NNSERVIP ",np->server_ip_addrstr,-1);
  13425.    (void)NNMivput(np,"NNCLIENT ",np->nnclient,-1);
  13426.    (void)NNMivput(np,"NNCLIEIP ",np->client_ip_addrstr,-1);
  13427.  }
  13428.  
  13429.  consock.sin_family       = AF_INET;
  13430.  consock.sin_port         = htons(NNTP_PORT_NUMBER);
  13431.  consock.sin_addr.s_addr  = np->server_ip_address;
  13432.  
  13433.  bindsock.sin_family      = AF_INET;
  13434.  bindsock.sin_port        = 0;
  13435. #ifdef SNSTCPIP
  13436.  bindsock.sin_addr.s_addr = INADDR_ANY;
  13437. #else
  13438.  bindsock.sin_addr.s_addr = np->client_ip_address;
  13439. #endif
  13440.  
  13441.  np->socknum = socket(AF_INET, SOCK_STREAM, 0);
  13442.  if (np->socknum < 0) {
  13443.    REPORT_TCP_ERROR(np->nnserver);
  13444.    ERR2("TCP/IP error: socket() failed to make socket for server %s.",
  13445.         np->nnserver);
  13446.    return FALSE;
  13447.  }
  13448.  
  13449.  bindsocklen = sizeof(bindsock);
  13450.  bindrc = Bind(np->socknum, &bindsock, bindsocklen);
  13451.  if (bindrc < 0) {
  13452.    REPORT_TCP_ERROR(np->nnserver);
  13453.    ERR2("TCP/IP error: bind() failed to bind socket for server %s.",
  13454.         np->nnserver);
  13455.    return FALSE;
  13456.  }
  13457.  
  13458.  if (np->batch_mode) {
  13459.    fprintf(np->batch_outfile,
  13460.            "Client %s (%s) connecting to news server on %s (%s)\n",
  13461.            np->client_hostname, np->client_ip_addrstr,
  13462.            np->server_hostname, np->server_ip_addrstr);
  13463.  }
  13464.  else {
  13465.    (void)NNMispf(np,"CONTROL DISPLAY LOCK");
  13466.    (void)NNMispf(np,"DISPLAY PANEL(NNMLCONN)");
  13467.  }
  13468.  
  13469.  if (np->debug_file) {
  13470.    fprintf(np->debug_file,
  13471.            "Client %s (%s) connecting to news server on %s (%s)\n",
  13472.            np->client_hostname, np->client_ip_addrstr,
  13473.            np->server_hostname, np->server_ip_addrstr);
  13474.  }
  13475.  
  13476.  consocklen = sizeof(consock);
  13477.  connrc = Connect(np->socknum, &consock, consocklen);
  13478.  
  13479.  if (connrc < 0) {
  13480.    REPORT_TCP_ERROR(np->nnserver);
  13481.    ERR2("TCP/IP failure: connect() failed to connect to server %s.",
  13482.         np->nnserver);
  13483.    return FALSE;
  13484.  }
  13485.  
  13486.  np->connected_to_server = TRUE;
  13487.  np->time_to_go_home     = FALSE;
  13488.  np->connection_broken   = FALSE;
  13489.  np->xhdr_not_available  = FALSE;
  13490.  
  13491.  /* Now that the connection has been established, the news server
  13492.   * is trying to send the first message:
  13493.   * "200 servername blah blah blah - posting allowed"
  13494.   * or
  13495.   * "201 servername blah blah blah - no posting allowed"
  13496.   * or
  13497.   * "502 servername won't talk to you - goodbye"
  13498.   * Receive that message.  Otherwise disconnect will fail.
  13499.   *
  13500.   * Read initial message from server.
  13501.   */
  13502.  
  13503.  for (;;) {
  13504.  
  13505.    NNMssrvr(np);                             /* Start server read */
  13506.  
  13507.    if (!NNMgsrvl(np,&lp)) return FALSE;      /* Get server line */
  13508.  
  13509.    switch (np->nntp_message_num) {
  13510.      case 200: np->posting_allowed = TRUE;   break;
  13511.      case 201: np->posting_allowed = FALSE;  break;
  13512.      case 502: NNMrperr(np);                /* Report procotol error */
  13513.                np->connection_broken = TRUE;
  13514.                NNMdisc(np);                 /* Clean up connection   */
  13515.                return FALSE;                /* and abandon attempt   */
  13516.     default:   NNMrperr(np);                /* Report protocol error */
  13517.                continue;                    /* and ignore bad data   */
  13518.    }
  13519.  
  13520.    break;
  13521.  
  13522.  }
  13523.  
  13524.  /* Clean up any other responses from server. */
  13525.  
  13526.  NNMesrvr(np);                             /* End server read */
  13527.  
  13528.  /* If server needs authorization, try to provide it.  Note that we
  13529.   * currently do this even on a reconnect.  A future optimization
  13530.   * could be to save the authorization info so that we don't have
  13531.   * to retrieve it all over again - as long as we don't retain
  13532.   * sensitive information in memory across ISPF displays.
  13533.   */
  13534.  
  13535.  if (NNMauth(np)) return TRUE;                 /* Send authinfo */
  13536.  else return FALSE;
  13537.  
  13538. }
  13539.  
  13540. ./ ADD NAME=NNMCOPY
  13541.  
  13542.  /********************************************************************/
  13543.  /*                                                                  */
  13544.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  13545.  /*                                                                  */
  13546.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  13547.  /* including the implied warranties of merchantability and fitness, */
  13548.  /* are expressly denied.                                            */
  13549.  /*                                                                  */
  13550.  /* Provided this copyright notice is included, this software may    */
  13551.  /* be freely distributed and not offered for sale.                  */
  13552.  /*                                                                  */
  13553.  /* Changes or modifications may be made and used only by the maker  */
  13554.  /* of same, and not further distributed.  Such modifications should */
  13555.  /* be mailed to the author for consideration for addition to the    */
  13556.  /* software and incorporation in subsequent releases.               */
  13557.  /*                                                                  */
  13558.  /********************************************************************/
  13559.  
  13560. #pragma  csect(code,  "NN@COPY ")
  13561. #pragma  csect(static,"NN$COPY ")
  13562. #include "nn.h"
  13563.  
  13564. /****** Copy string to non-volatile memory. **************************/
  13565.  
  13566. char *
  13567. NNMcopy(np,string)
  13568. Rstruc nncb *np;
  13569. char        *string;
  13570. {
  13571.  int         len = strlen(string);
  13572.  char       *cp;
  13573.  
  13574.  /* cheapo one malloc per string right now */
  13575.  
  13576.  GETMAIN(cp,char,len+1,"copy of string");
  13577.  if (!cp) return NULL;
  13578.  strcpy(cp,string);
  13579.  
  13580.  return cp;
  13581. }
  13582.  
  13583. ./ ADD NAME=NNMDCAN
  13584.  
  13585.  /********************************************************************/
  13586.  /*                                                                  */
  13587.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  13588.  /*                                                                  */
  13589.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  13590.  /*                                                                  */
  13591.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  13592.  /* including the implied warranties of merchantability and fitness, */
  13593.  /* are expressly denied.                                            */
  13594.  /*                                                                  */
  13595.  /* Provided this copyright notice is included, this software may    */
  13596.  /* be freely distributed and not offered for sale.                  */
  13597.  /*                                                                  */
  13598.  /* Changes or modifications may be made and used only by the maker  */
  13599.  /* of same, and not further distributed.  Such modifications should */
  13600.  /* be mailed to the author for consideration for addition to the    */
  13601.  /* software and incorporation in subsequent releases.               */
  13602.  /*                                                                  */
  13603.  /********************************************************************/
  13604.  
  13605. #pragma  csect(code,  "NN@DCAN ")
  13606. #pragma  csect(static,"NN$DCAN ")
  13607. #include "nn.h"
  13608.  
  13609. #define NEWSGROUPS_LENGTH   256-sizeof("Newsgroups: ")
  13610. #define SUBJECT_LENGTH      256-sizeof("Subject: ")
  13611. #define PATH_LENGTH         256-sizeof("Path: ")
  13612. #define FROM_LENGTH         256-sizeof("From: ")
  13613. #define APPROVED_LENGTH     256-sizeof("Approved: ")
  13614. #define CONTROL_LENGTH      256-sizeof("Control: ")
  13615. #define CANCEL_LENGTH       128-sizeof("cancel ")
  13616.  
  13617. /*
  13618.  * Note:  The algorithm for determining whether the user can cancel
  13619.  *        an article is:
  13620.  *
  13621.  *        (1) The article's FROM header must match the user's
  13622.  *            identification - i.e. userid@machine.host
  13623.  *
  13624.  *        - OR -
  13625.  *
  13626.  *        (2) if the article has an Approved: header, the user's
  13627.  *            identification must match the Approved: header.
  13628.  *            The assumption is that the Approved: header is the
  13629.  *            ID of the moderator of the newsgroup.
  13630.  *
  13631.  */
  13632.  
  13633. /****** Collect additional article headers that we may need. *********/
  13634.  
  13635. static void
  13636. get_more_headers(np,ap,from,approved)
  13637. Rstruc nncb          *np;
  13638. Rstruc newsarticle   *ap;
  13639. char                 *from;
  13640. char                 *approved;
  13641. {
  13642.  struct textline     *tp;
  13643.  struct texthdr      *thp;
  13644.  char                *cp;
  13645.  char                *newp;
  13646.  char                *colonp;
  13647.  int                  header_index;
  13648.  char                 the_header[INTERNET_SIZE];
  13649.  
  13650.  strcpy(from, "");
  13651.  strcpy(approved, "");
  13652.  
  13653.  if (!ap) return;
  13654.  
  13655.  /* Grovel through headers looking for what we want.
  13656.   */
  13657.  
  13658.  newp = NULL;
  13659.  thp = &ap->thdr;
  13660.  strcpy(the_header,"");
  13661.  for (tp=thp->first_text_line; tp; tp=tp->next) {
  13662.    if (tp->text[0] == '\0') break;
  13663.    if (tp->text[0] == ' '
  13664.     || tp->text[0] == '\t') {
  13665.      cp = skip_whitespace(tp->text);
  13666.      if (*cp == '\0') break;
  13667.    }
  13668.    else {
  13669.      header_index = 0;
  13670.      colonp = strchr(tp->text,':');
  13671.      if (!colonp) break;
  13672.      strcpy(the_header,"");
  13673.      for (cp = tp->text;cp<colonp;cp++) {
  13674.        the_header[header_index++] = toupper(*cp);
  13675.      }
  13676.      the_header[header_index] = '\0';
  13677.      cp = skip_whitespace(colonp+1);
  13678.    }
  13679.    if      (EQUAL(the_header,"FROM"))
  13680.            strncat(from,cp,FROM_LENGTH);
  13681.    else if (EQUAL(the_header,"APPROVED"))
  13682.            strncat(approved,cp,APPROVED_LENGTH);
  13683.  }
  13684.  
  13685.  lowercase_and_strip_trailing_in_place(from);
  13686.  lowercase_and_strip_trailing_in_place(approved);
  13687.  
  13688.  return;
  13689.  
  13690. }
  13691.  
  13692. /****** Cancel a news article. ***************************************/
  13693.  
  13694. Bool
  13695. NNMdcan(np,gp,ap)
  13696. Rstruc nncb         *np;
  13697. Rstruc newsgroup    *gp;
  13698. Rstruc newsarticle  *ap;
  13699. {
  13700.  Bool                posted_ok     = FALSE;
  13701.  Bool                post_error    = FALSE;
  13702.  int                 prc;
  13703.  char               *lp;
  13704.  char               *cp;
  13705.  char               *article_check_field;
  13706.  struct tm          *nowtime;
  13707.  time_t              ltime;
  13708.  char                datestr[64];
  13709.  char                midstr [64];
  13710.  char                zuser   [9];
  13711.  char                temp   [12];
  13712.  char                post_message_id    [128];
  13713.  char                post_subject       [SUBJECT_LENGTH];
  13714.  char                post_path          [PATH_LENGTH];
  13715.  char                post_newsgroups    [NEWSGROUPS_LENGTH];
  13716.  char                post_from          [FROM_LENGTH];
  13717.  char                post_control       [CONTROL_LENGTH];
  13718.  char                post_grape_nuts    [CANCEL_LENGTH];
  13719.  char                article_from       [FROM_LENGTH];
  13720.  char                article_approved   [APPROVED_LENGTH];
  13721.  
  13722.  (void)NNMivget(np,"ZUSER ",zuser,sizeof(zuser));
  13723.  
  13724.  /* assert ap is not null */
  13725.  
  13726.  strcpy (post_newsgroups, gp->name);
  13727.  sprintf(post_path,       "%s!%s", np->client_hostname, zuser);
  13728.  sprintf(post_grape_nuts, "cancel %s", ap->message_id);
  13729.  strcpy (post_subject,    post_grape_nuts);
  13730.  strcpy (post_control,    post_grape_nuts);
  13731.  sprintf(post_from,       "%s@%s", zuser, np->client_hostname);
  13732.  
  13733.  lowercase_in_place(post_from);
  13734.  
  13735.  get_more_headers(np,ap,article_from,article_approved);
  13736.  if ((cp=strpbrk(article_from,     " \t"))) *cp = '\0';
  13737.  if ((cp=strpbrk(article_approved, " \t"))) *cp = '\0';
  13738.  
  13739.  if (*article_approved) article_check_field = article_approved;
  13740.  else                   article_check_field = article_from;
  13741.  
  13742.  if (UNEQUAL(article_check_field, post_from)) {
  13743.    ERR3("Cancel refused.  You, %s, are not %s.",
  13744.         post_from, article_check_field);
  13745.    return FALSE;
  13746.  }
  13747.  
  13748.  /* Display confirmation panel containing the following info:
  13749.   *
  13750.   * newsgroup name  = NNCGROUP
  13751.   * article number  = NNCNUM
  13752.   * article subject = NNCSUBJ
  13753.   * message ID      = NNCMSGID
  13754.   */
  13755.  
  13756.  if (!np->batch_mode) {
  13757.    sprintf(temp,"%d",ap->number);
  13758.    (void)NNMivput(np,"NNCGROUP ",gp->name,         -1);
  13759.    (void)NNMivput(np,"NNCNUM   ",temp,             -1);
  13760.    (void)NNMivput(np,"NNCSUBJ  ",ap->subject,      -1);
  13761.    (void)NNMivput(np,"NNCMSGID ",ap->message_id,   -1);
  13762.    (void)NNMispf(np,"ADDPOP");
  13763.    (void)NNMispf(np,"DISPLAY PANEL(NNMPCAN)");
  13764.    prc = np->ispfrc;
  13765.    (void)NNMispf(np,"REMPOP");
  13766.    if (prc > 0) { /* see if user pressed END */
  13767.      WARN1("Operation cancelled, because you pressed END.");
  13768.      return FALSE;
  13769.    }
  13770.  }
  13771.  
  13772.  /* Start posting here.
  13773.   *
  13774.   * Me:     POST
  13775.   * Server: 340 send article to be posted.  End with <CR-LF>.<CR-LF>
  13776.   *     or: 440 posting not allowed
  13777.   * If 430...
  13778.   *
  13779.   * See RFC850 for details.
  13780.   *
  13781.   * Me:     required_header: xxx
  13782.   * ...
  13783.   * Me:     <null line>
  13784.   * Me:     <text with leading periods hacked>
  13785.   * Me:     .
  13786.   * Server: 240 article posted OK
  13787.   *     or: 441 posting failed
  13788.   */
  13789.  
  13790.   /* See NNMDPOST for more information. */
  13791.  
  13792.  /* Get current date and time, and generate a message id from it.
  13793.   * If the message id is a duplicate, loop around until it isn't.
  13794.   */
  13795.  
  13796.  do {
  13797.  
  13798.    time(<ime);
  13799.    nowtime = localtime(<ime);
  13800.    strftime(datestr,sizeof(datestr)-1,"%a, %d %b %Y %H:%M %Z",nowtime);
  13801.    strftime(midstr, sizeof(midstr)-1, "%Y%m%d%H%M%S",nowtime);
  13802.  
  13803.    sprintf(post_message_id, "<%s%s@%s>",
  13804.                             midstr, zuser, np->client_hostname);
  13805.  
  13806.  } while (EQUAL(post_message_id,np->messageid));
  13807.  
  13808.  strcpy(np->messageid,post_message_id);
  13809.  
  13810.  posted_ok = FALSE;
  13811.  
  13812.  do {
  13813.    strcpy(np->nntp_command,"POST");
  13814.    if (!NNMsockt(np))     break;  /* Send socket command to server */
  13815.    if (!NNMgsrvl(np,&lp)) break;  /* Get server line */
  13816.    switch (np->nntp_message_num) {
  13817.      case 340: post_error = FALSE;
  13818.                break;
  13819.      case 440: ERR2(
  13820.        "Cancellation failed.  Server %s did not accept the post.",
  13821.                     np->nnserver);
  13822.                post_error = TRUE;
  13823.                break;
  13824.      default:  NNMrperr(np);       /* Report protocol error */
  13825.                post_error = TRUE;
  13826.                break;
  13827.    }
  13828.  
  13829.    if (post_error) break;
  13830.  
  13831.    /* Assert np->server_finished_replying == TRUE
  13832.     *     && np->receiving_text == TRUE
  13833.     */
  13834.  
  13835.    sprintf(np->nntp_command,"Path: %s", post_path);
  13836.    if (!NNMsockt(np)) break;   /* Send socket command to server */
  13837.  
  13838.    sprintf(np->nntp_command,"Newsgroups: %s",post_newsgroups);
  13839.    if (!NNMsockt(np)) break;   /* Send socket command to server */
  13840.  
  13841.    sprintf(np->nntp_command,"Subject: %s",post_subject);
  13842.    if (!NNMsockt(np)) break;   /* Send socket command to server */
  13843.  
  13844.    sprintf(np->nntp_command,"Message-ID: %s", post_message_id);
  13845.    if (!NNMsockt(np)) break;   /* Send socket command to server */
  13846.  
  13847.    sprintf(np->nntp_command,"From: %s", post_from);
  13848.    if (!NNMsockt(np)) break;   /* Send socket command to server */
  13849.  
  13850.    sprintf(np->nntp_command,"Date: %s", datestr);
  13851.    if (!NNMsockt(np)) break;   /* Send socket command to server */
  13852.  
  13853.    if (*article_approved) {
  13854.      sprintf(np->nntp_command,"Approved: %s", article_approved);
  13855.      if (!NNMsockt(np)) break;   /* Send socket command to server */
  13856.    }
  13857.  
  13858.    sprintf(np->nntp_command,"Control: %s", post_control);
  13859.    if (!NNMsockt(np)) break;   /* Send socket command to server */
  13860.  
  13861.    strcpy(np->nntp_command,"");
  13862.    if (!NNMsockt(np)) break;   /* Send socket command to server */
  13863.  
  13864.    strcpy(np->nntp_command,post_grape_nuts);
  13865.    if (!NNMsockt(np)) break;   /* Send socket command to server */
  13866.  
  13867.    strcpy(np->nntp_command,".");
  13868.    if (!NNMsockt(np)) break;   /* Send socket command to server */
  13869.  
  13870.    if (!NNMgsrvl(np,&lp)) break;  /* Get server line */
  13871.    switch (np->nntp_message_num) {
  13872.      case 240: posted_ok = TRUE;
  13873.                break;
  13874.      case 441: NNMclrtx(np,NULL);               /* Clear text */
  13875.                NNMouttx(np,np->server_buf,NULL);/* Output text line */
  13876.                NNMvtx(np,NULL,NULL);            /* View text */
  13877.  ERR2("Cancel failed.  Server %s rejected the post.",np->nnserver);
  13878.                posted_ok = FALSE;
  13879.                break;
  13880.      default:  NNMrperr(np);       /* Report protocol error */
  13881.                posted_ok = FALSE;
  13882.                break;
  13883.    }
  13884.  
  13885.    NNMesrvr(np);                   /* End server read */
  13886.  
  13887.    break;
  13888.  
  13889.  } while(FALSE); /* one-time DO so I can break out of it */
  13890.  
  13891.  if (!posted_ok) return FALSE;
  13892.  
  13893.  WARN4("Cancel request for %s article %d sent to server %s.",
  13894.        gp->name, ap->number, np->nnserver);
  13895.  
  13896.  return TRUE;
  13897. }
  13898.  
  13899. ./ ADD NAME=NNMDFAIL
  13900.  
  13901.  /********************************************************************/
  13902.  /*                                                                  */
  13903.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  13904.  /*                                                                  */
  13905.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  13906.  /* including the implied warranties of merchantability and fitness, */
  13907.  /* are expressly denied.                                            */
  13908.  /*                                                                  */
  13909.  /* Provided this copyright notice is included, this software may    */
  13910.  /* be freely distributed and not offered for sale.                  */
  13911.  /*                                                                  */
  13912.  /* Changes or modifications may be made and used only by the maker  */
  13913.  /* of same, and not further distributed.  Such modifications should */
  13914.  /* be mailed to the author for consideration for addition to the    */
  13915.  /* software and incorporation in subsequent releases.               */
  13916.  /*                                                                  */
  13917.  /********************************************************************/
  13918.  
  13919. #pragma  csect(code,  "NN@DFAIL")
  13920. #pragma  csect(static,"NN$DFAIL")
  13921. #include "nn.h"
  13922.  
  13923. /****** Retrieve allocation failure messages. ************************/
  13924.  
  13925. void
  13926. NNMdfail(rc,p99)
  13927. int            rc;
  13928. __S99parms    *p99;
  13929. {
  13930.  int           zero = 0;
  13931.  unsigned int  dfid = 0x40320000;
  13932.  struct {
  13933.          short first_level_msg_len;
  13934.          short first_level_msg_offset;
  13935.          char  first_level_msg[251];
  13936.          short second_level_msg_len;
  13937.          short second_level_msg_offset;
  13938.          char  second_level_msg[251];
  13939.         }      dfbuffer;
  13940.  
  13941.  static int (*ikjeff18_pointer)() = NULL;
  13942.  
  13943. #ifndef FETCH
  13944.  extern int *ikjeff18();
  13945. #endif
  13946.  
  13947.  if (!ikjeff18_pointer) {
  13948. #ifdef FETCH
  13949.    ikjeff18_pointer = (int (*)())fetch("IKJEFF18");
  13950. #else
  13951.    ikjeff18_pointer = (int (*)())ikjeff18;
  13952. #endif
  13953.  }
  13954.  
  13955.  dfbuffer.first_level_msg_len = 4;
  13956.  dfbuffer.second_level_msg_len = 4;
  13957.  
  13958.  if (ikjeff18_pointer) {
  13959.    if ((*ikjeff18_pointer)(p99,&rc,&zero,&dfid,&zero,&dfbuffer)) {
  13960.      fprintf(stderr,"IKJEFF18 returned a nonzero return code\n");
  13961.    }
  13962.    if (dfbuffer.first_level_msg_len > 0) {
  13963.      fprintf(stderr,"%*.*s\n",
  13964.                     dfbuffer.first_level_msg_len-4,
  13965.                     dfbuffer.first_level_msg_len-4,
  13966.                     dfbuffer.first_level_msg);
  13967.    }
  13968.    if (dfbuffer.second_level_msg_len > 0) {
  13969.      fprintf(stderr,"%*.*s\n",
  13970.                     dfbuffer.second_level_msg_len-4,
  13971.                     dfbuffer.second_level_msg_len-4,
  13972.                     dfbuffer.second_level_msg);
  13973.    }
  13974.  }
  13975.  else {
  13976. #ifdef FETCH
  13977.    fprintf(stderr,"NNMVS: Cannot fetch IKJEFF18\n");
  13978. #else
  13979.    fprintf(stderr,"Cannot call IKJEFF18, not linked with NNMVS\n");
  13980. #endif
  13981.  }
  13982.  return;
  13983. }
  13984.  
  13985. ./ ADD NAME=NNMDISC
  13986.  
  13987.  /********************************************************************/
  13988.  /*                                                                  */
  13989.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  13990.  /*                                                                  */
  13991.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  13992.  /* including the implied warranties of merchantability and fitness, */
  13993.  /* are expressly denied.                                            */
  13994.  /*                                                                  */
  13995.  /* Provided this copyright notice is included, this software may    */
  13996.  /* be freely distributed and not offered for sale.                  */
  13997.  /*                                                                  */
  13998.  /* Changes or modifications may be made and used only by the maker  */
  13999.  /* of same, and not further distributed.  Such modifications should */
  14000.  /* be mailed to the author for consideration for addition to the    */
  14001.  /* software and incorporation in subsequent releases.               */
  14002.  /*                                                                  */
  14003.  /********************************************************************/
  14004.  
  14005. #pragma  csect(code,  "NN@DISC ")
  14006. #pragma  csect(static,"NN$DISC ")
  14007. #include "nn.h"
  14008.  
  14009. /****** Disconnect from news server. *********************************/
  14010.  
  14011. void
  14012. NNMdisc(np)
  14013. Rstruc nncb *np;
  14014. {
  14015.  int closerc;
  14016.  
  14017.  np->reconnect_in_progress = FALSE;
  14018.  np->closing_connection    = TRUE;
  14019.  
  14020.  if (np->connection_broken) {
  14021.    if (np->debug_file) {
  14022.      fprintf(np->debug_file,
  14023.     "Client %s (%s) connection with news server on %s (%s) was lost\n",
  14024.           np->client_hostname, np->client_ip_addrstr,
  14025.           np->server_hostname, np->server_ip_addrstr);
  14026.    }
  14027.    if (np->batch_mode) {
  14028.      fprintf(np->batch_outfile,
  14029.     "Client %s (%s) connection with news server on %s (%s) was lost\n",
  14030.           np->client_hostname, np->client_ip_addrstr,
  14031.           np->server_hostname, np->server_ip_addrstr);
  14032.    }
  14033.    np->connected_to_server   = FALSE;
  14034.  }
  14035.  else {
  14036.  
  14037.    np->newsgroup_selected    = FALSE;
  14038.    np->current_newsgroup     = NULL;
  14039.  
  14040.    /* In case of some kind of protocol error, don't let things hang. */
  14041.  
  14042.    NNMesrvr(np);         /* End server read */
  14043.  
  14044.    if (np->debug_file) {
  14045.      fprintf(np->debug_file,
  14046.           "Client %s (%s) disconnecting from news server on %s (%s)\n",
  14047.           np->client_hostname, np->client_ip_addrstr,
  14048.           np->server_hostname, np->server_ip_addrstr);
  14049.    }
  14050.  
  14051.    if (np->batch_mode) {
  14052.      fprintf(np->batch_outfile,
  14053.           "Client %s (%s) disconnecting from news server on %s (%s)\n",
  14054.           np->client_hostname, np->client_ip_addrstr,
  14055.           np->server_hostname, np->server_ip_addrstr);
  14056.    }
  14057.    else {
  14058.      (void)NNMivput(np,"NNSOLDER ",np->server_hostname,-1);
  14059.      (void)NNMivput(np,"NNSOLDIP ",np->server_ip_addrstr,-1);
  14060.      (void)NNMispf(np,"CONTROL DISPLAY LOCK");
  14061.      (void)NNMispf(np,"DISPLAY PANEL(NNMLDISC)");
  14062.  
  14063.    }
  14064.  
  14065.    /* Send the server a QUIT request.  In the past we got away without
  14066.     * doing this.  However, this is important for one reason:
  14067.     * If the connection was lost before we attempt the disconnect,
  14068.     * we want to know about it so that we don't attempt the close.
  14069.     * The best way to find out is to try to send something.
  14070.     * Fortunately, the protocol fits right in with that need.
  14071.     */
  14072.  
  14073.    strcpy(np->nntp_command,"QUIT");
  14074.    if (!NNMsockt(np)) return;      /* Send socket command to server */
  14075.  
  14076.    /* In case of some kind of protocol error, don't let things hang. */
  14077.  
  14078.    NNMesrvr(np);                   /* End server read */
  14079.  
  14080.    np->connected_to_server   = FALSE;
  14081.  
  14082.    TCP_DEBUG_ON;
  14083.    closerc = close(np->socknum);
  14084.    TCP_DEBUG_OFF;
  14085.  
  14086.    if (closerc < 0) {
  14087.      ERR2("TCP/IP error: close() failed to disconnect from server %s.",
  14088.           np->nnserver);
  14089.    }
  14090.  }
  14091.  
  14092.  return;
  14093. }
  14094.  
  14095. ./ ADD NAME=NNMDISPL
  14096.  
  14097.  /********************************************************************/
  14098.  /*                                                                  */
  14099.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  14100.  /*                                                                  */
  14101.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  14102.  /*                                                                  */
  14103.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  14104.  /* including the implied warranties of merchantability and fitness, */
  14105.  /* are expressly denied.                                            */
  14106.  /*                                                                  */
  14107.  /* Provided this copyright notice is included, this software may    */
  14108.  /* be freely distributed and not offered for sale.                  */
  14109.  /*                                                                  */
  14110.  /* Changes or modifications may be made and used only by the maker  */
  14111.  /* of same, and not further distributed.  Such modifications should */
  14112.  /* be mailed to the author for consideration for addition to the    */
  14113.  /* software and incorporation in subsequent releases.               */
  14114.  /*                                                                  */
  14115.  /********************************************************************/
  14116.  
  14117. #pragma  csect(code,  "NN@DISPL")
  14118. #pragma  csect(static,"NN$DISPL")
  14119. #include "nn.h"
  14120.  
  14121. #ifdef FETCH
  14122. #define VL_BIT(X) ((unsigned int)(X) | 0x80000000)
  14123. #else
  14124. #define VL_BIT(X) (X)
  14125. #endif
  14126.  
  14127. /****** Display ISPF panel. ******************************************/
  14128.  
  14129. int
  14130. NNMdispl(np,pan8)
  14131. Rstruc nncb    *np;
  14132. char           *pan8;
  14133. {
  14134.  
  14135.  if (np->setmsg) {
  14136.    np->ispfrc = ISPLINK("DISPLAY ", pan8, VL_BIT("ISRZ002 "));
  14137.  }
  14138.  else {
  14139.    np->ispfrc = ISPLINK("DISPLAY ", VL_BIT(pan8));
  14140.  }
  14141.  
  14142.  if (np->ispfrc > 8) NNMierr(np);   /* display ISPF error */
  14143.  
  14144.  np->setmsg = FALSE;
  14145.  
  14146.  return np->ispfrc;
  14147. }
  14148.  
  14149. ./ ADD NAME=NNMDLANG
  14150.  
  14151.  /********************************************************************/
  14152.  /*                                                                  */
  14153.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  14154.  /*                                                                  */
  14155.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  14156.  /*                                                                  */
  14157.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  14158.  /* including the implied warranties of merchantability and fitness, */
  14159.  /* are expressly denied.                                            */
  14160.  /*                                                                  */
  14161.  /* Provided this copyright notice is included, this software may    */
  14162.  /* be freely distributed and not offered for sale.                  */
  14163.  /*                                                                  */
  14164.  /* Changes or modifications may be made and used only by the maker  */
  14165.  /* of same, and not further distributed.  Such modifications should */
  14166.  /* be mailed to the author for consideration for addition to the    */
  14167.  /* software and incorporation in subsequent releases.               */
  14168.  /*                                                                  */
  14169.  /********************************************************************/
  14170.  
  14171. #pragma  csect(code,  "NN@DLANG")
  14172. #pragma  csect(static,"NN$DLANG")
  14173. #include "nn.h"
  14174.  
  14175. struct nndynarea {
  14176.                   struct newsgroup      *newsgroup;
  14177.                   char                   sel_attr;
  14178.                   char                   sel_field;
  14179.                   char                   name_attr;
  14180.                   char                   name[GROUP_NAME_SIZE];
  14181.                   char                   count_attr;
  14182.                   int                    count;
  14183.                  };
  14184.  
  14185. /****** Set date and time of last LIST or NEWGROUPS command. *********/
  14186.  
  14187. static void
  14188. set_date_and_time(np)
  14189. Rstruc nncb      *np;
  14190. {
  14191.   time_t          timeval;
  14192.   struct tm      *now;
  14193.  
  14194.   time(&timeval);
  14195.   now = localtime(&timeval);
  14196.   now->tm_mon++;             /* adjust for # of months since Jan. */
  14197.  
  14198.   sprintf(np->lastNGdate, "%02d%02d%02d",
  14199.                           now->tm_year, now->tm_mon, now->tm_mday);
  14200.   sprintf(np->lastNGtime, "%02d%02d%02d",
  14201.                           now->tm_hour, now->tm_min, now->tm_sec );
  14202.   return;
  14203. }
  14204.  
  14205. /****** Collect newsgroups using list from NEWSGROUPS request. *******/
  14206.  
  14207. static Bool
  14208. collect_newsgroups(np,just_new_groups)
  14209. Rstruc nncb         *np;
  14210. Fool                 just_new_groups;
  14211. {
  14212.  Rstruc newsgroup   *gp;
  14213.  struct newsgroup   *gpact;
  14214.  char               *lp;
  14215.  int                 list_first_article_number     = NO_VALUE;
  14216.  int                 list_last_article_number      = NO_VALUE;
  14217.  int                 ac;
  14218.  char                list_posting_allowed          = 'n';
  14219.  char                list_name[GROUP_NAME_SIZE]    = "";
  14220.  char                formatted_ac[12];
  14221.  
  14222.  np->sending_text = TRUE;
  14223.  gpact = NULL;
  14224.  
  14225.  for (;;) {
  14226.  
  14227.    if (!NNMgsrvl(np,&lp))    return FALSE;   /* Get server line */
  14228.    if (lp == NULL)           break;
  14229.    if (strcmp(lp,".") == 0)  break;
  14230.  
  14231.    if (just_new_groups) {
  14232.  
  14233.      /* Extract fields from response to "NEWGROUPS" socket request.
  14234.         Note that only newsgroup names are returned. */
  14235.  
  14236.      if (1 != sscanf(np->nntp_message_text, "%s", list_name)) {
  14237.        NNMrbfm(np);   /* Report bad format message */
  14238.        return FALSE;
  14239.      }
  14240.    }
  14241.    else {
  14242.  
  14243.      /* Extract fields from response to "LIST" socket request.
  14244.         Note that no article count is provided. */
  14245.  
  14246.      if (4 != sscanf(np->nntp_message_text, "%s %d %d %c",
  14247.                                  list_name,
  14248.                                 &list_last_article_number,
  14249.                                 &list_first_article_number,
  14250.                                 &list_posting_allowed       )) {
  14251.        NNMrbfm(np);   /* Report bad format message */
  14252.        return FALSE;
  14253.      }
  14254.    }
  14255.  
  14256.    if (just_new_groups) {
  14257.      ac = NO_VALUE;
  14258.      strcpy(formatted_ac,"");
  14259.    }
  14260.    else {
  14261.      ac = list_last_article_number - list_first_article_number + 1;
  14262.      sprintf(formatted_ac,"%d",ac);
  14263.    }
  14264.    if (!np->batch_mode) {
  14265.      if (np->update_adding_newsgroups) {
  14266.        (void)NNMivput(np,"NNLCOUNT ",formatted_ac,-1);
  14267.        (void)NNMivput(np,"NNLGROUP ",list_name,   -1);
  14268.        (void)NNMispf(np,"CONTROL DISPLAY LOCK");
  14269.        (void)NNMispf(np,"DISPLAY PANEL(NNMLADDG)");
  14270.      }
  14271.    }
  14272.  
  14273.    gp = NNMaddng(np,list_name);           /* Add newsgroup */
  14274.  
  14275.    if (just_new_groups) {
  14276.      np->new_newsgroup_count++;
  14277.      ClearGroupStatus(gp);
  14278.      SetNewGroup(gp);
  14279.      gp->registered = -1;
  14280.      continue;
  14281.    }
  14282.  
  14283.    /* Put group in the proper "active file" order */
  14284.  
  14285.    if (gpact) gpact->next2 = gp;
  14286.    else       np->first_newsgroup_alt = gp;
  14287.    gp->next2 = NULL;
  14288.    gpact = gp;
  14289.  
  14290.    OffNoSuchGroup(gp);    /* came from LIST, must exist now */
  14291.  
  14292.    if (NullGroupStatus(gp)) {
  14293.      if (np->brand_new_newsrc) {
  14294.        gp->registered = 0;     /* new news user, no autosubscribes */
  14295.      }
  14296.      else {
  14297.        np->new_newsgroup_count++;
  14298.        SetNewGroup(gp);
  14299.        gp->registered = -1;
  14300.      }
  14301.    }
  14302.  
  14303.    /*
  14304.     * Logic:
  14305.     * This code sets up newsgroups from NNTP LIST.
  14306.     * They are already found in .newsrc (unless new newsgroups),
  14307.     * and probably aren't GROUPed yet, but may have been.
  14308.     * So there is a possibility of an article vector existing,
  14309.     * but in most cases there won't be.
  14310.     * The overriding principle here is that the active file knows
  14311.     * best what's up to date, and is the arbiter of the
  14312.     * low_number and high_number fields.  On the off chance
  14313.     * that NEWSRC implied different values for these, the
  14314.     * various adjustments in other routines should handle it.
  14315.     */
  14316.  
  14317.    if (GroupFromNewsrc(gp)
  14318.     || GroupFromNNTP(gp)) {          /* Adjust unread articles */
  14319.      NNMadjua(np,gp,ac,list_first_article_number,
  14320.                        list_last_article_number);
  14321.    }
  14322.    else {
  14323.      gp->unread_count = ac;
  14324.    }
  14325.  
  14326.    gp->low_number    = list_first_article_number;
  14327.    gp->high_number   = list_last_article_number;
  14328.    gp->article_count = ac;
  14329.  
  14330.    SetGroupListed(gp);
  14331.  
  14332.  }
  14333.  
  14334.  np->dont_reconnect = FALSE;
  14335.  
  14336.  return TRUE;
  14337.  
  14338. }
  14339.  
  14340. /****** Display new newsgroups. **************************************/
  14341.  
  14342. static Bool
  14343. display_new_newsgroups(np,just_new_groups)
  14344. Rstruc nncb           *np;
  14345. Fool                   just_new_groups;
  14346. {
  14347.  Rstruc newsgroup     *gp;
  14348.  Rstruc nndynarea     *dp;
  14349.  struct nndynarea     *nndynarea_address;
  14350.  int                   nndynarea_length;
  14351.  int                   i;
  14352.  int                   prc;
  14353.  int                   nnlvl;
  14354.  int                   depth;
  14355.  int                   depthx80;
  14356.  int                   zscrolln;
  14357.  int                   topoff;
  14358.  int                   dynsize;
  14359.  char                 *cp;
  14360.  char                 *nndyna;
  14361.  char                 *nndyna_slice;
  14362.  Bool                  retval;
  14363.  Bool                  is_max;
  14364.  char                  savechar;
  14365.  char                  zverb    [9];
  14366.  char                  zscrolla [9];
  14367.  char                  zcmd    [81];
  14368.  
  14369.  retval = TRUE;
  14370.  
  14371.  if (np->new_newsgroup_count == 0) return TRUE;
  14372.  
  14373.  /* Allocate a block of "nndynarea" new-newsgroup structures. */
  14374.  
  14375.  GETMAIN(nndynarea_address, struct nndynarea,
  14376.          np->new_newsgroup_count,"nndynarea");
  14377.  
  14378.  if (!nndynarea_address) return FALSE;
  14379.  
  14380.  nndynarea_length = np->new_newsgroup_count * sizeof(struct nndynarea);
  14381.  
  14382.  dp = nndynarea_address;
  14383.  for (i = 0, gp = np->first_newsgroup; gp; gp = gp->next) {
  14384.    if (NewGroup(gp)) {  /* if new newsgroup */
  14385.      dp->newsgroup = gp;
  14386.      strcpy(dp->name,gp->name);
  14387.      dp->count = gp->article_count;
  14388.      dp++;
  14389.      i++;
  14390.    }
  14391.  }
  14392.  
  14393.  if (i != np->new_newsgroup_count) {
  14394.    fprintf(stderr,
  14395.            "Possible news server bug: %d new groups but %d NEWGROUPS\n",
  14396.            i, np->new_newsgroup_count);
  14397.  }
  14398.  
  14399.  /* Preinitialize all newsgroups to unsubscribed. */
  14400.  
  14401.  for (dp = nndynarea_address; i > 0; dp++, i--) {
  14402.    gp = dp->newsgroup;
  14403.    gp->registered = 0;
  14404.    OffNewGroup(gp);
  14405.    dp->sel_attr   = DATAIN_HIGH;
  14406.    dp->sel_field  = ' ';
  14407.    dp->name_attr  = DATAOUT_LOW; /* since all unregistered init'ly */
  14408.    dp->count_attr = DATAOUT_LOW;
  14409.  }
  14410.  
  14411.  /* Display new newsgroups in dynamic area panel. */
  14412.  
  14413.  (void)NNMispf(np,
  14414.        "PQUERY PANEL(NNMDNEWG) AREANAME(NNDYNA) DEPTH(NNDEPTH)");
  14415.  if (np->ispfrc != 0) return FALSE;
  14416.  depth = NNMiget(np,"NNDEPTH ");
  14417.  depthx80 = depth * 80;
  14418.  topoff  = 0;
  14419.  dynsize = 80*(np->new_newsgroup_count + depth) + 1;
  14420.  
  14421.  GETMAIN(nndyna, char, dynsize+1, "NNDYNA buffer");
  14422.  if (!nndyna) return FALSE;
  14423.  memset(nndyna,' ',dynsize);
  14424.  
  14425.  for (i = 0, cp=nndyna; i < np->new_newsgroup_count; i++, cp+=80) {
  14426.    dp = &nndynarea_address[i];
  14427.    memset(cp,' ',80);
  14428.    cp[ 0] = dp->sel_attr;
  14429.    cp[ 1] = dp->sel_field;
  14430.    cp[ 2] = dp->name_attr;
  14431.    memcpy(&cp[3],dp->name,strlen(dp->name));
  14432.    if (!just_new_groups) {
  14433.      cp[62] = dp->count_attr;
  14434.      sprintf(&cp[63],"%7d article%c",dp->count,
  14435.                                      dp->count == 1 ? ' ' : 's');
  14436.      cp[79] = ' ';
  14437.    }
  14438.  }
  14439.  
  14440.  (void)NNMivput(np,"NNDN1ST ","YES",-1);
  14441.  
  14442.  do {
  14443.    (void)NNMivput(np,"ZCMD ","",-1);
  14444.    (void)NNMivput(np,"NNDYNA ",nndyna+topoff*80,depthx80);
  14445.    prc = NNMdispl(np,"NNMDNEWG");
  14446.    if (prc > 8) break;
  14447.    (void)NNMivget(np,"ZCMD ",zcmd,sizeof(zcmd));
  14448.    if (zcmd[0] == 'Q'    /* QUIT   */
  14449.     || zcmd[0] == 'C') { /* CANCEL */
  14450.      retval = FALSE;
  14451.      break;
  14452.    }
  14453.    nnlvl = NNMiget(np,"NNLVL ");
  14454.    nndyna_slice = nndyna + topoff*80;
  14455.    savechar = nndyna_slice[depthx80];
  14456.    (void)NNMivget(np,"NNDYNA ",nndyna_slice,depthx80);
  14457.    nndyna_slice[depthx80] = savechar;
  14458.    for (i = 0, cp=nndyna_slice; i < nnlvl; i++, cp+=80) {
  14459.      if (i+topoff >= np->new_newsgroup_count) break;
  14460.      dp = &nndynarea_address[i+topoff];
  14461.      gp = dp->newsgroup;
  14462.      dp->sel_field = ' ';
  14463.      switch (cp[1]) {
  14464.        case 'r':
  14465.        case 'R': gp->registered = 1;
  14466.                  cp[1] = ' ';
  14467.                  cp[2] = DATAOUT_HIGH;
  14468.                  break;
  14469.        case 'd':
  14470.        case 'D': gp->registered = 0;
  14471.                  cp[1] = ' ';
  14472.                  cp[2] = DATAOUT_LOW;
  14473.                  break;
  14474.        case 'q':
  14475.        case 'Q': NNMqng(np,gp);
  14476.                  cp[1] = ' ';
  14477.                  break;
  14478.        case ' ': break;
  14479.        default:
  14480.                  cp[1] = '?';
  14481.                  cp[2] = DATAOUT_LOW;
  14482.                  break;
  14483.      }
  14484.    }
  14485.    (void)NNMivget(np,"ZVERB ",zverb,sizeof(zverb));
  14486.    (void)NNMivget(np,"ZSCROLLA ",zscrolla,sizeof(zscrolla));
  14487.    zscrolln = NNMiget(np,"ZSCROLLN ");
  14488.    is_max = EQUAL(zscrolla,"MAX");
  14489.    if      (EQUAL(zverb,"DOWN")) {
  14490.      if (is_max) topoff = np->new_newsgroup_count - nnlvl;
  14491.      else        topoff += zscrolln;
  14492.    }
  14493.    else if (EQUAL(zverb,"UP")) {
  14494.      if (is_max) topoff = 0;
  14495.      else        topoff -= zscrolln;
  14496.    }
  14497.    if (topoff < 0)
  14498.        topoff = 0;
  14499.    if (topoff > np->new_newsgroup_count)
  14500.        topoff = np->new_newsgroup_count;
  14501.  
  14502.  } while (prc == 0);
  14503.  
  14504.  FREEMAIN(nndyna,"NNDYNA buffer");
  14505.  FREEMAIN(nndynarea_address,"nndynarea");
  14506.  
  14507.  return retval;
  14508. }
  14509.  
  14510. /****** Display bogus newsgroups. ************************************/
  14511.  
  14512. static Bool
  14513. display_bogus_newsgroups(np)
  14514. Rstruc nncb           *np;
  14515. {
  14516.  Rstruc newsgroup     *gp;
  14517.  Rstruc nndynarea     *dp;
  14518.  struct nndynarea     *nndynarea_address;
  14519.  int                   nndynarea_length;
  14520.  int                   i;
  14521.  int                   prc;
  14522.  int                   nnlvl;
  14523.  int                   depth;
  14524.  int                   depthx80;
  14525.  int                   zscrolln;
  14526.  int                   topoff;
  14527.  int                   dynsize;
  14528.  int                   bogus_newsgroup_count;
  14529.  char                 *cp;
  14530.  char                 *k;
  14531.  char                 *nndyna;
  14532.  char                 *nndyna_slice;
  14533.  Bool                  retval;
  14534.  Bool                  is_max;
  14535.  char                  savechar;
  14536.  char                  zverb    [9];
  14537.  char                  zscrolla [9];
  14538.  char                  zcmd    [81];
  14539.  
  14540.  retval = TRUE;
  14541.  
  14542.  bogus_newsgroup_count = 0;
  14543.  
  14544.  for (gp = np->first_newsgroup; gp; gp = gp->next) {
  14545.    if (BogusGroup(gp)) bogus_newsgroup_count++;
  14546.  }
  14547.  
  14548.  if (bogus_newsgroup_count == 0) return TRUE;
  14549.  
  14550.  /* Allocate a block of "nndynarea" new-newsgroup structures. */
  14551.  
  14552.  GETMAIN(nndynarea_address, struct nndynarea,
  14553.          bogus_newsgroup_count,"nndynarea");
  14554.  
  14555.  if (!nndynarea_address) return FALSE;
  14556.  
  14557.  nndynarea_length = bogus_newsgroup_count * sizeof(struct nndynarea);
  14558.  
  14559.  dp = nndynarea_address;
  14560.  for (i = 0, gp = np->first_newsgroup; gp; gp = gp->next) {
  14561.    if (BogusGroup(gp)) {
  14562.      SetNoSuchGroup(gp);
  14563.      OffGroupFromNewsrc(gp);
  14564.      dp->newsgroup = gp;
  14565.      strcpy(dp->name,gp->name);
  14566.      dp++;
  14567.    }
  14568.  }
  14569.  
  14570.  for(dp = nndynarea_address, i=bogus_newsgroup_count; i>0; dp++, i--) {
  14571.    dp->sel_attr   = DATAIN_HIGH;
  14572.    dp->sel_field  = ' ';
  14573.    dp->name_attr  = DATAOUT_LOW; /* since all unregistered init'ly */
  14574.  }
  14575.  
  14576.  /* Display bogus newsgroups in dynamic area panel. */
  14577.  
  14578.  (void)NNMispf(np,
  14579.        "PQUERY PANEL(NNMDBOGG) AREANAME(NNDYNA) DEPTH(NNDEPTH)");
  14580.  if (np->ispfrc != 0) return FALSE;
  14581.  depth = NNMiget(np,"NNDEPTH ");
  14582.  depthx80 = depth * 80;
  14583.  topoff  = 0;
  14584.  dynsize = 80*(bogus_newsgroup_count + depth) + 1;
  14585.  
  14586.  GETMAIN(nndyna, char, dynsize+1, "NNDYNA buffer");
  14587.  if (!nndyna) return FALSE;
  14588.  memset(nndyna,' ',dynsize);
  14589.  
  14590.  for (i = 0, cp=nndyna; i < bogus_newsgroup_count; i++, cp+=80) {
  14591.    dp = &nndynarea_address[i];
  14592.    memset(cp,' ',80);
  14593.    cp[ 0] = dp->sel_attr;
  14594.    cp[ 1] = dp->sel_field;
  14595.    cp[ 2] = dp->name_attr;
  14596.    strncpy(&cp[3],dp->name,67);
  14597.    if ((k=memchr(&cp[3],'\0',67))) *k = ' ';
  14598.    cp[70] = DATAOUT_LOW;
  14599.    memcpy(&cp[71],"         ",9);
  14600.  }
  14601.  
  14602.  (void)NNMivput(np,"NNDB1ST ","YES",-1);
  14603.  
  14604.  do {
  14605.    (void)NNMivput(np,"ZCMD ","",-1);
  14606.    (void)NNMivput(np,"NNDYNA ",nndyna+topoff*80,depthx80);
  14607.    prc = NNMdispl(np,"NNMDBOGG");
  14608.    if (prc > 8) break;
  14609.    (void)NNMivget(np,"ZCMD ",zcmd,sizeof(zcmd));
  14610.    if (zcmd[0] == 'Q'    /* QUIT   */
  14611.     || zcmd[0] == 'C') { /* CANCEL */
  14612.      retval = FALSE;
  14613.      break;
  14614.    }
  14615.    nnlvl = NNMiget(np,"NNLVL ");
  14616.    nndyna_slice = nndyna + topoff*80;
  14617.    savechar = nndyna_slice[depthx80];
  14618.    (void)NNMivget(np,"NNDYNA ",nndyna_slice,depthx80);
  14619.    nndyna_slice[depthx80] = savechar;
  14620.    for (i = 0, cp=nndyna_slice; i < nnlvl; i++, cp+=80) {
  14621.      if (i+topoff >= bogus_newsgroup_count) break;
  14622.      dp = &nndynarea_address[i+topoff];
  14623.      gp = dp->newsgroup;
  14624.      dp->sel_field = ' ';
  14625.      switch (cp[1]) {
  14626.        case 'd':
  14627.        case 'D': SetNoSuchGroup(gp);
  14628.                  OffGroupFromNewsrc(gp);
  14629.                  gp->low_number            = 0;
  14630.                  gp->high_number           = 0;
  14631.                  gp->unread_count          = 0;
  14632.                  gp->article_count         = 0;
  14633.                  gp->registered            = 0;
  14634.                  cp[ 1] = ' ';
  14635.                  cp[ 2] = DATAOUT_LOW;
  14636.                  cp[70] = DATAOUT_HIGH;
  14637.                  memcpy(&cp[71],"Deleted  ",9);
  14638.                  break;
  14639.        case 'k':
  14640.        case 'K': OffNoSuchGroup(gp);
  14641.                  SetGroupFromNewsrc(gp);
  14642.                  gp->low_number            = 0;
  14643.                  gp->high_number           = 0;
  14644.                  gp->unread_count          = 0;
  14645.                  gp->article_count         = 0;
  14646.                  cp[1] = ' ';
  14647.                  cp[70] = DATAOUT_HIGH;
  14648.                  memcpy(&cp[71],"Kept     ",9);
  14649.                  break;
  14650.        case 'q':
  14651.        case 'Q': NNMqng(np,gp);
  14652.                  cp[1] = ' ';
  14653.                  break;
  14654.        case ' ':
  14655.                  cp[1] = ' ';
  14656.                  cp[70] = DATAOUT_LOW;
  14657.                  break;
  14658.        default:
  14659.                  cp[1] = '?';
  14660.                  cp[70] = DATAOUT_HIGH;
  14661.                  memcpy(&cp[71],"What?    ",9);
  14662.                  break;
  14663.      }
  14664.    }
  14665.    (void)NNMivget(np,"ZVERB ",zverb,sizeof(zverb));
  14666.    (void)NNMivget(np,"ZSCROLLA ",zscrolla,sizeof(zscrolla));
  14667.    zscrolln = NNMiget(np,"ZSCROLLN ");
  14668.    is_max = EQUAL(zscrolla,"MAX");
  14669.    if      (EQUAL(zverb,"DOWN")) {
  14670.      if (is_max) topoff = bogus_newsgroup_count - nnlvl;
  14671.      else        topoff += zscrolln;
  14672.    }
  14673.    else if (EQUAL(zverb,"UP")) {
  14674.      if (is_max) topoff = 0;
  14675.      else        topoff -= zscrolln;
  14676.    }
  14677.    if (topoff < 0)
  14678.        topoff = 0;
  14679.    if (topoff > bogus_newsgroup_count)
  14680.        topoff = bogus_newsgroup_count;
  14681.  
  14682.  } while (prc == 0);
  14683.  
  14684.  FREEMAIN(nndyna,"NNDYNA buffer");
  14685.  FREEMAIN(nndynarea_address,"nndynarea");
  14686.  
  14687.  return retval;
  14688. }
  14689.  
  14690. /****** Option.....list all new newsgroups. **************************/
  14691.  
  14692. static Bool
  14693. list_new(np)
  14694. Rstruc nncb *np;
  14695. {
  14696.  char       *lp;
  14697.  char        mmddyy[9];
  14698.  char        hhmmss[9];
  14699.  
  14700.  lp = np->lastNGdate + strspn(np->lastNGdate,"0");
  14701.  if (*lp == '\0') {
  14702.    ERR1(
  14703. "There is no previous date in the NEWSRC file.  Select the List option."
  14704.        );
  14705.    return FALSE;
  14706.  }
  14707.  
  14708.  sprintf(np->nntp_command, "NEWGROUPS %.6s %.6s",
  14709.                            np->lastNGdate, np->lastNGtime);
  14710.  
  14711.  if (!NNMsockt(np)) return FALSE;   /* Send socket command to server */
  14712.  
  14713. #ifdef RECONNECT_AND_MAYBE_DESTROY_NEWSRC
  14714.  
  14715.  np->dont_reconnect = TRUE;         /* this is where DDI wanted it */
  14716.  
  14717. #endif
  14718.  
  14719.  sprintf(mmddyy,"%2.2s/%2.2s/%2.2s",
  14720.          &np->lastNGdate[2], &np->lastNGdate[4], &np->lastNGdate[0]);
  14721.  sprintf(hhmmss,"%2.2s:%2.2s:%2.2s",
  14722.          &np->lastNGtime[0], &np->lastNGtime[2], &np->lastNGtime[4]);
  14723.  
  14724.  if (np->update_adding_newsgroups) {
  14725.    if (!np->batch_mode) {
  14726.      (void)NNMivput(np,"NNNGDT ",mmddyy,-1);
  14727.      (void)NNMivput(np,"NNNGTM ",hhmmss,-1);
  14728.      (void)NNMispf(np,"CONTROL DISPLAY LOCK");
  14729.      (void)NNMispf(np,"DISPLAY PANEL(NNMLNEWG)");
  14730.    }
  14731.  }
  14732.  
  14733.  if (!NNMgsrvl(np,&lp))             return FALSE; /* Get server line */
  14734.  if (np->nntp_message_num != 231)   NNMrperr(np);
  14735.  
  14736.  if (!collect_newsgroups(np,TRUE)) return FALSE;
  14737.  
  14738.  if (np->batch_mode) return TRUE;
  14739.  
  14740.  if (!display_new_newsgroups(np,TRUE)) return FALSE;
  14741.  
  14742.  set_date_and_time(np);
  14743.  
  14744.  if (np->new_newsgroup_count == 0) {
  14745.    ERR3(
  14746. "No new newsgroups since last use of L or N option, on %s %s",
  14747.         mmddyy, hhmmss);
  14748.    return FALSE;
  14749.  }
  14750.  
  14751.  return TRUE;
  14752. }
  14753.  
  14754. /****** Option.....list all known newsgroups. ************************/
  14755.  
  14756. static Bool
  14757. list_all(np,just_rescan)
  14758. Rstruc nncb *np;
  14759. Fool         just_rescan;
  14760. {
  14761.  char       *lp;
  14762.  
  14763.  strcpy(np->nntp_command,"LIST");
  14764.  if (!NNMsockt(np)) return FALSE;   /* Send socket command to server */
  14765.  
  14766.  if (!np->batch_mode) {
  14767.    (void)NNMispf(np,"CONTROL DISPLAY LOCK");
  14768.    (void)NNMispf(np,"DISPLAY PANEL(NNMLLIST)");
  14769.  }
  14770.  
  14771.  if (!NNMgsrvl(np,&lp))             return FALSE; /* Get server line */
  14772.  if (np->nntp_message_num != 215)   NNMrperr(np);
  14773.  
  14774.  if (!collect_newsgroups(np,FALSE)) return FALSE;
  14775.  
  14776.  if (np->batch_mode) return TRUE;
  14777.  
  14778.  if (!display_new_newsgroups(np,FALSE)) return FALSE;
  14779.  
  14780.  if (!display_bogus_newsgroups(np)) return FALSE;
  14781.  
  14782.  set_date_and_time(np);
  14783.  
  14784.  np->new_newsgroup_count = 0;
  14785.  
  14786.  if (just_rescan) return TRUE;
  14787.  
  14788.  np->show_all_newsgroups = TRUE;
  14789.  
  14790.  return NNMvng(np);                           /* View newsgroups */
  14791. }
  14792.  
  14793. /****** Fake disconnect. ********************************************/
  14794.  
  14795. static void
  14796. fake_disconnect(np)
  14797. Rstruc nncb         *np;
  14798. {
  14799.  char               *dummy = "503 Simulated disconnect.";
  14800.  int                 index;
  14801.  
  14802.  /* fake a disconnect condition by sending an NNTP "QUIT".
  14803.   * The next attempt to communicate with the socket will get
  14804.   * the simulated response instead of what it expected.
  14805.   */
  14806.  
  14807.  strcpy(np->nntp_command,"QUIT");
  14808.  if (!NNMsockt(np)) return;        /* Send socket command to server */
  14809.  
  14810.  index = strlen(dummy);
  14811.  strcpy(np->g_buf+1,dummy);
  14812.  np->g_buf[index+1] = CARRIAGE_RETURN;
  14813.  np->g_buf[index+2] = LINE_FEED;
  14814.  np->g_bytes_returned = index+3;
  14815.  np->g_buf_index = 0;
  14816.  
  14817.  return;
  14818. }
  14819.  
  14820. /****** List all or new groups. **************************************/
  14821.  
  14822. Bool
  14823. NNMdlang(np,option)
  14824. Rstruc nncb      *np;
  14825. enum list_option  option;
  14826. {
  14827.  
  14828. #ifndef RECONNECT_AND_MAYBE_DESTROY_NEWSRC
  14829.  
  14830.  /* Since an attempt to reconnect while reading data from the server
  14831.   * will leave the news reader in an inconsistent state and possibly
  14832.   * lead to destroyed newsrc file, we suppress all attempts to do an
  14833.   * automatic reconnection while this is in progress.
  14834.   */
  14835.  
  14836.  if (option != LIST_ALL_RESCAN) {
  14837.    np->dont_reconnect = TRUE;
  14838.  }
  14839.  
  14840. #endif
  14841.  
  14842.  switch (option) {
  14843.    case LIST_ALL:            return list_all(np,FALSE);
  14844.    case LIST_NEW:            return list_new(np);
  14845.    case LIST_ALL_RESCAN:     return list_all(np,TRUE);
  14846.    case LIST_ALL_DISCONNECT: fake_disconnect(np);
  14847.                              return list_all(np,FALSE);
  14848.  }
  14849.  
  14850.  np->dont_reconnect = FALSE;
  14851.  
  14852. }
  14853.  
  14854. ./ ADD NAME=NNMDMAIL
  14855.  
  14856.  /********************************************************************/
  14857.  /*                                                                  */
  14858.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  14859.  /*                                                                  */
  14860.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  14861.  /*                                                                  */
  14862.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  14863.  /* including the implied warranties of merchantability and fitness, */
  14864.  /* are expressly denied.                                            */
  14865.  /*                                                                  */
  14866.  /* Provided this copyright notice is included, this software may    */
  14867.  /* be freely distributed and not offered for sale.                  */
  14868.  /*                                                                  */
  14869.  /* Changes or modifications may be made and used only by the maker  */
  14870.  /* of same, and not further distributed.  Such modifications should */
  14871.  /* be mailed to the author for consideration for addition to the    */
  14872.  /* software and incorporation in subsequent releases.               */
  14873.  /*                                                                  */
  14874.  /********************************************************************/
  14875.  
  14876. #pragma  csect(code,  "NN@DMAIL")
  14877. #pragma  csect(static,"NN$DMAIL")
  14878. #include "nn.h"
  14879.  
  14880. #define TO_LENGTH          256-sizeof("To: ")
  14881. #define SUBJECT_LENGTH     256-sizeof("Subject: ")
  14882. #define FROM_LENGTH        256-sizeof("From: ")
  14883. #define REPLY_TO_LENGTH    256-sizeof("Reply-to: ")
  14884.  
  14885. /****** Determine to whom to reply, according to RFC822 standards ****/
  14886.  
  14887. static char *
  14888. to_whom_to_reply(np,ap)
  14889. Rstruc nncb          *np;
  14890. Rstruc newsarticle   *ap;
  14891. {
  14892.  struct textline     *tp;
  14893.  struct texthdr      *thp;
  14894.  char                *cp;
  14895.  char                *colonp;
  14896.  char                *resent_reply_to    = NULL;
  14897.  char                *resent_from        = NULL;
  14898.  char                *reply_to           = NULL;
  14899.  char                *from               = NULL;
  14900.  char                *resent_sender      = NULL;
  14901.  char                *sender             = NULL;
  14902.  int                  header_index;
  14903.  char                 the_header[INTERNET_SIZE];
  14904.  
  14905.  if (!ap) return "";
  14906.  
  14907.  /* Since RFC1036 (Standard for Interchange of USENET Messages)
  14908.   * seems to imply that RFC822 header format is OK, we would
  14909.   * expect to do this.  In reality, headers like Reply-to: are
  14910.   * often filled with the name of the mailing list (e.g. BITNET).
  14911.   * Therefore, the user needs to have the option of using
  14912.   * the From: header for replies.  Anyhow...
  14913.   */
  14914.  
  14915.  /* Grovel through headers looking for likely candidates.  The official
  14916.   * pecking order is:
  14917.   *
  14918.   * Resent-Reply-To:
  14919.   * Resent-From:
  14920.   * Reply-To:
  14921.   * From:
  14922.   * Resent-Sender:
  14923.   * Sender:
  14924.   *
  14925.   * If none of the above, punt by returning a null string.
  14926.   *
  14927.   * NOTE: There is no provision in this code for continued headers.
  14928.   *       If you want to handle continued headers, use the code in
  14929.   *       NNMDPOST as a model.  You will have to allocate your own
  14930.   *       storage to hold 'em.
  14931.   */
  14932.  
  14933.  thp = &ap->thdr;
  14934.  strcpy(the_header,"");
  14935.  for (tp=thp->first_text_line; tp; tp=tp->next) {
  14936.    if (tp->text[0] == '\0') break;
  14937.    if (tp->text[0] == ' '
  14938.     || tp->text[0] == '\t') {
  14939.      cp = skip_whitespace(tp->text);
  14940.      if (*cp == '\0') break;
  14941.    }
  14942.    else {
  14943.      header_index = 0;
  14944.      colonp = strchr(tp->text,':');
  14945.      if (!colonp) break;
  14946.      strcpy(the_header,"");
  14947.      for (cp = tp->text;cp<colonp;cp++) {
  14948.        the_header[header_index++] = toupper(*cp);
  14949.      }
  14950.      the_header[header_index] = '\0';
  14951.    }
  14952.    cp = skip_whitespace(colonp+1);
  14953.  
  14954.    if      (!strcmp(the_header,"RESENT-REPLY-TO")) resent_reply_to = cp;
  14955.    else if (!strcmp(the_header,"RESENT-FROM"    )) resent_from     = cp;
  14956.    else if (!strcmp(the_header,"REPLY-TO"       )) reply_to        = cp;
  14957.    else if (!strcmp(the_header,"FROM"           )) from            = cp;
  14958.    else if (!strcmp(the_header,"RESENT-SENDER"  )) resent_sender   = cp;
  14959.    else if (!strcmp(the_header,"SENDER"         )) sender          = cp;
  14960.  }
  14961.  
  14962.  return (resent_reply_to ? resent_reply_to :
  14963.          resent_from     ? resent_from     :
  14964.          reply_to        ? reply_to        :
  14965.          from            ? from            :
  14966.          resent_sender   ? resent_sender   :
  14967.          sender          ? sender          :
  14968.          "");
  14969.  
  14970. }
  14971.  
  14972. /****** Reply to a news article by mail, or just mail a message ******/
  14973.  
  14974. void
  14975. NNMdmail(np,gp,ap)
  14976. Rstruc nncb         *np;
  14977. Rstruc newsgroup    *gp;
  14978. Rstruc newsarticle  *ap;
  14979. {
  14980.  Bool                filled       = FALSE;
  14981.  Bool                edit_error   = FALSE;
  14982.  Bool                mail_error   = FALSE;
  14983.  int                 l;
  14984.  int                 display_rc;
  14985.  FILE               *efp          = NULL;
  14986.  FILE               *mfp          = NULL;
  14987.  FILE               *sfp          = NULL;
  14988.  struct tm          *now;
  14989.  char               *cp;
  14990.  time_t              ltime;
  14991.  char                datestr [64];
  14992.  char                midstr  [64];
  14993.  char                zuser   [ 9];
  14994.  char                tempdsn [L_tmpnam];
  14995.  char                outpdsn [L_tmpnam];
  14996.  char                editstr [40+L_tmpnam];
  14997.  char                edit_profile     [  9];
  14998.  char                signature_file   [ 64];
  14999.  char                mail_message_id  [128];
  15000.  char                zcmd             [ 81];
  15001.  char                nnmailfr         [FROM_LENGTH];
  15002.  char                nnmailrt         [REPLY_TO_LENGTH];
  15003.  char                mail_from        [FROM_LENGTH];
  15004.  char                mail_to          [TO_LENGTH];
  15005.  char                mail_subject     [SUBJECT_LENGTH];
  15006.  char                mailline         [260];
  15007.  char                sigline          [260];
  15008.  char                mail_command     [260];
  15009.  
  15010.  (void)NNMivget(np,"ZUSER ",zuser,sizeof(zuser));
  15011.  
  15012.  if (ap) {
  15013.    if (strlen(ap->subject) >= 3 &&
  15014.        (!memcmp(ap->subject,"Re:",3) ||
  15015.         !memcmp(ap->subject,"re:",3) ||
  15016.         !memcmp(ap->subject,"RE:",3)))   strcpy(mail_subject,"");
  15017.    else                                  strcpy(mail_subject,"Re: ");
  15018.    strncat(mail_subject, ap->subject, sizeof(mail_subject));
  15019.  }
  15020.  else strcpy(mail_subject,"");
  15021.  
  15022.  (void)NNMivput(np,"NNMAILTO ",to_whom_to_reply(np,ap),-1);
  15023.  (void)NNMivput(np,"NNMAILOT ",(ap ? ap->from : "")   ,-1);
  15024.  (void)NNMivput(np,"NNMAILSJ ",mail_subject,-1);
  15025.  
  15026.  strcpy(outpdsn,"");
  15027.  
  15028.  /* Can't use this - C/370 compiler bug... */
  15029.  /* strcpy(tempdsn,ap ? "" : np->maildsn); */
  15030.  
  15031.  if (ap) strcpy(tempdsn,"");
  15032.  else    strcpy(tempdsn,np->maildsn);
  15033.  
  15034.  if (!*tempdsn) {
  15035.    if (!tmpnam(tempdsn)) {
  15036.      ERR1(
  15037. "A temporary data set name could not be created.  tmpnam() error.");
  15038.      return;
  15039.    }
  15040.    if (!(efp = OPEN_TEXT_FILE_FOR_WRITE(tempdsn))) {
  15041.      ERR2("Error trying to open temp data set: %s", tempdsn);
  15042.      return;
  15043.    }
  15044.    if (fclose(efp) < 0) {
  15045.      ERR2("Error trying to close temp data set: %s", tempdsn);
  15046.      return;
  15047.    }
  15048.    efp = NULL;
  15049.    if (!ap) strcpy(np->maildsn,tempdsn);
  15050.  }
  15051.  
  15052.  while (NNMdispl(np,"NNMQMAIL") == 0) {
  15053.  
  15054.    NNMivget(np,"NNMAILTO ",mail_to,        sizeof(mail_to)        );
  15055.    NNMivget(np,"NNMAILSJ ",mail_subject,   sizeof(mail_subject)   );
  15056.    NNMivget(np,"NNMAILRT ",nnmailrt,       sizeof(nnmailrt)       );
  15057.    NNMivget(np,"NNMAILFR ",nnmailfr,       sizeof(nnmailfr)       );
  15058.    NNMivget(np,"NNMAILSF ",signature_file, sizeof(signature_file) );
  15059.    NNMivget(np,"NNEDPROF ",edit_profile,   sizeof(edit_profile)   );
  15060.  
  15061.    (void)NNMivput(np,"NNTEMPDS ",tempdsn,-1);
  15062.  
  15063.    /* Insure that we can access the signature file, if given. */
  15064.  
  15065.    if (*signature_file) {
  15066.      if (!(sfp=fopen(signature_file,"r"))) {
  15067.        perror(signature_file);
  15068.        ERR2("Cannot open signature file %s.  Check that it is valid.",
  15069.              signature_file);
  15070.        continue;
  15071.      }
  15072.    }
  15073.    else sfp = NULL;
  15074.  
  15075.    /* Fill temporary data set with message to which we are replying,
  15076.     * if this is a REPLY request,
  15077.     * and the contents of the signature file if any.
  15078.     */
  15079.  
  15080.    if (!filled) {
  15081.      if (!(efp = OPEN_TEXT_FILE_FOR_WRITE(tempdsn))) {
  15082.        ERR2("Error trying to open temp data set: %s", tempdsn);
  15083.        continue;
  15084.      }
  15085.      if (ap) {
  15086.        np->extract_file            = efp;
  15087.        np->extract_appending       = FALSE;
  15088.        np->extract_separator_line  = FALSE;
  15089.        np->extract_tab_expanding   = TRUE;
  15090.        np->following_up            = TRUE;
  15091.        fprintf(efp, "In article %s,\n%s writes:\n\n",
  15092.                     ap->message_id, ap->from);
  15093.        (void)NNMxtx(np,ap,FALSE);            /* Extract article text */
  15094.        np->following_up            = FALSE;
  15095.        if (ferror(efp)) {
  15096.          ERR2("Error trying to write to temp data set: %s", tempdsn);
  15097.          continue;
  15098.        }
  15099.      }
  15100.  
  15101.      if (sfp) {
  15102.        fprintf(efp,"\n-- \n",efp);
  15103.        if (ferror(efp)) np->extract_write_error = TRUE;
  15104.        for (;;) {
  15105.          fgets(sigline,sizeof(sigline),sfp);
  15106.          if (ferror(sfp)) {
  15107.            ERR2(
  15108.   "Cannot read from signature file %s.  Check that it is valid.",
  15109.                 signature_file);
  15110.            break;
  15111.          }
  15112.          if (feof(sfp)) break;
  15113.          if ((cp=strchr(sigline,'\n'))) *cp = '\0';
  15114.          l = strlen(sigline);
  15115.          fwrite(sigline,(l>251 ? 251 : l),1,efp);
  15116.          if (ferror(efp)) {
  15117.            np->extract_write_error = TRUE; break;
  15118.          }
  15119.          if (fputc('\n',efp) == EOF) {
  15120.            np->extract_write_error = TRUE; break;
  15121.          }
  15122.        }
  15123.        (void)fclose(sfp);
  15124.        if (ferror(efp)) {
  15125.          ERR2("Error trying to write to temp data set: %s", tempdsn);
  15126.          continue;
  15127.        }
  15128.      }
  15129.      if (fclose(efp) < 0) {
  15130.        ERR2("Error trying to close temp data set: %s", tempdsn);
  15131.        continue;
  15132.      }
  15133.      filled = TRUE;
  15134.    }
  15135.  
  15136.    efp = NULL;
  15137.  
  15138. #ifndef I370
  15139.    sprintf(editstr,"EDIT DATASET(%s) PROFILE(%s)",tempdsn,edit_profile);
  15140. #else
  15141.    sprintf(editstr, "EDIT DATASET('%s') PROFILE(%s)",
  15142.            tempdsn+4, edit_profile);
  15143. #endif
  15144.  
  15145.    edit_error = FALSE;
  15146.  
  15147.    (void)NNMispf(np,editstr);
  15148.    switch (np->ispfrc) {
  15149.      case 0:  edit_error = FALSE;            break;
  15150.      case 4:  ERR1(
  15151. "Edit ended without SAVE, mailing cancelled.  Reenter and SAVE to mail."
  15152.                   );                         continue;
  15153.      default: edit_error = TRUE;             break;
  15154.    }
  15155.  
  15156.    if (edit_error) continue;
  15157.  
  15158.    /* Confirm mailing. */
  15159.  
  15160.    (void)NNMispf (np,"ADDPOP ");
  15161.    display_rc = NNMdispl(np,"NNMPCONM");
  15162.    (void)NNMispf (np,"REMPOP ");
  15163.    (void)NNMivget(np,"ZCMD ",zcmd,sizeof(zcmd));
  15164.    if (display_rc > 0) continue;
  15165.    if (*zcmd == 'c' || *zcmd == 'C') {
  15166.      (void)NNMivput(np,"ZCMD ","",-1);
  15167.      ERR1("Mailing cancelled by user.  Reenter EDIT and SAVE to mail.");
  15168.      return;
  15169.    }
  15170.  
  15171.    if (!(efp = fopen(tempdsn,"r"))) {
  15172.      ERR2("Error trying to open temp data set: %s", tempdsn);
  15173.      continue;
  15174.    }
  15175.  
  15176.    /* Get current date and time, and generate a message id from it.
  15177.     * If the message id is a duplicate, loop around until it isn't.
  15178.     */
  15179.  
  15180.    do {
  15181.  
  15182.      time(<ime);
  15183.      now = localtime(<ime);
  15184.      strftime(datestr,sizeof(datestr)-1,"%a, %d %b %Y %H:%M %Z",now);
  15185.      strftime(midstr, sizeof(midstr)-1, "%Y%m%d%H%M%S",         now);
  15186.  
  15187.      sprintf(mail_message_id,"<%s%s@%s>",
  15188.                              midstr, zuser, np->client_hostname);
  15189.  
  15190.    } while (EQUAL(mail_message_id,np->messageid));
  15191.  
  15192.    strcpy(np->messageid,mail_message_id);
  15193.  
  15194.    if (!*outpdsn) {
  15195.      if (!tmpnam(outpdsn)) {
  15196.      ERR1(
  15197. "A temporary data set name could not be created.  tmpnam() error."
  15198.          );
  15199.        continue;
  15200.      }
  15201.    }
  15202.  
  15203.    if (!(mfp = OPEN_TEXT_FILE_FOR_WRITE(outpdsn))) {
  15204.      ERR2("Error trying to open temp data set: %s", outpdsn);
  15205.      continue;
  15206.    }
  15207.  
  15208.    do {
  15209.  
  15210.      if (*nnmailfr)
  15211.           sprintf(mail_from,"%s@%s (%s)",
  15212.                             zuser, np->client_hostname, nnmailfr);
  15213.      else sprintf(mail_from,"%s@%s",
  15214.                             zuser, np->client_hostname);
  15215.  
  15216.      fprintf(mfp,"From: %s\n",       mail_from);
  15217.      fprintf(mfp,"To: %s\n",         mail_to);
  15218.      fprintf(mfp,"Subject: %s\n",    mail_subject);
  15219.      fprintf(mfp,"Date: %s\n",       datestr);
  15220.      fprintf(mfp,"Message-ID: %s\n", mail_message_id);
  15221.  
  15222.      /* insert optional headers here */
  15223.  
  15224.      if (*nnmailrt) {
  15225.        fprintf(mfp,"Reply-to: %s\n", nnmailrt);
  15226.      }
  15227.  
  15228.      fprintf(mfp,"Sender: MVS NNTP News Reader <%s@%s>\n",
  15229.                  NNMVS_NAME, np->client_hostname);
  15230.  
  15231.      if (ap) {
  15232.     /*
  15233.      * Uncomment this section when a references field in the
  15234.      * newsarticle struct is added.  Will require total recompilation
  15235.      *
  15236.      * if (ap->references)
  15237.      *  sprintf(np->nntp_command,"References: %s %s\n",
  15238.      *          ap->references, ap->message_id);
  15239.      * else
  15240.      */
  15241.        fprintf(mfp,"References: %s\n",ap->message_id);
  15242.      }
  15243.  
  15244.      /* By rights the following should be a null line.
  15245.       * However, C/370 always makes it a single blank anyhow,
  15246.       * and even if it were a null line (as SAS/C does),
  15247.       * UCLA/MAIL would break.  Hence, make it a single blank.
  15248.       */
  15249.  
  15250.      fprintf(mfp," \n");
  15251.  
  15252.      while (!feof(efp) && !ferror(efp)) {
  15253.        fgets(mailline,sizeof(mailline),efp);
  15254.        if (feof(efp)) break;
  15255.        if (ferror(efp)) break;
  15256.        if (*mailline && mailline[l=strlen(mailline)-1] == '\n')
  15257.           mailline[l] = '\0';
  15258.        fprintf(mfp,"%s\n",mailline);
  15259.      }
  15260.  
  15261.      fclose(mfp);
  15262.  
  15263. #ifndef I370
  15264.      sprintf(mail_command,"NNMMAIL %s %s",outpdsn,mail_to);
  15265. #else
  15266.      sprintf(mail_command,"NNMMAIL '%s' %s",outpdsn+4,mail_to);
  15267. #endif
  15268.  
  15269.      if (NNMtso(mail_command) != 0) {
  15270.        ERR1("Mail failed.  Failure trying to send your message.");
  15271.        mail_error = TRUE;
  15272.      }
  15273.  
  15274.      remove(outpdsn);
  15275.  
  15276.      break;
  15277.  
  15278.    } while(FALSE); /* one-time DO so I can break out of it */
  15279.  
  15280.    if (!mail_error) {
  15281.      (void)NNMivput(np,"NNMAILID ",mail_message_id,-1);
  15282.      WARN1("Your mail message has been sent, presumably successfully.");
  15283.      break;
  15284.    }
  15285.  
  15286.  }
  15287.  
  15288.  if (!efp) return;
  15289.  
  15290.  if (ferror(efp)) {
  15291.    ERR2("Error trying to read from temp data set: %s", tempdsn);
  15292.  }
  15293.  
  15294.  if (fclose(efp) < 0) {
  15295.    ERR2("Error trying to close temp data set: %s", tempdsn);
  15296.  }
  15297.  
  15298.  if (ap) {
  15299.    if (remove(tempdsn) < 0) {
  15300.      ERR2("Error trying to delete temp data set: %s", tempdsn);
  15301.    }
  15302.  }
  15303.  
  15304.  return;
  15305. }
  15306.  
  15307. ./ ADD NAME=NNMDMENU
  15308.  
  15309.  /********************************************************************/
  15310.  /*                                                                  */
  15311.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  15312.  /*                                                                  */
  15313.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  15314.  /*                                                                  */
  15315.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  15316.  /* including the implied warranties of merchantability and fitness, */
  15317.  /* are expressly denied.                                            */
  15318.  /*                                                                  */
  15319.  /* Provided this copyright notice is included, this software may    */
  15320.  /* be freely distributed and not offered for sale.                  */
  15321.  /*                                                                  */
  15322.  /* Changes or modifications may be made and used only by the maker  */
  15323.  /* of same, and not further distributed.  Such modifications should */
  15324.  /* be mailed to the author for consideration for addition to the    */
  15325.  /* software and incorporation in subsequent releases.               */
  15326.  /*                                                                  */
  15327.  /********************************************************************/
  15328.  
  15329. #pragma  csect(code,  "NN@DMENU")
  15330. #pragma  csect(static,"NN$DMENU")
  15331. #include "nn.h"
  15332.  
  15333. /****** Report invalid or unsupported selection. *********************/
  15334.  
  15335. static Bool
  15336. display_invalid_selection(np)
  15337. Rstruc nncb *np;
  15338. {
  15339.  ERR1("Your selection is not valid.  Please choose an available one.");
  15340.  return FALSE;
  15341. }
  15342.  
  15343. /****** Option.....set user options. *********************************/
  15344.  
  15345. static Bool
  15346. display_set_options(np)
  15347. Rstruc nncb *np;
  15348. {
  15349.  NNMdsopt(np,NULL);
  15350.  return FALSE;
  15351. }
  15352.  
  15353. /****** Option.....execute NNTP commands. ****************************/
  15354.  
  15355. static Bool
  15356. display_nntp(np)
  15357. Rstruc nncb *np;
  15358. {
  15359.  NNMdnntp(np,NULL);
  15360.  return FALSE;
  15361. }
  15362.  
  15363. /****** Option.....list ALL newsgroups from NEWSRC file. *************/
  15364.  
  15365. static Bool
  15366. display_all_from_newsrc(np)
  15367. Rstruc nncb        *np;
  15368. {
  15369.  
  15370.  if (np->newsgroup_order == NNTP_LIST_ORDER)
  15371.     np->newsgroup_order = ALPHABETICAL_ORDER;
  15372.  np->show_all_newsgroups = TRUE;
  15373.  return NNMvng(np);                           /* View newsgroups */
  15374. }
  15375.  
  15376. /****** Option.....list REGISTERED newsgroups from NEWSRC file. ******/
  15377.  
  15378. static Bool
  15379. display_reg_from_newsrc(np)
  15380. Rstruc nncb        *np;
  15381. {
  15382.  char               nnrgans[4];
  15383.  int                prc;
  15384.  Rstruc newsgroup  *gp;
  15385.  struct countdown   cd;
  15386.  
  15387.  /* Before viewing the newsgroup list, go through all the newsgroups
  15388.   * and get the status of each one by selecting it.
  15389.   * This is controlled by the NNREGNNG variable if an option was
  15390.   * preselected and Y or N was specified for REGISTERSTATUS.
  15391.   */
  15392.  
  15393.  nnrgans[0] = 'P';
  15394.  if (np->preselection) {
  15395.    switch (np->nnregnng[0]) {
  15396.      case 'N': nnrgans[0] = 'N'; break;
  15397.      case 'Y': nnrgans[0] = 'Y'; break;
  15398.    }
  15399.  }
  15400.  
  15401.  if (nnrgans[0] == 'P') {
  15402.  
  15403.    /* Display panel asking if user really wants to do this. */
  15404.  
  15405.    (void)NNMispf(np,"ADDPOP");
  15406.    prc = NNMdispl(np,"NNMPGREG");
  15407.    (void)NNMispf(np,"REMPOP");
  15408.    if (prc > 0) return FALSE;  /* see if user pressed END */
  15409.    (void)NNMivget(np,"NNRGANS ",nnrgans,sizeof(nnrgans));
  15410.  
  15411.  }
  15412.  
  15413.  if (nnrgans[0] == 'Y') {
  15414.    if (np->updatefreq >= 0) {
  15415.      cd.do_update = TRUE;
  15416.      cd.done      = 0;
  15417.      cd.to_do     = 0;
  15418.      for (gp=np->first_newsgroup;gp;gp=gp->next) {
  15419.        if (gp->registered) cd.to_do++;
  15420.      }
  15421.    }
  15422.    for (gp=np->first_newsgroup;gp;gp=gp->next) {
  15423.      if (gp->registered) {
  15424.        if (np->updatefreq >= 0) {
  15425.          (void)NNMivput(np,"NNLGROUP ",gp->name,-1);
  15426.          /*
  15427.           * (void)NNMispf(np,"CONTROL DISPLAY LOCK");
  15428.           * (void)NNMispf(np,"DISPLAY PANEL(NNMLRETG)");
  15429.           */
  15430.          NNMupdt(np,&cd,np->updatefreq > 0 ? "NNMLRET2" : "NNMLRET3");
  15431.        }
  15432.        NNMdng(np,gp,NULL);        /* do newsgroup by address */
  15433.      }
  15434.    }
  15435.  }
  15436.  
  15437.  if (np->newsgroup_order == NNTP_LIST_ORDER)
  15438.     np->newsgroup_order = ALPHABETICAL_ORDER;
  15439.  np->show_all_newsgroups = FALSE;
  15440.  return NNMvng(np);                           /* View newsgroups */
  15441. }
  15442.  
  15443. /****** Option.....list all newsgroups. ******************************/
  15444.  
  15445. static Bool
  15446. list_all_newsgroups(np)
  15447. Rstruc nncb       *np;
  15448. {
  15449.  return NNMdlang(np,LIST_ALL);
  15450. }
  15451.  
  15452. /****** Option.....list all newsgroups with fake disconnect. *********/
  15453.  
  15454. static Bool
  15455. list_all_newsgroups_with_fake_disconnect(np)
  15456. Rstruc nncb       *np;
  15457. {
  15458.  return NNMdlang(np,LIST_ALL_DISCONNECT);
  15459. }
  15460.  
  15461. /****** Option.....list new newsgroups. ******************************/
  15462.  
  15463. static Bool
  15464. list_new_newsgroups(np)
  15465. Rstruc nncb       *np;
  15466. {
  15467.  return NNMdlang(np,LIST_NEW);
  15468. }
  15469.  
  15470. /****** Option.....retrieve articles from specified newsgroup. *******/
  15471.  
  15472. static Bool
  15473. display_specific_newsgroup(np)
  15474. Rstruc nncb       *np;
  15475. {
  15476.  Rstruc newsgroup *gp;
  15477.  
  15478.  np->newsgroup_selected = FALSE;
  15479.  
  15480.  /* The ISPF variable NNGROUPI contains the name of the newsgroup. */
  15481.  
  15482.  if (NNMivget(np,"NNGROUPI ",np->nngroup,sizeof(np->nngroup))) {
  15483.  
  15484.    lowercase_in_place(np->nngroup);
  15485.  
  15486.    (void)NNMivput(np,"NNGROUP ",np->nngroup,-1);
  15487.  
  15488.    gp = NNMdng(np,NULL,np->nngroup);    /* do newsgroup by name */
  15489.    if (!gp) {
  15490.      (void)NNMivput(np,"NNCURSOR ","NNGROUPI ",8);
  15491.      return FALSE;
  15492.    }
  15493.  
  15494.    np->show_all_articles       = TRUE;
  15495.    np->bypass_header_retrieval = FALSE;
  15496.    np->unread_articles_only    = FALSE;
  15497.  
  15498.    (void)NNMvar(np,gp);              /* View articles */
  15499.  }
  15500.  
  15501.  return TRUE;
  15502. }
  15503.  
  15504. /****** Display menu. ************************************************/
  15505.  
  15506. enum display_retval
  15507. NNMdmenu(np,selfunp)
  15508. Rstruc nncb   *np;
  15509. Bool        (**selfunp)();
  15510. {
  15511.  char        zcmd[72];
  15512.  char        new_nnserver[MAXHOSTNAMELEN];
  15513.  Bool        server_changed = FALSE;
  15514.  
  15515.  *selfunp = NULL;
  15516.  
  15517.  if (np->preselection) {
  15518.    zcmd[0] = toupper(np->preselection);
  15519.    np->preselection = SELECTION_EXIT;
  15520.    (void)NNMispf(np,
  15521.                  "VGET (NNSERVER NNNEWSRC NNREGNNG NNGROUPI) PROFILE");
  15522.  }
  15523.  else {
  15524.  
  15525.    (void)NNMispf(np,"CONTROL DISPLAY REFRESH");
  15526.  
  15527.    (void)NNMdispl(np,"NNM     ");
  15528.    if (np->ispfrc > 8) return DISPLAY_FAILURE;
  15529.    if (np->ispfrc > 0) return DISPLAY_EXIT;
  15530.    if (!NNMivget(np,"ZCMD ",zcmd,sizeof(zcmd))) return DISPLAY_ERROR;
  15531.  }
  15532.  
  15533.  if (!NNMivget(np,"NNSERVER ",new_nnserver,MAXHOSTNAMELEN)
  15534.   || !NNMivget(np,"NNREGNNG ",np->nnregnng,sizeof(np->nnregnng))) {
  15535.    np->preselection = '\0';
  15536.    return DISPLAY_ERROR;
  15537.  }
  15538.  
  15539.  /* Note: selection functions return Bool value indicating whether
  15540.   *       to rewrite NEWSRC file (TRUE) or not (FALSE).
  15541.   *       See NNMMAIN for implementation of this.
  15542.   */
  15543.  
  15544.  switch (zcmd[0]) {
  15545.    case SELECTION_ALL:   *selfunp = display_all_from_newsrc;    break;
  15546.    case SELECTION_REG:   *selfunp = display_reg_from_newsrc;    break;
  15547.    case SELECTION_GROUP: *selfunp = display_specific_newsgroup; break;
  15548.    case SELECTION_LIST:  *selfunp = list_all_newsgroups;        break;
  15549.    case SELECTION_NEWG:  *selfunp = list_new_newsgroups;        break;
  15550.    case SELECTION_NNTP:  *selfunp = display_nntp;               break;
  15551.    case SELECTION_OPTS:  *selfunp = display_set_options;        break;
  15552.    case SELECTION_EXIT:  return DISPLAY_EXIT;
  15553.    case SELECTION_LIST_DISCONNECT:
  15554.                  *selfunp = list_all_newsgroups_with_fake_disconnect;
  15555.                  break;
  15556.    default:              *selfunp = display_invalid_selection;
  15557.                          np->preselection = '\0';
  15558.                          return DISPLAY_REPEAT;
  15559.  };
  15560.  
  15561.  /* If user typed a different server name, or this is the first time,
  15562.     connect to the requested server. */
  15563.  
  15564.  if (UNEQUAL(new_nnserver,np->nnserver)) {
  15565.    server_changed = TRUE;
  15566.  }
  15567.  if (!np->connected_to_server || np->connection_broken ||
  15568.      server_changed) {
  15569.    strcpy(np->nnserver,new_nnserver);
  15570.    if (!NNMconn(np)) {                  /* Connect to news server */
  15571.      (void)NNMivput(np,"NNCURSOR ","NNSERVER ",8);
  15572.      *selfunp = NULL;
  15573.      np->preselection = '\0';
  15574.      return DISPLAY_ERROR;
  15575.    }
  15576.  }
  15577.  
  15578.  return DISPLAY_REPEAT;
  15579. }
  15580.  
  15581. ./ ADD NAME=NNMDNG
  15582.  
  15583.  /********************************************************************/
  15584.  /*                                                                  */
  15585.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  15586.  /*                                                                  */
  15587.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  15588.  /*                                                                  */
  15589.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  15590.  /* including the implied warranties of merchantability and fitness, */
  15591.  /* are expressly denied.                                            */
  15592.  /*                                                                  */
  15593.  /* Provided this copyright notice is included, this software may    */
  15594.  /* be freely distributed and not offered for sale.                  */
  15595.  /*                                                                  */
  15596.  /* Changes or modifications may be made and used only by the maker  */
  15597.  /* of same, and not further distributed.  Such modifications should */
  15598.  /* be mailed to the author for consideration for addition to the    */
  15599.  /* software and incorporation in subsequent releases.               */
  15600.  /*                                                                  */
  15601.  /********************************************************************/
  15602.  
  15603. #pragma  csect(code,  "NN@DNG  ")
  15604. #pragma  csect(static,"NN$DNG  ")
  15605. #include "nn.h"
  15606.  
  15607. /****** Process newsgroup by name or address. ************************/
  15608.  
  15609. struct newsgroup *
  15610. NNMdng(np,gp,group)
  15611. Rstruc nncb         *np;
  15612. Rstruc newsgroup    *gp;
  15613. char                *group;
  15614. {
  15615.  int                 group_article_count         = NO_VALUE;
  15616.  int                 group_first_article_number  = NO_VALUE;
  15617.  int                 group_last_article_number   = NO_VALUE;
  15618.  char                group_name[GROUP_NAME_SIZE] = "";
  15619.  
  15620.  /* Tell the server to select the requested newsgroup. */
  15621.  
  15622.  if (!NNMestng(np,gp ? gp->name : group)) /* Establish newsgroup */
  15623.     return NULL;
  15624.  
  15625.  /* From the response to the "GROUP xxx" NNTP selection request,
  15626.     extract the number of articles and the numbers of the
  15627.     first and last articles, as well as the actual name. */
  15628.  
  15629.  if (4 != sscanf(np->nntp_message_text, "%d %d %d %s",
  15630.                               &group_article_count,
  15631.                               &group_first_article_number,
  15632.                               &group_last_article_number,
  15633.                                group_name)) {
  15634.    NNMrbfm(np);   /* Report bad format message */
  15635.    return NULL;
  15636.  }
  15637.  
  15638.  lowercase_in_place(group_name);
  15639.  
  15640.  if (!gp) gp = NNMaddng(np,group_name);   /* Add newsgroup */
  15641.  
  15642.  OffNoSuchGroup(gp);
  15643.  OffGroupError(gp);
  15644.  
  15645.  /* Logic:
  15646.   * This code sets up a newsgroup from NNTP GROUP.
  15647.   * They are already found in .newsrc (unless new newsgroups),
  15648.   * and may or may not have already been LISTed.
  15649.   * So there is a possibility of an article vector existing,
  15650.   * but in most cases there won't be.
  15651.   * The overriding principle here is that the active file knows
  15652.   * best the actual range, but the GROUP command will return
  15653.   * information about missing articles at either end of the list.
  15654.   */
  15655.  
  15656.  if (GroupFromNewsrc(gp)
  15657.   || GroupFromNNTP(gp)) {          /* Adjust unread articles */
  15658.    NNMadjua(np,gp,group_article_count,
  15659.                   group_first_article_number,
  15660.                   group_last_article_number);
  15661.  }
  15662.  else {
  15663.    gp->unread_count = group_article_count;
  15664.  }
  15665.  
  15666.  /* Allocate article vector */
  15667.  
  15668.  NNMallav(np,gp,group_first_article_number,group_last_article_number);
  15669.  
  15670.  gp->article_count = group_article_count;
  15671.  
  15672.  if (gp->article_vector) {
  15673.    if (gp->low_number == 0
  15674.     || gp->low_number > group_first_article_number
  15675.     || !GroupFromNNTP(gp)) {
  15676.        gp->low_number = group_first_article_number;
  15677.    }
  15678.    if (gp->high_number == 0
  15679.     || gp->high_number < group_last_article_number) {
  15680.        gp->high_number = group_last_article_number;
  15681.    }
  15682.  }
  15683.  
  15684.  /*
  15685.   *
  15686.   * Don't know why this was here, but it is causing a bug with
  15687.   * registering new groups, so take it out.
  15688.   *
  15689.   * if (!GroupFromNewsrc(gp)) {
  15690.   *   gp->registered = 0;
  15691.   * }
  15692.   */
  15693.  
  15694.  if (np->show_all_articles) SetGroupSelected(gp);
  15695.  else                       SetGroupSelectedUnread(gp);
  15696.  
  15697.  return gp;
  15698. }
  15699. ./ ADD NAME=NNMDNNTP
  15700.  
  15701.  /********************************************************************/
  15702.  /*                                                                  */
  15703.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  15704.  /*                                                                  */
  15705.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  15706.  /* including the implied warranties of merchantability and fitness, */
  15707.  /* are expressly denied.                                            */
  15708.  /*                                                                  */
  15709.  /* Provided this copyright notice is included, this software may    */
  15710.  /* be freely distributed and not offered for sale.                  */
  15711.  /*                                                                  */
  15712.  /* Changes or modifications may be made and used only by the maker  */
  15713.  /* of same, and not further distributed.  Such modifications should */
  15714.  /* be mailed to the author for consideration for addition to the    */
  15715.  /* software and incorporation in subsequent releases.               */
  15716.  /*                                                                  */
  15717.  /********************************************************************/
  15718.  
  15719. #pragma  csect(code,  "NN@DNNTP")
  15720. #pragma  csect(static,"NN$DNNTP")
  15721. #include "nn.h"
  15722.  
  15723. /****** Option ... process native NNTP protocol commands. ************/
  15724.  
  15725. void
  15726. NNMdnntp(np,command)
  15727. Rstruc nncb *np;
  15728. char        *command;
  15729. {
  15730.  
  15731.  if (command && *command) {
  15732.    strncpy(np->nntp_command, command, CLIENT_BUF_MSGSIZE);
  15733.    NNMnntp(np);                    /* execute NNTP commands */
  15734.  }
  15735.  
  15736.  else while (NNMdispl(np,"NNM0    ") == 0 && !np->quit) {
  15737.  
  15738.    (void)NNMivget(np,"NNCMD ",np->nntp_command,CLIENT_BUF_MSGSIZE);
  15739.    if (np->ispfrc == 0) NNMnntp(np); /* execute NNTP commands */
  15740.  
  15741.    if (np->quit) break;
  15742.  }
  15743.  
  15744.  return;
  15745. }
  15746.  
  15747. ./ ADD NAME=NNMDOIT
  15748.  
  15749.  /********************************************************************/
  15750.  /*                                                                  */
  15751.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  15752.  /*                                                                  */
  15753.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  15754.  /* including the implied warranties of merchantability and fitness, */
  15755.  /* are expressly denied.                                            */
  15756.  /*                                                                  */
  15757.  /* Provided this copyright notice is included, this software may    */
  15758.  /* be freely distributed and not offered for sale.                  */
  15759.  /*                                                                  */
  15760.  /* Changes or modifications may be made and used only by the maker  */
  15761.  /* of same, and not further distributed.  Such modifications should */
  15762.  /* be mailed to the author for consideration for addition to the    */
  15763.  /* software and incorporation in subsequent releases.               */
  15764.  /*                                                                  */
  15765.  /********************************************************************/
  15766.  
  15767. #pragma  csect(code,  "NN@DOIT ")
  15768. #pragma  csect(static,"NN$DOIT ")
  15769. #include "nn.h"
  15770.  
  15771. /****** Do it (whatever it is) to the article. ***********************/
  15772.  
  15773. void
  15774. NNMdoit(np,ap,whatfor)
  15775. Rstruc nncb          *np;
  15776. Rstruc newsarticle   *ap;
  15777. Fool                  whatfor;
  15778. {
  15779.  Rstruc newsgroup    *gp;
  15780.  VARK                *vp;
  15781.  
  15782.  gp = np->current_newsgroup;
  15783.  vp = &GETVARK(gp,ap->number);
  15784.  
  15785.  switch (whatfor) {
  15786.    case 'S':
  15787.             NNMvtx(np,gp,ap);                 /* View text */
  15788.             NNMmarr(np,gp,vp);                /* Make article read */
  15789.             ap->action = READ;
  15790.             break;
  15791.    case 'E':
  15792.             np->extract_write_error = FALSE;
  15793.             np->extract_close_error = FALSE;
  15794.             np->printing            = FALSE;
  15795.             if (NNMxtx(np,ap,TRUE)) {         /* Extract text */
  15796.               if (!np->extract_write_error &&
  15797.                   !np->extract_close_error) {
  15798.                 NNMmarr(np,gp,vp);            /* Make article read */
  15799.                 ap->action = EXTRACTED;
  15800.               }
  15801.             }
  15802.             break;
  15803.    case 'P':
  15804.             np->extract_write_error = FALSE;
  15805.             np->extract_close_error = FALSE;
  15806.             np->printing            = TRUE;
  15807.             if (NNMxtx(np,ap,TRUE)) {         /* Print text */
  15808.               if (!np->extract_write_error &&
  15809.                   !np->extract_close_error) {
  15810.                 NNMmarr(np,gp,vp);            /* Make article read */
  15811.                 ap->action = PRINTED;
  15812.               }
  15813.             }
  15814.             break;
  15815.    case 'F':
  15816.             NNMdpost(np,gp,ap);               /* Post followup */
  15817.             ap->action = RETRIEVED;
  15818.             break;
  15819.    case 'R':
  15820.             NNMdmail(np,gp,ap);               /* Mail reply */
  15821.             ap->action = RETRIEVED;
  15822.             break;
  15823.    case 'C':
  15824.             if (NNMdcan(np,gp,ap)) {          /* Cancel article */
  15825.               ap->action = CANCELLED;
  15826.             }
  15827.             break;
  15828.  }
  15829.  
  15830.  np->top_article = ap->number;
  15831.  np->top_sorted_article = np->current_sortvark;
  15832.  
  15833.  return;
  15834. }
  15835.  
  15836. ./ ADD NAME=NNMDPOST
  15837.  
  15838.  /********************************************************************/
  15839.  /*                                                                  */
  15840.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  15841.  /*                                                                  */
  15842.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  15843.  /*                                                                  */
  15844.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  15845.  /* including the implied warranties of merchantability and fitness, */
  15846.  /* are expressly denied.                                            */
  15847.  /*                                                                  */
  15848.  /* Provided this copyright notice is included, this software may    */
  15849.  /* be freely distributed and not offered for sale.                  */
  15850.  /*                                                                  */
  15851.  /* Changes or modifications may be made and used only by the maker  */
  15852.  /* of same, and not further distributed.  Such modifications should */
  15853.  /* be mailed to the author for consideration for addition to the    */
  15854.  /* software and incorporation in subsequent releases.               */
  15855.  /*                                                                  */
  15856.  /********************************************************************/
  15857.  
  15858. #pragma  csect(code,  "NN@DPOST")
  15859. #pragma  csect(static,"NN$DPOST")
  15860. #include "nn.h"
  15861.  
  15862. #define NEWSGROUPS_LENGTH   256-sizeof("Newsgroups: ")
  15863. #define SUBJECT_LENGTH      256-sizeof("Subject: ")
  15864. #define PATH_LENGTH         256-sizeof("Path: ")
  15865. #define FROM_LENGTH         256-sizeof("From: ")
  15866. #define REPLY_TO_LENGTH     256-sizeof("Reply-to: ")
  15867. #define FOLLOWUP_TO_LENGTH  256-sizeof("Followup-to: ")
  15868.  
  15869. #define HEADCAT(A,B)        strncat((A),(B),NEWSGROUPS_LENGTH)
  15870.  
  15871. #define READER_MUST_GENERATE_PATH
  15872.  
  15873. /****** Make a comma delimited list out of user's newsgroup spec. ****/
  15874.  
  15875. static void
  15876. make_comma_delimited_list(instring,outstring)
  15877. char                *instring;
  15878. char                *outstring;
  15879. {
  15880.  char               *icp;
  15881.  char               *ocp;
  15882.  Bool                between;
  15883.  
  15884.  between = FALSE;
  15885.  icp = instring + strspn(instring," ,");
  15886.  ocp = outstring;
  15887.  do {
  15888.    switch (*icp) {
  15889.      case '\0': *ocp = '\0'; break;
  15890.      case ' ' :
  15891.      case ',' :  between = TRUE; break;
  15892.      default  :  if (between) {
  15893.                    between = FALSE;
  15894.                    *(ocp++) = ',';
  15895.                  }
  15896.                  *(ocp++) = tolower(*icp);
  15897.                  break;
  15898.    }
  15899.  } while (*icp++);
  15900.  
  15901. }
  15902.  
  15903. /****** Collect additional article headers that we may need. *********/
  15904.  
  15905. static void
  15906. get_more_headers(np,ap,newsgroups,followup_to)
  15907. Rstruc nncb          *np;
  15908. Rstruc newsarticle   *ap;
  15909. char                 *newsgroups;
  15910. char                 *followup_to;
  15911. {
  15912.  struct textline     *tp;
  15913.  struct texthdr      *thp;
  15914.  char                *cp;
  15915.  char                *newp;
  15916.  char                *colonp;
  15917.  int                  header_index;
  15918.  char                 the_header[INTERNET_SIZE];
  15919.  
  15920.  strcpy(newsgroups,  "");
  15921.  strcpy(followup_to, "");
  15922.  
  15923.  if (!ap) return;
  15924.  
  15925.  /* Grovel through headers looking for what we want.  */
  15926.  
  15927.  newp = NULL;
  15928.  thp = &ap->thdr;
  15929.  strcpy(the_header,"");
  15930.  for (tp=thp->first_text_line; tp; tp=tp->next) {
  15931.    if (tp->text[0] == '\0') break;
  15932.    if (tp->text[0] == ' '
  15933.     || tp->text[0] == '\t') {
  15934.      cp = skip_whitespace(tp->text);
  15935.      if (*cp == '\0') break;
  15936.    }
  15937.    else {
  15938.      header_index = 0;
  15939.      colonp = strchr(tp->text,':');
  15940.      if (!colonp) break;
  15941.      strcpy(the_header,"");
  15942.      for (cp = tp->text;cp<colonp;cp++) {
  15943.        the_header[header_index++] = toupper(*cp);
  15944.      }
  15945.      the_header[header_index] = '\0';
  15946.      cp = skip_whitespace(colonp+1);
  15947.    }
  15948.    if      (EQUAL(the_header,"NEWSGROUPS"  )) HEADCAT(newsgroups, cp);
  15949.    else if (EQUAL(the_header,"FOLLOWUP-TO" )) HEADCAT(followup_to,cp);
  15950.  }
  15951.  
  15952.  lowercase_and_strip_trailing_in_place(newsgroups);
  15953.  lowercase_and_strip_trailing_in_place(followup_to);
  15954.  
  15955.  return;
  15956.  
  15957. }
  15958.  
  15959. /****** Post a news article. *****************************************/
  15960.  
  15961. void
  15962. NNMdpost(np,gp,ap)
  15963. Rstruc nncb         *np;
  15964. Rstruc newsgroup    *gp;
  15965. Rstruc newsarticle  *ap;
  15966. {
  15967.  Bool                filled       = FALSE;
  15968.  Bool                edit_error   = FALSE;
  15969.  Bool                post_error   = FALSE;
  15970.  int                 l;
  15971.  int                 display_rc;
  15972.  char               *postdefault  = NULL;
  15973.  char               *lp;
  15974.  char               *cp;
  15975.  FILE               *efp          = NULL;
  15976.  FILE               *sfp          = NULL;
  15977.  struct tm          *now;
  15978.  time_t              ltime;
  15979.  char                datestr [64];
  15980.  char                midstr  [64];
  15981.  char                zuser   [ 9];
  15982.  char                temp    [12];
  15983.  char                tempdsn [L_tmpnam];
  15984.  char                editstr [40+L_tmpnam];
  15985.  char                edit_profile     [  9];
  15986.  char                signature_file   [ 64];
  15987.  char                post_message_id  [128];
  15988.  char                zcmd             [ 81];
  15989.  char                post_subject     [SUBJECT_LENGTH];
  15990.  char                post_path        [PATH_LENGTH];
  15991.  char                post_newsgroups  [NEWSGROUPS_LENGTH];
  15992.  char                post_followup_to [NEWSGROUPS_LENGTH];
  15993.  char                post_from        [FROM_LENGTH];
  15994.  char                nnpostng         [NEWSGROUPS_LENGTH];
  15995.  char                nnpostrt         [REPLY_TO_LENGTH];
  15996.  char                nnpostfo         [FOLLOWUP_TO_LENGTH];
  15997.  char                nnpostfr         [FROM_LENGTH];
  15998.  char                newsgroups       [NEWSGROUPS_LENGTH];
  15999.  char                followup_to      [NEWSGROUPS_LENGTH];
  16000.  char                postline         [260];
  16001.  char                sigline          [260];
  16002.  
  16003.  (void)NNMivget(np,"ZUSER ",zuser,sizeof(zuser));
  16004.  
  16005.  if (ap) {
  16006.    if (strlen(ap->subject) >= 3 &&
  16007.        (!memcmp(ap->subject,"Re:",3) ||
  16008.         !memcmp(ap->subject,"re:",3) ||
  16009.         !memcmp(ap->subject,"RE:",3)))   strcpy(post_subject,"");
  16010.    else                                  strcpy(post_subject,"Re: ");
  16011.    strncat(post_subject, ap->subject, sizeof(post_subject));
  16012.  }
  16013.  else strcpy(post_subject,"");
  16014.  
  16015.  sprintf(post_path,"%s!%s", np->client_hostname, zuser);
  16016.  
  16017.  (void)NNMivput(np,"NNPOSTSJ ",post_subject,-1);
  16018.  if (ap) {
  16019.    sprintf(temp,"%d",ap->number);
  16020.    (void)NNMivput(np,"NNPOSTHA ",temp,        -1);
  16021.    (void)NNMivput(np,"NNPOSTHG ",gp->name,    -1);
  16022.  }
  16023.  else {
  16024.    (void)NNMivput(np,"NNPOSTHA ","",          -1);
  16025.    (void)NNMivput(np,"NNPOSTHG ",""          ,-1);
  16026.  }
  16027.  
  16028.  /*
  16029.   * Simple-minded and wrong - newsgroups to post to = current one
  16030.   *
  16031.   * (void)NNMivput(np,"NNPOSTNG ",gp ? gp->name : "",-1);
  16032.   *
  16033.   * The correct way:  if we are following up an article, then
  16034.   * if the Followup_to header is present, use that, else
  16035.   * use the Newsgroups: header.  If not there, use the newsgroup name.
  16036.   *
  16037.   * If fresh post, use the newsgroup name.
  16038.   */
  16039.  
  16040.  if (gp) {
  16041.    if (ap) {  /* this is a followup */
  16042.      strcpy(newsgroups, "");
  16043.      strcpy(followup_to,"");
  16044.      get_more_headers(np,ap,newsgroups,followup_to);
  16045.      if      (EQUAL(followup_to,"poster")) {
  16046.        ERR1(
  16047. "Followups are directed to the poster.  Suggest you use REPLY instead."
  16048.            );
  16049.        postdefault = "";
  16050.      }
  16051.      else if (strchr(followup_to,'@')) {
  16052.        ERR1(
  16053. "Followup header contains mailing address.  Suggest you REPLY instead."
  16054.            );
  16055.        postdefault = "";
  16056.      }
  16057.      else if (*followup_to)  postdefault = followup_to;
  16058.      else if (*newsgroups)   postdefault = newsgroups;
  16059.      else                    postdefault = gp->name;
  16060.    }
  16061.    else {     /* this is a fresh posting */
  16062.      postdefault = gp->name;
  16063.    }
  16064.  }
  16065.  else {
  16066.    postdefault = "";
  16067.  }
  16068.  
  16069.  (void)NNMivput(np,"NNPOSTNG ",postdefault,-1);
  16070.  
  16071.  /* Can't use this - C/370 compiler bug... */
  16072.  /* strcpy(tempdsn,ap ? "" : np->maildsn); */
  16073.  
  16074.  if (ap) strcpy(tempdsn,"");
  16075.  else    strcpy(tempdsn,np->maildsn);
  16076.  
  16077.  if (!*tempdsn) {
  16078.    if (!tmpnam(tempdsn)) {
  16079.      ERR1(
  16080. "A temporary data set name could not be created.  tmpnam() error."
  16081.          );
  16082.      return;
  16083.    }
  16084.    if (!(efp = OPEN_TEXT_FILE_FOR_WRITE(tempdsn))) {
  16085.      ERR2("Error trying to open temp data set: %s", tempdsn);
  16086.      return;
  16087.    }
  16088.    if (fclose(efp) < 0) {
  16089.      ERR2("Error trying to close temp data set: %s", tempdsn);
  16090.      return;
  16091.    }
  16092.    efp = NULL;
  16093.    if (!ap) strcpy(np->maildsn,tempdsn);
  16094.  }
  16095.  
  16096.  while (NNMdispl(np,"NNMQPOST") == 0) {
  16097.  
  16098.    NNMivget(np,"NNPOSTNG ",nnpostng,       sizeof(nnpostng));
  16099.    NNMivget(np,"NNPOSTRT ",nnpostrt,       sizeof(nnpostrt));
  16100.    NNMivget(np,"NNPOSTFO ",nnpostfo,       sizeof(nnpostfo));
  16101.    NNMivget(np,"NNPOSTFR ",nnpostfr,       sizeof(nnpostfr));
  16102.    NNMivget(np,"NNPOSTSJ ",post_subject,   sizeof(post_subject)   );
  16103.    NNMivget(np,"NNPOSTSF ",signature_file, sizeof(signature_file) );
  16104.    NNMivget(np,"NNEDPROF ",edit_profile,   sizeof(edit_profile)   );
  16105.  
  16106.    /* Create correctly formatted newsgroup listing. */
  16107.  
  16108.    make_comma_delimited_list(nnpostng,post_newsgroups);
  16109.  
  16110.    make_comma_delimited_list(nnpostfo,post_followup_to);
  16111.  
  16112.    (void)NNMivput(np,"NNTEMPDS ",tempdsn,-1);
  16113.  
  16114.    /* Insure that we can access the signature file, if given. */
  16115.  
  16116.    if (*signature_file) {
  16117.      if (!(sfp=fopen(signature_file,"r"))) {
  16118.        perror(signature_file);
  16119.        ERR2("Cannot open signature file %s.  Check that it is valid.",
  16120.              signature_file);
  16121.        continue;
  16122.      }
  16123.    }
  16124.    else sfp = NULL;
  16125.  
  16126.    /* Fill temporary data set with message to which we are replying,
  16127.     * if this is a FOLLOWUP request,
  16128.     * and the contents of the signature file if any.
  16129.     */
  16130.  
  16131.    if (!filled) {
  16132.      if (!(efp = OPEN_TEXT_FILE_FOR_WRITE(tempdsn))) {
  16133.        ERR2("Error trying to open temp data set: %s", tempdsn);
  16134.        continue;
  16135.      }
  16136.      if (ap) {
  16137.        np->extract_file            = efp;
  16138.        np->extract_appending       = FALSE;
  16139.        np->extract_separator_line  = FALSE;
  16140.        np->extract_tab_expanding   = TRUE;
  16141.        np->following_up            = TRUE;
  16142.        fprintf(efp, "In article %s,\n%s writes:\n\n",
  16143.                     ap->message_id, ap->from);
  16144.        (void)NNMxtx(np,ap,FALSE);            /* Extract article text */
  16145.        np->following_up            = FALSE;
  16146.        if (ferror(efp)) {
  16147.          ERR2("Error trying to write to temp data set: %s", tempdsn);
  16148.          continue;
  16149.        }
  16150.      }
  16151.      if (sfp) {
  16152.        fprintf(efp,"\n-- \n",efp);
  16153.        if (ferror(efp)) np->extract_write_error = TRUE;
  16154.        for (;;) {
  16155.          fgets(sigline,sizeof(sigline),sfp);
  16156.          if (ferror(sfp)) {
  16157.            ERR2(
  16158.   "Cannot read from signature file %s.  Check that it is valid.",
  16159.                 signature_file);
  16160.            break;
  16161.          }
  16162.          if (feof(sfp)) break;
  16163.          if ((cp=strchr(sigline,'\n'))) *cp = '\0';
  16164.          l = strlen(sigline);
  16165.          fwrite(sigline,(l>251 ? 251 : l),1,efp);
  16166.          if (ferror(efp)) {
  16167.            np->extract_write_error = TRUE; break;
  16168.          }
  16169.          if (fputc('\n',efp) == EOF) {
  16170.            np->extract_write_error = TRUE; break;
  16171.          }
  16172.        }
  16173.        (void)fclose(sfp);
  16174.        if (ferror(efp)) {
  16175.          ERR2("Error trying to write to temp data set: %s", tempdsn);
  16176.          continue;
  16177.        }
  16178.      }
  16179.      if (fclose(efp) < 0) {
  16180.        ERR2("Error trying to close temp data set: %s", tempdsn);
  16181.        continue;
  16182.      }
  16183.      filled = TRUE;
  16184.    }
  16185.  
  16186.    efp = NULL;
  16187.  
  16188. #ifndef I370
  16189.    sprintf(editstr,"EDIT DATASET(%s) PROFILE(%s)",tempdsn,edit_profile);
  16190. #else
  16191.    sprintf(editstr, "EDIT DATASET('%s') PROFILE(%s)",
  16192.            tempdsn+4, edit_profile);
  16193. #endif
  16194.  
  16195.    edit_error = FALSE;
  16196.  
  16197.    (void)NNMispf(np,editstr);
  16198.    switch (np->ispfrc) {
  16199.      case 0:  edit_error = FALSE;      break;
  16200.      case 4:  ERR1(
  16201. "Edit ended without SAVE, posting cancelled.  Reenter and SAVE to post."
  16202.                   );                         continue;
  16203.      default: edit_error = TRUE;       break;
  16204.    }
  16205.  
  16206.    if (edit_error) continue;
  16207.  
  16208.    /* Confirm posting. */
  16209.  
  16210.    (void)NNMispf (np,"ADDPOP ");
  16211.    display_rc = NNMdispl(np,"NNMPCONP");
  16212.    (void)NNMispf (np,"REMPOP ");
  16213.    (void)NNMivget(np,"ZCMD ",zcmd,sizeof(zcmd));
  16214.    if (display_rc > 0) continue;
  16215.    if (*zcmd == 'c' || *zcmd == 'C') {
  16216.      (void)NNMivput(np,"ZCMD ","",-1);
  16217.      ERR1("Posting cancelled by user.  Reenter EDIT and SAVE to post.");
  16218.      return;
  16219.    }
  16220.  
  16221.    if (!(efp = fopen(tempdsn,"r"))) {
  16222.      ERR2("Error trying to open temp data set: %s", tempdsn);
  16223.      continue;
  16224.    }
  16225.  
  16226.    /* Start posting here.
  16227.     *
  16228.     * Me:     POST
  16229.     * Server: 340 send article to be posted.  End with <CR-LF>.<CR-LF>
  16230.     *     or: 440 posting not allowed
  16231.     * If 430...
  16232.     *
  16233.     * See RFC850 for details.
  16234.     *
  16235.     * Me:     required_header: xxx
  16236.     * ...
  16237.     * Me:     <null line>
  16238.     * Read text from tempdsn
  16239.     * Me:     <text with leading periods hacked>
  16240.     * Me:     .
  16241.     * Server: 240 article posted OK
  16242.     *     or: 441 posting failed
  16243.     */
  16244.  
  16245.     /* See RFC 1036 for full information. */
  16246.  
  16247.    /* Required headers - from, date, subject, newsgroups,
  16248.     *                    message-id, path
  16249.     */
  16250.  
  16251.    /* Optional headers - reply-to, sender, followup-to, expires, xref,
  16252.     *                    references, control, distribution, lines,
  16253.     *                    organization, keywords, summary, approved
  16254.     */
  16255.  
  16256.  
  16257.    /* Get current date and time, and generate a message id from it.
  16258.     * If the message id is a duplicate, loop around until it isn't.
  16259.     */
  16260.  
  16261.    do {
  16262.  
  16263.      time(<ime);
  16264.      now = localtime(<ime);
  16265.      strftime(datestr,sizeof(datestr)-1,"%a, %d %b %Y %H:%M %Z",now);
  16266.      strftime(midstr, sizeof(midstr)-1, "%Y%m%d%H%M%S",now);
  16267.  
  16268.      sprintf(post_message_id,"<%s%s@%s>",
  16269.                              midstr, zuser, np->client_hostname);
  16270.  
  16271.    } while (EQUAL(post_message_id,np->messageid));
  16272.  
  16273.    strcpy(np->messageid,post_message_id);
  16274.  
  16275.    do {
  16276.      strcpy(np->nntp_command,"POST");
  16277.      if (!NNMsockt(np))     break;  /* Send socket command to server */
  16278.      if (!NNMgsrvl(np,&lp)) break;  /* Get server line */
  16279.      switch (np->nntp_message_num) {
  16280.        case 340: post_error = FALSE;
  16281.                  break;
  16282.        case 440: ERR2(
  16283.          "Posting not allowed.  Server %s did not accept the post.",
  16284.                       np->nnserver);
  16285.                  post_error = TRUE;
  16286.                  break;
  16287.        default:  NNMrperr(np);       /* Report protocol error */
  16288.                  post_error = TRUE;
  16289.                  break;
  16290.      }
  16291.  
  16292.      if (post_error) break;
  16293.  
  16294.      /* Assert np->server_finished_replying == TRUE
  16295.       *     && np->receiving_text == TRUE
  16296.       */
  16297.  
  16298.      if (*nnpostfr)
  16299.           sprintf(post_from,"%s@%s (%s)",
  16300.                             zuser, np->client_hostname, nnpostfr);
  16301.      else sprintf(post_from,"%s@%s",
  16302.                             zuser, np->client_hostname);
  16303.  
  16304. #ifdef READER_MUST_GENERATE_PATH
  16305.      sprintf(np->nntp_command,"Path: %s", post_path);
  16306.      if (!NNMsockt(np)) break;   /* Send socket command to server */
  16307. #endif
  16308.  
  16309.      sprintf(np->nntp_command,"Newsgroups: %s",post_newsgroups);
  16310.      if (!NNMsockt(np)) break;   /* Send socket command to server */
  16311.  
  16312.      sprintf(np->nntp_command,"Subject: %s",post_subject);
  16313.      if (!NNMsockt(np)) break;   /* Send socket command to server */
  16314.  
  16315.      sprintf(np->nntp_command,"Message-ID: %s", post_message_id);
  16316.      if (!NNMsockt(np)) break;   /* Send socket command to server */
  16317.  
  16318.      sprintf(np->nntp_command,"From: %s", post_from);
  16319.      if (!NNMsockt(np)) break;   /* Send socket command to server */
  16320.  
  16321.      sprintf(np->nntp_command,"Date: %s", datestr);
  16322.      if (!NNMsockt(np)) break;   /* Send socket command to server */
  16323.  
  16324.      /* insert optional headers here if we ever have any */
  16325.  
  16326.      sprintf(np->nntp_command,"Sender: MVS NNTP News Reader <%s@%s>",
  16327.                               NNMVS_NAME, np->client_hostname);
  16328.      if (!NNMsockt(np)) break;   /* Send socket command to server */
  16329.  
  16330.      if (ap) {
  16331.     /*
  16332.      * Uncomment this section when a references field in the
  16333.      * newsarticle struct is added.  Will require total recompilation
  16334.      *
  16335.      * if (ap->references)
  16336.      *  sprintf(np->nntp_command,"References: %s %s",
  16337.      *          ap->references, ap->message_id);
  16338.      * else
  16339.      */
  16340.         sprintf(np->nntp_command,"References: %s",ap->message_id);
  16341.        if (!NNMsockt(np)) break;   /* Send socket command to server */
  16342.      }
  16343.  
  16344.      /* optional headers */
  16345.  
  16346.      if (*nnpostrt) {
  16347.        sprintf(np->nntp_command,"Reply-to: %s", nnpostrt);
  16348.        if (!NNMsockt(np)) break;   /* Send socket command to server */
  16349.      }
  16350.      if (*post_followup_to) {
  16351.        sprintf(np->nntp_command,"Followup-to: %s", post_followup_to);
  16352.        if (!NNMsockt(np)) break;   /* Send socket command to server */
  16353.      }
  16354.  
  16355.      strcpy(np->nntp_command,"");
  16356.      if (!NNMsockt(np)) break;   /* Send socket command to server */
  16357.  
  16358.      while (!feof(efp) && !ferror(efp)) {
  16359.        fgets(postline,sizeof(postline),efp);
  16360.        if (feof(efp)) break;
  16361.        if (ferror(efp)) break;
  16362.        if (*postline && postline[l=strlen(postline)-1] == '\n')
  16363.           postline[l] = '\0';
  16364.        if (postline[0] == '.') strcpy(np->nntp_command,".");
  16365.        else                    strcpy(np->nntp_command,"");
  16366.        strcat(np->nntp_command,postline);
  16367.        if (!NNMsockt(np)) break;   /* Send socket command to server */
  16368.      }
  16369.  
  16370.      strcpy(np->nntp_command,".");
  16371.      if (!NNMsockt(np)) break;   /* Send socket command to server */
  16372.  
  16373.      if (!NNMgsrvl(np,&lp)) break;  /* Get server line */
  16374.      switch (np->nntp_message_num) {
  16375.        case 240: post_error = FALSE;
  16376.                  break;
  16377.        case 441: NNMclrtx(np,NULL);               /* Clear text */
  16378.                  NNMouttx(np,np->server_buf,NULL);/* Output text line */
  16379.                  NNMvtx(np,NULL,NULL);            /* View text */
  16380.  ERR2("Posting failed.  Server %s rejected the post.",np->nnserver);
  16381.                  post_error = TRUE;
  16382.                  break;
  16383.        default:  NNMrperr(np);       /* Report protocol error */
  16384.                  post_error = TRUE;
  16385.                  break;
  16386.      }
  16387.  
  16388.      NNMesrvr(np);                   /* End server read */
  16389.  
  16390.      break;
  16391.  
  16392.    } while(FALSE); /* one-time DO so I can break out of it */
  16393.  
  16394.    if (!post_error) {
  16395.      (void)NNMivput(np,"NNPOSTID ",post_message_id,-1);
  16396.      WARN2("Your article has been posted.  Message ID: %s",
  16397.            post_message_id);
  16398.      break;
  16399.    }
  16400.  
  16401.  }
  16402.  
  16403.  if (!efp) return;
  16404.  
  16405.  if (ferror(efp)) {
  16406.    ERR2("Error trying to read from temp data set: %s", tempdsn);
  16407.  }
  16408.  
  16409.  if (fclose(efp) < 0) {
  16410.    ERR2("Error trying to close temp data set: %s", tempdsn);
  16411.  }
  16412.  
  16413.  if (ap) {
  16414.    if (remove(tempdsn) < 0) {
  16415.      ERR2("Error trying to delete temp data set: %s", tempdsn);
  16416.    }
  16417.  }
  16418.  
  16419.  return;
  16420. }
  16421.  
  16422. ./ ADD NAME=NNMDSOPT
  16423.  
  16424.  /********************************************************************/
  16425.  /*                                                                  */
  16426.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  16427.  /*                                                                  */
  16428.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  16429.  /* including the implied warranties of merchantability and fitness, */
  16430.  /* are expressly denied.                                            */
  16431.  /*                                                                  */
  16432.  /* Provided this copyright notice is included, this software may    */
  16433.  /* be freely distributed and not offered for sale.                  */
  16434.  /*                                                                  */
  16435.  /* Changes or modifications may be made and used only by the maker  */
  16436.  /* of same, and not further distributed.  Such modifications should */
  16437.  /* be mailed to the author for consideration for addition to the    */
  16438.  /* software and incorporation in subsequent releases.               */
  16439.  /*                                                                  */
  16440.  /********************************************************************/
  16441.  
  16442. #pragma  csect(code,  "NN@DSOPT")
  16443. #pragma  csect(static,"NN$DSOPT")
  16444. #include "nn.h"
  16445.  
  16446. /****** Set options. *************************************************/
  16447.  
  16448. static void
  16449. set_options(np,panelname,which)
  16450. Rstruc nncb       *np;
  16451. char              *panelname;
  16452. enum user_option   which;
  16453. {
  16454.  
  16455.  while (NNMdispl(np,panelname) == 0) {
  16456.    NNMsopt(np,which);               /* Actually set options */
  16457.  }
  16458.  
  16459.  return;
  16460. }
  16461.  
  16462. /****** Option ... set NNMVS default processing options. *************/
  16463.  
  16464. void
  16465. NNMdsopt(np,option)
  16466. Rstruc nncb *np;
  16467. char        *option;
  16468. {
  16469.  Bool        asked_for;
  16470.  Bool        force_choice;
  16471.  char        nnchoice[9];
  16472.  
  16473.  force_choice = FALSE;
  16474.  
  16475.  do {
  16476.  
  16477.    asked_for = TRUE;
  16478.  
  16479.    if (!force_choice && option && *option) {
  16480.      strncpy(nnchoice,option,sizeof(nnchoice)-1);
  16481.  
  16482.    }
  16483.    else {
  16484.  
  16485.      (void)NNMispf(np,"ADDPOP");
  16486.      if (NNMdispl(np,"NNMPOPT ") > 0) {
  16487.        asked_for = FALSE;
  16488.      }
  16489.      else {
  16490.        (void)NNMivget(np,"NNCHOICE ",nnchoice,sizeof(nnchoice));
  16491.        if (*nnchoice == '?') {
  16492.          ERR1("Invalid choice;\
  16493. Move the cursor to a selection (or type S next to it) and press ENTER."
  16494.              );
  16495.        }
  16496.      }
  16497.  
  16498.      (void)NNMispf(np,"REMPOP");
  16499.    }
  16500.  
  16501.    if (asked_for) {
  16502.  
  16503.      if      (EQUAL(nnchoice,"1")) {
  16504.        set_options(np,"NNMRFCH ",OPTION_HEADER);
  16505.        break;
  16506.      }
  16507.      else if (EQUAL(nnchoice,"2")) {
  16508.        set_options(np,"NNMOPTS ",OPTION_OTHER);
  16509.        break;
  16510.      }
  16511.      else if (EQUAL(nnchoice,"3")) {
  16512.        set_options(np,"NNMOPTT ",OPTION_VIEW);
  16513.        break;
  16514.      }
  16515.      else {
  16516.        ERR1("Invalid choice;\
  16517. Move the cursor to a selection (or type S next to it) and press ENTER."
  16518.            );
  16519.        force_choice = TRUE;
  16520.        continue;
  16521.      }
  16522.    }
  16523.  
  16524.  } while (asked_for);
  16525.  
  16526.  return;
  16527.  
  16528. }
  16529.  
  16530. ./ ADD NAME=NNMDUMP
  16531.  
  16532.  /********************************************************************/
  16533.  /*                                                                  */
  16534.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  16535.  /*                                                                  */
  16536.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  16537.  /* including the implied warranties of merchantability and fitness, */
  16538.  /* are expressly denied.                                            */
  16539.  /*                                                                  */
  16540.  /* Provided this copyright notice is included, this software may    */
  16541.  /* be freely distributed and not offered for sale.                  */
  16542.  /*                                                                  */
  16543.  /* Changes or modifications may be made and used only by the maker  */
  16544.  /* of same, and not further distributed.  Such modifications should */
  16545.  /* be mailed to the author for consideration for addition to the    */
  16546.  /* software and incorporation in subsequent releases.               */
  16547.  /*                                                                  */
  16548.  /********************************************************************/
  16549.  
  16550. #pragma  csect(code,  "NN@DUMP ")
  16551. #pragma  csect(static,"NN$DUMP ")
  16552. #include "nn.h"
  16553.  
  16554. /****** Dump some data. **********************************************/
  16555.  
  16556. void
  16557. NNMdump(struct nncb *np, char *label, char *p,int r)
  16558. {
  16559.  int i;
  16560.  
  16561.  if (!np->debug_file) return;
  16562.  
  16563.  if (r == -2) {
  16564.    fprintf(np->debug_file,"%s:  %d\n",label,(int)p);
  16565.    return;
  16566.  }
  16567.  
  16568.  if (r == -1) r = strlen(p);
  16569.  
  16570.  fprintf(np->debug_file,"%s:   (%d characters)\n",label,r);
  16571.  for (i=0;i<77;i++) fprintf(np->debug_file,"-");
  16572.  fprintf(np->debug_file,"\n");
  16573.  for (i=0;i<r;i++) {
  16574.    char c = *(p+i);
  16575.    if (isprint(c))  fprintf(np->debug_file,"%c",c);
  16576.    else             fprintf(np->debug_file,"<0x%2.2x>",c);
  16577.  }
  16578.  fprintf(np->debug_file,"\n");
  16579.  for (i=0;i<77;i++) fprintf(np->debug_file,"-");
  16580.  fprintf(np->debug_file,"\n");
  16581.  
  16582.  fflush(np->debug_file);
  16583.  
  16584.  return;
  16585.  
  16586. }
  16587.  
  16588. ./ ADD NAME=NNMESRVR
  16589.  
  16590.  /********************************************************************/
  16591.  /*                                                                  */
  16592.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  16593.  /*                                                                  */
  16594.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  16595.  /* including the implied warranties of merchantability and fitness, */
  16596.  /* are expressly denied.                                            */
  16597.  /*                                                                  */
  16598.  /* Provided this copyright notice is included, this software may    */
  16599.  /* be freely distributed and not offered for sale.                  */
  16600.  /*                                                                  */
  16601.  /* Changes or modifications may be made and used only by the maker  */
  16602.  /* of same, and not further distributed.  Such modifications should */
  16603.  /* be mailed to the author for consideration for addition to the    */
  16604.  /* software and incorporation in subsequent releases.               */
  16605.  /*                                                                  */
  16606.  /********************************************************************/
  16607.  
  16608. #pragma  csect(code,  "NN@ESRVR")
  16609. #pragma  csect(static,"NN$ESRVR")
  16610. #include "nn.h"
  16611.  
  16612. /****** End server read. *********************************************/
  16613.  
  16614. void
  16615. NNMesrvr(np)
  16616. Rstruc nncb  *np;
  16617. {
  16618.  char       *lp;
  16619.  Bool        found_more_server_data = FALSE;
  16620.  Bool        save_dont_reissue_socket_command;
  16621.  
  16622.  NNMclrtx(np,NULL);                    /* Clear text */
  16623.  
  16624.  save_dont_reissue_socket_command = np->dont_reissue_socket_command;
  16625.  np->dont_reissue_socket_command = TRUE;
  16626.  
  16627.  do {
  16628.  
  16629.    if (NNMgsrvl(np,&lp)) {             /* Get server line */
  16630.      if (lp) {
  16631.        found_more_server_data = TRUE;
  16632.        (void)NNMouttx(np,lp,NULL);     /* Output text line */
  16633.      }
  16634.    }
  16635.  
  16636.  } while (lp);
  16637.  
  16638.  if (found_more_server_data) {
  16639.    ERR1(
  16640. "More data was returned by the news server than the client expected."
  16641.        );
  16642.    NNMvtx(np,NULL,NULL);               /* View text */
  16643.  }
  16644.  
  16645.  np->dont_reissue_socket_command = save_dont_reissue_socket_command;
  16646.  
  16647.  return;
  16648. }
  16649.  
  16650. ./ ADD NAME=NNMESTNG
  16651.  
  16652.  /********************************************************************/
  16653.  /*                                                                  */
  16654.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  16655.  /*                                                                  */
  16656.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  16657.  /* including the implied warranties of merchantability and fitness, */
  16658.  /* are expressly denied.                                            */
  16659.  /*                                                                  */
  16660.  /* Provided this copyright notice is included, this software may    */
  16661.  /* be freely distributed and not offered for sale.                  */
  16662.  /*                                                                  */
  16663.  /* Changes or modifications may be made and used only by the maker  */
  16664.  /* of same, and not further distributed.  Such modifications should */
  16665.  /* be mailed to the author for consideration for addition to the    */
  16666.  /* software and incorporation in subsequent releases.               */
  16667.  /*                                                                  */
  16668.  /********************************************************************/
  16669.  
  16670. #pragma  csect(code,  "NN@ESTNG")
  16671. #pragma  csect(static,"NN$ESTNG")
  16672. #include "nn.h"
  16673.  
  16674. /****** Establish newsgroup. *****************************************/
  16675.  
  16676. Bool
  16677. NNMestng(np,group)
  16678. Rstruc nncb        *np;
  16679. char               *group;
  16680. {
  16681.  char              *lp;
  16682.  Bool               null_group_passed = FALSE;
  16683.  
  16684.  /* A null group means reissue the server command to select the
  16685.     current newsgroup if it is necessary. */
  16686.  
  16687.  if (!group) {
  16688.    null_group_passed = TRUE;
  16689.    if (!np->current_newsgroup) {
  16690.      fprintf(stderr,"NNMestng: no current newsgroup\n");
  16691.      return FALSE;
  16692.    }
  16693.    if (np->newsgroup_selected) return TRUE;
  16694.    group = np->current_newsgroup->name;
  16695.  }
  16696.  
  16697.  np->newsgroup_not_found = FALSE;
  16698.  
  16699.  /* Send "GROUP xxxx" to news server. */
  16700.  
  16701.  strcpy(np->nntp_command,"GROUP ");
  16702.  strcat(np->nntp_command,group);
  16703.  if (!NNMsockt(np)) return FALSE;    /* Send socket command to server */
  16704.  
  16705.    /* Receive response.  Should be one of:
  16706.     *   211 n f l s group selected
  16707.     *   411 no such news group
  16708.     */
  16709.  
  16710.  if (!NNMgsrvl(np,&lp)) return FALSE;  /* Get server line */
  16711.  switch (np->nntp_message_num) {
  16712.    case 211:                           /* n f l s group selected */
  16713.              break;
  16714.    case 411:                               /* no such news group */
  16715.              fprintf(stderr,"%s: no such newsgroup\n",group);
  16716.              ERR3("No such newsgroup.  %s is unknown to server %s.",
  16717.                   group, np->nnserver);
  16718.              np->newsgroup_not_found = TRUE;
  16719.              return FALSE;
  16720.    default:
  16721.              NNMrperr(np);        /* Report protocol error */
  16722.              return FALSE;
  16723.  }
  16724.  
  16725.  np->newsgroup_selected = TRUE;
  16726.  
  16727.  return TRUE;
  16728.  
  16729. }
  16730.  
  16731. ./ ADD NAME=NNMFREEM
  16732.  
  16733.  /********************************************************************/
  16734.  /*                                                                  */
  16735.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  16736.  /*                                                                  */
  16737.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  16738.  /* including the implied warranties of merchantability and fitness, */
  16739.  /* are expressly denied.                                            */
  16740.  /*                                                                  */
  16741.  /* Provided this copyright notice is included, this software may    */
  16742.  /* be freely distributed and not offered for sale.                  */
  16743.  /*                                                                  */
  16744.  /* Changes or modifications may be made and used only by the maker  */
  16745.  /* of same, and not further distributed.  Such modifications should */
  16746.  /* be mailed to the author for consideration for addition to the    */
  16747.  /* software and incorporation in subsequent releases.               */
  16748.  /*                                                                  */
  16749.  /********************************************************************/
  16750.  
  16751. #pragma  csect(code,  "NN@FREEM")
  16752. #pragma  csect(static,"NN$FREEM")
  16753. #include "nn.h"
  16754.  
  16755. /****** Free memory. *************************************************/
  16756.  
  16757. void
  16758. NNMfreem(np,stuff,whatfor)
  16759. Rstruc nncb    *np;
  16760. char           *stuff;
  16761. char           *whatfor;
  16762. {
  16763.  
  16764.  free(stuff);
  16765.  
  16766.  if (np->debug_file) {
  16767.    fprintf(np->debug_file,"NNMfreem: freed memory for %s\n", whatfor);
  16768.  }
  16769.  return;
  16770.  
  16771. }
  16772.  
  16773. ./ ADD NAME=NNMGETDS
  16774.  
  16775.  /********************************************************************/
  16776.  /*                                                                  */
  16777.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  16778.  /*                                                                  */
  16779.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  16780.  /*                                                                  */
  16781.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  16782.  /* including the implied warranties of merchantability and fitness, */
  16783.  /* are expressly denied.                                            */
  16784.  /*                                                                  */
  16785.  /* Provided this copyright notice is included, this software may    */
  16786.  /* be freely distributed and not offered for sale.                  */
  16787.  /*                                                                  */
  16788.  /* Changes or modifications may be made and used only by the maker  */
  16789.  /* of same, and not further distributed.  Such modifications should */
  16790.  /* be mailed to the author for consideration for addition to the    */
  16791.  /* software and incorporation in subsequent releases.               */
  16792.  /*                                                                  */
  16793.  /********************************************************************/
  16794.  
  16795. #pragma  csect(code,  "NN@GETDS")
  16796. #pragma  csect(static,"NN$GETDS")
  16797. #include "nn.h"
  16798.  
  16799. #define DUMMY_FILE_POINTER_FOR_PDS  (FILE *)(-1)
  16800.  
  16801. struct sysout    {
  16802.                   int        copies;
  16803.                   char       class [2];
  16804.                   char       dest  [9];
  16805.                   char       forms [5];
  16806.                   char       ucs   [5];
  16807.                  };
  16808.  
  16809. /****** Function to close sequential data set after extraction. ******/
  16810.  
  16811. static void
  16812. close_seq(np,ep,xfp,final)
  16813. Rstruc nncb         *np;
  16814. Rstruc extraction   *ep;
  16815. FILE                *xfp;
  16816. Fool                 final;
  16817. {
  16818.  
  16819.  if (fclose(xfp) < 0) {
  16820.    /* perror(ep->dsname); */
  16821.    ERR2("An error occurred closing %s.", ep->dsname);
  16822.    np->extract_close_error = TRUE;
  16823.  }
  16824.  
  16825. }
  16826.  
  16827. /****** Function to close partitioned data set after extraction. *****/
  16828.  
  16829. static void
  16830. close_pds(np,ep,xfp,final)
  16831. Rstruc nncb         *np;
  16832. Rstruc extraction   *ep;
  16833. FILE                *xfp;
  16834. Fool                 final;
  16835. {
  16836.  
  16837.  if (final) {
  16838.    (void)NNMunalc(ep->ddname);     /* Unallocate the PDS */
  16839.  }
  16840.  else {
  16841.    if (fclose(xfp) < 0) {
  16842.      /* perror(ep->dsname); */
  16843.      ERR2("An error occurred closing %s.", ep->dsname);
  16844.      np->extract_close_error = TRUE;
  16845.    }
  16846.  }
  16847.  
  16848. }
  16849.  
  16850. /****** Function to close SYSOUT print file after printing. **********/
  16851.  
  16852. static void
  16853. close_jes(np,ep,xfp,final)
  16854. Rstruc nncb         *np;
  16855. Rstruc extraction   *ep;
  16856. FILE                *xfp;
  16857. Fool                 final;
  16858. {
  16859.  
  16860.  if (fclose(xfp) < 0) {
  16861.    /* perror(ep->dsname); */
  16862.    ERR2("An error occurred closing %s.", ep->dsname);
  16863.    np->extract_close_error = TRUE;
  16864.  }
  16865.  if (final) {
  16866.    (void)NNMunalc(ep->ddname);     /* Unallocate the SYSOUT file */
  16867.  }
  16868.  
  16869. }
  16870.  
  16871. /****** Allocate SYSOUT file. ****************************************/
  16872.  
  16873. static Bool
  16874. allocate_sysout(ep,sp)
  16875. Rstruc extraction   *ep;
  16876. Rstruc sysout       *sp;
  16877. {
  16878.  int          i;
  16879.  int          rc;
  16880.  char        *cp;
  16881.  __S99parms   stuff99;   /* The manual has it wrong.  No "struct". */
  16882.  TEXTUNIT    *tu [ 7];
  16883.  TEXTUNIT     tu_sysout;
  16884.  TEXTUNIT     tu_copies;
  16885.  TEXTUNIT     tu_dest;
  16886.  TEXTUNIT     tu_forms;
  16887.  TEXTUNIT     tu_ucs;
  16888.  TEXTUNIT     tu_rtddn;
  16889.  
  16890.  memset((char *)&stuff99,0,sizeof(__S99parms));
  16891.  
  16892.  stuff99.__S99RBLN   = 20;
  16893.  stuff99.__S99VERB   = S99VRBAL;
  16894.  stuff99.__S99FLAG1  = S99NOCNV << 8;
  16895.  stuff99.__S99ERROR  = 0;
  16896.  stuff99.__S99INFO   = 0;
  16897.  stuff99.__S99TXTPP  = tu;
  16898.  stuff99.__S99FLAG2  = 0;
  16899.  
  16900.  i = 0;
  16901.  
  16902.  tu[i++] = &tu_sysout;
  16903.  
  16904.  tu_sysout.key        = DALSYSOU;
  16905.  tu_sysout.num        = 1;
  16906.  tu_sysout.ent.len    = 1;
  16907.  tu_sysout.ent.prm[0] = toupper(sp->class[0]);
  16908.  
  16909.  tu[i++] = &tu_copies;
  16910.  
  16911.  tu_copies.key        = DALCOPYS;
  16912.  tu_copies.num        = 1;
  16913.  tu_copies.ent.len    = 1;
  16914.  tu_copies.ent.prm[0] = (unsigned char)sp->copies;
  16915.  
  16916.  if (sp->dest[0] > ' ') {
  16917.  
  16918.   tu[i++] = &tu_dest;
  16919.  
  16920.   tu_dest.key          = DALSUSER;
  16921.   tu_dest.num          = 1;
  16922.   copy_uppercase_and_strip_trailing(tu_dest.ent.prm,sp->dest,cp);
  16923.   tu_dest.ent.len      = cp - tu_dest.ent.prm;
  16924.  
  16925.  }
  16926.  
  16927.  if (sp->forms[0] > ' ') {
  16928.  
  16929.   tu[i++] = &tu_forms;
  16930.  
  16931.   tu_forms.key         = DALSFMNO;
  16932.   tu_forms.num         = 1;
  16933.   copy_uppercase_and_strip_trailing(tu_forms.ent.prm,sp->forms,cp);
  16934.   tu_forms.ent.len     = cp - tu_forms.ent.prm;
  16935.  
  16936.  }
  16937.  
  16938.  if (sp->ucs[0] > ' ') {
  16939.  
  16940.   tu[i++] = &tu_ucs;
  16941.  
  16942.   tu_ucs.key           = DALUCS;
  16943.   tu_ucs.num           = 1;
  16944.   copy_uppercase_and_strip_trailing(tu_ucs.ent.prm,sp->ucs,cp);
  16945.   tu_ucs.ent.len       = cp - tu_ucs.ent.prm;
  16946.  
  16947.  }
  16948.  
  16949.  tu[i++] = &tu_rtddn;
  16950.  
  16951.  tu_rtddn.key         = DALRTDDN;
  16952.  tu_rtddn.num         = 1;
  16953.  tu_rtddn.ent.len     = 8;
  16954.  memset(tu_rtddn.ent.prm,' ',8);
  16955.  
  16956.  tu[i] = (void *)0x80000000;
  16957.  
  16958.  rc = svc99(&stuff99);
  16959.  
  16960.  if (rc == 0) {
  16961.    memcpy(ep->ddname,(char *)tu_rtddn.ent.prm,8);
  16962.    ep->ddname[8] = ' ';
  16963.    *(strchr(ep->ddname,' ')) = '\0';
  16964.    return TRUE;
  16965.  }
  16966.  else {
  16967.    NNMdfail(rc,&stuff99);
  16968.    return FALSE;
  16969.  }
  16970. }
  16971.  
  16972. /****** Prompt user for the name of a data set to extract into. ******/
  16973.  
  16974. FILE *
  16975. NNMgetds(np,ep)
  16976. Rstruc nncb         *np;
  16977. Rstruc extraction   *ep;
  16978. {
  16979.  FILE               *xfp;
  16980.  char               *panel_to_display;
  16981.  Bool                asked_for;
  16982.  struct sysout       sys;
  16983.  char                nnexdsn[65];    /* data set name for extraction */
  16984.  char                nnexapp [4];    /* YES or NO for append mode    */
  16985.  char                nnextab [4];    /* YES or NO for tab expansion  */
  16986.  char                nnexblk [4];    /* YES or NO for blank after sep*/
  16987.  char                nnexspa [4];    /* YES or NO for page ejects    */
  16988.  char                nnexsep[81];    /* Separator line (optional)    */
  16989.  char                nnexan1[16];    /* From article number          */
  16990.  char                nnexan2[16];    /* To   article number          */
  16991.  char                nnexpmp [9];    /* PDS member name prefix       */
  16992.  char                nnexscl [2];    /* Print SYSOUT class name      */
  16993.  char                nnexsco [4];    /* Print SYSOUT copies number   */
  16994.  char                nnexsde [9];    /* Print SYSOUT destination     */
  16995.  char                nnexsfo [5];    /* Print SYSOUT forms           */
  16996.  char                nnexsuc [5];    /* Print SYSOUT UCS             */
  16997.  char                quoted_dsname [67];
  16998.  
  16999.  /* Display panel asking for data set name into which to extract. */
  17000.  
  17001.  xfp = NULL;
  17002.  asked_for = TRUE;
  17003.  
  17004.  (void)NNMispf(np,"ADDPOP");
  17005.  
  17006.  if (ep->mode == JES) {
  17007.    (void)NNMivput(np,"NNWHICH ",ep->panelname,-1);
  17008.    (void)NNMivput(np,"NNALLPR ",
  17009. #ifdef FULLSYSOUT
  17010.                      "Y",
  17011. #else
  17012.                      "",
  17013. #endif
  17014.                      -1);
  17015.    panel_to_display = "NNMPPRT ";
  17016.  }
  17017.  else panel_to_display = ep->panelname;
  17018.  
  17019.  while (!xfp) {
  17020.  
  17021.    /* Keep asking for a dsname until one works or END pressed. */
  17022.  
  17023.    if (NNMdispl(np,panel_to_display) > 0) {
  17024.      asked_for = FALSE;
  17025.      xfp = NULL;
  17026.      break;
  17027.    }
  17028.  
  17029.    if (ep->mode == JES) {
  17030.      (void)NNMivget(np,"NNEXSCL ",nnexscl,sizeof(nnexscl));
  17031.      (void)NNMivget(np,"NNEXSCO ",nnexsco,sizeof(nnexsco));
  17032. #ifdef FULLSYSOUT
  17033.      (void)NNMivget(np,"NNEXSDE ",nnexsde,sizeof(nnexsde));
  17034.      (void)NNMivget(np,"NNEXSFO ",nnexsfo,sizeof(nnexsfo));
  17035.      (void)NNMivget(np,"NNEXSUC ",nnexsuc,sizeof(nnexsuc));
  17036. #else
  17037.      *nnexsde = '\0';
  17038.      *nnexsfo = '\0';
  17039.      *nnexsuc = '\0';
  17040. #endif
  17041.      (void)NNMivget(np,"NNEXAN1 ",nnexan1,sizeof(nnexan1));
  17042.      (void)NNMivget(np,"NNEXAN2 ",nnexan2,sizeof(nnexan2));
  17043.      (void)NNMivget(np,"NNEXSPA ",nnexspa,sizeof(nnexspa));
  17044.      (void)NNMivget(np,"NNEXBLK ",nnexblk,sizeof(nnexblk));
  17045.      (void)NNMivget(np,"NNEXSEP ",nnexsep,sizeof(nnexsep));
  17046.    }
  17047.    else {
  17048.      (void)NNMivget(np,"NNEXDSN ",nnexdsn,sizeof(nnexdsn));
  17049.      (void)NNMivget(np,"NNEXTAB ",nnextab,sizeof(nnextab));
  17050.      (void)NNMivget(np,"NNEXAN1 ",nnexan1,sizeof(nnexan1));
  17051.      (void)NNMivget(np,"NNEXAN2 ",nnexan2,sizeof(nnexan2));
  17052.      if (ep->mode == PDS) {
  17053.        (void)NNMivget(np,"NNEXPMP ",nnexpmp,sizeof(nnexpmp));
  17054.      }
  17055.      else {
  17056.        (void)NNMivget(np,"NNEXAPP ",nnexapp,sizeof(nnexapp));
  17057.        (void)NNMivget(np,"NNEXBLK ",nnexblk,sizeof(nnexblk));
  17058.        (void)NNMivget(np,"NNEXSEP ",nnexsep,sizeof(nnexsep));
  17059.      }
  17060.    }
  17061.  
  17062.    if (ep->mode == PDS) {
  17063.  
  17064.      ep->closer = close_pds;
  17065.      ep->appending = FALSE;
  17066.      ep->blanking  = FALSE;
  17067.      strcpy(ep->separator,"");
  17068.      strcpy(ep->ddname,"");
  17069.      strcpy(ep->member_prefix,nnexpmp);
  17070.  
  17071.      /* Note: panel forces fully-qualified name to pass to allocate */
  17072.  
  17073.      if (nnexdsn[0] != '\'') {
  17074.        strcpy(quoted_dsname,"'");
  17075.        strcat(quoted_dsname,nnexdsn);
  17076.        strcat(quoted_dsname,"'");
  17077.      }
  17078.      else strcpy(quoted_dsname,nnexdsn);
  17079.  
  17080.      /* Check if PDS already exists. */
  17081.  
  17082.      if (np->warn_overwrite) {
  17083.        if (TEST_IF_FILE_EXISTS(xfp,quoted_dsname)) {
  17084.          CLEANUP_IF_FILE_EXISTS(xfp);
  17085.          xfp = NULL;
  17086.          if (NNMdispl(np,"NNMPEXPW") > 0) {
  17087.            WARN1("Operation cancelled, because you pressed END.");
  17088.            break;
  17089.          }
  17090.        }
  17091.      }
  17092.  
  17093.      if (!NNMalloc(nnexdsn,ep->ddname,PDS,ep->article_count)) {
  17094.        ERR2("Allocation failed for data set %s.", nnexdsn);
  17095.        xfp = NULL;
  17096.        continue;
  17097.      }
  17098.      strcpy(ep->dsname,    nnexdsn);
  17099.      ep->tab_expanding = (nnextab[0] == 'Y');
  17100.    }
  17101.    else if (ep->mode == JES) {
  17102.      ep->closer = close_jes;
  17103.      strcpy(ep->separator, nnexsep);
  17104.      sprintf(ep->dsname,"SYSOUT class %s",nnexscl);
  17105.      memset(&sys,0,sizeof(sys));
  17106.      strcpy(sys.class, nnexscl);
  17107.      sys.copies = atoi(nnexsco);
  17108.      if (sys.copies < 1) sys.copies = 1;
  17109.      strcpy(sys.dest,  nnexsde);
  17110.      strcpy(sys.forms, nnexsfo);
  17111.      strcpy(sys.ucs,   nnexsuc);
  17112.      ep->ejecting      = (nnexspa[0] == 'Y');
  17113.      ep->appending     = FALSE;
  17114.      ep->blanking      = (nnexblk[0] == 'Y');
  17115.      ep->tab_expanding = TRUE;
  17116.    }
  17117.    else {
  17118.      ep->closer = close_seq;
  17119.      strcpy(ep->separator, nnexsep);
  17120.      strcpy(ep->dsname,    nnexdsn);
  17121.      ep->appending      = (nnexapp[0] == 'Y');
  17122.      ep->blanking       = (nnexblk[0] == 'Y');
  17123.      ep->tab_expanding  = (nnextab[0] == 'Y');
  17124.    }
  17125.  
  17126.    if (*nnexan1) ep->from_article_number = atoi(nnexan1);
  17127.    else          ep->from_article_number = 0;
  17128.    if (*nnexan2) ep->to_article_number   = atoi(nnexan2);
  17129.    else          ep->to_article_number   = INT_MAX;
  17130.  
  17131.    /* check if the dataset already exists */
  17132.    /* (Wonder if this will compile.  Have fun, "cc"...) */
  17133.  
  17134.    if (ep->mode != JES) {
  17135.      if (ep->appending ? np->warn_append : np->warn_overwrite) {
  17136.        if (TEST_IF_FILE_EXISTS(xfp,nnexdsn)) {
  17137.          CLEANUP_IF_FILE_EXISTS(xfp);
  17138.          xfp = NULL;
  17139.          if (NNMdispl(np,"NNMPEXOW") > 0) {
  17140.            WARN1("Operation cancelled, because you pressed END.");
  17141.            break;
  17142.          }
  17143.        }
  17144.      }
  17145.    }
  17146.  
  17147.    if (ep->mode == JES) {
  17148.      if (allocate_sysout(ep,&sys)) {
  17149.        sprintf(nnexdsn,"dd:%s",ep->ddname);
  17150.      }
  17151.      else *nnexdsn = '\0';
  17152.    }
  17153.  
  17154.    if (ep->mode == PDS) {
  17155.      xfp = DUMMY_FILE_POINTER_FOR_PDS;
  17156.      break;
  17157.    }
  17158.  
  17159.    if (*nnexdsn) {
  17160.  
  17161.      if (ep->mode == JES) {
  17162.        xfp = OPEN_SYSOUT_FILE(nnexdsn);
  17163.      }
  17164.      else {
  17165.        xfp = OPEN_TEXT_FILE_FOR_WRITE_OR_APPEND(nnexdsn,ep->appending);
  17166.      }
  17167.  
  17168.      if (!xfp) {
  17169.        fprintf(stderr,"Open failure: errno=%d\n",errno);
  17170.        perror(nnexdsn);
  17171.        ERR2("Cannot open %s.", ep->dsname);
  17172.      }
  17173.    }
  17174.  }
  17175.  
  17176.  (void)NNMispf(np,"REMPOP");
  17177.  
  17178.  return xfp;
  17179.  
  17180. }
  17181.  
  17182. ./ ADD NAME=NNMGETM
  17183.  
  17184.  /********************************************************************/
  17185.  /*                                                                  */
  17186.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  17187.  /*                                                                  */
  17188.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  17189.  /* including the implied warranties of merchantability and fitness, */
  17190.  /* are expressly denied.                                            */
  17191.  /*                                                                  */
  17192.  /* Provided this copyright notice is included, this software may    */
  17193.  /* be freely distributed and not offered for sale.                  */
  17194.  /*                                                                  */
  17195.  /* Changes or modifications may be made and used only by the maker  */
  17196.  /* of same, and not further distributed.  Such modifications should */
  17197.  /* be mailed to the author for consideration for addition to the    */
  17198.  /* software and incorporation in subsequent releases.               */
  17199.  /*                                                                  */
  17200.  /********************************************************************/
  17201.  
  17202. #pragma  csect(code,  "NN@GETM ")
  17203. #pragma  csect(static,"NN$GETM ")
  17204. #include "nn.h"
  17205.  
  17206. /****** Get memory. **************************************************/
  17207.  
  17208. void
  17209. NNMgetm(np,pointer,howmuch,whatfor)
  17210. Rstruc nncb    *np;
  17211. char          **pointer;
  17212. int             howmuch;
  17213. char           *whatfor;
  17214. {
  17215.  
  17216.  *pointer = (char *)malloc(howmuch);
  17217.  
  17218.  if (!*pointer) {
  17219.    fprintf(stderr,"NNMVS: Cannot obtain %d bytes of memory for %s\n",
  17220.                   howmuch,whatfor);
  17221.  }
  17222.  else if (np->debug_file) {
  17223.    fprintf(np->debug_file,"NNMgetm: got %d bytes of memory for %s\n",
  17224.                            howmuch,whatfor);
  17225.  }
  17226.  return;
  17227.  
  17228. }
  17229.  
  17230. ./ ADD NAME=NNMGSRVL
  17231.  
  17232.  /********************************************************************/
  17233.  /*                                                                  */
  17234.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  17235.  /*                                                                  */
  17236.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  17237.  /* including the implied warranties of merchantability and fitness, */
  17238.  /* are expressly denied.                                            */
  17239.  /*                                                                  */
  17240.  /* Provided this copyright notice is included, this software may    */
  17241.  /* be freely distributed and not offered for sale.                  */
  17242.  /*                                                                  */
  17243.  /* Changes or modifications may be made and used only by the maker  */
  17244.  /* of same, and not further distributed.  Such modifications should */
  17245.  /* be mailed to the author for consideration for addition to the    */
  17246.  /* software and incorporation in subsequent releases.               */
  17247.  /*                                                                  */
  17248.  /********************************************************************/
  17249.  
  17250. #pragma  csect(code,  "NN@GSRVL")
  17251. #pragma  csect(static,"NN$GSRVL")
  17252. #include "nn.h"
  17253.  
  17254. #define  GOT_NOTHING        0
  17255. #define  GOT_SOMETHING      1
  17256. #define  GOT_DISCONNECT     2
  17257. #define  GOT_NOTAUTHORIZED  3
  17258.  
  17259. /* separate this and call it NNMGAUTH eventually */
  17260.  
  17261. /****** Send authorization to news server. ***************************/
  17262.  
  17263. static Bool
  17264. NNMgauth(np)
  17265. Rstruc nncb *np;
  17266. {
  17267.  
  17268.  char              *lp;
  17269.  FILE              *fp;
  17270.  int                display_rc;
  17271.  Bool               auth_error;
  17272.  Bool               connection_probably_closed;
  17273.  char               nnauser   [65];
  17274.  char               nnapass   [65];
  17275.  
  17276.  /* NNTP numbers must be the following as defined in C News source:
  17277.   *
  17278.   * OK_AUTHSYS    280  authorization system OK
  17279.   * OK_AUTH       281  authorization OK
  17280.   * NEED_AUTHINFO 380  authorization is required
  17281.   * NEED_AUTHDATA 381  <type> authorization data required (e.g. PASS)
  17282.   * ERR_NOAUTH    480  authorization required for command
  17283.   * ERR_AUTHSYS   481  authorization system invalid
  17284.   * ERR_AUTHREJ   482  authorization data rejected
  17285.   * ERR_CMDSYN    501  command syntax error
  17286.   * ERR_COMMAND   500  command not implemented
  17287.   * ERR_ACCESS    502  access to server denied
  17288.   * ERR_AUTHBAD   580  authorization failed
  17289.   *
  17290.   * Me:     AUTHINFO USER username
  17291.   * Server: 381 PASS required
  17292.   *     or: 482 Authorization already completed
  17293.   *     or: 500 Command not recognized
  17294.   *
  17295.   * If 482, server does not accept our attempt to gain authorization.
  17296.   *
  17297.   * If 500, authorization is not needed or the server has never
  17298.   * heard of authorization.  Either way, we proceed as "authorized".
  17299.   *
  17300.   * If 381 ...
  17301.   *
  17302.   * Me:     AUTHINFO PASS password
  17303.   * Server: 281 Authorization OK
  17304.   *     or: 482 authorization data rejected
  17305.   *     or: 502 access to server denied
  17306.   *     or: 580 authorization failed
  17307.   *
  17308.   * If 502, the server has disconnected me and I should return FALSE.
  17309.   * Otherwise, everything is OK, and I should return TRUE.
  17310.   *
  17311.   */
  17312.  
  17313.  lp = "None - local system error accessing authorization file";
  17314.  
  17315.  auth_error = FALSE;
  17316.  connection_probably_closed = FALSE;
  17317.  *nnauser   = '\0';
  17318.  *nnapass   = '\0';
  17319.  
  17320.  (void)NNMivget(np,"NNAUSER ",nnauser,sizeof(nnauser));
  17321.  if (!*nnauser) {
  17322.    (void)NNMivget(np,"ZUSER ",nnauser,sizeof(nnauser));
  17323.    lowercase_in_place(nnauser);
  17324.    (void)NNMivput(np,"NNAUSER ",nnauser,-1);
  17325.  }
  17326.  
  17327.  /* Read user and pass from terminal */
  17328.  /* temporary. change to panel */
  17329.  
  17330.  (void)NNMivput(np,"NNSERVER ",np->nnserver,-1);
  17331.  (void)NNMispf(np,"ADDPOP");
  17332.  (void)NNMdispl(np,"NNMPGAUT");
  17333.  display_rc = np->ispfrc;
  17334.  (void)NNMispf(np,"REMPOP");
  17335.  if (display_rc != 0) return FALSE;
  17336.  (void)NNMivget(np,"NNAUSER ",nnauser,sizeof(nnauser));
  17337.  (void)NNMivget(np,"NNAPASS ",nnapass,sizeof(nnapass));
  17338.  sprintf(np->nntp_command,"AUTHINFO USER %s", nnauser);
  17339.  if (!NNMsockt(np)) return FALSE; /* Send socket command to server */
  17340.  if (!NNMgsrvl(np,&lp)) return FALSE;  /* Get server line */
  17341.  switch (np->nntp_message_num) {
  17342.    case 381: /* PASS required */
  17343.              break;
  17344.    default:  NNMrperr(np);       /* Report protocol error */
  17345.              auth_error = TRUE;
  17346.              break;
  17347.  }
  17348.  
  17349.  if (!auth_error) {
  17350.    sprintf(np->nntp_command,"AUTHINFO PASS %s", nnapass);
  17351.    if (!NNMsockt(np)) return FALSE; /* Send socket command to server */
  17352.    if (!NNMgsrvl(np,&lp)) return FALSE;  /* Get server line */
  17353.    switch (np->nntp_message_num) {
  17354.      case 281: /* authorization OK */
  17355.                return TRUE;
  17356.      case 502: /* access to server denied */
  17357.                /* Also, we have been disconnected at this point. */
  17358.                connection_probably_closed = TRUE;
  17359.                auth_error = TRUE;
  17360.                break;
  17361.      default:  NNMrperr(np);       /* Report protocol error */
  17362.                auth_error = TRUE;
  17363.                break;
  17364.    }
  17365.  }
  17366.  
  17367.  NNMesrvr(np);                   /* End server read */
  17368.  
  17369.  if (auth_error) {
  17370.  
  17371.    if (connection_probably_closed) {
  17372.      ERR2("Authorization failed;\
  17373. The NNTP server at %s refuses to authorize you.  \
  17374. Some news operations may fail.",\
  17375.           np->nnserver);
  17376.      /* np->connection_broken = TRUE; */
  17377.      /* NNMdisc(np); */               /* Complete disconnection */
  17378.      return FALSE;
  17379.    }
  17380.    else {
  17381.      if (np->batch_mode) {
  17382.        fprintf(stderr,
  17383.         "NNMVS could not obtain authorization from the NNTP server.\n");
  17384.        fprintf(stderr,
  17385.         "NNMVS will proceed, but some news operations may fail.\n");
  17386.        fprintf(stderr,
  17387.         "The response from server %s was:\n\n%s\n\n", np->nnserver,lp);
  17388.        return FALSE;
  17389.      }
  17390.      else {
  17391.        NNMivput(np,"NNSRVRSP ",lp,          -1);
  17392.        (void)NNMispf(np,"ADDPOP ");
  17393.        (void)NNMispf(np,"DISPLAY PANEL(NNMPAUTH)");
  17394.        display_rc = np->ispfrc;
  17395.        (void)NNMispf(np,"REMPOP ");
  17396.        if (display_rc == 0) return FALSE;
  17397.        else {
  17398.          /* NNMdisc(np); */
  17399.          return FALSE;
  17400.        }
  17401.      }
  17402.    }
  17403.  }
  17404.  
  17405.  return TRUE;
  17406.  
  17407. }
  17408.  
  17409. /****** Input one character from the server. *************************/
  17410.  
  17411. static int
  17412. socket_getchar(np)
  17413. Rstruc nncb  *np;
  17414. {
  17415.  int         readrc;
  17416.  
  17417.  if (np->g_buf_index == -1 ||
  17418.      np->g_buf_index >= np->g_bytes_returned - 1) {
  17419.    np->g_buf_index = -1;
  17420.    if (np->dont_read) return(SOCKET_NO_MORE);
  17421.    else {
  17422.      TCP_DEBUG_ON;
  17423.      readrc = read(np->socknum, np->g_buf, READ_BYTES);
  17424.      TCP_DEBUG_OFF;
  17425.      if (readrc == -1) {
  17426.        np->connection_broken = TRUE;
  17427.        return SOCKET_GETCHAR_ERROR;
  17428.      }
  17429.      else if (readrc == 0) {
  17430.        np->connection_broken = TRUE;
  17431.        return SOCKET_READ_NOTHING;
  17432.      }
  17433.      else {
  17434. #ifdef MVS
  17435.        ASCII_TO_EBCDIC(np->g_buf,readrc);
  17436. #endif
  17437.        np->g_bytes_returned = readrc;
  17438.        if (np->debug_file) {
  17439.          NNMdump(np,"Data read from server",np->g_buf,readrc);
  17440.        }
  17441.      }
  17442.    }
  17443.  }
  17444.  return np->g_buf[++np->g_buf_index];
  17445. }
  17446.  
  17447. /****** Input one data line at a time from the server. ***************/
  17448.  
  17449. static enum socket_retval
  17450. socket_from_server(np)
  17451. Rstruc nncb *np;
  17452. {
  17453.  char       *s_buf;
  17454.  int         s_bytes;
  17455.  int         s_buf_index;
  17456.  int         character;
  17457.  int         previous_character;
  17458.  
  17459.  s_buf   = np->server_buf;
  17460.  s_bytes = SERVER_BUF_MSGSIZE;
  17461.  
  17462.  /* Get characters from the server until CRLF is reached. */
  17463.  
  17464.  s_buf_index = 0;
  17465.  previous_character = -1;
  17466.  for (;;) {
  17467.    character = socket_getchar(np);
  17468.    if (character == LINE_FEED && previous_character == CARRIAGE_RETURN)
  17469.       break;
  17470.    if (character == SOCKET_GETCHAR_ERROR)  return(SERVER_READ_ERROR);
  17471.    if (character == SOCKET_NO_MORE)        return(SERVER_NO_MORE);
  17472.    if (character == SOCKET_READ_NOTHING)   return(SERVER_READ_ERROR);
  17473.    previous_character = character;
  17474.    if (s_buf_index >= s_bytes) {
  17475.      fprintf(stderr,"Error: np->server_buf overflowed.\n");
  17476.      fprintf(stderr,
  17477.              "More than %d bytes collected without CR/LF seen.\n",
  17478.              s_bytes);
  17479.      if (np->debug_file) {
  17480.        NNMdump(np,"Data collected so far",np->server_buf,s_bytes);
  17481.      }
  17482.      return(SERVER_BUFFER_ERROR);
  17483.    }
  17484.    if (character == '\0') {
  17485.      fprintf(stderr,
  17486. "Warning: null character found in data from server, changed to blank\n"
  17487.             );
  17488.      character = ' ';
  17489.    }
  17490.    s_buf[s_buf_index++] = (unsigned char)character;
  17491.  }
  17492.  s_buf[s_buf_index] = '\0';
  17493.  return(SERVER_READ_OK);
  17494. }
  17495.  
  17496. /****** Try to reconnect. ********************************************/
  17497.  
  17498. static Bool
  17499. try_to_reconnect(np)
  17500. Rstruc nncb     *np;
  17501. {
  17502.  
  17503.  if (np->closing_connection || np->reconnect_in_progress) return FALSE;
  17504.  
  17505.  if (!NNMrecon(np)) return FALSE;      /* Reconnect to server */
  17506.  
  17507.  /* have to reissue most recently written command */
  17508.  
  17509.  if (np->dont_reissue_socket_command) {
  17510.    NNMesrvr(np);           /* End server read */
  17511.  }
  17512.  else if (!NNMsockt(np)) { /* Send socket command to server */
  17513.    return FALSE;
  17514.  }
  17515.  
  17516.  WARN2("Successfully reconnected to server %s after disconnect.",
  17517.        np->nnserver);
  17518.  return TRUE;
  17519.  
  17520. }
  17521.  
  17522. /****** Try to authorize. ********************************************/
  17523.  
  17524. static Bool
  17525. try_to_authorize(np)
  17526. Rstruc nncb     *np;
  17527. {
  17528.  char            save_command[CLIENT_BUF_MSGSIZE+4];
  17529.  Bool            rc;
  17530.  
  17531.  if (np->closing_connection) return FALSE;
  17532.  
  17533.  NNMesrvr(np);           /* End server read */
  17534.  
  17535.  strcpy(save_command,np->nntp_command);
  17536.  rc = NNMgauth(np);                    /* Get authorization   */
  17537.  strcpy(np->nntp_command,save_command);
  17538.  if (!rc) return FALSE;
  17539.  
  17540.  /* have to reissue most recently written command */
  17541.  
  17542.  if (np->dont_reissue_socket_command) {
  17543.    NNMesrvr(np);           /* End server read */
  17544.  }
  17545.  else if (!NNMsockt(np)) { /* Send socket command to server */
  17546.    return FALSE;
  17547.  }
  17548.  
  17549.  return TRUE;
  17550.  
  17551. }
  17552.  
  17553. /****** Try to get something. ****************************************/
  17554.  
  17555. static int
  17556. try_to_get_something(np,pointer)
  17557. Rstruc nncb  *np;
  17558. char        **pointer;
  17559.  
  17560. {
  17561.  char              *sbufp;
  17562.  char              *p;
  17563.  int                scan_count;
  17564.  Bool               authorization_required;  /* put this in nncb? */
  17565.  
  17566.  authorization_required = FALSE;
  17567.  
  17568.  switch (socket_from_server(np)) {
  17569.    case SERVER_READ_OK:      break;
  17570.    case SERVER_READ_ERROR:   ERR2(
  17571.      "Lost server connection.  Failure reading data from server %s.",
  17572.                                   np->nnserver);
  17573.                              np->time_to_go_home = TRUE;
  17574.                              break;
  17575.    case SERVER_BUFFER_ERROR: ERR2(
  17576.  "Read error.  No linefeed character found in data from server %s.",
  17577.                                   np->nnserver);
  17578.                              np->time_to_go_home = TRUE;
  17579.                              break;
  17580.    case SERVER_NO_MORE:      np->server_has_something_pending = FALSE;
  17581.                              break;
  17582.  }
  17583.  
  17584.  if (np->connection_broken)  return GOT_DISCONNECT;
  17585.  if (np->time_to_go_home)    return GOT_NOTHING;
  17586.  if (np->dont_read && !np->server_has_something_pending)
  17587.                              return GOT_SOMETHING;
  17588.  
  17589.  np->something_to_print = TRUE;
  17590.  
  17591.  sbufp = np->server_buf;
  17592.  
  17593.  if (np->sending_text) {
  17594.    if (*sbufp == '.') {
  17595.      /*
  17596.      NNMdump(np,"Line that starts with a period",sbufp,strlen(sbufp));
  17597.      */
  17598.      switch (*(sbufp+1)) {
  17599.         case CARRIAGE_RETURN:
  17600.         case LINE_FEED:
  17601.         case '\0':
  17602.                   np->server_finished_replying = TRUE;
  17603.                /* np->something_to_print = FALSE; */
  17604.                   break;
  17605.         case '.':
  17606.                   break;
  17607.         default:
  17608.                   NNMdump(np,"Warning, bad period in line from server",
  17609.                           sbufp,strlen(sbufp));
  17610.                   break;
  17611.      }
  17612.    }
  17613.    else /* nothing - still sending that there text */ ;
  17614.  
  17615.    np->nntp_message_num  = NO_NNTP_MESSAGE_NUM;
  17616.    np->nntp_message_text = sbufp;
  17617.  }
  17618.  else {
  17619.        np->nntp_message_num = NO_NNTP_MESSAGE_NUM;
  17620.        scan_count = 0;
  17621.        sscanf(sbufp,"%d %n",&np->nntp_message_num,&scan_count);
  17622.        np->nntp_message_text = sbufp + scan_count;
  17623.        /*  NNMdump(np,"message_num", np->nntp_message_num, -2);  */
  17624.        /*  NNMdump(np,"message_text",np->nntp_message_text,-1);  */
  17625.        switch (np->nntp_message_num) {
  17626.           case 205:
  17627.           case 400:
  17628.        /* case 502: */
  17629.                    np->server_finished_replying = TRUE;
  17630.                    np->time_to_go_home = TRUE;
  17631.                    break;
  17632.           case 503:
  17633.                    np->server_finished_replying = TRUE;
  17634.                    np->connection_broken = TRUE;
  17635.                    np->time_to_go_home = TRUE;
  17636.                    np->g_bytes_returned = 0;
  17637.                    np->g_buf_index = -1;
  17638.                    np->something_to_print = FALSE;
  17639.                    break;
  17640.           case 380:
  17641.           case 480:
  17642.                    authorization_required = TRUE;
  17643.                    np->server_finished_replying = TRUE;
  17644.                    np->connection_broken = FALSE;
  17645.                    np->g_bytes_returned = 0;
  17646.                    np->g_buf_index = -1;
  17647.                    np->something_to_print = FALSE;
  17648.                    break;
  17649.           case 335:
  17650.           case 340:
  17651.                    np->server_finished_replying = TRUE;
  17652.                    np->receiving_text = TRUE;
  17653.                    break;
  17654.           case 100:
  17655.           case 199:
  17656.           case 215:
  17657.           case 220:
  17658.           case 221:
  17659.           case 222:
  17660.           case 230:
  17661.           case 231:
  17662.                    np->sending_text = TRUE;
  17663.                    break;
  17664.           case NO_NNTP_MESSAGE_NUM:
  17665.                    fprintf(stderr,
  17666.     "Error: No NNTP message ID number in response from server %s.\n",
  17667.                                   np->nnserver);
  17668.                    np->sending_text = TRUE;
  17669.                    np->receiving_text = FALSE;
  17670.                    break;
  17671.           default:
  17672.                    np->server_finished_replying = TRUE;
  17673.                    break;
  17674.    }
  17675.  }
  17676.  
  17677.  if (np->something_to_print) {
  17678.    /* Last character of output buffer is a CR without LF. */
  17679.    p = sbufp + strlen(sbufp)-1;
  17680.    if (p >= sbufp) {
  17681.      if (*p == CARRIAGE_RETURN) *p = '\0';
  17682.      else {
  17683.        fprintf(stderr,
  17684.    "Warning: No carriage return in data from server (%d bytes):\n%s\n",
  17685.                strlen(sbufp), sbufp);
  17686.          CRIT2(
  17687. "Carriage return expected but not seen in data from server %s.",
  17688.                np->nnserver);
  17689.           }
  17690.    }
  17691.    *pointer = sbufp;
  17692.  }
  17693.  
  17694.  if (np->debug_file) {
  17695.    NNMdump(np,"Response from server",sbufp,strlen(sbufp));
  17696.  }
  17697.  
  17698.  return (
  17699.          np->connection_broken        ? GOT_DISCONNECT
  17700.        : authorization_required       ? GOT_NOTAUTHORIZED
  17701.        : np->time_to_go_home          ? GOT_NOTHING
  17702.        :                                GOT_SOMETHING
  17703.         );
  17704. }
  17705.  
  17706. /****** Get server line. *********************************************/
  17707.  
  17708. Bool
  17709. NNMgsrvl(np,pointer)
  17710. Rstruc nncb  *np;
  17711. char        **pointer;
  17712. {
  17713.  int                tries;
  17714.  Bool               retry;
  17715.  Bool               rc;
  17716.  
  17717.  *pointer = NULL;
  17718.  
  17719.  if (np->receiving_text) { /* as when POSTing a news item... */
  17720.    return TRUE;
  17721.  }
  17722.  
  17723.  if (np->server_finished_replying) np->dont_read = TRUE;
  17724.  
  17725.  for (tries=0;tries<2;tries++) {
  17726.  
  17727.    switch (try_to_get_something(np,pointer)) {
  17728.      case GOT_SOMETHING:     return TRUE;
  17729.      case GOT_NOTHING:       return FALSE;
  17730.      case GOT_DISCONNECT:    if (try_to_reconnect(np)) continue;
  17731.                              else return FALSE;
  17732.      case GOT_NOTAUTHORIZED: if (try_to_authorize(np)) continue;
  17733.                              else return FALSE;
  17734.    }
  17735.  
  17736.  }
  17737.  
  17738. }
  17739.  
  17740. ./ ADD NAME=NNMIERR
  17741.  
  17742.  /********************************************************************/
  17743.  /*                                                                  */
  17744.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  17745.  /*                                                                  */
  17746.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  17747.  /* including the implied warranties of merchantability and fitness, */
  17748.  /* are expressly denied.                                            */
  17749.  /*                                                                  */
  17750.  /* Provided this copyright notice is included, this software may    */
  17751.  /* be freely distributed and not offered for sale.                  */
  17752.  /*                                                                  */
  17753.  /* Changes or modifications may be made and used only by the maker  */
  17754.  /* of same, and not further distributed.  Such modifications should */
  17755.  /* be mailed to the author for consideration for addition to the    */
  17756.  /* software and incorporation in subsequent releases.               */
  17757.  /*                                                                  */
  17758.  /********************************************************************/
  17759.  
  17760. #pragma  csect(code,  "NN@IERR ")
  17761. #pragma  csect(static,"NN$IERR ")
  17762. #include "nn.h"
  17763.  
  17764. /****** ISPF error handler. ******************************************/
  17765.  
  17766. void
  17767. NNMierr(np)
  17768. Rstruc nncb *np;
  17769. {
  17770.  char        errbuf[] = "DISPLAY PANEL(ISPTERM)";
  17771.  int         errlen;
  17772.  
  17773.  if (np->batch_mode) {
  17774.    fprintf(stderr,"ISPF services cannot be called from batch mode.\n");
  17775.    return;
  17776.  }
  17777.  
  17778.  errlen = strlen(errbuf);
  17779.  switch (ISPEXEC(&errlen,errbuf)) {
  17780.    case  0:
  17781.    case  4:
  17782.    case  8: break;
  17783.    default: fprintf(stderr,
  17784. "\n*** Severe ISPF error, cannot even display ISPTERM error panel.\n");
  17785.             fprintf(stderr,
  17786. "\n*** Return code from ISPF service is %d\n",np->ispfrc);
  17787.             break;
  17788.  }
  17789.  
  17790.  return;
  17791. }
  17792.  
  17793. ./ ADD NAME=NNMIGET
  17794.  
  17795.  /********************************************************************/
  17796.  /*                                                                  */
  17797.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  17798.  /*                                                                  */
  17799.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  17800.  /* including the implied warranties of merchantability and fitness, */
  17801.  /* are expressly denied.                                            */
  17802.  /*                                                                  */
  17803.  /* Provided this copyright notice is included, this software may    */
  17804.  /* be freely distributed and not offered for sale.                  */
  17805.  /*                                                                  */
  17806.  /* Changes or modifications may be made and used only by the maker  */
  17807.  /* of same, and not further distributed.  Such modifications should */
  17808.  /* be mailed to the author for consideration for addition to the    */
  17809.  /* software and incorporation in subsequent releases.               */
  17810.  /*                                                                  */
  17811.  /********************************************************************/
  17812.  
  17813. #pragma  csect(code,  "NN@IGET ")
  17814. #pragma  csect(static,"NN$IGET ")
  17815. #include "nn.h"
  17816.  
  17817. /****** Retrieve the value of an ISPF variable into an integer. ******/
  17818.  
  17819. int
  17820. NNMiget(np,varname)
  17821. Rstruc nncb *np;
  17822. char        *varname;
  17823. {
  17824.  char        varbuf[16];
  17825.  int         vcopy_length;
  17826.  
  17827.  if (!strchr(varname,' ')) {
  17828.    fprintf(stderr,"NNMiget: no blank passed in var name\n");
  17829.    return FALSE;
  17830.  }
  17831.  
  17832.  vcopy_length = sizeof(varbuf);
  17833.  
  17834.  np->ispfrc = ISPLINK("VCOPY",varname,&vcopy_length,varbuf,"MOVE");
  17835.  switch (np->ispfrc) {
  17836.    case  0:
  17837.            varbuf[vcopy_length] = '\0';
  17838.            return atoi(varbuf);
  17839.    case  8:
  17840.            return 0;
  17841.    case 16:
  17842.            fprintf(stderr,
  17843.                    "Error: ISPF variable buffer too short to get %s\n",
  17844.                    varname);
  17845.            return 0;
  17846.    default:
  17847.            NNMierr(np);   /* handle ISPF error */
  17848.            return 0;
  17849.  }
  17850. }
  17851.  
  17852. ./ ADD NAME=NNMINIT
  17853.  
  17854.  /********************************************************************/
  17855.  /*                                                                  */
  17856.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  17857.  /*                                                                  */
  17858.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  17859.  /*                                                                  */
  17860.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  17861.  /* including the implied warranties of merchantability and fitness, */
  17862.  /* are expressly denied.                                            */
  17863.  /*                                                                  */
  17864.  /* Provided this copyright notice is included, this software may    */
  17865.  /* be freely distributed and not offered for sale.                  */
  17866.  /*                                                                  */
  17867.  /* Changes or modifications may be made and used only by the maker  */
  17868.  /* of same, and not further distributed.  Such modifications should */
  17869.  /* be mailed to the author for consideration for addition to the    */
  17870.  /* software and incorporation in subsequent releases.               */
  17871.  /*                                                                  */
  17872.  /********************************************************************/
  17873.  
  17874. #pragma  csect(code,  "NN@INIT ")
  17875. #pragma  csect(static,"NN$INIT ")
  17876. #include "nn.h"
  17877.  
  17878. #define ARGSIZE            72
  17879.  
  17880. #define clear_subject(X)   if ((X)->selsubj) {*(X)->selsubj = '\0';}
  17881. #define subjectlt(X)       subjectcmp(X) < 0
  17882. #define NO_COMPARISON      TRUE
  17883. #define subjectmatch       NNMsumat(_subj,_ap->subject)
  17884. #define SEMI               ;
  17885. #define NOTHINGFUN(A)      /* */
  17886. #define ANYFUN(A)          SetUnknown(A)
  17887. #define NOFUN(A)           /* */
  17888. #define SETSUBJECTFUN(A)   _subj = set_subject(np,A->subject)
  17889. #define NOSUBJECTFUN(A)    clear_subject(np)
  17890.  
  17891. #define SEARCH_FIRST_TO_LAST(Apnew,Apold,Initfun,Compfun,Any) \
  17892.         SEARCH(Apnew,Apold,Initfun##FUN,Compfun,Any##FUN,\
  17893.          (_wp = _wpfirst SEMI _wp <= _wplast SEMI _wp++),\
  17894.          (_vp = _vpfirst SEMI _vp <= _vplast SEMI _vp++))
  17895.  
  17896. #define SEARCH_LAST_TO_FIRST(Apnew,Apold,Initfun,Compfun,Any) \
  17897.         SEARCH(Apnew,Apold,Initfun##FUN,Compfun,Any##FUN,\
  17898.          (_wp = _wplast SEMI _wp >= _wpfirst SEMI _wp--),\
  17899.          (_vp = _vplast SEMI _vp >= _vpfirst SEMI _vp--))
  17900.  
  17901. #define SEARCH_CURRENT_TO_FIRST(Apnew,Apold,Initfun,Compfun,Any) \
  17902.         SEARCH(Apnew,Apold,Initfun##FUN,Compfun,Any##FUN,\
  17903.  (_wp = (np->current_sortvark-1) SEMI  _wp >= _wpfirst SEMI  _wp--),\
  17904.  (_vp = &GETVARK(gp,Apold->number)-1 SEMI  _vp >= _vpfirst SEMI  _vp--))
  17905.  
  17906. #define SEARCH_CURRENT_TO_LAST(Apnew,Apold,Initfun,Compfun,Any) \
  17907.         SEARCH(Apnew,Apold,Initfun##FUN,Compfun,Any##FUN,\
  17908.  (_wp = (np->current_sortvark+1) SEMI  _wp <= _wplast SEMI  _wp++),\
  17909.  (_vp = &GETVARK(gp,Apold->number)+1 SEMI  _vp <= _vplast SEMI  _vp++))
  17910.  
  17911. #define SEARCH(Apnew,Apold,Initexp,Compexp,Anyexp,Forwp,Forvp) \
  17912.  {\
  17913.   struct newsarticle  *_ap;\
  17914.   VARK                *_vp;\
  17915.   VARK                *_vpfirst;\
  17916.   VARK                *_vplast;\
  17917.   VARK               **_wp;\
  17918.   VARK               **_wpfirst;\
  17919.   VARK               **_wplast;\
  17920.   char                *_subj;\
  17921. \
  17922.   Initexp(Apold);\
  17923.   Apnew = NULL;\
  17924.    if (gp->sort_vector) {\
  17925.      _wpfirst = gp->sort_vector;\
  17926.      _wplast  = gp->sort_vector + gp->sort_count - 1;\
  17927.      for Forwp {\
  17928.        vp = *_wp;\
  17929.        Anyexp(*vp);\
  17930.        if (NNMcar(np,gp,0,vp,&_ap,&cd,RETRIEVE) && (Compexp)) {\
  17931.          np->current_sortvark = _wp;\
  17932.          Apnew = _ap;\
  17933.          break;\
  17934.        }\
  17935.      }\
  17936.    }\
  17937.    else if (gp->article_vector) {\
  17938.      _vpfirst = &GETVARKFIRST(gp);\
  17939.      _vplast  = &GETVARKLAST(gp);\
  17940.      for Forvp {\
  17941.        vp = _vp;\
  17942.        Anyexp(*vp);\
  17943.        if (NNMcar(np,gp,0,vp,&_ap,&cd,RETRIEVE) && (Compexp)) {\
  17944.          Apnew = _ap;\
  17945.          break;\
  17946.        }\
  17947.      }\
  17948.    }\
  17949.  }
  17950.  
  17951. #define ERROR_NEXT_ARTICLE              \
  17952.              "There are no further articles in this newsgroup."
  17953. #define ERROR_PREV_ARTICLE              \
  17954.              "There are no previous articles in this newsgroup."
  17955. #define ERROR_NEXT_TABLED_ARTICLE       \
  17956.  "There are no more news articles that satisfy the current criteria."
  17957. #define ERROR_PREV_TABLED_ARTICLE       \
  17958. "There are no previous news articles that satisfy the current criteria."
  17959. #define ERROR_NEXT_UNREAD_ARTICLE       \
  17960.             "There are no further unread articles in this newsgroup."
  17961. #define ERROR_PREV_UNREAD_ARTICLE       \
  17962.            "There are no previous unread articles in this newsgroup."
  17963. #define ERROR_NEXT_THREAD_ARTICLE       \
  17964.    np->show_all_articles ? \
  17965.    "There are no further articles on this subject in this newsgroup." \
  17966.    : \
  17967.    "No further UNREAD articles on this subject in this newsgroup."
  17968. #define ERROR_PREV_THREAD_ARTICLE       \
  17969.    np->show_all_articles ? \
  17970.   "There are no previous articles on this subject in this newsgroup." \
  17971.    : \
  17972.   "No previous UNREAD articles on this subject in this newsgroup."
  17973. #define ERROR_FIRST_THREAD_ARTICLE      \
  17974.    np->show_all_articles ? \
  17975.   "No other article could be found on this subject in this newsgroup." \
  17976.    : \
  17977.   "No UNREAD article could be found on this subject in this newsgroup."
  17978. #define ERROR_LAST_THREAD_ARTICLE       \
  17979.    np->show_all_articles ? \
  17980.   "No other article could be found on this subject in this newsgroup." \
  17981.    : \
  17982.   "No UNREAD article could be found on this subject in this newsgroup."
  17983. #define ERROR_NEW_THREAD_ARTICLE        \
  17984.   "There are no unread articles on other subjects in this newsgroup."
  17985.  
  17986. #define CDSET cd.do_update = (np->updatefreq >= 0);\
  17987.               cd.done = 0;\
  17988.               if (cd.do_update && gp->article_vector) {\
  17989.                 cd.to_do = 0;\
  17990.                 for (vp = vpfirst; vp <= vplast; vp++) {\
  17991.                   if (IsNull(*vp)) cd.to_do++;\
  17992.                 }\
  17993.               }\
  17994.               else cd.to_do = -1
  17995.  
  17996. enum getop_option {
  17997.                    GETOP_NOMORE,
  17998.                    GETOP_ASIS,
  17999.                    GETOP_UPPERCASE,
  18000.                    GETOP_LOWERCASE,
  18001.                    GETOP_INTEGER
  18002.                   };
  18003.  
  18004. /****** Get the next operand of the command. *************************/
  18005.  
  18006. static Bool
  18007. getop(np,bufpp,argp,option)
  18008. Rstruc nncb            *np;
  18009. char                  **bufpp;
  18010. char                   *argp;
  18011. enum getop_option       option;
  18012. {
  18013.  register char         *icp;
  18014.  register char         *ocp;
  18015.  register int           olen;
  18016.  int                    maxlen;
  18017.  char                   quote;
  18018.  char                   work[12];
  18019.  
  18020.  icp = skip_ISPF_whitespace(*bufpp);
  18021.  if (!*icp) {                          /* if reached end of buffer  */
  18022.    *bufpp = icp;
  18023.    switch (option) {
  18024.      case GETOP_NOMORE:  return TRUE;            /* indicate no more */
  18025.      case GETOP_INTEGER: ERR1("A numeric integer value is required.");
  18026.                          return FALSE;
  18027.      default:            *argp = '\0';  /* set operand to null string*/
  18028.                          return TRUE;
  18029.    }
  18030.  }
  18031.  
  18032.  /* icp points to next argument in buffer */
  18033.  
  18034.  if (option == GETOP_NOMORE) return FALSE;   /* too many operands */
  18035.  
  18036.  if (option == GETOP_INTEGER) {
  18037.    ocp = work;
  18038.    maxlen = sizeof(work);
  18039.    quote = '\0';
  18040.   }
  18041.  else {
  18042.    ocp = argp;
  18043.    maxlen = ARGSIZE;
  18044.    switch (*icp) {
  18045.      case '\'':
  18046.      case '"' :  quote = *icp; break;
  18047.      default:    quote = '\0'; break;
  18048.    }
  18049.  }
  18050.  
  18051.  if (quote) {
  18052.    for (icp++,olen=0; ; icp++,ocp++,olen++) {
  18053.      if (!*icp) {
  18054.        ERR1("Beginning quote mark not matched by ending quote mark.");
  18055.        *bufpp = icp;
  18056.        return FALSE;
  18057.      }
  18058.      if (*icp == quote) {
  18059.        if (*(++icp) != quote) {
  18060.          *bufpp = icp;
  18061.          break;
  18062.        }
  18063.      }
  18064.      if (olen <= maxlen) {
  18065.        switch (option) {
  18066.          case GETOP_LOWERCASE:  *ocp = tolower(*icp); break;
  18067.          case GETOP_UPPERCASE:  *ocp = toupper(*icp); break;
  18068.          default:               *ocp = *icp;          break;
  18069.        }
  18070.      }
  18071.    }
  18072.    if (olen > maxlen) {
  18073.      ERR2("An operand longer than %d characters is not valid.", maxlen);
  18074.      return FALSE;
  18075.    }
  18076.  }
  18077.  else {
  18078.    find_ISPF_whitespace(*bufpp,icp);
  18079.    olen = *bufpp - icp;
  18080.  
  18081.    if (olen > maxlen) {
  18082.      ERR2("An operand longer than %d characters is not valid.", maxlen);
  18083.      return FALSE;
  18084.    }
  18085.  
  18086.    switch (option) {
  18087.      case GETOP_LOWERCASE: while (olen--) *ocp++ = tolower(*icp++);
  18088.                            break;
  18089.      case GETOP_UPPERCASE: while (olen--) *ocp++ = toupper(*icp++);
  18090.                            break;
  18091.      default:              while (olen--) *ocp++ = *icp++;
  18092.                            break;
  18093.    }
  18094.  }
  18095.  
  18096.  *ocp = '\0';
  18097.  
  18098.  if (option == GETOP_INTEGER) {
  18099.    if (*(work + strspn(work,"0123456789"))) {
  18100.      ERR1("A numeric integer value is required.");
  18101.      return FALSE;
  18102.    }
  18103.    *(int *)argp = atoi(work);
  18104.  }
  18105.  
  18106.  return TRUE;
  18107.  
  18108. }
  18109.  
  18110. /****** Subject compare, for locating by subject. ********************/
  18111.  
  18112. /* May want to emulate NNMstrlc for more efficiency.  All that is
  18113.  * needed is to add code to NNMstrlc to strip re's.
  18114.  */
  18115.  
  18116. static int
  18117. subjectcmp(a,b)
  18118. char        *a;
  18119. char        *b;
  18120. {
  18121.  char       *c1;
  18122.  char       *c2;
  18123.  int         re_count_1;
  18124.  int         re_count_2;
  18125.  int         answer;
  18126.  char        s2[257];
  18127.  
  18128.  /* arg 1 already lowercased */
  18129.  
  18130.  strncpy(s2,b,256);
  18131.  
  18132.  lowercase_and_strip_trailing_in_place(s2);
  18133.  
  18134.  c1 = a;
  18135.  c2 = s2;
  18136.  
  18137.  re_count_1 = 0;
  18138.  while (!memcmp(c1,"re:",3)) {
  18139.    c1 = skip_whitespace(c1+3);
  18140.    re_count_1++;
  18141.  }
  18142.  re_count_2 = 0;
  18143.  while (!memcmp(c2,"re:",3)) {
  18144.    c2 = skip_whitespace(c2+3);
  18145.    re_count_2++;
  18146.  }
  18147.  
  18148.  if ((answer=strcmp(c1,c2)) != 0) return answer;
  18149.  else return re_count_1 - re_count_2;
  18150.  
  18151. }
  18152.  
  18153. /****** Mark all articles read. **************************************/
  18154.  
  18155. static Bool
  18156. mark_all_articles_read(np,gp,prompt)
  18157. Rstruc nncb          *np;
  18158. Rstruc newsgroup     *gp;
  18159. Fool                  prompt;
  18160. {
  18161.  int                  prc;
  18162.  VARK                *vp;
  18163.  VARK                *vpfirst;
  18164.  VARK                *vplast;
  18165.  
  18166.  /* Display panel asking if user really wants to do this. */
  18167.  
  18168.  if (prompt && !np->batch_mode) {
  18169.    (void)NNMivput(np,"NNMARK ","Read",-1);
  18170.    (void)NNMispf(np,"ADDPOP");
  18171.    prc = NNMdispl(np,"NNMPMARK");
  18172.    (void)NNMispf(np,"REMPOP");
  18173.    if (prc > 0) { /* see if user pressed END */
  18174.      WARN1("Operation cancelled, because you pressed END.");
  18175.      return TRUE;
  18176.    }
  18177.  }
  18178.  
  18179.  if (gp->article_vector) {
  18180.    vpfirst = &GETVARKFIRST(gp);
  18181.    vplast  = &GETVARKLAST(gp);
  18182.    for (vp = vpfirst; vp <= vplast; vp++) {
  18183.      SetRead(*vp);
  18184.    }
  18185.  }
  18186.  else {  /* no article vector, group was never selected */
  18187.    if (gp->saved_newsrc_line
  18188.     && gp->saved_newsrc_line != gp->saved_newsrc_data) {
  18189.      FREEMAIN(gp->saved_newsrc_line,"unparsed newsrc line");
  18190.    }
  18191.    gp->saved_newsrc_line = gp->saved_newsrc_data;
  18192.    sprintf(gp->saved_newsrc_data,"<%d",gp->high_number);
  18193.  }
  18194.  
  18195.  gp->unread_count = 0;
  18196.  
  18197.  WARN2("All of the articles in %s are now marked READ.",
  18198.        gp->name);
  18199.  
  18200.  return TRUE;
  18201. }
  18202.  
  18203. /****** Mark all articles unread. ************************************/
  18204.  
  18205. static Bool
  18206. mark_all_articles_unread(np,gp,prompt)
  18207. Rstruc nncb          *np;
  18208. Rstruc newsgroup     *gp;
  18209. Fool                  prompt;
  18210. {
  18211.  int                  prc;
  18212.  int                  uc;
  18213.  VARK                *vp;
  18214.  VARK                *vpfirst;
  18215.  VARK                *vplast;
  18216.  
  18217.  /* Display panel asking if user really wants to do this. */
  18218.  
  18219.  if (prompt && !np->batch_mode) {
  18220.    (void)NNMivput(np,"NNMARK ","Unread",-1);
  18221.    (void)NNMispf(np,"ADDPOP");
  18222.    prc = NNMdispl(np,"NNMPMARK");
  18223.    (void)NNMispf(np,"REMPOP");
  18224.    if (prc > 0) { /* see if user pressed END */
  18225.      WARN1("Operation cancelled, because you pressed END.");
  18226.      return TRUE;
  18227.    }
  18228.  }
  18229.  
  18230.  if (gp->article_vector) {
  18231.    uc = 0;
  18232.    vpfirst = &GETVARKFIRST(gp);
  18233.    vplast  = &GETVARKLAST(gp);
  18234.    for (vp = vpfirst; vp <= vplast; vp++) {
  18235.      /* Note that we don't mark missing articles unread. */
  18236.      if (IsPresent(*vp)) {
  18237.        if (IsRead(*vp)) uc++;
  18238.        SetUnread(*vp);
  18239.      }
  18240.    }
  18241.    gp->unread_count += uc;
  18242.  }
  18243.  else {  /* no article vector, group was never selected */
  18244.    if (gp->saved_newsrc_line
  18245.     && gp->saved_newsrc_line != gp->saved_newsrc_data) {
  18246.      FREEMAIN(gp->saved_newsrc_line,"unparsed newsrc line");
  18247.    }
  18248.    gp->saved_newsrc_line = gp->saved_newsrc_data;
  18249.    strcpy(gp->saved_newsrc_data,"<0");
  18250.    gp->unread_count = gp->article_count;
  18251.  }
  18252.  
  18253.  WARN2("All of the articles in %s are now marked UNREAD.",
  18254.        gp->name);
  18255.  
  18256.  return TRUE;
  18257. }
  18258.  
  18259. /****** Set subject. *************************************************/
  18260.  
  18261. static char *
  18262. set_subject(np,subj)
  18263. Rstruc nncb         *np;
  18264. char                *subj;
  18265. {
  18266.  char               *s;
  18267.  
  18268.  if (*np->selsubj) return np->selsubj;
  18269.  
  18270.  strncpy(np->selsubj, subj, sizeof(np->selsubj)-1);
  18271.  s = np->selsubj;
  18272.  lowercase_and_strip_trailing_in_place(s);
  18273.  while (!memcmp(s,"re:",3)) {
  18274.    s = skip_whitespace(s+3);
  18275.  }
  18276.  
  18277.  return s;
  18278.  
  18279. }
  18280.  
  18281. /****** Process newsgroup LOCATE command. ****************************/
  18282.  
  18283. static Bool
  18284. newsgroup_locate_command(np,gp,rest)
  18285. Rstruc nncb         *np;
  18286. Rstruc newsgroup    *gp;
  18287. char                *rest;
  18288. {
  18289.  char                string[ARGSIZE];
  18290.  
  18291.  /*
  18292.   * Pass back the group name to position to.  NNMVNG will do the rest.
  18293.   */
  18294.  
  18295.  if (!getop(np,&rest,&string,GETOP_LOWERCASE)) return FALSE;
  18296.  
  18297.  if (!*string || !getop(np,&rest,NULL,GETOP_NOMORE)) {
  18298.    ERR1("The LOCATE command requires exactly one operand.");
  18299.    return FALSE;
  18300.  }
  18301.  
  18302.  strcpy(np->newsgroup_locate_string, string);
  18303.  
  18304.  np->please_locate_group = TRUE;
  18305.  
  18306.  return TRUE;
  18307. }
  18308.  
  18309. /****** Process newsgroup ONLY command. ******************************/
  18310.  
  18311. static Bool
  18312. newsgroup_only_command(np,gp,rest)
  18313. Rstruc nncb         *np;
  18314. Rstruc newsgroup    *gp;
  18315. char                *rest;
  18316. {
  18317.  char                string[ARGSIZE];
  18318.  
  18319.  if (!getop(np,&rest,&string,GETOP_LOWERCASE)) return FALSE;
  18320.  
  18321.  if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
  18322.    ERR1(
  18323. "The ONLY command may have only one operand.  Try quoting the string."
  18324.        );
  18325.    return FALSE;
  18326.  }
  18327.  
  18328.  strcpy(np->newsgroup_only_string, string);
  18329.  
  18330.  np->newsgroup_criterion_changed = TRUE;
  18331.  
  18332.  if (*np->newsgroup_only_string) {
  18333.    WARN2(
  18334.     "To redisplay %s newsgroups, use ONLY command without operands.",
  18335.          (np->show_all_newsgroups ? "all" : "all registered"));
  18336.  }
  18337.  
  18338.  return TRUE;
  18339. }
  18340.  
  18341. /****** Process newsgroup FIND command. ******************************/
  18342.  
  18343. static Bool
  18344. newsgroup_find_command(np,gp,rest)
  18345. Rstruc nncb         *np;
  18346. Rstruc newsgroup    *gp;
  18347. char                *rest;
  18348. {
  18349.  Bool                string_given;
  18350.  Bool                option_given;
  18351.  char                string [ARGSIZE];
  18352.  char                opt    [ARGSIZE];
  18353.  
  18354.  /*
  18355.   * Pass back the group name to position to.  NNMVNG will do the rest.
  18356.   */
  18357.  
  18358.  if (!getop(np,&rest,&string,GETOP_LOWERCASE)) return FALSE;
  18359.  if (!getop(np,&rest,&opt   ,GETOP_LOWERCASE)) return FALSE;
  18360.  
  18361.  if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
  18362.    ERR1(
  18363.     "Too many operands on the FIND command.  Try quoting the string.");
  18364.    return FALSE;
  18365.  }
  18366.  
  18367.  string_given = *string;
  18368.  option_given = *opt;
  18369.  
  18370.  if (string_given) {
  18371.    strcpy(np->newsgroup_find_string,string);
  18372.  }
  18373.  else if (!*np->newsgroup_find_string) {
  18374.    ERR1(
  18375.       "The FIND command requires a string the first time it is used.");
  18376.    return FALSE;
  18377.  }
  18378.  
  18379.  if (option_given) {
  18380.    if      (EQUAL(opt,"next"  )) np->newsgroup_find_option = FIND_NEXT;
  18381.    else if (EQUAL(opt,"first" )) np->newsgroup_find_option = FIND_FIRST;
  18382.    else if (EQUAL(opt,"prev"  )) np->newsgroup_find_option = FIND_PREV;
  18383.    else if (EQUAL(opt,"last"  )) np->newsgroup_find_option = FIND_LAST;
  18384.    else {
  18385.      ERR1("Unknown FIND option.  Specify NEXT, PREV, FIRST or LAST.");
  18386.      return FALSE;
  18387.    }
  18388.  }
  18389.  else {
  18390.    if (string_given)  np->newsgroup_find_option = FIND_NEXT;
  18391.    else switch (np->newsgroup_find_option) {
  18392.      case FIND_NEXT:  np->newsgroup_find_option = FIND_NEXT; break;
  18393.      case FIND_PREV:  np->newsgroup_find_option = FIND_PREV; break;
  18394.      case FIND_FIRST: np->newsgroup_find_option = FIND_NEXT; break;
  18395.      case FIND_LAST:  np->newsgroup_find_option = FIND_PREV; break;
  18396.      default:         np->newsgroup_find_option = FIND_NEXT; break;
  18397.    }
  18398.  }
  18399.  
  18400.  np->please_find_group = TRUE;
  18401.  np->repeat_find = (!string_given && !option_given);
  18402.  
  18403.  return TRUE;
  18404. }
  18405.  
  18406. /****** Process newsgroup EXTRACT command. ***************************/
  18407.  
  18408. static Bool
  18409. newsgroup_extract_command(np,gp,rest)
  18410. Rstruc nncb         *np;
  18411. struct newsgroup    *gp;
  18412. char                *rest;
  18413. {
  18414.  
  18415.  if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
  18416.    ERR1("The EXTRACT command does not accept any operands.");
  18417.    return FALSE;
  18418.  }
  18419.  
  18420.  return NNMxlist(np,SEQ);  /* Extract newsgroup listing */
  18421.  
  18422. }
  18423.  
  18424. /****** Process newsgroup PRINT command. *****************************/
  18425.  
  18426. static Bool
  18427. newsgroup_print_command(np,gp,rest)
  18428. Rstruc nncb         *np;
  18429. struct newsgroup    *gp;
  18430. char                *rest;
  18431. {
  18432.  
  18433.  if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
  18434.    ERR1("The PRINT command does not accept any operands.");
  18435.    return FALSE;
  18436.  }
  18437.  
  18438.  return NNMxlist(np,JES);  /* Extract newsgroup listing */
  18439.  
  18440. }
  18441.  
  18442. /****** Process newsgroup REG command. *******************************/
  18443.  
  18444. static Bool
  18445. newsgroup_reg_command(np,gp,rest)
  18446. Rstruc nncb         *np;
  18447. Rstruc newsgroup    *gp;
  18448. char                *rest;
  18449. {
  18450.  
  18451.  np->newsgroup_criterion_changed = TRUE;
  18452.  np->show_all_newsgroups = FALSE;
  18453.  if (*np->newsgroup_only_string) {
  18454.    WARN2(
  18455.     "To redisplay %s newsgroups, use ONLY command without operands.",
  18456.          (np->show_all_newsgroups ? "all" : "all registered"));
  18457.  }
  18458.  
  18459.  return TRUE;
  18460. }
  18461.  
  18462. /****** Process newsgroup ALL command. *******************************/
  18463.  
  18464. static Bool
  18465. newsgroup_all_command(np,gp,rest)
  18466. Rstruc nncb         *np;
  18467. Rstruc newsgroup    *gp;
  18468. char                *rest;
  18469. {
  18470.  
  18471.  np->newsgroup_criterion_changed = TRUE;
  18472.  np->show_all_newsgroups = TRUE;
  18473.  if (*np->newsgroup_only_string) {
  18474.    WARN2(
  18475.     "To redisplay %s newsgroups, use ONLY command without operands.",
  18476.          (np->show_all_newsgroups ? "all" : "all registered"));
  18477.  }
  18478.  
  18479.  return TRUE;
  18480. }
  18481.  
  18482. /****** Process newsgroup ORDER command. *****************************/
  18483.  
  18484. static Bool
  18485. newsgroup_order_command(np,gp,rest)
  18486. Rstruc nncb         *np;
  18487. Rstruc newsgroup    *gp;
  18488. char                *rest;
  18489. {
  18490.  char                string[ARGSIZE];
  18491.  char                order;
  18492.  
  18493.  /* Usage: ORDER A   -  display newsgroups in alphabetical order
  18494.   *        ORDER L   -  display newsgroups in NNTP list order
  18495.   *        ORDER N   -  display newsgroups in NEWSRC order
  18496.   */
  18497.  
  18498.  if (!getop(np,&rest,&string,GETOP_ASIS)) return FALSE;
  18499.  
  18500.  if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
  18501.    ERR1(
  18502.      "The ORDER command requires one operand: Alphabetical or List.");
  18503.    return FALSE;
  18504.  }
  18505.  
  18506.  switch (string[0]) {
  18507.    case 'a':
  18508.    case 'A': order = ALPHABETICAL_ORDER;  break;
  18509.    case 'l':
  18510.    case 'L': order = NNTP_LIST_ORDER;     break;
  18511.    case 'n':
  18512.    case 'N': order = NEWSRC_ORDER;        break;
  18513.    default:
  18514.              ERR1(
  18515.      "The ORDER command requires one operand: Alphabetical or List.");
  18516.                                           return FALSE;
  18517.  }
  18518.  
  18519.  if (order == NEWSRC_ORDER) {
  18520.    ERR1("Sorry, but NEWSRC order has not been implemented.");
  18521.    return FALSE;
  18522.  }
  18523.  
  18524.  if (order == NNTP_LIST_ORDER && !np->first_newsgroup_alt) {
  18525.    ERR1(
  18526. "List order is valid only when newsgroup list retrieved from server."
  18527.        );
  18528.    return FALSE;
  18529.  }
  18530.  
  18531.  np->newsgroup_order_changed = TRUE;
  18532.  np->newsgroup_order = order;
  18533.  
  18534.  return TRUE;
  18535. }
  18536.  
  18537. /****** Process newsgroup RESCAN command. *DDI************************/
  18538.  
  18539. static Bool
  18540. newsgroup_rescan_command(np,gp,rest)
  18541. Rstruc nncb         *np;
  18542. Rstruc newsgroup    *gp;
  18543. char                *rest;
  18544. {
  18545.  
  18546.  if (!NNMdlang(np,LIST_ALL_RESCAN)) return FALSE;
  18547.  
  18548.  /* Must turn off GroupSelected status so that NNMpng will call NNMdng
  18549.   * when the group is later selected. Pretty nervous about this one.
  18550.   * -DDI
  18551.   */
  18552.  
  18553.  for (gp=np->first_newsgroup; gp; gp=gp->next) {
  18554.    OffGroupSelected(gp);
  18555.  }
  18556.  
  18557.  return TRUE;
  18558. }
  18559.  
  18560. /****** Process article RESCAN command. *DDI**************************/
  18561.  
  18562. static Bool
  18563. article_rescan_command(np,gp,rest)
  18564. Rstruc nncb         *np;
  18565. Rstruc newsgroup    *gp;
  18566. char                *rest;
  18567. {
  18568.  
  18569.  NNMdlang(np,LIST_ALL_RESCAN);
  18570.  np->current_newsgroup = gp;  /* undo NNMdlang's damage */
  18571.  NNMdng(np,gp,NULL);
  18572.  np->article_criterion_changed = TRUE;
  18573.  
  18574.  return TRUE;
  18575. }
  18576.  
  18577. /****** Process article LOCATE command. ******************************/
  18578.  
  18579. static Bool
  18580. article_locate_command(np,gp,rest)
  18581. Rstruc nncb          *np;
  18582. Rstruc newsgroup     *gp;
  18583. char                 *rest;
  18584. {
  18585.  struct newsarticle  *ap;
  18586.  VARK               **wp;
  18587.  VARK               **wpfirst;
  18588.  VARK               **wplast;
  18589.  int                  lnum;
  18590.  struct countdown     cd;
  18591.  char                 string[ARGSIZE];
  18592.  
  18593.  if (gp->sort_vector) {
  18594.    if (!getop(np,&rest,&string,GETOP_LOWERCASE)) return FALSE;
  18595.    if (!*string || !getop(np,&rest,NULL,GETOP_NOMORE)) {
  18596.      ERR1("The LOCATE command requires exactly one operand.");
  18597.      return FALSE;
  18598.    }
  18599.    /* Position to article with subject closest to requested subject */
  18600.    wpfirst = gp->sort_vector;
  18601.    wplast  = gp->sort_vector + gp->sort_count - 1;
  18602.    for (wp = wpfirst; wp < wplast; wp++) {
  18603.      if (NNMcar(np,gp,0,*wp,&ap,&cd,RETRIEVE)
  18604.       && subjectcmp(string,ap->subject) <= 0)
  18605.          break;
  18606.    }
  18607.    np->current_sortvark = wp;
  18608.    np->top_sorted_article = wp;
  18609.  }
  18610.  else {
  18611.    if (!getop(np,&rest,(char *)&lnum,GETOP_INTEGER)) return FALSE;
  18612.    if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
  18613.      ERR1("The LOCATE command requires exactly one operand.");
  18614.      return FALSE;
  18615.    }
  18616.    /* Position to article with number closest to requested number */
  18617.    if (lnum < gp->vector_first) lnum = gp->vector_first;
  18618.    if (lnum > gp->vector_last)  lnum = gp->vector_last;
  18619.    np->top_article = lnum;
  18620.  }
  18621.  
  18622.  /* Note: We don't worry about whether that article, or any of the
  18623.   * articles between the current one and this one, are in the table.
  18624.   * When NNMvar regenerates the display, it will know that the top
  18625.   * article has changed and will figure it out.
  18626.   */
  18627.  
  18628.  return TRUE;
  18629. }
  18630.  
  18631. /****** Process article FIND command. ********************************/
  18632.  
  18633. static Bool
  18634. article_find_command(np,gp,rest)
  18635. Rstruc nncb         *np;
  18636. Rstruc newsgroup    *gp;
  18637. char                *rest;
  18638. {
  18639.  int                 save_top_article;
  18640.  VARK              **save_top_sorted_article;
  18641.  struct newsarticle *ap;
  18642.  VARK               *vp;
  18643.  VARK               *vpfirst;
  18644.  VARK               *vplast;
  18645.  VARK              **wp;
  18646.  VARK              **wpfirst;
  18647.  VARK              **wplast;
  18648.  VARK              **found_sorted_article;
  18649.  int                 found_article;
  18650.  int                 findbump;
  18651.  int                 anum;
  18652.  Bool                string_given;
  18653.  Bool                option_given;
  18654.  char                string [ARGSIZE];
  18655.  char                option [ARGSIZE];
  18656.  struct countdown    cd;
  18657.  
  18658.  if (!getop(np,&rest,&string,GETOP_LOWERCASE)) return FALSE;
  18659.  if (!getop(np,&rest,&option,GETOP_LOWERCASE)) return FALSE;
  18660.  
  18661.  if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
  18662.    ERR1(
  18663.     "Too many operands on the FIND command.  Try quoting the string.");
  18664.    return FALSE;
  18665.  }
  18666.  
  18667.  string_given = *string;
  18668.  option_given = *option;
  18669.  
  18670.  if (string_given) {
  18671.    strcpy(np->article_find_string,string);
  18672.  }
  18673.  else if (!*np->article_find_string) {
  18674.    ERR1(
  18675.       "The FIND command requires a string the first time it is used.");
  18676.    return FALSE;
  18677.  }
  18678.  
  18679.  if (option_given) {
  18680.    if      (EQUAL(option,"next" )) np->article_find_option = FIND_NEXT;
  18681.    else if (EQUAL(option,"first")) np->article_find_option = FIND_FIRST;
  18682.    else if (EQUAL(option,"prev" )) np->article_find_option = FIND_PREV;
  18683.    else if (EQUAL(option,"last" )) np->article_find_option = FIND_LAST;
  18684.    else {
  18685.      ERR1("Unknown FIND option.  Specify NEXT, PREV, FIRST or LAST.");
  18686.      return FALSE;
  18687.    }
  18688.  }
  18689.  else {
  18690.    if (string_given) np->article_find_option = FIND_NEXT;
  18691.    else switch (np->article_find_option) {
  18692.      case FIND_NEXT:  np->article_find_option = FIND_NEXT; break;
  18693.      case FIND_PREV:  np->article_find_option = FIND_PREV; break;
  18694.      case FIND_FIRST: np->article_find_option = FIND_NEXT; break;
  18695.      case FIND_LAST:  np->article_find_option = FIND_PREV; break;
  18696.      default:         np->article_find_option = FIND_NEXT; break;
  18697.    }
  18698.  }
  18699.  
  18700.  np->article_repeat_find = !string_given;
  18701.  
  18702.  /* do the find here */
  18703.  
  18704.  if (gp->sort_vector) {
  18705.    save_top_sorted_article = np->top_sorted_article;
  18706.    wpfirst = gp->sort_vector;
  18707.    wplast  = gp->sort_vector + gp->sort_count - 1;
  18708.    switch (np->article_find_option) {
  18709.      case FIND_NEXT:
  18710.                      findbump = 1;
  18711.                      if (np->article_repeat_find) {
  18712.                        if (np->article_text_not_found)
  18713.                           np->top_sorted_article = wpfirst;
  18714.                        else np->top_sorted_article++;
  18715.                      }
  18716.                      break;
  18717.      case FIND_PREV:
  18718.                      findbump = -1;
  18719.                      if (np->article_repeat_find) {
  18720.                        if (np->article_text_not_found)
  18721.                           np->top_sorted_article = wplast;
  18722.                        else np->top_sorted_article--;
  18723.                      }
  18724.                      break;
  18725.      case FIND_FIRST:
  18726.                      np->top_sorted_article = wpfirst;
  18727.                      findbump = 1;
  18728.                      break;
  18729.      case FIND_LAST:
  18730.                      np->top_sorted_article = wplast;
  18731.                      findbump = -1;
  18732.                      break;
  18733.    }
  18734.  
  18735.    found_sorted_article = NULL;
  18736.    for (wp = np->top_sorted_article;
  18737.         wp <= wplast && wp >= wpfirst; wp += findbump) {
  18738.      /* ap = VARK2PARTICLE(**wp); */
  18739.      if (NNMcar(np,gp,0,*wp,&ap,&cd,RETRIEVE)
  18740.       && NNMstrlc(ap->subject,np->article_find_string)) {
  18741.        found_sorted_article = wp;
  18742.        break;
  18743.      }
  18744.    }
  18745.    if (!found_sorted_article) {
  18746.      np->top_sorted_article = save_top_sorted_article;
  18747.      np->article_text_not_found = TRUE;
  18748.    }
  18749.    else {
  18750.      np->top_sorted_article = found_sorted_article;
  18751.      np->article_text_not_found = FALSE;
  18752.    }
  18753.  }
  18754.  else {  /* not sorted */
  18755.    save_top_article = np->top_article;
  18756.    switch (np->article_find_option) {
  18757.      case FIND_NEXT:
  18758.                      findbump = 1;
  18759.                      if (np->article_repeat_find) {
  18760.                        if (np->article_text_not_found)
  18761.                           np->top_article = gp->vector_first;
  18762.                        else np->top_article++;
  18763.                      }
  18764.                      break;
  18765.      case FIND_PREV:
  18766.                      findbump = -1;
  18767.                      if (np->article_repeat_find) {
  18768.                        if (np->article_text_not_found)
  18769.                           np->top_article = gp->vector_last;
  18770.                        else np->top_article--;
  18771.                      }
  18772.                      break;
  18773.      case FIND_FIRST:
  18774.                      np->top_article = gp->vector_first;
  18775.                      findbump = 1;
  18776.                      break;
  18777.      case FIND_LAST:
  18778.                      np->top_article = gp->vector_last;
  18779.                      findbump = -1;
  18780.                      break;
  18781.    }
  18782.    if (!np->top_article) return FALSE;
  18783.  
  18784.    vpfirst = &GETVARKFIRST(gp);
  18785.    vplast  = &GETVARKLAST(gp);
  18786.  
  18787.    CDSET;
  18788.  
  18789.    found_article = 0;
  18790.  
  18791.    for (anum = np->top_article;
  18792.         anum <= gp->vector_last && anum >= gp->vector_first;
  18793.         anum += findbump) {
  18794.      if (NNMcar(np,gp,anum,NULL,&ap,&cd,RETRIEVE)
  18795.       && NNMstrlc(ap->subject,np->article_find_string)) {
  18796.        found_article = anum;
  18797.        break;
  18798.      }
  18799.    }
  18800.    if (found_article == 0) {
  18801.      np->top_article = save_top_article;
  18802.      np->article_text_not_found = TRUE;
  18803.    }
  18804.    else {
  18805.      np->top_article = found_article;
  18806.      np->article_text_not_found = FALSE;
  18807.    }
  18808.  
  18809.  }
  18810.  
  18811.  if (np->article_text_not_found) {
  18812.    ERR3("No %s articles with subject of: '%s'",
  18813.         (findbump > 0 ? "more" : "previous"),
  18814.         np->article_find_string);
  18815.  }
  18816.  else {
  18817.    WARN1("Article found;\
  18818. The article whose subject contains the desired text tops the display.");
  18819.  }
  18820.  
  18821.  return TRUE;
  18822.  
  18823. }
  18824.  
  18825. /****** Process article ONLY command. *******************************/
  18826.  
  18827. static Bool
  18828. article_only_command(np,gp,rest)
  18829. Rstruc nncb         *np;
  18830. Rstruc newsgroup    *gp;
  18831. char                *rest;
  18832. {
  18833.  char                string[ARGSIZE];
  18834.  VARK               *vp;
  18835.  VARK               *vpfirst;
  18836.  VARK               *vplast;
  18837.  
  18838.  if (!getop(np,&rest,&string,GETOP_LOWERCASE)) return FALSE;
  18839.  
  18840.  if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
  18841.    ERR1(
  18842. "The ONLY command may have only one operand.  Try quoting the string."
  18843.        );
  18844.    return FALSE;
  18845.  }
  18846.  
  18847.  strcpy(np->article_only_string, string);
  18848.  
  18849.  if (gp->article_vector) {
  18850.    vpfirst = &GETVARKFIRST(gp);
  18851.    vplast  = &GETVARKLAST(gp);
  18852.    for (vp = vpfirst; vp <= vplast; vp++) {
  18853.      SetUnknown(*vp);
  18854.    }
  18855.  }
  18856.  
  18857.  np->article_criterion_changed = TRUE;
  18858.  np->top_article = gp->vector_first;
  18859.  np->top_sorted_article = gp->sort_vector;
  18860.  if (*np->article_only_string) {
  18861.    WARN1(
  18862. "To show articles with all subjects, use ONLY command with no operand."
  18863.         );
  18864.  }
  18865.  
  18866.  return TRUE;
  18867. }
  18868.  
  18869. /****** Process article SORT command. *******************************/
  18870.  
  18871. static Bool
  18872. article_sort_command(np,gp,rest)
  18873. Rstruc nncb         *np;
  18874. Rstruc newsgroup    *gp;
  18875. char                *rest;
  18876. {
  18877.  Bool                by_subject;
  18878.  char                string[ARGSIZE];
  18879.  
  18880.  /* Usage: SORT Subject
  18881.   *        SORT Number
  18882.   */
  18883.  
  18884.  if (!getop(np,&rest,&string,GETOP_ASIS)) return FALSE;
  18885.  
  18886.  if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
  18887.    ERR1("The SORT command requires one operand: Subject or Number.");
  18888.    return FALSE;
  18889.  }
  18890.  
  18891.  switch (string[0]) {
  18892.    case 's':
  18893.    case 'S': by_subject = TRUE;  break;
  18894.    case 'n':
  18895.    case 'N': by_subject = FALSE; break;
  18896.    default:
  18897.      ERR1("The SORT command requires one operand: Subject or Number.");
  18898.      return FALSE;
  18899.  }
  18900.  
  18901.  if (!gp->article_vector) {
  18902.    ERR1("There are no articles in this newsgroup to sort.");
  18903.    return TRUE;
  18904.  }
  18905.  
  18906.  if (by_subject) {
  18907.    if (!NNMsort(np,gp)) return FALSE;
  18908.  }
  18909.  else {
  18910.    if (gp->sort_vector) {
  18911.      FREEMAIN(gp->sort_vector,"sort vector");
  18912.      gp->sort_vector = NULL;
  18913.    }
  18914.  }
  18915.  
  18916.  np->article_criterion_changed = TRUE;
  18917.  np->top_article = 0;
  18918.  np->top_sorted_article = gp->sort_vector;
  18919.  
  18920.  return TRUE;
  18921. }
  18922.  
  18923. /****** Process article EXTRACT command. *****************************/
  18924.  
  18925. static Bool
  18926. article_extract_command(np,gp,rest)
  18927. Rstruc nncb         *np;
  18928. Rstruc newsgroup    *gp;
  18929. char                *rest;
  18930. {
  18931.  Bool                asked_for;
  18932.  char                nnchoice[2];
  18933.  
  18934.  if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
  18935.    ERR1("The EXTRACT command does not accept any operands.");
  18936.    return FALSE;
  18937.  }
  18938.  
  18939.  (void)NNMivput(np,"NNLGROUP ",gp->name,-1);
  18940.  
  18941.  /* Display panel asking whether it's list of titles or log of text */
  18942.  
  18943.  asked_for = TRUE;
  18944.  
  18945.  (void)NNMispf(np,"ADDPOP");
  18946.  for (;;) {
  18947.    if (NNMdispl(np,"NNMPEXNT") > 0) {
  18948.      asked_for = FALSE;
  18949.      break;
  18950.    }
  18951.    (void)NNMivget(np,"NNCHOICE ",nnchoice,sizeof(nnchoice));
  18952.    if (*nnchoice == '?') {
  18953.      ERR1("Invalid choice;\
  18954. Move the cursor to a selection (or type S next to it) and press ENTER."
  18955.          );
  18956.    }
  18957.    else break;
  18958.  }
  18959.  
  18960.  (void)NNMispf(np,"REMPOP");
  18961.  if (!asked_for) return TRUE;
  18962.  
  18963.  switch (*nnchoice) {
  18964.    case '1':  return NNMxartt(np,gp,SEQ);
  18965.    case '2':  return NNMxartx(np,gp,SEQ);
  18966.    case '3':  return NNMxartx(np,gp,PDS);
  18967.  }
  18968.  
  18969.  return FALSE;
  18970. }
  18971.  
  18972. /****** Process article PRINT command. *******************************/
  18973.  
  18974. static Bool
  18975. article_print_command(np,gp,rest)
  18976. Rstruc nncb         *np;
  18977. Rstruc newsgroup    *gp;
  18978. char                *rest;
  18979. {
  18980.  Bool                asked_for;
  18981.  char                nnchoice[2];
  18982.  
  18983.  if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
  18984.    ERR1("The PRINT command does not accept any operands.");
  18985.    return FALSE;
  18986.  }
  18987.  
  18988.  (void)NNMivput(np,"NNLGROUP ",gp->name,-1);
  18989.  
  18990.  /* Display panel asking whether it's list of titles or log of text */
  18991.  
  18992.  asked_for = TRUE;
  18993.  
  18994.  (void)NNMispf(np,"ADDPOP");
  18995.  for (;;) {
  18996.    if (NNMdispl(np,"NNMPPRNT") > 0) {
  18997.      asked_for = FALSE;
  18998.      break;
  18999.    }
  19000.    (void)NNMivget(np,"NNCHOICE ",nnchoice,sizeof(nnchoice));
  19001.    if (*nnchoice == '?') {
  19002.      ERR1("Invalid choice;\
  19003. Move the cursor to a selection (or type S next to it) and press ENTER."
  19004.          );
  19005.    }
  19006.    else break;
  19007.  }
  19008.  
  19009.  (void)NNMispf(np,"REMPOP");
  19010.  if (!asked_for) return TRUE;
  19011.  
  19012.  switch (*nnchoice) {
  19013.    case '1':  return NNMxartt(np,gp,JES);
  19014.    case '2':  return NNMxartx(np,gp,JES);
  19015.  }
  19016.  
  19017.  return FALSE;
  19018. }
  19019.  
  19020. /****** Process article MARKALL command. *****************************/
  19021.  
  19022. static Bool
  19023. article_markall_command(np,gp,rest)
  19024. Rstruc nncb          *np;
  19025. Rstruc newsgroup     *gp;
  19026. char                 *rest;
  19027. {
  19028.  struct newsarticle  *ap;
  19029.  VARK                *vp;
  19030.  VARK                *vpfirst;
  19031.  VARK                *vplast;
  19032.  int                  prc;
  19033.  Bool                 allp;
  19034.  struct countdown     cd;
  19035.  char                 nnchoice[9];
  19036.  
  19037.  if (!gp->article_vector) {
  19038.    ERR1("There are no articles to mark.");
  19039.    return TRUE;
  19040.  }
  19041.  
  19042.  /* Display panel asking what user really wants to do. */
  19043.  
  19044.  strcpy(nnchoice,"");
  19045.  
  19046.  for (;;) {
  19047.    (void)NNMivput(np,"NNMARK ","Read",-1);
  19048.    (void)NNMispf(np,"ADDPOP");
  19049.    prc = NNMdispl(np,"NNMPMALL");
  19050.    (void)NNMispf(np,"REMPOP");
  19051.    if (prc > 0) strcpy(nnchoice,"3");
  19052.    else (void)NNMivget(np,"NNCHOICE ",nnchoice,sizeof(nnchoice));
  19053.    switch (nnchoice[0]) {
  19054.      case '1': allp = TRUE;  break;
  19055.      case '2': allp = FALSE; break;
  19056.      case '3': ERR1("Operation cancelled by your request.");
  19057.                return TRUE;
  19058.      default:
  19059.                 ERR1("Invalid choice;\
  19060. Move the cursor to a selection (or type S next to it) and press ENTER."
  19061.          );
  19062.                 continue;
  19063.    }
  19064.    break;
  19065.  }
  19066.  
  19067.  /*
  19068.   * This isn't really too good.  It means that ALL the articles
  19069.   * will have to be retrieved in order to mark them read.
  19070.   *
  19071.   * A better way would be to set a flag in the VARK saying
  19072.   * "marked read" rather than "read", so that future fetches
  19073.   * would put the article in the table but set the action to
  19074.   * "read".  We're going to need a "cross-posted-read" flag
  19075.   * that's independent of fetching the article anyhow...
  19076.   *
  19077.   * How about this?  Add a new article status, ARTICLE_DUMMY,
  19078.   * set when unique storage is allocated for a struct newsarticle
  19079.   * but neither the headers nor the body have been retrieved.
  19080.   * It would have null values in it, but:
  19081.   *
  19082.   * the action field could be set when article is marked (un)read
  19083.   * the subject field could be set from an XHDR request
  19084.   * likewise for date, etc. fields
  19085.   *
  19086.   * If NNMrarh is asked to retrieve such an article, it will fill
  19087.   * it in with stuff.
  19088.   *
  19089.   * NNMcar could be modified to be asked to create dummy articles
  19090.   * instead of retrieving headers for them.  This would be done if
  19091.   * just going through and setting ap->actions or ap->subjects.
  19092.   */
  19093.  
  19094.  vpfirst = &GETVARKFIRST(gp);
  19095.  vplast  = &GETVARKLAST(gp);
  19096.  
  19097.  CDSET;
  19098.  
  19099.  if (allp) {
  19100.    mark_all_articles_read(np,gp,FALSE);
  19101.    for (vp = vpfirst; vp <= vplast; vp++) {
  19102.      if (NNMcar(np,gp,0,vp,&ap,&cd,MARK_ONLY)) { /* choose article */
  19103.        if (ap) ap->action = READ;
  19104.      }
  19105.    }
  19106.    gp->unread_count = 0;
  19107.  }
  19108.  else {
  19109.    for (vp = vpfirst; vp <= vplast; vp++) {
  19110.      if (NNMcar(np,gp,0,vp,&ap,&cd,MARK_ONLY)) { /* choose article */
  19111.        NNMmarr(np,gp,vp);                /* mark article read */
  19112.      }
  19113.    }
  19114.  }
  19115.  
  19116.  return TRUE;
  19117. }
  19118.  
  19119. /****** Process article UNMARKALL command. ***************************/
  19120.  
  19121. static Bool
  19122. article_unmarkall_command(np,gp,rest)
  19123. Rstruc nncb          *np;
  19124. Rstruc newsgroup     *gp;
  19125. char                 *rest;
  19126. {
  19127.  struct newsarticle  *ap;
  19128.  VARK                *vp;
  19129.  VARK                *vpfirst;
  19130.  VARK                *vplast;
  19131.  int                  prc;
  19132.  Bool                 allp;
  19133.  char                 nnchoice[9];
  19134.  struct countdown     cd;
  19135.  
  19136.  if (!gp->article_vector) {
  19137.    ERR1("There are no articles to mark.");
  19138.    return TRUE;
  19139.  }
  19140.  
  19141.  /* Display panel asking what user really wants to do. */
  19142.  
  19143.  strcpy(nnchoice,"");
  19144.  
  19145.  for (;;) {
  19146.    (void)NNMivput(np,"NNMARK ","Unread",-1);
  19147.    (void)NNMispf(np,"ADDPOP");
  19148.    prc = NNMdispl(np,"NNMPMALL");
  19149.    (void)NNMispf(np,"REMPOP");
  19150.    if (prc > 0) strcpy(nnchoice,"3");
  19151.    else (void)NNMivget(np,"NNCHOICE ",nnchoice,sizeof(nnchoice));
  19152.    switch (nnchoice[0]) {
  19153.      case '1': allp = TRUE;  break;
  19154.      case '2': allp = FALSE; break;
  19155.      case '3': ERR1("Operation cancelled by your request.");
  19156.                return TRUE;
  19157.      default:
  19158.                 ERR1("Invalid choice;\
  19159. Move the cursor to a selection (or type S next to it) and press ENTER."
  19160.          );
  19161.                 continue;
  19162.    }
  19163.    break;
  19164.  }
  19165.  
  19166.  /* see comments under previous function.  they apply here too */
  19167.  
  19168.  vpfirst = &GETVARKFIRST(gp);
  19169.  vplast  = &GETVARKLAST(gp);
  19170.  
  19171.  CDSET;
  19172.  
  19173.  if (allp) {
  19174.    mark_all_articles_unread(np,gp,FALSE);
  19175.    for (vp = vpfirst; vp <= vplast; vp++) {
  19176.      if (NNMcar(np,gp,0,vp,&ap,&cd,MARK_ONLY)) { /* choose article */
  19177.        if (ap) ap->action = UNREAD;
  19178.      }
  19179.    }
  19180.    gp->unread_count = gp->article_count;
  19181.  }
  19182.  else {
  19183.    for (vp = vpfirst; vp <= vplast; vp++) {
  19184.      if (NNMcar(np,gp,0,vp,&ap,&cd,MARK_ONLY)) { /* choose article */
  19185.        NNMmaru(np,gp,vp);                /* mark article read */
  19186.      }
  19187.    }
  19188.  }
  19189.  
  19190.  return TRUE;
  19191. }
  19192.  
  19193. /****** Process article TITLES command. ******************************/
  19194.  
  19195. static Bool
  19196. article_titles_command(np,gp,rest)
  19197. Rstruc nncb         *np;
  19198. Rstruc newsgroup    *gp;
  19199. char                *rest;
  19200. {
  19201.  
  19202.  /* Actually, this probably ought to be a NOP, since we always ought to
  19203.   * be retrieving article titles as we display a screenful.
  19204.   * Since this command retrieves ALL titles, it's kind of wasteful.
  19205.   */
  19206.  
  19207.  (void)NNMrart(np,gp,TRUE,TRUE); /* Retrieve *all* article titles */
  19208.  
  19209.  return TRUE;
  19210.  
  19211. }
  19212.  
  19213. /****** Process article QUERY command. *******************************/
  19214.  
  19215. static Bool
  19216. article_query_command(np,gp,rest)
  19217. Rstruc nncb         *np;
  19218. Rstruc newsgroup    *gp;
  19219. char                *rest;
  19220. {
  19221.  
  19222.  NNMqng(np,gp);                          /* Query newsgroup */
  19223.  
  19224.  return TRUE;
  19225. }
  19226.  
  19227. /****** Process POST command. ****************************************/
  19228.  
  19229. static Bool
  19230. general_post_command(np,gp,rest)
  19231. Rstruc nncb         *np;
  19232. Rstruc newsgroup    *gp;
  19233. char                *rest;
  19234. {
  19235.  
  19236.  NNMdpost(np,gp,NULL);      /* Do posting (no article up to follow) */
  19237.  
  19238.  return TRUE;
  19239. }
  19240.  
  19241. /****** Process MAIL command. ****************************************/
  19242.  
  19243. static Bool
  19244. general_mail_command(np,gp,rest)
  19245. Rstruc nncb         *np;
  19246. Rstruc newsgroup    *gp;
  19247. char                *rest;
  19248. {
  19249.  
  19250.  NNMdmail(np,gp,NULL);      /* Do mailing (no article to to reply) */
  19251.  
  19252.  return TRUE;
  19253. }
  19254.  
  19255. /****** Process TEST command. ****************************************/
  19256.  
  19257. static Bool
  19258. general_test_command(np,gp,rest)
  19259. Rstruc nncb         *np;
  19260. struct newsgroup    *gp;
  19261. char                *rest;
  19262. {
  19263.  
  19264.  np->test_mode = TRUE;
  19265.  __ctest(rest);
  19266.  
  19267.  return TRUE;
  19268. }
  19269.  
  19270. /****** Process NNTP command. ****************************************/
  19271.  
  19272. static Bool
  19273. general_nntp_command(np,gp,rest)
  19274. Rstruc nncb         *np;
  19275. struct newsgroup    *gp;
  19276. char                *rest;
  19277. {
  19278.  
  19279.  (void)NNMdnntp(np,rest);      /* Do native NNTP */
  19280.  
  19281.  return TRUE;
  19282. }
  19283.  
  19284. /****** Process SAVE command. ****************************************/
  19285.  
  19286. static Bool
  19287. general_save_command(np,gp,rest)
  19288. Rstruc nncb         *np;
  19289. struct newsgroup    *gp;
  19290. char                *rest;
  19291. {
  19292.  
  19293.  return NNMsave(np,rest);  /* Save NEWSRC file */
  19294.  
  19295. }
  19296.  
  19297. /****** Process OPTIONS command. *************************************/
  19298.  
  19299. static Bool
  19300. general_options_command(np,gp,rest)
  19301. Rstruc nncb         *np;
  19302. struct newsgroup    *gp;
  19303. char                *rest;
  19304. {
  19305.  char                option[ARGSIZE];
  19306.  
  19307.  if (!getop(np,&rest,&option,GETOP_LOWERCASE)) return FALSE;
  19308.  
  19309.  NNMdsopt(np,option);         /* Do "set options" function */
  19310.  
  19311.  return TRUE;
  19312. }
  19313.  
  19314. /****** Process QUIT command. ****************************************/
  19315.  
  19316. static Bool
  19317. general_quit_command(np,gp,rest)
  19318. Rstruc nncb         *np;
  19319. struct newsgroup    *gp;
  19320. char                *rest;
  19321. {
  19322.  
  19323.  np->quit = TRUE;
  19324.  
  19325.  return TRUE;
  19326. }
  19327.  
  19328. /****** Process CRASHNNMVS command. **********************************/
  19329.  
  19330. static Bool
  19331. general_crashnnmvs_command(np,gp,rest)
  19332. Rstruc nncb         *np;
  19333. struct newsgroup    *gp;
  19334. char                *rest;
  19335. {
  19336.  
  19337.  fprintf(stderr,"Terminating NNMVS with extreme prejudice.\n");
  19338.  
  19339.  exit(999);
  19340.  
  19341. }
  19342.  
  19343. /****** Process DEBUG command. ***************************************/
  19344.  
  19345. static Bool
  19346. general_debug_command(np,gp,rest)
  19347. Rstruc nncb         *np;
  19348. struct newsgroup    *gp;
  19349. char                *rest;
  19350. {
  19351.  
  19352.  if (!np->debug_mode) {
  19353.  
  19354.    if (!(np->debug_file = fopen("dd:nndebug","a"))) {
  19355.      perror("debug file (DD NNDEBUG)");
  19356.    }
  19357.    else np->debug_mode = TRUE;
  19358.  }
  19359.  
  19360.  return TRUE;
  19361. }
  19362.  
  19363. /****** Process NODEBUG command. *************************************/
  19364.  
  19365. static Bool
  19366. general_nodebug_command(np,gp,rest)
  19367. Rstruc nncb         *np;
  19368. struct newsgroup    *gp;
  19369. char                *rest;
  19370. {
  19371.  
  19372.  if (np->debug_mode) {
  19373.    if (np->debug_file) {
  19374.      if (fclose(np->debug_file) < 0) {
  19375.        fprintf(stderr,"Error closing debug file (DD NNDEBUG)\n");
  19376.      }
  19377.      np->debug_file = NULL;
  19378.    }
  19379.    np->debug_mode = FALSE;
  19380.  }
  19381.  
  19382.  return TRUE;
  19383. }
  19384.  
  19385. /****** Process DISCONNECT command. *********************************/
  19386.  
  19387. static Bool
  19388. general_disconnect_command(np,gp,rest)
  19389. Rstruc nncb         *np;
  19390. struct newsgroup    *gp;
  19391. char                *rest;
  19392. {
  19393.  char               *dummy = "503 Simulated disconnect.";
  19394.  int                 index;
  19395.  
  19396.  /* fake a disconnect condition by sending an NNTP "QUIT".
  19397.   * The next attempt to communicate with the socket will get
  19398.   * the simulated response instead of what it expected.
  19399.   */
  19400.  
  19401.  strcpy(np->nntp_command,"QUIT");
  19402.  if (!NNMsockt(np)) return FALSE;  /* Send socket command to server */
  19403.  
  19404.  index = strlen(dummy);
  19405.  strcpy(np->g_buf+1,dummy);
  19406.  np->g_buf[index+1] = CARRIAGE_RETURN;
  19407.  np->g_buf[index+2] = LINE_FEED;
  19408.  np->g_bytes_returned = index+3;
  19409.  np->g_buf_index = 0;
  19410.  
  19411.  return TRUE;
  19412. }
  19413.  
  19414. /****** Process newsgroup S selection. *******************************/
  19415.  
  19416. static Bool
  19417. newsgroup_s_selection(np,gp)
  19418. Rstruc nncb          *np;
  19419. Rstruc newsgroup     *gp;
  19420. {
  19421.  
  19422.  np->show_all_articles       = FALSE;
  19423.  np->bypass_header_retrieval = FALSE;
  19424.  np->unread_articles_only    = FALSE;
  19425.  
  19426.  return(NNMpng(np,gp,FALSE,FALSE));                /* Pick newsgroup */
  19427.  
  19428. }
  19429.  
  19430. /****** Process newsgroup N selection. *******************************/
  19431.  
  19432. static Bool
  19433. newsgroup_n_selection(np,gp)
  19434. Rstruc nncb          *np;
  19435. Rstruc newsgroup     *gp;
  19436. {
  19437.  
  19438.  np->show_all_articles       = FALSE;
  19439.  np->bypass_header_retrieval = FALSE;
  19440.  np->unread_articles_only    = TRUE;
  19441.  
  19442.  return(NNMpng(np,gp,FALSE,FALSE));                /* Pick newsgroup */
  19443.  
  19444. }
  19445.  
  19446. /****** Process newsgroup A selection. *******************************/
  19447.  
  19448. static Bool
  19449. newsgroup_a_selection(np,gp)
  19450. Rstruc nncb          *np;
  19451. Rstruc newsgroup     *gp;
  19452. {
  19453.  
  19454.  np->show_all_articles       = TRUE;
  19455.  np->bypass_header_retrieval = FALSE;
  19456.  np->unread_articles_only    = FALSE;
  19457.  
  19458.  return(NNMpng(np,gp,FALSE,FALSE));                /* Pick newsgroup */
  19459.  
  19460. }
  19461.  
  19462. /****** Process newsgroup Z selection. *******************************/
  19463.  
  19464. static Bool
  19465. newsgroup_z_selection(np,gp)
  19466. Rstruc nncb          *np;
  19467. Rstruc newsgroup     *gp;
  19468. {
  19469.  
  19470.  np->show_all_articles       = TRUE;
  19471.  np->bypass_header_retrieval = TRUE;
  19472.  np->unread_articles_only    = FALSE;
  19473.  
  19474.  return(NNMpng(np,gp,FALSE,FALSE));                /* Pick newsgroup */
  19475.  
  19476. }
  19477.  
  19478. /****** Process newsgroup $ selection. *******************************/
  19479.  
  19480. static Bool
  19481. newsgroup_dollar_selection(np,gp)
  19482. Rstruc nncb          *np;
  19483. Rstruc newsgroup     *gp;
  19484. {
  19485.  
  19486.  np->show_all_articles       = FALSE;
  19487.  np->bypass_header_retrieval = FALSE;
  19488.  np->unread_articles_only    = FALSE;
  19489.  
  19490.  return(NNMpng(np,gp,TRUE,TRUE)); /* pick group, get titles, sort it */
  19491.  
  19492. }
  19493.  
  19494. /****** Process newsgroup @ selection. *******************************/
  19495.  
  19496. static Bool
  19497. newsgroup_atsign_selection(np,gp)
  19498. Rstruc nncb          *np;
  19499. Rstruc newsgroup     *gp;
  19500. {
  19501.  
  19502.  np->show_all_articles       = TRUE;
  19503.  np->bypass_header_retrieval = FALSE;
  19504.  np->unread_articles_only    = FALSE;
  19505.  
  19506.  return(NNMpng(np,gp,TRUE,TRUE)); /* pick group, get titles, sort it */
  19507.  
  19508. }
  19509.  
  19510. /****** Process newsgroup Q selection. *******************************/
  19511.  
  19512. static Bool
  19513. newsgroup_q_selection(np,gp)
  19514. Rstruc nncb         *np;
  19515. Rstruc newsgroup    *gp;
  19516. {
  19517.  
  19518.  NNMqng(np,gp);                          /* Query newsgroup */
  19519.  
  19520.  return TRUE;
  19521. }
  19522.  
  19523. /****** Process newsgroup R selection. *******************************/
  19524.  
  19525. static Bool
  19526. newsgroup_r_selection(np,gp)
  19527. Rstruc nncb          *np;
  19528. Rstruc newsgroup     *gp;
  19529. {
  19530.  
  19531.  gp->registered = 1;
  19532.  
  19533.  WARN2("Newsgroup %s registered (subscribed).", gp->name);
  19534.  
  19535.  return TRUE;
  19536. }
  19537.  
  19538. /****** Process newsgroup D selection. *******************************/
  19539.  
  19540. static Bool
  19541. newsgroup_d_selection(np,gp)
  19542. Rstruc nncb          *np;
  19543. Rstruc newsgroup     *gp;
  19544. {
  19545.  
  19546.  gp->registered = 0;
  19547.  
  19548.  WARN2("Newsgroup %s deregistered (unsubscribed).", gp->name);
  19549.  
  19550.  return TRUE;
  19551. }
  19552.  
  19553. /****** Process newsgroup M selection. *******************************/
  19554.  
  19555. static Bool
  19556. newsgroup_m_selection(np,gp)
  19557. Rstruc nncb          *np;
  19558. Rstruc newsgroup     *gp;
  19559. {
  19560.  
  19561.  return mark_all_articles_read(np,gp,TRUE);
  19562.  
  19563. }
  19564.  
  19565. /****** Process newsgroup U selection. *******************************/
  19566.  
  19567. static Bool
  19568. newsgroup_u_selection(np,gp)
  19569. Rstruc nncb          *np;
  19570. Rstruc newsgroup     *gp;
  19571. {
  19572.  
  19573.  return mark_all_articles_unread(np,gp,TRUE);
  19574.  
  19575. }
  19576.  
  19577. /****** Process article E selection. *********************************/
  19578.  
  19579. static Bool
  19580. article_e_selection(np,ap)
  19581. Rstruc nncb          *np;
  19582. Rstruc newsarticle   *ap;
  19583. {
  19584.  
  19585.  np->extract_file = NULL;
  19586.  if (!NNMpick(np,ap)) return FALSE;
  19587.  NNMdoit(np,ap,'E');
  19588.  return TRUE;
  19589.  
  19590. }
  19591.  
  19592. /****** Process article F selection. *********************************/
  19593.  
  19594. static Bool
  19595. article_f_selection(np,ap)
  19596. Rstruc nncb          *np;
  19597. Rstruc newsarticle   *ap;
  19598. {
  19599.  
  19600.  if (!NNMpick(np,ap)) return FALSE;
  19601.  NNMdoit(np,ap,'F');
  19602.  return TRUE;
  19603.  
  19604. }
  19605.  
  19606. /****** Process article C selection. *********************************/
  19607.  
  19608. static Bool
  19609. article_c_selection(np,ap)
  19610. Rstruc nncb          *np;
  19611. Rstruc newsarticle   *ap;
  19612. {
  19613.  
  19614.  if (!NNMpick(np,ap)) return FALSE;
  19615.  NNMdoit(np,ap,'C');
  19616.  return TRUE;
  19617.  
  19618. }
  19619.  
  19620. /****** Process article M selection. *********************************/
  19621.  
  19622. static Bool
  19623. article_m_selection(np,ap)
  19624. Rstruc nncb         *np;
  19625. Rstruc newsarticle  *ap;
  19626. {
  19627.  Rstruc newsgroup   *gp = np->current_newsgroup;
  19628.  VARK               *vp = &GETVARK(gp,ap->number);
  19629.  
  19630.  NNMmarr(np,gp,vp);                          /* Make article read */
  19631.  
  19632.  return TRUE;
  19633. }
  19634.  
  19635. /****** Process article P selection. *********************************/
  19636.  
  19637. static Bool
  19638. article_p_selection(np,ap)
  19639. Rstruc nncb          *np;
  19640. Rstruc newsarticle   *ap;
  19641. {
  19642.  
  19643.  np->extract_file = NULL;
  19644.  if (!NNMpick(np,ap)) return FALSE;
  19645.  NNMdoit(np,ap,'P');
  19646.  return TRUE;
  19647.  
  19648. }
  19649.  
  19650. /****** Process article Q selection. *********************************/
  19651.  
  19652. static Bool
  19653. article_q_selection(np,ap)
  19654. Rstruc nncb         *np;
  19655. Rstruc newsarticle  *ap;
  19656. {
  19657.  
  19658.  return NNMqar(np,ap);
  19659. }
  19660.  
  19661. /****** Process article R selection. *********************************/
  19662.  
  19663. static Bool
  19664. article_r_selection(np,ap)
  19665. Rstruc nncb          *np;
  19666. Rstruc newsarticle   *ap;
  19667. {
  19668.  
  19669.  if (!NNMpick(np,ap)) return FALSE;
  19670.  NNMdoit(np,ap,'R');
  19671.  return TRUE;
  19672.  
  19673. }
  19674.  
  19675. /****** Process article S selection. *********************************/
  19676.  
  19677. static Bool
  19678. article_s_selection(np,ap)
  19679. Rstruc nncb          *np;
  19680. Rstruc newsarticle   *ap;
  19681. {
  19682.  Rstruc newsgroup    *gp = np->current_newsgroup;
  19683.  Rstruc newsarticle  *ap1 = ap;
  19684.  Rstruc newsarticle  *ap2 = NULL;
  19685.  VARK                *vp;
  19686.  VARK                *vpfirst;
  19687.  VARK                *vplast;
  19688.  VARK                *vp1;
  19689.  enum article_cookie  cookie;
  19690.  Bool                 save_show_all_articles;
  19691.  struct countdown     cd;
  19692.  
  19693.  np->extract_file = NULL;
  19694.  clear_subject(np);
  19695.  
  19696.  /* Continue as long as NEXT/PREV/UNREAD requests occur. */
  19697.  
  19698.  for (;;) {
  19699.    if (!NNMpick(np,ap1)) return FALSE;  /* Pick article to process */
  19700.    NNMdoit(np,ap1,'S');                 /* Process article */
  19701.    cookie = np->another_article;
  19702.    if (cookie == NULL_ARTICLE_COOKIE) break;
  19703.    vpfirst = &GETVARKFIRST(gp);
  19704.    vplast  = &GETVARKLAST(gp);
  19705.    CDSET;
  19706.    switch (cookie) {
  19707.      case REDISPLAY_ARTICLE:
  19708.           ap2 = NULL;
  19709.           break;
  19710.      case UNREAD_THIS_ARTICLE:
  19711.           clear_subject(np);
  19712.           vp1 = &GETVARK(gp,ap1->number);
  19713.           NNMmaru(np,gp,vp1);            /* Make article unread */
  19714.           return TRUE;
  19715.      case NEXT_ARTICLE:
  19716.           save_show_all_articles = np->show_all_articles;
  19717.           np->show_all_articles = TRUE;
  19718.           SEARCH_CURRENT_TO_LAST(ap2,ap1,NOSUBJECT,NO_COMPARISON,ANY);
  19719.           np->show_all_articles = save_show_all_articles;
  19720.           if (!ap2) ERR1(ERROR_NEXT_ARTICLE);
  19721.           break;
  19722.      case PREV_ARTICLE:
  19723.           save_show_all_articles = np->show_all_articles;
  19724.           np->show_all_articles = TRUE;
  19725.           SEARCH_CURRENT_TO_FIRST(ap2,ap1,NOSUBJECT,NO_COMPARISON,ANY);
  19726.           np->show_all_articles = save_show_all_articles;
  19727.           if (!ap2) ERR1(ERROR_PREV_ARTICLE);
  19728.           break;
  19729.      case NEXT_TABLED_ARTICLE:
  19730.           SEARCH_CURRENT_TO_LAST(ap2,ap1,NOSUBJECT,IsEligible(*vp),NO);
  19731.           if (!ap2) ERR1(ERROR_NEXT_TABLED_ARTICLE);
  19732.           break;
  19733.      case PREV_TABLED_ARTICLE:
  19734.           SEARCH_CURRENT_TO_FIRST(ap2,ap1,NOSUBJECT,IsEligible(*vp),NO);
  19735.           if (!ap2) ERR1(ERROR_PREV_TABLED_ARTICLE);
  19736.           break;
  19737.      case NEXT_UNREAD_ARTICLE:
  19738.           SEARCH_CURRENT_TO_LAST(ap2,ap1,NOSUBJECT,IsUnread(*vp),NO);
  19739.           if (!ap2) ERR1(ERROR_NEXT_UNREAD_ARTICLE);
  19740.           break;
  19741.      case PREV_UNREAD_ARTICLE:
  19742.           SEARCH_CURRENT_TO_FIRST(ap2,ap1,NOSUBJECT,IsUnread(*vp),NO);
  19743.           if (!ap2) ERR1(ERROR_PREV_UNREAD_ARTICLE);
  19744.           break;
  19745.      case NEXT_THREAD_ARTICLE:
  19746.           SEARCH_CURRENT_TO_LAST(ap2,ap1,SETSUBJECT,subjectmatch,NO);
  19747.           if (!ap2) {
  19748.             ERR1(ERROR_NEXT_THREAD_ARTICLE);
  19749.             clear_subject(np);
  19750.           }
  19751.           break;
  19752.      case PREV_THREAD_ARTICLE:
  19753.           SEARCH_CURRENT_TO_FIRST(ap2,ap1,SETSUBJECT,subjectmatch,NO);
  19754.           if (!ap2) {
  19755.             ERR1(ERROR_PREV_THREAD_ARTICLE);
  19756.             clear_subject(np);
  19757.           }
  19758.           break;
  19759.      case FIRST_THREAD_ARTICLE:
  19760.           SEARCH_FIRST_TO_LAST(ap2,ap1,SETSUBJECT,subjectmatch,NO);
  19761.           if (!ap2) {
  19762.             ERR1(ERROR_FIRST_THREAD_ARTICLE);
  19763.             clear_subject(np);
  19764.           }
  19765.           break;
  19766.      case LAST_THREAD_ARTICLE:
  19767.           SEARCH_LAST_TO_FIRST(ap2,ap1,SETSUBJECT,subjectmatch,NO);
  19768.           if (!ap2) {
  19769.             ERR1(ERROR_LAST_THREAD_ARTICLE);
  19770.             clear_subject(np);
  19771.           }
  19772.           break;
  19773.      case NEW_THREAD_ARTICLE:
  19774.           SEARCH_FIRST_TO_LAST(ap2,ap1,SETSUBJECT,
  19775.                                IsUnread(*vp) && !subjectmatch,NO);
  19776.           clear_subject(np);
  19777.           if (!ap2) ERR1(ERROR_NEW_THREAD_ARTICLE);
  19778.           else (void)set_subject(np,ap2->subject);
  19779.           break;
  19780.      default:
  19781.           clear_subject(np);
  19782.           ap2 = NULL;
  19783.           break;
  19784.    }
  19785.  
  19786.    if (ap2) {
  19787.      /* Bump display to article to be seen */
  19788.      if (gp->sort_vector)
  19789.           np->top_sorted_article = np->current_sortvark;
  19790.      else np->top_article = ap2->number;
  19791.      SetEligible(*vp); /* Force it eligible for display */
  19792.      ap1 = ap2;
  19793.    }
  19794.  }
  19795.  
  19796.  clear_subject(np);
  19797.  
  19798.  return TRUE;
  19799.  
  19800. }
  19801.  
  19802. /****** Process article U selection. *********************************/
  19803.  
  19804. static Bool
  19805. article_u_selection(np,ap)
  19806. Rstruc nncb         *np;
  19807. Rstruc newsarticle  *ap;
  19808. {
  19809.  Rstruc newsgroup   *gp = np->current_newsgroup;
  19810.  VARK               *vp = &GETVARK(gp,ap->number);
  19811.  
  19812.  NNMmaru(np,gp,vp);                         /* Make article unread */
  19813.  
  19814.  return TRUE;
  19815. }
  19816.  
  19817. /*********************************************************************/
  19818.  
  19819. void
  19820. NNMinit(np)
  19821. Rstruc nncb            *np;
  19822. {
  19823.  
  19824.  static struct tabledesc newsgroup_display_table;
  19825.  static struct tabledesc article_display_table;
  19826.  static struct tabledesc text_display_table;
  19827.  static struct cmddesc   newsgroup_commands[] = {
  19828.                           {"L          ",newsgroup_locate_command   },
  19829.                           {"LOC        ",newsgroup_locate_command   },
  19830.                           {"LOCATE     ",newsgroup_locate_command   },
  19831.                           {"F          ",newsgroup_find_command     },
  19832.                           {"FIND       ",newsgroup_find_command     },
  19833.                           {"EXT        ",newsgroup_extract_command  },
  19834.                           {"EXTRACT    ",newsgroup_extract_command  },
  19835.                           {"PRT        ",newsgroup_print_command    },
  19836.                           {"PRNT       ",newsgroup_print_command    },
  19837.                           {"REG        ",newsgroup_reg_command      },
  19838.                           {"REGISTER   ",newsgroup_reg_command      },
  19839.                           {"ALL        ",newsgroup_all_command      },
  19840.                           {"ONLY       ",newsgroup_only_command     },
  19841.                           {"ORDER      ",newsgroup_order_command    },
  19842.                           {"RESCAN     ",newsgroup_rescan_command   },
  19843.                           {"           ",NULL}
  19844.                          };
  19845.  static struct cmddesc   article_commands[] = {
  19846.                           {"L          ",article_locate_command     },
  19847.                           {"LOC        ",article_locate_command     },
  19848.                           {"LOCATE     ",article_locate_command     },
  19849.                           {"F          ",article_find_command       },
  19850.                           {"FIND       ",article_find_command       },
  19851.                           {"EXT        ",article_extract_command    },
  19852.                           {"EXTRACT    ",article_extract_command    },
  19853.                           {"PRT        ",article_print_command      },
  19854.                           {"PRNT       ",article_print_command      },
  19855.                           {"MARKALL    ",article_markall_command    },
  19856.                           {"UNMARKALL  ",article_unmarkall_command  },
  19857.                           {"TITLE      ",article_titles_command     },
  19858.                           {"TITLES     ",article_titles_command     },
  19859.                           {"ONLY       ",article_only_command       },
  19860.                           {"Q          ",article_query_command      },
  19861.                           {"QUERY      ",article_query_command      },
  19862.                           {"SORT       ",article_sort_command       },
  19863.                           {"RESCAN     ",article_rescan_command     },
  19864.                           {"           ",NULL}
  19865.                          };
  19866.  
  19867.  static struct cmddesc   general_commands[] = {
  19868.                           {"POST       ",general_post_command       },
  19869.                           {"MAIL       ",general_mail_command       },
  19870.                           {"TEST       ",general_test_command       },
  19871.                           {"NNTP       ",general_nntp_command       },
  19872.                           {"SAVE       ",general_save_command       },
  19873.                           {"OPTIONS    ",general_options_command    },
  19874.                           {"OPT        ",general_options_command    },
  19875.                           {"QUIT       ",general_quit_command       },
  19876.                           {"DEBUG      ",general_debug_command      },
  19877.                           {"NODEBUG    ",general_nodebug_command    },
  19878.                           {"DISCONNECT ",general_disconnect_command },
  19879.                           {"DISC       ",general_disconnect_command },
  19880.                           {"CRASHNNMVS ",general_crashnnmvs_command },
  19881.                           {"           ",NULL}
  19882.                          };
  19883.  
  19884.  static struct seldesc   newsgroup_selections[] = {
  19885.                           {'S',newsgroup_s_selection },
  19886.                           {'N',newsgroup_n_selection },
  19887.                           {'A',newsgroup_a_selection },
  19888.                           {'R',newsgroup_r_selection },
  19889.                           {'D',newsgroup_d_selection },
  19890.                           {'M',newsgroup_m_selection },
  19891.                           {'U',newsgroup_u_selection },
  19892.                           {'Q',newsgroup_q_selection },
  19893.                        /* {'Z',newsgroup_z_selection }, */
  19894.                           {'$',newsgroup_dollar_selection },
  19895.                           {'@',newsgroup_atsign_selection },
  19896.                           {' ',NULL}
  19897.                          };
  19898.  static struct seldesc   article_selections[] = {
  19899.                           {'S',article_s_selection },
  19900.                           {'E',article_e_selection },
  19901.                           {'P',article_p_selection },
  19902.                           {'M',article_m_selection },
  19903.                           {'U',article_u_selection },
  19904.                           {'F',article_f_selection },
  19905.                           {'R',article_r_selection },
  19906.                           {'Q',article_q_selection },
  19907.                           {'C',article_c_selection },
  19908.                           {' ',NULL}
  19909.                          };
  19910.  
  19911.  static struct tablevector all_display_tables;
  19912.  
  19913.  newsgroup_display_table.command_variable   = "NNGCMD ";
  19914.  newsgroup_display_table.first_cmddesc      = newsgroup_commands;
  19915.  newsgroup_display_table.next_cmddesc       = general_commands;
  19916.  newsgroup_display_table.first_seldesc      = newsgroup_selections;
  19917.  
  19918.  article_display_table.command_variable     = "NNTCMD ";
  19919.  article_display_table.first_cmddesc        = article_commands;
  19920.  article_display_table.next_cmddesc         = general_commands;
  19921.  article_display_table.first_seldesc        = article_selections;
  19922.  
  19923.  text_display_table.command_variable        = "ZCMD ";
  19924.  text_display_table.first_cmddesc           = NULL; /* filled later */
  19925.  text_display_table.next_cmddesc            = general_commands;
  19926.  text_display_table.first_seldesc           = NULL;
  19927.  
  19928.  all_display_tables.newsgroup_display_table = &newsgroup_display_table;
  19929.  all_display_tables.article_display_table   = &article_display_table;
  19930.  all_display_tables.text_display_table      = &text_display_table;
  19931.  
  19932.  np->display_table_vector = &all_display_tables;
  19933.  
  19934.  return;
  19935. }
  19936. ./ ADD NAME=NNMISPF
  19937.  
  19938.  /********************************************************************/
  19939.  /*                                                                  */
  19940.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  19941.  /*                                                                  */
  19942.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  19943.  /* including the implied warranties of merchantability and fitness, */
  19944.  /* are expressly denied.                                            */
  19945.  /*                                                                  */
  19946.  /* Provided this copyright notice is included, this software may    */
  19947.  /* be freely distributed and not offered for sale.                  */
  19948.  /*                                                                  */
  19949.  /* Changes or modifications may be made and used only by the maker  */
  19950.  /* of same, and not further distributed.  Such modifications should */
  19951.  /* be mailed to the author for consideration for addition to the    */
  19952.  /* software and incorporation in subsequent releases.               */
  19953.  /*                                                                  */
  19954.  /********************************************************************/
  19955.  
  19956. #pragma  csect(code,  "NN@ISPF ")
  19957. #pragma  csect(static,"NN$ISPF ")
  19958. #include "nn.h"
  19959.  
  19960. /****** Call ISPF service. *******************************************/
  19961.  
  19962. Bool
  19963. NNMispf(np,ispfbuf)
  19964. Rstruc nncb *np;
  19965. char        *ispfbuf;
  19966. {
  19967.  int         ispflen;
  19968.  
  19969.  ispflen = strlen(ispfbuf);
  19970.  
  19971. #ifndef ISPFV2
  19972.  if (np->test_mode) {
  19973. #endif
  19974.    if (ispflen >= 6
  19975.       && (memcmp(ispfbuf,"ADDPOP",6) == 0
  19976.        || memcmp(ispfbuf,"REMPOP",6) == 0)) {
  19977.      np->ispfrc = 0;
  19978.      return TRUE;
  19979.    }
  19980. #ifndef ISPFV2
  19981.  }
  19982. #endif
  19983.  
  19984.  np->ispfrc = ISPEXEC(&ispflen,ispfbuf);
  19985.  if (np->ispfrc > 8) {
  19986.  
  19987.    /* Ignore ADDPOP and REMPOP errors, especially if they are due to
  19988.       ISPF V3 not being active. */
  19989.  
  19990.    if (np->ispfrc == 20
  19991.     && np->debug_mode == FALSE
  19992.     && ispflen >= 6
  19993.     && (memcmp(ispfbuf,"ADDPOP",6) == 0
  19994.      || memcmp(ispfbuf,"REMPOP",6) == 0)) {
  19995.      return TRUE;
  19996.    }
  19997.  
  19998.    NNMierr(np);             /* handle ISPF error */
  19999.    return FALSE;
  20000.  }
  20001.  return TRUE;
  20002. }
  20003.  
  20004. ./ ADD NAME=NNMIVGET
  20005.  
  20006.  /********************************************************************/
  20007.  /*                                                                  */
  20008.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  20009.  /*                                                                  */
  20010.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  20011.  /* including the implied warranties of merchantability and fitness, */
  20012.  /* are expressly denied.                                            */
  20013.  /*                                                                  */
  20014.  /* Provided this copyright notice is included, this software may    */
  20015.  /* be freely distributed and not offered for sale.                  */
  20016.  /*                                                                  */
  20017.  /* Changes or modifications may be made and used only by the maker  */
  20018.  /* of same, and not further distributed.  Such modifications should */
  20019.  /* be mailed to the author for consideration for addition to the    */
  20020.  /* software and incorporation in subsequent releases.               */
  20021.  /*                                                                  */
  20022.  /********************************************************************/
  20023.  
  20024. #pragma  csect(code,  "NN@IVGET")
  20025. #pragma  csect(static,"NN$IVGET")
  20026. #include "nn.h"
  20027.  
  20028. /****** Retrieve the value of an ISPF variable. **********************/
  20029.  
  20030. Bool
  20031. NNMivget(np,varname,varbuf,varbuflen)
  20032. Rstruc nncb *np;
  20033. char        *varname;
  20034. char        *varbuf;
  20035. int          varbuflen;
  20036. {
  20037.  int         vcopy_length;
  20038.  
  20039.  if (!strchr(varname,' ')) {
  20040.    fprintf(stderr,"NNMivget: no blank passed in var name\n");
  20041.    return FALSE;
  20042.  }
  20043.  
  20044.  /*
  20045.   * If varbuflen is negative, that means that the value is not to be
  20046.   * treated as a C string, and the null character is not to be
  20047.   * appended to the resulting value.  This is used for hex values
  20048.   * (like addresses) that are stored in ISPF table row variables.
  20049.   */
  20050.  
  20051.  if (varbuflen < 0)  vcopy_length = -varbuflen;
  20052.  else vcopy_length = varbuflen;
  20053.  
  20054.  /* Note that on entry, vcopy_length is an integer that contains
  20055.     the length of the buffer.  On return it is updated to the length
  20056.     of the value returned.  Since we have to stick a null character
  20057.     on the end of it for C, the actual buffer passed must be at least
  20058.     one character longer than the length as defined to ISPF.
  20059.  */
  20060.  
  20061.  np->ispfrc = ISPLINK("VCOPY",varname,&vcopy_length,varbuf,"MOVE");
  20062.  switch (np->ispfrc) {
  20063.    case  0:
  20064.            if (varbuflen >= 0) varbuf[vcopy_length] = '\0';
  20065.            return TRUE;
  20066.    case  8:
  20067.            strcpy(varbuf,"");
  20068.            return TRUE;
  20069.    case 16:
  20070.            fprintf(stderr,
  20071.                    "Error: ISPF variable buffer too short to get %s\n",
  20072.                    varname);
  20073.            return FALSE;
  20074.    default:
  20075.            NNMierr(np);   /* handle ISPF error */
  20076.            return FALSE;
  20077.  }
  20078. }
  20079.  
  20080. ./ ADD NAME=NNMIVPUT
  20081.  
  20082.  /********************************************************************/
  20083.  /*                                                                  */
  20084.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  20085.  /*                                                                  */
  20086.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  20087.  /* including the implied warranties of merchantability and fitness, */
  20088.  /* are expressly denied.                                            */
  20089.  /*                                                                  */
  20090.  /* Provided this copyright notice is included, this software may    */
  20091.  /* be freely distributed and not offered for sale.                  */
  20092.  /*                                                                  */
  20093.  /* Changes or modifications may be made and used only by the maker  */
  20094.  /* of same, and not further distributed.  Such modifications should */
  20095.  /* be mailed to the author for consideration for addition to the    */
  20096.  /* software and incorporation in subsequent releases.               */
  20097.  /*                                                                  */
  20098.  /********************************************************************/
  20099.  
  20100. #pragma  csect(code,  "NN@IVPUT")
  20101. #pragma  csect(static,"NN$IVPUT")
  20102. #include "nn.h"
  20103.  
  20104. /****** Set the value of an ISPF variable. ***************************/
  20105.  
  20106. Bool
  20107. NNMivput(np,varname,varbuf,varlen)
  20108. Rstruc nncb *np;
  20109. char        *varname;
  20110. char        *varbuf;
  20111. int         varlen;
  20112. {
  20113.  int         vreplace_length;
  20114.  
  20115.  vreplace_length = (varlen < 0 ? strlen(varbuf) : varlen);
  20116.  
  20117.  np->ispfrc = ISPLINK("VREPLACE",varname,&vreplace_length,varbuf);
  20118.  switch (np->ispfrc) {
  20119.    case  0:
  20120.            return TRUE;
  20121.    case 16:
  20122.            fprintf(stderr,
  20123.                    "Error: ISPF variable buffer too short to put %s\n",
  20124.                    varname);
  20125.            return FALSE;
  20126.    default:
  20127.            NNMierr(np);   /* handle ISPF error */
  20128.            return FALSE;
  20129.  }
  20130. }
  20131.  
  20132. ./ ADD NAME=NNMMAIN
  20133.  
  20134.  /********************************************************************/
  20135.  /*                                                                  */
  20136.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  20137.  /*                                                                  */
  20138.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  20139.  /*                                                                  */
  20140.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  20141.  /* including the implied warranties of merchantability and fitness, */
  20142.  /* are expressly denied.                                            */
  20143.  /*                                                                  */
  20144.  /* Provided this copyright notice is included, this software may    */
  20145.  /* be freely distributed and not offered for sale.                  */
  20146.  /*                                                                  */
  20147.  /* Changes or modifications may be made and used only by the maker  */
  20148.  /* of same, and not further distributed.  Such modifications should */
  20149.  /* be mailed to the author for consideration for addition to the    */
  20150.  /* software and incorporation in subsequent releases.               */
  20151.  /*                                                                  */
  20152.  /********************************************************************/
  20153.  
  20154.  /********************************************************************/
  20155.  /*                                                                  */
  20156.  /*                             NNMVS                                */
  20157.  /*                                                                  */
  20158.  /*                   MVS news reader dialog driver                  */
  20159.  /*                                                                  */
  20160.  /*                            Author:                               */
  20161.  /*                   Steve Bacher <seb@draper.com>                  */
  20162.  /*                                                                  */
  20163.  /*                    Enhancements contributed by:                  */
  20164.  /*                  Dale Ingold <snoddi@mvs.sas.com>                */
  20165.  /*                                                                  */
  20166.  /*                      Version: 3  Release: 1                      */
  20167.  /*                                                                  */
  20168.  /********************************************************************/
  20169.  
  20170. #ifdef SASC
  20171. #pragma  runopts(EXECOPS)
  20172. #else
  20173. #pragma  runopts(heap(8k,8k,anywhere,))
  20174. #pragma  runopts(nospie,nostae)
  20175. #endif
  20176.  
  20177. #pragma  csect(code,  "NN@MAIN ")
  20178. #pragma  csect(static,"NN$MAIN ")
  20179. #include "nn.h"
  20180.  
  20181. /*********************************************************************/
  20182.  
  20183. static char copyright_notice[] =
  20184.    "Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992   \n\
  20185.                                                                     \n\
  20186.     SAS enhancements copyright (c) 1992 SAS Institute, Inc.         \n\
  20187.                                                                     \n\
  20188.     This software is provided on an 'AS IS' basis.  All warranties, \n\
  20189.     including the implied warranties of merchantability and fitness,\n\
  20190.     are expressly denied.                                           \n\
  20191.                                                                     \n\
  20192.     Provided this copyright notice is included, this software may   \n\
  20193.     be freely distributed and not offered for sale.                 \n\
  20194.                                                                     \n\
  20195.     Changes or modifications may be made and used only by the maker \n\
  20196.     of same, and not further distributed.  Such modifications should\n\
  20197.     be mailed to the author for consideration for addition to the   \n\
  20198.     software and incorporation in subsequent releases.";
  20199.  
  20200. /*********************************************************************/
  20201.  
  20202. #ifdef I370
  20203. char * _style = "tso:";
  20204. #endif
  20205.  
  20206. /*********************************************************************/
  20207.  
  20208. static void
  20209. trap_ispf_command(np,verb,action)
  20210. Rstruc nncb      *np;
  20211. char             *verb;
  20212. char             *action;
  20213. {
  20214.  char             zcttrunc [16];
  20215.  char             zctact   [64];
  20216.  char             zctdesc [128];
  20217.  
  20218.  if (!NNMivput(np,"ZCTVERB ",verb,-1)) return;
  20219.  
  20220.  if (!NNMispf(np,"TBTOP ISPCMDS")) return;
  20221.  if (!NNMispf(np,"TBSCAN ISPCMDS ARGLIST(ZCTVERB)")) return;
  20222.  if (!NNMivget(np,"ZCTACT ",zctact,sizeof(zctact)))  return;
  20223.  if (UNEQUAL(zctact,action)) {
  20224.    NNMivget(np,"ZCTTRUNC ",zcttrunc, sizeof(zcttrunc));
  20225.    NNMivget(np,"ZCTDESC  ",zctdesc,sizeof(zctdesc));
  20226.    if (!NNMispf(np,"TBTOP ISPCMDS ")) return;
  20227.    NNMivput(np,"ZCTACT   ",action   ,-1);
  20228.    NNMivput(np,"ZCTTRUNC ",zcttrunc ,-1);
  20229.    NNMivput(np,"ZCTDESC  ",zctdesc  ,-1);
  20230.    if (!NNMispf(np,"TBADD ISPCMDS ")) return;
  20231.  }
  20232.  
  20233.  return;
  20234. }
  20235.  
  20236. /*********************************************************************/
  20237.  
  20238. static Bool
  20239. alloc_newsrc(newsrc_dsname,newsrc_ddname)
  20240. char           *newsrc_dsname;
  20241. char           *newsrc_ddname;
  20242. {
  20243.  int            space;
  20244.  char          *lparp;
  20245.  char          *rparp;
  20246.  FILE          *mfile;
  20247.  char           dsnseq [81];
  20248.  char           member [81];
  20249.  char           what_to_open [81];
  20250.  
  20251.  space = 2;
  20252.  strcpy(member,"");
  20253.  strcpy(dsnseq,newsrc_dsname);
  20254.  lparp = strchr(dsnseq,'(');
  20255.  rparp = strchr(dsnseq,')');
  20256.  if (lparp && rparp && (lparp < rparp) && (*(rparp+1) == '\0')) {
  20257.    *lparp = '\0';            /* makes dsnseq the seq part only */
  20258.    *rparp = '\0';            /* turns member into a string     */
  20259.    strcpy(member, lparp+1);
  20260.    space = 10;
  20261.  }
  20262.  
  20263.  if (!NNMalloc(newsrc_dsname,newsrc_ddname,SEQ,space)) return FALSE;
  20264.  
  20265.  /* If the data set had a member specified, it may have been
  20266.   * allocated as NEW, or the member may not exist.  Therefore,
  20267.   * force the member to exist by opening it for output and closing
  20268.   * it if it doesn't exist.  Then reallocate it as an existing
  20269.   * data set to prevent a B14 abend when we try to write a new
  20270.   * PDS + member for output and close it.
  20271.   *
  20272.   * Otherwise, make sure the data set is not empty by opening it
  20273.   * in append mode - this also insures that it is writable.
  20274.   */
  20275.  
  20276. #ifdef SASC
  20277.  
  20278.  if (*member) {
  20279.    sprintf(what_to_open, "'%s(%s)'", dsnseq, member);
  20280.  
  20281.    /* SAS/C doesn't distinguish "member not found" from "file not
  20282.     * found".  He also likes to complain a lot.
  20283.     * -DDI
  20284.     */
  20285.  
  20286.    quiet(1);                         /* turn off stupid messages */
  20287.    mfile = fopen(what_to_open,"r");
  20288.    quiet(0);                         /* turn stupid messages back on */
  20289.    if (!mfile && errno == ENFOUND) {        /* Member not found */
  20290.      mfile = fopen(what_to_open,"w");   /* create new member */
  20291.    }
  20292.    if (!mfile) {
  20293.      perror(what_to_open);
  20294.      return FALSE;
  20295.    }
  20296.    else if (fclose(mfile) < 0) {
  20297.      fprintf(stderr, "Error closing %s\n", what_to_open);
  20298.      return FALSE;
  20299.    }
  20300.    (void)NNMunalc(newsrc_ddname);
  20301.    if (!NNMalloc(newsrc_dsname,newsrc_ddname,SEQ,0)) return FALSE;
  20302.  }
  20303.  else {
  20304.    sprintf(what_to_open, "dd:%s", newsrc_ddname);
  20305.  
  20306.    /* SAS/C treats an empty file as "non-existent", so we have to
  20307.     * write out a blank so that NNMonrf can later open it for input
  20308.     * successfully (even though nothing is there).  Bizarre, huh?
  20309.     * -DDI
  20310.     */
  20311.  
  20312.    quiet(1);                         /* turn off stupid messages */
  20313.    mfile = fopen(what_to_open,"r");  /* attempt to open for input */
  20314.    quiet(0);                         /* turn stupid messages back on */
  20315.    if (!mfile) {                     /* if open failed, must be empty */
  20316.      mfile = fopen(what_to_open,"w");/* so open for output */
  20317.      if (!mfile) {                   /* if that fails, give up */
  20318.        perror(what_to_open);
  20319.        return FALSE;
  20320.      }
  20321.      fputc(' ',mfile);               /* make it non-empty */
  20322.    }
  20323.    if (fclose(mfile) < 0) {          /* and close it either way */
  20324.      fprintf(stderr, "Error closing %s\n", what_to_open);
  20325.      return FALSE;
  20326.    }
  20327.  
  20328.  }
  20329.  
  20330. #else
  20331.  
  20332.  if (*member) {
  20333.    sprintf(what_to_open, "'%s(%s)'", dsnseq, member);
  20334.    mfile = fopen(what_to_open,"r");
  20335.    if (!mfile && errno == 104) {        /* Member not found */
  20336.      mfile = fopen(what_to_open,"w");   /* create new member */
  20337.    }
  20338.    if (!mfile) {
  20339.      perror(what_to_open);
  20340.      return FALSE;
  20341.    }
  20342.    else if (fclose(mfile) < 0) {
  20343.      fprintf(stderr, "Error closing %s\n", what_to_open);
  20344.      return FALSE;
  20345.    }
  20346.    (void)NNMunalc(newsrc_ddname);
  20347.    if (!NNMalloc(newsrc_dsname,newsrc_ddname,SEQ,0)) return FALSE;
  20348.  }
  20349.  else {
  20350.    sprintf(what_to_open, "dd:%s", newsrc_ddname);
  20351.    mfile = fopen(what_to_open,"a");
  20352.    if (!mfile) {
  20353.      perror(what_to_open);
  20354.      return FALSE;
  20355.    }
  20356.    else if (fclose(mfile) < 0) {
  20357.      fprintf(stderr, "Error closing %s\n", what_to_open);
  20358.      return FALSE;
  20359.    }
  20360.  }
  20361.  
  20362. #endif
  20363.  
  20364.  return TRUE;
  20365. }
  20366.  
  20367. /*********************************************************************/
  20368.  
  20369. int
  20370. main(argc,argv)
  20371. int      argc;
  20372. char   **argv;
  20373.  
  20374. {
  20375.  struct nncb            *np;
  20376.  char                   *p;
  20377.  Bool                  (*selection_processor)();
  20378.  struct hostent         *client_hp;
  20379.  int                     gethostnamerc;
  20380.  int                     exit_return_code;
  20381.  Bool                    display_continue;
  20382.  Bool                    ok_to_update_newsrc;
  20383.  struct nncb             nn;
  20384.  char                    newsrc_dsname  [65];
  20385.  
  20386.  exit_return_code = 0;
  20387.  
  20388.  memset(&nn,0,sizeof(struct nncb));
  20389.  
  20390.  np = &nn;
  20391.  
  20392.  np->test_mode  = FALSE;
  20393.  np->debug_mode = FALSE;
  20394.  np->batch_mode = FALSE;
  20395.  np->preselection = '\0';
  20396.  if (argc > 1) {
  20397.    p = argv[1];
  20398.    if (*p == '-') {
  20399.      while (*++p) {
  20400.        switch (toupper(*p)) {
  20401.          case 'T':  np->test_mode  = TRUE;    break;
  20402.          case 'D':  np->debug_mode = TRUE;    break;
  20403.          case 'B':  np->batch_mode = TRUE;    break;
  20404.          case SELECTION_ALL:
  20405.          case SELECTION_REG:
  20406.          case SELECTION_NNTP:
  20407.          case SELECTION_GROUP:
  20408.          case SELECTION_LIST:
  20409.          case SELECTION_NEWG:
  20410.          case SELECTION_OPTS:
  20411.          case SELECTION_EXIT:
  20412.                     np->preselection = *p;    break;
  20413.          default: fprintf(stderr,"NNMVS: Bad parameter flag %c\n", *p);
  20414.                   exit_return_code = 8;
  20415.        }
  20416.      }
  20417.    }
  20418.    else {
  20419.      fprintf(stderr,"NNMVS: Bad parameter string %s\n",p);
  20420.      exit_return_code = 8;
  20421.    }
  20422.  }
  20423.  
  20424.  if (np->test_mode) __ctest(NULL);
  20425.  
  20426.  if (np->debug_mode) {
  20427.    if (!(np->debug_file = fopen("dd:nndebug","w"))) {
  20428.      perror("debug file (DD NNDEBUG)");
  20429.      exit_return_code = 4;
  20430.    }
  20431.  }
  20432.  else np->debug_file = NULL;
  20433.  
  20434.  if (np->batch_mode) {
  20435.    if (!(np->batch_infile = fopen("dd:NNBATIN","r"))) {
  20436.      perror("batch input file (dd:NNBATIN)");
  20437.    }
  20438.    if (!(np->batch_outfile = fopen("dd:NNBATOUT","w"))) {
  20439.      perror("batch output file (dd:NNBATOUT)");
  20440.    }
  20441.  }
  20442.  else {
  20443.    np->batch_infile  = NULL;
  20444.    np->batch_outfile = NULL;
  20445.  }
  20446.  
  20447.  /* This doesn't work, and may even make things worse.
  20448.   * if (signal(SIGINT,attention_handler) == SIG_ERR) {
  20449.   *   fprintf(stderr,"Error: unable to establish attention handler.\n");
  20450.   *   exit(27);
  20451.   * }
  20452.   */
  20453.  
  20454.  np->g_bytes_returned = 0;
  20455.  np->g_buf_index      = -1;
  20456.  
  20457.  /* Determine the local path name. */
  20458.  
  20459.  gethostnamerc = gethostname(np->client_hostname,MAXHOSTNAMELEN);
  20460.  if (gethostnamerc < 0) {
  20461.    fprintf(stderr,"NNMVS: gethostname() failed, don't know my name\n");
  20462.    exit_return_code = 8;
  20463.  }
  20464.  else {
  20465.    client_hp = gethostbyname(np->client_hostname);
  20466.    if (!client_hp) {
  20467.      fprintf(stderr,
  20468.              "NNMVS: gethostbyname() failed, can't get my name\n");
  20469.      exit_return_code = 8;
  20470.    }
  20471.    else {
  20472.      strcpy(np->nnclient,np->client_hostname);
  20473.      strcpy(np->client_hostname, client_hp->h_name);
  20474.      np->client_ip_address = *(IPADDRESS *)client_hp->h_addr;
  20475.    }
  20476.  }
  20477.  
  20478.  strcpy(np->nnserver,"");
  20479.  np->connected_to_server   = FALSE;
  20480.  np->closing_connection    = FALSE;
  20481.  np->reconnect_in_progress = FALSE;
  20482.  np->receiving_text        = FALSE;
  20483.  np->newsgroup_selected    = FALSE;
  20484.  
  20485.  GETMAIN(np->server_buf,   char, SERVER_BUF_MSGSIZE+4,"server buffer");
  20486.  GETMAIN(np->client_buf,   char, CLIENT_BUF_MSGSIZE+4,"client buffer");
  20487.  GETMAIN(np->nntp_command, char, CLIENT_BUF_MSGSIZE+4,"NNTP command");
  20488.  
  20489.  if (exit_return_code > 4) /* nothing */;
  20490.  else if (np->batch_mode) {
  20491.    exit_return_code = NNMbatch(np);
  20492.  }
  20493.  else {
  20494.  
  20495. #ifdef FETCH
  20496.  
  20497.    np->isplink_pointer = (int (*) ())fetch("ISPLINK");
  20498.    np->ispexec_pointer = (int (*) ())fetch("ISPEXEC");
  20499.  
  20500. #endif
  20501.  
  20502.    if (!NNMispf(np,"CONTROL ERRORS RETURN")) exit_return_code = 20;
  20503.  
  20504.    else {
  20505.  
  20506.      NNMinit(np);  /* Set up command and selection code tables */
  20507.  
  20508.      (void)NNMivput(np,"ZCMD "    ,"",-1);
  20509.      (void)NNMivput(np,"NNCURSOR ","",-1);
  20510.  
  20511.      trap_ispf_command(np,"RFIND","&YRFIND");  /* enable RFIND */
  20512.  
  20513.      NNMsopt(np,OPTION_ALL); /* Set options */
  20514.  
  20515.      strcpy(np->newsrc_to_open,"dd:");
  20516.  
  20517.      do {
  20518.        NNMunalc(np->newsrc_to_open+3);
  20519.        switch (NNMdmenu(np,&selection_processor)) {  /* Display menu */
  20520.          case DISPLAY_REPEAT:
  20521.          case DISPLAY_ERROR:   display_continue = TRUE;  break;
  20522.          case DISPLAY_EXIT:
  20523.          case DISPLAY_FAILURE: display_continue = FALSE; break;
  20524.        }
  20525.        if (display_continue
  20526.         && selection_processor
  20527.         && NNMivget(np,"NNNEWSRC ",newsrc_dsname,sizeof(newsrc_dsname))
  20528.         && alloc_newsrc(newsrc_dsname,np->newsrc_to_open+3)) {
  20529.          NNMclrng(np);                          /* Clear newsgroups */
  20530.          NNMclrtx(np,NULL);                     /* Clear text       */
  20531.          NNMonrf(np,NULL);                      /* Open NEWSRC file */
  20532.          (void)NNMivput(np,"ZCMD ","",-1);      /* Clear ZCMD field */
  20533.  
  20534.          /* Call selected function. If returns TRUE, rewrite NEWSRC */
  20535.  
  20536.          ok_to_update_newsrc = (*selection_processor)(np);
  20537.          NNMcnrf(np,NULL,
  20538.                  ok_to_update_newsrc); /* Close/rewrite NEWSRC file */
  20539.        }
  20540.      } while (display_continue && !np->quit);
  20541.  
  20542.      exit_return_code = 0;
  20543.  
  20544.    }
  20545.  
  20546.  }
  20547.  
  20548.  if (*np->maildsn) {
  20549.    if (remove(np->maildsn) < 0) {
  20550.      fprintf(stderr,"NNMVS: Error removing mail dataset %s\n");
  20551.    }
  20552.  }
  20553.  
  20554.  if (np->connected_to_server) {
  20555.    NNMdisc(np);                 /* disconnect from news server */
  20556.  }
  20557.  
  20558.  NNMclrng(np);                  /* Clear newsgroups */
  20559.  
  20560.  FREEMAIN(np->nntp_command,"nntp command");
  20561.  FREEMAIN(np->server_buf,  "server buffer");
  20562.  FREEMAIN(np->client_buf,  "client buffer");
  20563.  
  20564.  #define FINAL_CLOSE(A,B) \
  20565.    if (A) { \
  20566.             if (fclose(A) < 0) fprintf(stderr,B); \
  20567.           }
  20568.  
  20569.  FINAL_CLOSE(np->newsrc_file   , "Error closing newsrc file\n");
  20570.  FINAL_CLOSE(np->debug_file    , "Error closing debug file\n");
  20571.  FINAL_CLOSE(np->batch_infile  , "Error closing batch input file\n");
  20572.  FINAL_CLOSE(np->batch_outfile , "Error closing batch output file\n");
  20573.  
  20574.  exit(exit_return_code);
  20575. }
  20576.  
  20577. ./ ADD NAME=NNMMARR
  20578.  
  20579.  /********************************************************************/
  20580.  /*                                                                  */
  20581.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  20582.  /*                                                                  */
  20583.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  20584.  /* including the implied warranties of merchantability and fitness, */
  20585.  /* are expressly denied.                                            */
  20586.  /*                                                                  */
  20587.  /* Provided this copyright notice is included, this software may    */
  20588.  /* be freely distributed and not offered for sale.                  */
  20589.  /*                                                                  */
  20590.  /* Changes or modifications may be made and used only by the maker  */
  20591.  /* of same, and not further distributed.  Such modifications should */
  20592.  /* be mailed to the author for consideration for addition to the    */
  20593.  /* software and incorporation in subsequent releases.               */
  20594.  /*                                                                  */
  20595.  /********************************************************************/
  20596.  
  20597. #pragma  csect(code,  "NN@MARR ")
  20598. #pragma  csect(static,"NN$MARR ")
  20599. #include "nn.h"
  20600.  
  20601. /****** Make article read. *******************************************/
  20602.  
  20603. void
  20604. NNMmarr(np,gp,vp)
  20605. Rstruc nncb         *np;
  20606. Rstruc newsgroup    *gp;
  20607. register VARK       *vp;
  20608. {
  20609.  struct newsarticle *ap;
  20610.  
  20611.  if (IsUnread(*vp)) {
  20612.    SetRead(*vp);
  20613.    gp->unread_count--;
  20614.  }
  20615.  
  20616.  if (!IsNull(*vp) && !IsMissing(*vp)) {
  20617.    ap = VARK2PARTICLE(*vp);
  20618.    ap->action = READ;
  20619.  }
  20620.  
  20621.  return;
  20622. }
  20623.  
  20624. ./ ADD NAME=NNMMARU
  20625.  
  20626.  /********************************************************************/
  20627.  /*                                                                  */
  20628.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  20629.  /*                                                                  */
  20630.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  20631.  /* including the implied warranties of merchantability and fitness, */
  20632.  /* are expressly denied.                                            */
  20633.  /*                                                                  */
  20634.  /* Provided this copyright notice is included, this software may    */
  20635.  /* be freely distributed and not offered for sale.                  */
  20636.  /*                                                                  */
  20637.  /* Changes or modifications may be made and used only by the maker  */
  20638.  /* of same, and not further distributed.  Such modifications should */
  20639.  /* be mailed to the author for consideration for addition to the    */
  20640.  /* software and incorporation in subsequent releases.               */
  20641.  /*                                                                  */
  20642.  /********************************************************************/
  20643.  
  20644. #pragma  csect(code,  "NN@MARU ")
  20645. #pragma  csect(static,"NN$MARU ")
  20646. #include "nn.h"
  20647.  
  20648. /****** Make article unread. *****************************************/
  20649.  
  20650. void
  20651. NNMmaru(np,gp,vp)
  20652. Rstruc nncb         *np;
  20653. Rstruc newsgroup    *gp;
  20654. register VARK       *vp;
  20655. {
  20656.  struct newsarticle *ap;
  20657.  
  20658.  if (IsRead(*vp)) {
  20659.    SetUnread(*vp);
  20660.    gp->unread_count++;
  20661.  }
  20662.  
  20663.  if (!IsNull(*vp) && !IsMissing(*vp)) {
  20664.    ap = VARK2PARTICLE(*vp);
  20665.    ap->action = UNREAD;
  20666.  }
  20667.  
  20668.  return;
  20669. }
  20670.  
  20671. ./ ADD NAME=NNMNNTP
  20672.  
  20673.  /********************************************************************/
  20674.  /*                                                                  */
  20675.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  20676.  /*                                                                  */
  20677.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  20678.  /* including the implied warranties of merchantability and fitness, */
  20679.  /* are expressly denied.                                            */
  20680.  /*                                                                  */
  20681.  /* Provided this copyright notice is included, this software may    */
  20682.  /* be freely distributed and not offered for sale.                  */
  20683.  /*                                                                  */
  20684.  /* Changes or modifications may be made and used only by the maker  */
  20685.  /* of same, and not further distributed.  Such modifications should */
  20686.  /* be mailed to the author for consideration for addition to the    */
  20687.  /* software and incorporation in subsequent releases.               */
  20688.  /*                                                                  */
  20689.  /********************************************************************/
  20690.  
  20691. #pragma  csect(code,  "NN@NNTP ")
  20692. #pragma  csect(static,"NN$NNTP ")
  20693. #include "nn.h"
  20694.  
  20695. /****** Read server data. ********************************************/
  20696.  
  20697. static Bool
  20698. read_server_data(np)
  20699. Rstruc nncb         *np;
  20700. {
  20701.  char               *lp;
  20702.  
  20703.  NNMclrtx(np,NULL);                   /* Clear text */
  20704.  
  20705.  do {
  20706.  
  20707.    if (NNMgsrvl(np,&lp))              /* Get server line */
  20708.      if (lp) {
  20709.        (void)NNMouttx(np,lp,NULL);   /* Output text line */
  20710.      }
  20711.  
  20712.  } while (lp);
  20713.  
  20714.  if (np->time_to_go_home) return FALSE;
  20715.  else return TRUE;
  20716. }
  20717.  
  20718. /************ Execute native NNTP protocol commands. *****************/
  20719.  
  20720. void
  20721. NNMnntp(np)
  20722. Rstruc nncb *np;
  20723. {
  20724.  struct texthdr   saveth;
  20725.  
  20726.  /* np->nntp_command must contain NNTP command */
  20727.  
  20728.  if (!np->receiving_text && !*np->nntp_command) return;
  20729.  
  20730.  np->newsgroup_selected = FALSE;  /* in case we change server's state
  20731.                                      with a command like "GROUP xxx" */
  20732.  
  20733.  memcpy(&saveth,&np->thdr,sizeof(struct texthdr));
  20734.  memset(&np->thdr,0,sizeof(struct texthdr));
  20735.  
  20736.  if (NNMsockt(np)) {              /* Send socket command to server */
  20737.    if (read_server_data(np,NULL)) {           /* Read server data */
  20738.      NNMvtx(np,NULL,NULL);                    /* View text        */
  20739.    }
  20740.    NNMclrtx(np,NULL);
  20741.  }
  20742.  memcpy(&np->thdr,&saveth,sizeof(struct texthdr));
  20743.  return;
  20744. }
  20745.  
  20746. ./ ADD NAME=NNMONRF
  20747.  
  20748.  /********************************************************************/
  20749.  /*                                                                  */
  20750.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  20751.  /*                                                                  */
  20752.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  20753.  /*                                                                  */
  20754.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  20755.  /* including the implied warranties of merchantability and fitness, */
  20756.  /* are expressly denied.                                            */
  20757.  /*                                                                  */
  20758.  /* Provided this copyright notice is included, this software may    */
  20759.  /* be freely distributed and not offered for sale.                  */
  20760.  /*                                                                  */
  20761.  /* Changes or modifications may be made and used only by the maker  */
  20762.  /* of same, and not further distributed.  Such modifications should */
  20763.  /* be mailed to the author for consideration for addition to the    */
  20764.  /* software and incorporation in subsequent releases.               */
  20765.  /*                                                                  */
  20766.  /********************************************************************/
  20767.  
  20768. #pragma  csect(code,  "NN@ONRF ")
  20769. #pragma  csect(static,"NN$ONRF ")
  20770. #include "nn.h"
  20771.  
  20772. /****** Open NEWSRC file. ********************************************/
  20773.  
  20774. void
  20775. NNMonrf(np,what_to_open)
  20776. Rstruc nncb         *np;
  20777. char                *what_to_open;
  20778. {
  20779.  char                newsrc_line[256];
  20780.  char                newsrc_name[GROUP_NAME_SIZE];
  20781.  Rstruc newsgroup   *gp;
  20782.  register char      *nlp;
  20783.  char               *temp;
  20784.  int                 sscanf_rc;
  20785.  int                 newsrc_registered;
  20786.  int                 newsrc_unread;
  20787.  int                 newsrc_topnum;
  20788.  int                 newsrc_scan_count;
  20789.  int                 newsrc_save_length;
  20790.  
  20791.  if (!what_to_open) what_to_open = np->newsrc_to_open;
  20792.  
  20793.  /* If the file does not exist, then create it. */
  20794.  
  20795.  newsrc_scan_count = 0;
  20796.  np->brand_new_newsrc = TRUE;
  20797.  
  20798.  errno = 0;
  20799.  
  20800.  if (!(np->newsrc_file = fopen(what_to_open,"r"))) {
  20801.    if (errno == 104) {  /* Member not found */
  20802.      if (!(np->newsrc_file = fopen(what_to_open,"w"))) {
  20803.        perror("Cannot create NEWSRC PDS member");
  20804.      }
  20805.      else if (fclose(np->newsrc_file) < 0) {
  20806.        fprintf(stderr, "Error closing %s\n", what_to_open);
  20807.        np->newsrc_file = NULL;
  20808.      }
  20809.      else np->newsrc_file = fopen(what_to_open,"r");
  20810.    }
  20811.    else perror("Cannot open NEWSRC file");
  20812.  }
  20813.  if (!np->newsrc_file) {
  20814.    fprintf(stderr,"Severe error, NEWSRC file cannot be opened.\n");
  20815.    if (!np->batch_mode) {
  20816.      (void)NNMdispl(np,"NNMRCERR");
  20817.    }
  20818.    exit(12);
  20819.  }
  20820.  
  20821.  np->new_newsgroup_count = 0;
  20822.  
  20823.  /* Read from the file, saving the state information. */
  20824.  
  20825.  /********************************************************************/
  20826.  /*                                                                  */
  20827.  /* Note:  The format used here is designed to be compatible with    */
  20828.  /*        the format used by ANU-NEWS.  This is not an attempt to   */
  20829.  /*        duplicate the "look and feel" of ANU-NEWS - it is just    */
  20830.  /*        to be compatible with the saved state of VAX NEWS users.  */
  20831.  /*                                                                  */
  20832.  /********************************************************************/
  20833.  
  20834.  if (feof(np->newsrc_file)) return;
  20835.  
  20836.  /* First line: time in hex digits of last "registration", and some
  20837.   * other junk.  We now interpret this as the last time the status
  20838.   * of the server's newsgroups was interrogated (LIST or NEWGROUPS)
  20839.   * and save it.
  20840.   */
  20841.  
  20842.  fgets(newsrc_line,sizeof(newsrc_line),np->newsrc_file);
  20843.  if (strlen(newsrc_line) >= 13)      /* if new format .newsrc file  */
  20844.     sscanf(newsrc_line, "%6c %6c", &np->lastNGdate, &np->lastNGtime);
  20845.  
  20846.  if (feof(np->newsrc_file)) return;
  20847.  
  20848.  /* The rest of the file consists of information about newsgroups.
  20849.     Read until end of file or one of the special markers is found. */
  20850.  
  20851.  fgets(newsrc_line,sizeof(newsrc_line),np->newsrc_file);
  20852.  
  20853.  while (!feof(np->newsrc_file)) {
  20854.  
  20855.    if (EQUAL(newsrc_line,"MARKLIST\n"))  break;
  20856.    if (EQUAL(newsrc_line,"KILLLIST\n"))  break;
  20857.    if (EQUAL(newsrc_line,"PROFILE\n"))   break;
  20858.  
  20859.  /* For each line, build a newsgroup entry and fill it in with
  20860.     the values taken from the input line. */
  20861.  
  20862.  /* Right now we are not checking for {classname,classname} as we
  20863.     don't know how, and it would complicate things. */
  20864.  
  20865.    nlp = strchr(newsrc_line,':');
  20866.    if (!nlp) nlp = strchr(newsrc_line,'\n');
  20867.    if (!nlp) {
  20868.      fprintf(stderr,"Bad name in newsrc file, ignored:\n%s\n\n",
  20869.                     newsrc_line);
  20870.      fgets(newsrc_line,sizeof(newsrc_line),np->newsrc_file);
  20871.      continue;
  20872.    }
  20873.    memcpy(newsrc_name,newsrc_line,nlp-newsrc_line);
  20874.    newsrc_name[nlp-newsrc_line] = '\0';
  20875.    if (*nlp == '\n' || *(nlp+1) == '\n') sscanf_rc = 0;
  20876.    else
  20877.     sscanf_rc = sscanf(nlp,": (%d) [%d,%d] %n",
  20878.                              &newsrc_registered,
  20879.                              &newsrc_unread,
  20880.                              &newsrc_topnum,
  20881.                              &newsrc_scan_count);
  20882.  
  20883.    switch (sscanf_rc) {    /* Note use of switch WITHOUT break here. */
  20884.       case EOF: newsrc_registered = 1;
  20885.       case 0:   newsrc_registered = 1;
  20886.       case 1:   newsrc_unread     = 0;
  20887.       case 2:   newsrc_topnum     = 0;
  20888.                 nlp = NULL;
  20889.       case 3:   break;
  20890.       default:  break;
  20891.    }
  20892.  
  20893.    np->brand_new_newsrc = FALSE;
  20894.  
  20895.    /* Allocate a newsgroup for this record. */
  20896.  
  20897.    gp = NNMaddng(np,newsrc_name);     /* Add newsgroup */
  20898.    if (!gp) {
  20899.       fprintf(stderr,"Cannot initialize newsgroup: %s\n",newsrc_name);
  20900.       fgets(newsrc_line,sizeof(newsrc_line),np->newsrc_file);
  20901.       continue;
  20902.    }
  20903.  
  20904.    /* Now, collect the information on what articles were read. */
  20905.  
  20906.    SetGroupFromNewsrc(gp);
  20907.    gp->low_number    = 1;             /* or new field from newsrc? */
  20908.    gp->high_number   = newsrc_topnum;
  20909.    gp->vector_first  = 0;
  20910.    gp->vector_last   = 0;
  20911.    gp->article_count = gp->high_number - gp->low_number + 1;
  20912.    gp->unread_count  = newsrc_unread;
  20913.    gp->registered    = newsrc_registered;
  20914.  
  20915.    if (gp->registered == -1) {
  20916.      SetNewGroup(gp);
  20917.      gp->registered = 0;
  20918.      np->new_newsgroup_count++;
  20919.    }
  20920.  
  20921.    /* At this early point, we just save the NEWSRC line and
  20922.     * create the article vector later, when we really need it.
  20923.     */
  20924.  
  20925.    if (!nlp) {
  20926.      fgets(newsrc_line,sizeof(newsrc_line),np->newsrc_file);
  20927.      continue;
  20928.    }
  20929.  
  20930.    nlp += newsrc_scan_count;
  20931.  
  20932.    /* Save the newsrc data (following the [unread,topnum] spec) */
  20933.  
  20934.    if (gp->saved_newsrc_line != gp->saved_newsrc_data) {
  20935.      FREEMAIN(gp->saved_newsrc_line,"stale saved newsrc line");
  20936.    }
  20937.    if (*nlp == '\0') nlp = "\n";
  20938.    newsrc_save_length = strlen(nlp) + 1;
  20939.    if (newsrc_save_length <= sizeof(gp->saved_newsrc_data)) {
  20940.      gp->saved_newsrc_line = gp->saved_newsrc_data;
  20941.    }
  20942.    else {
  20943.      GETMAIN(gp->saved_newsrc_line,char,newsrc_save_length,
  20944.              "saved newsrc line");
  20945.      if (!gp->saved_newsrc_line) {
  20946.        fprintf(stderr,"Cannot save newsrc line for %s, terminating.\n",
  20947.                       newsrc_name);
  20948.        return;
  20949.      }
  20950.    }
  20951.    strcpy(gp->saved_newsrc_line,nlp);
  20952.  
  20953.    for (;;) {
  20954.  
  20955.      fgets(newsrc_line,sizeof(newsrc_line),np->newsrc_file);
  20956.      if (feof(np->newsrc_file)) break;
  20957.      if (newsrc_line[0] != ' ') break;
  20958.      nlp = newsrc_line;
  20959.      GETMAIN(temp,char,strlen(gp->saved_newsrc_line)+strlen(nlp)+1,
  20960.                        "saved newsrc line continuation");
  20961.      if (!temp) {
  20962.        fprintf(stderr,"Cannot save newsrc line for %s, terminating.\n",
  20963.                       newsrc_name);
  20964.        return;
  20965.      }
  20966.      strcpy(temp,gp->saved_newsrc_line);  /* should include newline */
  20967.      strcat(temp,nlp);
  20968.      if (gp->saved_newsrc_line != gp->saved_newsrc_data) {
  20969.        FREEMAIN(gp->saved_newsrc_line,"old saved newsrc line");
  20970.      }
  20971.      gp->saved_newsrc_line = temp;
  20972.  
  20973.    } /* end for - at this point we have no more newsrc continuations */
  20974.  
  20975.  } /* end while */
  20976.  
  20977.  /* At this point we have finished reading newsrc.
  20978.     Ignore everything once MARKLIST, KILLLIST, or PROFILE is seen.
  20979.     We don't handle any of that stuff. */
  20980.  
  20981.  return;
  20982. }
  20983.  
  20984. ./ ADD NAME=NNMOUTTX
  20985.  
  20986.  /********************************************************************/
  20987.  /*                                                                  */
  20988.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  20989.  /*                                                                  */
  20990.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  20991.  /* including the implied warranties of merchantability and fitness, */
  20992.  /* are expressly denied.                                            */
  20993.  /*                                                                  */
  20994.  /* Provided this copyright notice is included, this software may    */
  20995.  /* be freely distributed and not offered for sale.                  */
  20996.  /*                                                                  */
  20997.  /* Changes or modifications may be made and used only by the maker  */
  20998.  /* of same, and not further distributed.  Such modifications should */
  20999.  /* be mailed to the author for consideration for addition to the    */
  21000.  /* software and incorporation in subsequent releases.               */
  21001.  /*                                                                  */
  21002.  /********************************************************************/
  21003.  
  21004. #pragma  csect(code,  "NN@OUTTX")
  21005. #pragma  csect(static,"NN$OUTTX")
  21006. #include "nn.h"
  21007.  
  21008. /****** Output a line of text retrieved from the server. *************/
  21009.  
  21010. struct textline *
  21011. NNMouttx(np,line,ap)
  21012. Rstruc nncb         *np;
  21013. char                *line;
  21014. Rstruc newsarticle  *ap;
  21015.  
  21016. {
  21017.  struct texthdr     *thp;
  21018.  struct textline    *tp;
  21019.  short              line_length;
  21020.  short              total_text_length;
  21021.  short              tab_expansion_length;
  21022.  Bool               tabs_present;
  21023.  char              *p;
  21024.  char              *q;
  21025.  char              *t;
  21026.  int                e;
  21027.  int                u;
  21028.  
  21029.  static char        tab_expansion_buffer[8*TEXT_BYTES];
  21030.  
  21031.  /* If article is not specified, use main nncb, else article's text */
  21032.  
  21033.  thp = (ap ? &ap->thdr : &np->thdr);
  21034.  
  21035.  /* If line starts with double period, make it a single period. */
  21036.  
  21037.  if (ap && memcmp(line,"..",2) == 0) line++;
  21038.  
  21039.  /* Add this line to the current queue of server text lines. */
  21040.  
  21041.  /* First, expand tabs in the line. */
  21042.  
  21043.  line_length = strlen(line);
  21044.  t = strchr(line,'\t');
  21045.  if (!t) {
  21046.    tabs_present = FALSE;
  21047.    total_text_length = line_length + 1;
  21048.  }
  21049.  else {                                   /* expand tabs */
  21050.    tabs_present = TRUE;
  21051.    p = line;
  21052.    q = line + line_length;
  21053.    e = 0;
  21054.    memset(tab_expansion_buffer,' ',sizeof(tab_expansion_buffer));
  21055.    for (;;) {
  21056.      u = t - p;
  21057.      if (u > 0) {
  21058.        memcpy(tab_expansion_buffer+e,p,u);
  21059.        e += u;
  21060.      }
  21061.      if (t == q) break;
  21062.      e = e / 8 * 8 + 8;
  21063.      p = t+1;
  21064.      t = strchr(p,'\t');
  21065.      if (!t) t = q;
  21066.    }
  21067.    tab_expansion_length = e;
  21068.    tab_expansion_buffer[tab_expansion_length] = '\0';
  21069.    total_text_length = line_length + tab_expansion_length + 1;
  21070.  }
  21071.  
  21072.  GETMAIN(tp, char, offsetof(struct textline, text) + total_text_length,
  21073.                    "text line");
  21074.  
  21075.  if (!tp) {
  21076.    ERR1("There is not enough virtual storage to process server text.");
  21077.    return NULL;
  21078.  }
  21079.  
  21080.  tp->next = NULL;
  21081.  tp->text_length = line_length;
  21082.  strcpy(tp->text,line);
  21083.  if (tabs_present) {
  21084.    tp->tab_expanded_text_length = tab_expansion_length;
  21085.    tp->tab_expanded_text = tp->text + line_length;
  21086.    strcpy(tp->tab_expanded_text,tab_expansion_buffer);
  21087.  }
  21088.  else {
  21089.    tp->tab_expanded_text_length = line_length;
  21090.    tp->tab_expanded_text = tp->text;
  21091.  }
  21092.  
  21093.  if (!thp->last_text_line) {
  21094.    thp->first_text_line   = tp;
  21095.    thp->text_body_line    = tp;
  21096.    thp->current_text_line = tp;
  21097.  }
  21098.  else thp->last_text_line->next = tp;
  21099.  
  21100.  thp->last_text_line = tp;
  21101.  thp->text_line_count++;
  21102.  
  21103.  if (thp->text_max_length < tp->text_length)
  21104.      thp->text_max_length = tp->text_length;
  21105.  if (thp->text_max_tab_expanded_length < tp->tab_expanded_text_length)
  21106.      thp->text_max_tab_expanded_length = tp->tab_expanded_text_length;
  21107.  
  21108.  return tp;
  21109.  
  21110. }
  21111.  
  21112. ./ ADD NAME=NNMPICK
  21113.  
  21114.  /********************************************************************/
  21115.  /*                                                                  */
  21116.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  21117.  /*                                                                  */
  21118.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  21119.  /*                                                                  */
  21120.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  21121.  /* including the implied warranties of merchantability and fitness, */
  21122.  /* are expressly denied.                                            */
  21123.  /*                                                                  */
  21124.  /* Provided this copyright notice is included, this software may    */
  21125.  /* be freely distributed and not offered for sale.                  */
  21126.  /*                                                                  */
  21127.  /* Changes or modifications may be made and used only by the maker  */
  21128.  /* of same, and not further distributed.  Such modifications should */
  21129.  /* be mailed to the author for consideration for addition to the    */
  21130.  /* software and incorporation in subsequent releases.               */
  21131.  /*                                                                  */
  21132.  /********************************************************************/
  21133.  
  21134. #pragma  csect(code,  "NN@PICK ")
  21135. #pragma  csect(static,"NN$PICK ")
  21136. #include "nn.h"
  21137.  
  21138. /****** Collect text. ************************************************/
  21139.  
  21140. static void
  21141. collect_text(np,ap)
  21142. Rstruc nncb         *np;
  21143. Rstruc newsarticle  *ap;
  21144. {
  21145.  char               *lp;
  21146.  
  21147.  np->sending_text = TRUE;
  21148.  
  21149.  for (;;) {
  21150.  
  21151.    if (!NNMgsrvl(np,&lp))         break; /* Get server line */
  21152.    if (lp == NULL)                break;
  21153.    if (strcmp(lp,".") == 0)       break;
  21154.    if (!NNMouttx(np,lp,ap))       break; /* Output text line */
  21155.  
  21156.  }
  21157.  
  21158.  return;
  21159.  
  21160. }
  21161.  
  21162. /****** Maybe suppress header line. **********************************/
  21163.  
  21164. static void
  21165. maybe_suppress_header_line(np,ap,tp,header_name)
  21166. Rstruc nncb         *np;
  21167. Rstruc newsarticle  *ap;
  21168. Rstruc textline     *tp;
  21169. char                *header_name;
  21170. {
  21171.  char                temphdr[INTERNET_SIZE+2];
  21172.  Bool                suppress;
  21173.  
  21174.  switch (np->nnrfcopt[0]) {
  21175.    case '\0':
  21176.    case 'A':                /* show all RFC822 headers */
  21177.               suppress = FALSE;
  21178.               break;
  21179.    case 'B':                /* show all except those in exclude list */
  21180.               sprintf(temphdr," %s ",header_name);
  21181.               if (strstr(np->nnrfcexc,temphdr)) suppress = TRUE;
  21182.               else                              suppress = FALSE;
  21183.               break;
  21184.    case 'C':                /* show only those in include list */
  21185.               sprintf(temphdr," %s ",header_name);
  21186.               if (strstr(np->nnrfcinc,temphdr)) suppress = FALSE;
  21187.               else                              suppress = TRUE;
  21188.               break;
  21189.    case 'D':                /* show none */
  21190.               suppress = TRUE;
  21191.               break;
  21192.  }
  21193.  
  21194.  if (suppress) {
  21195.    if (tp->text_length >= 0) {
  21196.      tp->text_length |= 0x8000;    /* force sign bit negative */
  21197.      ap->thdr.text_line_count--;
  21198.    }
  21199.  }
  21200.  else {
  21201.    if (tp->text_length < 0) {
  21202.      tp->text_length &= 0x7fff;    /* force sign bit positive */
  21203.      ap->thdr.text_line_count++;
  21204.    }
  21205.  }
  21206.  
  21207.  return;
  21208. }
  21209.  
  21210. /****** Apply header suppression.  ***********************************/
  21211.  
  21212. static void
  21213. apply_header_suppression(np,ap)
  21214. Rstruc nncb         *np;
  21215. Rstruc newsarticle  *ap;
  21216. {
  21217.  struct textline     *tp;
  21218.  struct texthdr      *thp;
  21219.  char                *cp;
  21220.  char                *colonp;
  21221.  int                  header_index;
  21222.  char                 header_name[INTERNET_SIZE];
  21223.  
  21224.  thp = &ap->thdr;
  21225.  strcpy(header_name,"");
  21226.  for (tp=thp->first_text_line; tp; tp=tp->next) {
  21227.    if (tp->text[0] == '\0') break;
  21228.    if (tp->text[0] == ' ' ||
  21229.        tp->text[0] == '\t') {
  21230.      cp = tp->text + strspn(tp->text," \t");
  21231.      if (*cp == '\0') break;
  21232.    }
  21233.    else {
  21234.      header_index = 0;
  21235.      colonp = strchr(tp->text,':');
  21236.      if (!colonp) break;
  21237.      strcpy(header_name,"");
  21238.      for (cp = tp->text;cp<colonp;cp++) {
  21239.        header_name[header_index++] = toupper(*cp);
  21240.      }
  21241.      header_name[header_index] = '\0';
  21242.    }
  21243.    if (*header_name) {
  21244.       maybe_suppress_header_line(np,ap,tp,header_name);
  21245.    }
  21246.  }
  21247.  
  21248.  thp->text_body_line = tp;
  21249.  
  21250.  return;
  21251. }
  21252.  
  21253. /****** Pick article before processing. ******************************/
  21254.  
  21255. Bool
  21256. NNMpick(np,ap)
  21257. Rstruc nncb          *np;
  21258. Rstruc newsarticle   *ap;
  21259. {
  21260.  Rstruc newsgroup    *gp;
  21261.  char                *lp;
  21262.  char                 bad_status        = ERROR;
  21263.  Bool                 retval            = TRUE;
  21264.  Bool                 retrieve_header   = FALSE;
  21265.  Bool                 retrieve_body     = FALSE;
  21266.  
  21267.  np->another_article = NULL_ARTICLE_COOKIE;
  21268.  
  21269.  gp = np->current_newsgroup;
  21270.  
  21271.  if (!gp) {
  21272.    CRIT1("No current newsgroup.  This should never happen.");
  21273.    return FALSE;
  21274.  }
  21275.  
  21276.  if (ap == V_NULL_ARTICLE) {
  21277.    ERR1("This article does not exist - how could it be chosen?");
  21278.    return FALSE;
  21279.  }
  21280.  
  21281.  if (ap == V_MISSING_ARTICLE) {
  21282.    ERR1("This article is missing - how could it be chosen?");
  21283.    return FALSE;
  21284.  }
  21285.  
  21286.  if (NoSuchArticle(ap)) {
  21287.    ERR4("Article %d of %s does not exist in server %s.",
  21288.         ap->number, gp->name, np->nnserver);
  21289.    retval = FALSE;
  21290.  }
  21291.  else if (ArticleAbsent(ap)) {
  21292.    ERR4("Article %d of %s was not retrieved by server %s.",
  21293.         ap->number, gp->name, np->nnserver);
  21294.    retval = FALSE;
  21295.  }
  21296.  else if (ArticleError(ap)) {
  21297.    ERR4("Error getting article %d of %s from server %s.",
  21298.         ap->number, gp->name, np->nnserver);
  21299.    retval = FALSE;
  21300.  }
  21301.  else {
  21302.    retrieve_header = !ArticleHeadRetrieved(ap);
  21303.    retrieve_body   = !ArticleBodyRetrieved(ap);
  21304.  }
  21305.  
  21306.  if (retrieve_header || retrieve_body) {
  21307.  
  21308.    if (!NNMestng(np,NULL)) {           /* Establish newsgroup */
  21309.      SetGroupError(gp);
  21310.      OffGroupSelected(gp);
  21311.      return FALSE;
  21312.    }
  21313.  
  21314.    if (retrieve_header) {
  21315.      if (!NNMrarh(np,gp,NULL,ap->number,NULL)) {
  21316.        ERR4("Article %d of %s could not be retrieved from server %s.",
  21317.             ap->number, gp->name, np->nnserver);
  21318.        ap->action = MISSING;
  21319.        return FALSE;
  21320.      }
  21321.    }
  21322.  
  21323.    sprintf(np->nntp_command,"BODY %d",ap->number);
  21324.    if (!NNMsockt(np))      return FALSE; /* Send socket cmd to server*/
  21325.    if (!NNMgsrvl(np,&lp))  return FALSE; /* Get server line */
  21326.    switch(np->nntp_message_num) {
  21327.      case 220:       /* article retrieved - head and body follow    */
  21328.                break;
  21329.      case 221:       /* article retrieved - head follows            */
  21330.                break;
  21331.      case 222:       /* article retrieved - body follows            */
  21332.                break;
  21333.      case 423:       /* no such article number in this group        */
  21334.                ERR4("Article %d of %s is missing from server %s.",
  21335.                     ap->number, gp->name, np->nnserver);
  21336.                bad_status = MISSING;
  21337.                retval = FALSE;
  21338.                break;
  21339.      case 430:       /* no such article found                       */
  21340.                ERR4("Article %d of %s could not be found by server %s.",
  21341.                     ap->number, gp->name, np->nnserver);
  21342.                bad_status = MISSING;
  21343.                retval = FALSE;
  21344.                break;
  21345.      case 223:       /* article retrieved - request text separately */
  21346.      case 412:       /* no newsgroup has been selected              */
  21347.      case 420:       /* no current article has been selected        */
  21348.      default:  NNMrperr(np);      /* Report protocol error */
  21349.                retval = FALSE;
  21350.                break;
  21351.    }
  21352.  }
  21353.  
  21354.  if (retval == FALSE) {
  21355.    ap->action = bad_status;
  21356.    return FALSE;
  21357.  }
  21358.  
  21359.  SetArticleRetrieved(ap);
  21360.  ap->action = NO_ACTION;
  21361.  
  21362.  if (retrieve_body) {
  21363.    if (!NNMouttx(np," ",ap)) return FALSE;    /* output text line */
  21364.    collect_text(np,ap);
  21365.  }
  21366.  
  21367.  apply_header_suppression(np,ap);
  21368.  
  21369.  return TRUE;
  21370. }
  21371.  
  21372. ./ ADD NAME=NNMPMSG
  21373.  
  21374.  /********************************************************************/
  21375.  /*                                                                  */
  21376.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  21377.  /*                                                                  */
  21378.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  21379.  /* including the implied warranties of merchantability and fitness, */
  21380.  /* are expressly denied.                                            */
  21381.  /*                                                                  */
  21382.  /* Provided this copyright notice is included, this software may    */
  21383.  /* be freely distributed and not offered for sale.                  */
  21384.  /*                                                                  */
  21385.  /* Changes or modifications may be made and used only by the maker  */
  21386.  /* of same, and not further distributed.  Such modifications should */
  21387.  /* be mailed to the author for consideration for addition to the    */
  21388.  /* software and incorporation in subsequent releases.               */
  21389.  /*                                                                  */
  21390.  /********************************************************************/
  21391.  
  21392. #define  SUPPRESS_V_DECLARATION
  21393. #pragma  csect(code,  "NN@PMSG ")
  21394. #pragma  csect(static,"NN$PMSG ")
  21395. #include "nn.h"
  21396.  
  21397. /****** Set an ISPF message, or write to SYSOUT if batch mode. *******/
  21398.  
  21399. void
  21400. NNMpmsg(np,msgtype,msghelp,msgformat) /* also ... for sprintf args */
  21401. Rstruc nncb *np;
  21402. int          msgtype;
  21403. char        *msghelp;
  21404. char        *msgformat;
  21405. {
  21406.  va_list     argp;
  21407.  char       *cp;
  21408.  char        zerrsm    [25];
  21409.  char        zerrhm     [9];
  21410.  char        zerralrm   [4];
  21411.  char        zerrlm   [ZERRLM_SIZE];
  21412.  char        buf      [257];
  21413.  
  21414.  va_start(argp,msgformat);
  21415.  vsprintf(buf,msgformat,argp);
  21416.  va_end(argp);
  21417.  
  21418.  cp = strchr(buf,';');
  21419.  if (cp) {
  21420.   *cp = '\0';
  21421.   strncpy(zerrsm,buf, sizeof(zerrsm));
  21422.   strncpy(zerrlm,cp+1,sizeof(zerrlm));
  21423.  }
  21424.  else {
  21425.   strcpy(zerrsm,"");
  21426.   strncpy(zerrlm,buf,sizeof(zerrlm));
  21427.  }
  21428.  
  21429.  zerrsm[sizeof(zerrsm)-1] = '\0';
  21430.  zerrlm[sizeof(zerrlm)-1] = '\0';
  21431.  
  21432.  if (msghelp) strcpy(zerrhm, msghelp);
  21433.  else         strcpy(zerrhm, "*"    );
  21434.  
  21435.  if (np->batch_mode) {
  21436.    if (!*zerrsm) {
  21437.      switch (msgtype) {
  21438.        case NOTIFY_MSG:    strcpy(zerrsm,"Note");  break;
  21439.        case WARNING_MSG:
  21440.        case CRITICAL_MSG:
  21441.        default:            strcpy(zerrsm,"Error"); break;
  21442.      }
  21443.    }
  21444.    fprintf(np->batch_outfile,"%s: %s\n", zerrsm, zerrlm);
  21445.    return;
  21446.  }
  21447.  
  21448.  switch (msgtype) {
  21449.    case NOTIFY_MSG:    strcpy(zerralrm,"NO "); break;
  21450.    case WARNING_MSG:
  21451.    case CRITICAL_MSG:
  21452.    default:            strcpy(zerralrm,"YES"); break;
  21453.  }
  21454.  
  21455.  (void)NNMivput(np,"ZERRSM ",  zerrsm,   -1);
  21456.  (void)NNMivput(np,"ZERRLM ",  zerrlm,   -1);
  21457.  (void)NNMivput(np,"ZERRHM ",  zerrhm,   -1);
  21458.  (void)NNMivput(np,"ZERRALRM ",zerralrm, -1);
  21459.  
  21460.  np->setmsg = TRUE;
  21461.  
  21462.  return;
  21463. }
  21464.  
  21465. ./ ADD NAME=NNMPNG
  21466.  
  21467.  /********************************************************************/
  21468.  /*                                                                  */
  21469.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  21470.  /*                                                                  */
  21471.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  21472.  /* including the implied warranties of merchantability and fitness, */
  21473.  /* are expressly denied.                                            */
  21474.  /*                                                                  */
  21475.  /* Provided this copyright notice is included, this software may    */
  21476.  /* be freely distributed and not offered for sale.                  */
  21477.  /*                                                                  */
  21478.  /* Changes or modifications may be made and used only by the maker  */
  21479.  /* of same, and not further distributed.  Such modifications should */
  21480.  /* be mailed to the author for consideration for addition to the    */
  21481.  /* software and incorporation in subsequent releases.               */
  21482.  /*                                                                  */
  21483.  /********************************************************************/
  21484.  
  21485. #pragma  csect(code,  "NN@PNG  ")
  21486. #pragma  csect(static,"NN$PNG  ")
  21487. #include "nn.h"
  21488.  
  21489. /****** Set articles missing based on XHDR info. *********************/
  21490.  
  21491. static void
  21492. set_articles_missing(np,gp,anum,xnum)
  21493. Rstruc nncb      *np;
  21494. Rstruc newsgroup *gp;
  21495. int               anum;
  21496. int               xnum;
  21497. {
  21498.  VARK            *vp;
  21499.  
  21500.  while (anum < xnum) {
  21501.    if (np->debug_file) {
  21502.      fprintf(np->debug_file, "Setting article %d missing\n",anum);
  21503.    }
  21504.    vp = &GETVARK(gp,anum);
  21505.    if (IsUnread(*vp)) gp->unread_count--;
  21506.    SetMissingRead(*vp);
  21507.    anum++;
  21508.  }
  21509.  
  21510.  return;
  21511. }
  21512.  
  21513. /****** Do XHDR stuff for newsgroup. *********************************/
  21514.  
  21515. static void
  21516. do_xhdr(np,gp,allp)
  21517. Rstruc nncb         *np;
  21518. Rstruc newsgroup    *gp;
  21519. Bool                 allp;
  21520. {
  21521.  char               *lp;
  21522.  char               *xhdr_subject;
  21523.  VARK               *vplow;
  21524.  VARK               *vphigh;
  21525.  VARK               *vpfirst;
  21526.  VARK               *vplast;
  21527.  int                 range;
  21528.  int                 xhdr_article_number;
  21529.  int                 scan_count;
  21530.  int                 xhdr_low;
  21531.  int                 xhdr_high;
  21532.  int                 anum;
  21533.  
  21534.  /* If we need to know about missing articles,
  21535.   * we try to determine it via XHDR.
  21536.   *
  21537.   *    We don't do anything useful with the headers yet.  We should.
  21538.   *    That requires doing something with the allocation of the
  21539.   *    newsarticle structures.
  21540.   *
  21541.   * We use XHDR when:
  21542.   *
  21543.   * (1) the total article count is less than the difference between
  21544.   *     the low and high count from the GROUP command
  21545.   *
  21546.   * (2) there are null (never-retrieved) articles
  21547.   *
  21548.   * Fine, but requires looping around the article vector.
  21549.   * Now, if we only want unread articles, we don't want to XHDR
  21550.   * the whole thing, so in that case we only do this if there are
  21551.   * any null-and-unread articles.
  21552.   *
  21553.   * *** this is still no good because articles are set missing
  21554.   * *** but cannot be set present if we don't know if they will
  21555.   * *** be eligible or not.  I will HAVE to keep the subject and
  21556.   * *** set the article pointer to a placeholder with the subject,
  21557.   * *** which means more article structures allocated, but that is
  21558.   * *** probably the best thing to do.
  21559.   *
  21560.   * Solution: we call this routine only when a group migrates
  21561.   * from unselected to selected status - either when it goes
  21562.   * from never-selected to selected-unread, from never-selected
  21563.   * to selected-all, or from selected-unread to selected-all.
  21564.   * The first of the above cases is where allp is set to false
  21565.   * so that we don't XHDR the whole thing just for a few unread items.
  21566.   *
  21567.   */
  21568.  
  21569.  if (!gp->article_vector) return;
  21570.  if (np->xhdr_not_available) return;
  21571.  
  21572.  range = gp->vector_last - gp->vector_first + 1;
  21573.  if (range <= gp->article_count) return;
  21574.  
  21575.  vpfirst = &GETVARKFIRST(gp);
  21576.  vplast  = &GETVARKLAST(gp);
  21577.  
  21578.  if (allp) {
  21579.    for (vplow = vpfirst; vplow <= vplast; vplow++) {
  21580.      if (IsNull(*vplow)) break;
  21581.    }
  21582.    if (vplow > vplast) return; /* if no null articles */
  21583.    for (vphigh = vplast; vphigh > vplow; vphigh--) {
  21584.      if (IsNull(*vphigh)) break;
  21585.    }
  21586.  }
  21587.  else {
  21588.    for (vplow = vpfirst; vplow <= vplast; vplow++) {
  21589.      if (IsNull(*vplow) && IsUnread(*vplow)) break;
  21590.    }
  21591.    if (vplow > vplast) return; /* if no null articles */
  21592.    for (vphigh = vplast; vphigh > vplow; vphigh--) {
  21593.      if (IsNull(*vphigh) && IsUnread(*vphigh)) break;
  21594.    }
  21595.  }
  21596.  
  21597.  xhdr_low  = VARK2NUMBER(gp,vplow);
  21598.  xhdr_high = VARK2NUMBER(gp,vphigh);
  21599.  
  21600.  /* Send "XHDR SUBJECT nnn-nnn" to news server. */
  21601.  
  21602.  NNMestng(np,NULL);  /* set server "GROUP" if necessary */
  21603.                      /* e.g. going from unread-only to all */
  21604.  
  21605.  sprintf(np->nntp_command,"XHDR SUBJECT %d-%d",xhdr_low,xhdr_high);
  21606.  if (!NNMsockt(np)) return;          /* Send socket command to server */
  21607.  
  21608.  if (!NNMgsrvl(np,&lp)) return;        /* Get server line */
  21609.  switch (np->nntp_message_num) {
  21610.    case 221:                           /* subject fields follow */
  21611.              np->xhdr_not_available = FALSE;
  21612.              break;
  21613.    case 500:                           /* command unrecognized  */
  21614.              np->xhdr_not_available = TRUE;
  21615.              break;
  21616.    default:
  21617.              NNMrperr(np);        /* Report protocol error */
  21618.              return;
  21619.  }
  21620.  
  21621.  if (np->xhdr_not_available) return;
  21622.  
  21623.  /* assert np->sending_text == TRUE; */
  21624.  
  21625.  anum = xhdr_low;
  21626.  
  21627.  for (;;) {
  21628.  
  21629.    if (!NNMgsrvl(np,&lp))    return;   /* Get server line */
  21630.    if (lp == NULL)           break;
  21631.    if (strcmp(lp,".") == 0)  break;
  21632.  
  21633.    if (1 != sscanf(np->nntp_message_text, "%d %n",
  21634.                    &xhdr_article_number, &scan_count)) {
  21635.      NNMrbfm(np);   /* Report bad format message */
  21636.      return;
  21637.    }
  21638.  
  21639.    xhdr_subject = np->nntp_message_text + scan_count;
  21640.  
  21641.    if (np->debug_file) {
  21642.      fprintf(np->debug_file,"XHDR: article='%d', subject='%s'\n",
  21643.                             xhdr_article_number, xhdr_subject);
  21644.    }
  21645.    set_articles_missing(np,gp,anum,xhdr_article_number);
  21646.    anum = xhdr_article_number + 1;
  21647.  }
  21648.  
  21649.  set_articles_missing(np,gp,anum,xhdr_high);
  21650.  
  21651.  return;
  21652. }
  21653.  
  21654. /****** Pick newsgroup. **********************************************/
  21655.  
  21656. Bool
  21657. NNMpng(np,gp,do_titles,do_sort)
  21658. Rstruc nncb          *np;
  21659. Rstruc newsgroup     *gp;
  21660. Fool                  do_titles;
  21661. Fool                  do_sort;
  21662. {
  21663.  Rstruc newsgroup    *gp1;
  21664.  Bool                 result = TRUE;
  21665.  Bool                 was_selected_unread;
  21666.  Bool                 was_selected_read;
  21667.  
  21668.  np->current_newsgroup   = gp;
  21669.  np->newsgroup_selected  = FALSE;
  21670.  np->newsgroup_not_found = FALSE;
  21671.  
  21672.  was_selected_read   = GroupSelectedRead(gp);
  21673.  was_selected_unread = GroupSelectedUnread(gp);
  21674.  
  21675.  if (!np->batch_mode) {
  21676.    (void)NNMivput(np,"NNGROUP ",gp->name,-1);
  21677.  }
  21678.  
  21679.  if (GroupSelected(gp)) {
  21680.    if (np->show_all_articles) {
  21681.      SetGroupSelectedRead(gp);
  21682.    }
  21683.    gp1 = gp;
  21684.  }
  21685.  else {
  21686.    gp1 = NNMdng(np,gp,NULL);  /* do newsgroup by address */
  21687.  }
  21688.  
  21689.  if (!gp1) {
  21690.    result = FALSE;
  21691.  }
  21692.  else if (np->newsgroup_not_found) {
  21693.    SetNoSuchGroup(gp);
  21694.    gp->article_count = 0;
  21695.    gp->unread_count  = 0;
  21696.    result = FALSE;
  21697.  }
  21698.  else {
  21699.    gp = gp1;;
  21700.  
  21701.    if (!was_selected_read && GroupSelectedRead(gp)) {
  21702.      do_xhdr(np,gp,TRUE);             /* do XHDR stuff for all */
  21703.    }
  21704.    else if (!was_selected_unread && GroupSelectedUnread(gp)) {
  21705.      do_xhdr(np,gp,FALSE);            /* do XHDR stuff for unread */
  21706.    }
  21707.  
  21708.    if (do_titles) (void)NNMrart(np,gp,FALSE,TRUE);
  21709.    if (do_sort)   (void)NNMsort(np,gp);
  21710.  
  21711.    result = NNMvar(np,gp);                   /* View articles */
  21712.  }
  21713.  
  21714.  np->current_newsgroup = NULL;
  21715.  np->newsgroup_selected = FALSE;
  21716.  
  21717.  /* hack to position newsgroup display*/
  21718.  
  21719.  strcpy(np->nngroup, gp->name);
  21720.  
  21721.  return result;
  21722. }
  21723.  
  21724. ./ ADD NAME=NNMQAR
  21725.  
  21726.  /********************************************************************/
  21727.  /*                                                                  */
  21728.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  21729.  /*                                                                  */
  21730.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  21731.  /* including the implied warranties of merchantability and fitness, */
  21732.  /* are expressly denied.                                            */
  21733.  /*                                                                  */
  21734.  /* Provided this copyright notice is included, this software may    */
  21735.  /* be freely distributed and not offered for sale.                  */
  21736.  /*                                                                  */
  21737.  /* Changes or modifications may be made and used only by the maker  */
  21738.  /* of same, and not further distributed.  Such modifications should */
  21739.  /* be mailed to the author for consideration for addition to the    */
  21740.  /* software and incorporation in subsequent releases.               */
  21741.  /*                                                                  */
  21742.  /********************************************************************/
  21743.  
  21744. #pragma  csect(code,  "NN@QAR  ")
  21745. #pragma  csect(static,"NN$QAR  ")
  21746. #include "nn.h"
  21747.  
  21748. #define OUT1(A)       (void)NNMouttx(np,(A),NULL)
  21749. #define OUT2(A,B)     sprintf(temp,(A),(B)),     OUT1(temp)
  21750. #define OUT3(A,B,C)   sprintf(temp,(A),(B),(C)), OUT1(temp)
  21751. #define ADD1(A)       strcat(stat,(A))
  21752. #define ADD2(A,B)     sprintf(temp,(A),(B)),     ADD1(temp)
  21753.  
  21754. /****** Query article. ***********************************************/
  21755.  
  21756. Bool
  21757. NNMqar(np,ap)
  21758. Rstruc nncb         *np;
  21759. Rstruc newsarticle  *ap;
  21760. {
  21761.  Rstruc newsgroup   *gp;
  21762.  char                stat[129];
  21763.  char                temp[129];
  21764.  
  21765.  gp = np->current_newsgroup;
  21766.  
  21767.  if (!gp) {
  21768.   CRIT1("No current newsgroup.  This should never happen.");
  21769.   return FALSE;
  21770.  }
  21771.  
  21772.  NNMclrtx(np,NULL);
  21773.  
  21774.  if (ap == V_NULL_ARTICLE) {
  21775.    OUT1("Null article");
  21776.  }
  21777.  
  21778.  else if (ap == V_MISSING_ARTICLE) {
  21779.    OUT1("Missing article");
  21780.  }
  21781.  
  21782.  else {
  21783.  
  21784.    OUT1("");
  21785.    OUT3("  Struct at %8.8X: Article %d", ap, ap->number);
  21786.    OUT1("");
  21787.    OUT2("status.........................%2.2X", ap->status);
  21788.    if (NoSuchArticle(ap))          OUT1(" NoSuchArticle"        );
  21789.    if (ArticleAbsent(ap))          OUT1(" ArticleAbsent"        );
  21790.    if (ArticleError(ap))           OUT1(" ArticleError"         );
  21791.    if (ArticleBadData(ap))         OUT1(" ArticleBadData"       );
  21792.    if (ArticleHeadRetrieved(ap))   OUT1(" ArticleHeadRetrieved" );
  21793.    if (ArticleBodyRetrieved(ap))   OUT1(" ArticleBodyRetrieved" );
  21794.    strcpy(stat,"action.........................");
  21795.    switch (ap->action) {
  21796.      case NO_ACTION:             ADD1("NO_ACTION");             break;
  21797.      case READ:                  ADD1("READ");                  break;
  21798.      case RETRIEVED:             ADD1("RETRIEVED");             break;
  21799.      case EXTRACTED:             ADD1("EXTRACTED");             break;
  21800.      case PRINTED:               ADD1("PRINTED");               break;
  21801.      case UNREAD:                ADD1("UNREAD");                break;
  21802.      case MISSING:               ADD1("MISSING");               break;
  21803.      case ERROR:                 ADD1("ERROR");                 break;
  21804.      case CANCELLED:             ADD1("CANCELLED");             break;
  21805.      default:                    ADD2("%d",ap->action);         break;
  21806.    }
  21807.    OUT1(stat);
  21808.    OUT2("number.........................%d",    ap->number);
  21809.    OUT2("from...........................%s",    ap->from);
  21810.    OUT2("subject........................%s",    ap->subject);
  21811.    OUT2("date...........................%s",    ap->date);
  21812.    OUT2("message_id.....................%s",    ap->message_id);
  21813.  
  21814.    if (ap->csubject)
  21815.      OUT2("csubject.......................%s",  ap->csubject);
  21816.    else
  21817.      OUT1("csubject is NULL");
  21818.  
  21819.    OUT2("text line count................%d", ap->thdr.text_line_count);
  21820.    OUT2("text max length................%d", ap->thdr.text_max_length);
  21821.    OUT2("text max tab expanded length...%d",
  21822.                                 ap->thdr.text_max_tab_expanded_length);
  21823.    OUT2("text body line..............%8.8X",ap->thdr.text_body_line);
  21824.    OUT2("first text line.............%8.8X",ap->thdr.first_text_line);
  21825.    OUT2("current text line...........%8.8X",ap->thdr.current_text_line);
  21826.    OUT2("last text line..............%8.8X",ap->thdr.last_text_line);
  21827.  
  21828.  }
  21829.  
  21830.  NNMvtx(np,NULL,NULL);
  21831.  
  21832.  return TRUE;
  21833. }
  21834.  
  21835. ./ ADD NAME=NNMQNG
  21836.  
  21837.  /********************************************************************/
  21838.  /*                                                                  */
  21839.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  21840.  /*                                                                  */
  21841.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  21842.  /* including the implied warranties of merchantability and fitness, */
  21843.  /* are expressly denied.                                            */
  21844.  /*                                                                  */
  21845.  /* Provided this copyright notice is included, this software may    */
  21846.  /* be freely distributed and not offered for sale.                  */
  21847.  /*                                                                  */
  21848.  /* Changes or modifications may be made and used only by the maker  */
  21849.  /* of same, and not further distributed.  Such modifications should */
  21850.  /* be mailed to the author for consideration for addition to the    */
  21851.  /* software and incorporation in subsequent releases.               */
  21852.  /*                                                                  */
  21853.  /********************************************************************/
  21854.  
  21855. #pragma  csect(code,  "NN@QNG  ")
  21856. #pragma  csect(static,"NN$QNG  ")
  21857. #include "nn.h"
  21858.  
  21859. #define OUT1(A)       (void)NNMouttx(np,(A),NULL)
  21860. #define OUT2(A,B)     sprintf(temp,(A),(B)),     OUT1(temp)
  21861. #define OUT3(A,B,C)   sprintf(temp,(A),(B),(C)), OUT1(temp)
  21862. #define ADD1(A)       strcat(stat,(A))
  21863. #define ADD2(A,B)     sprintf(temp,(A),(B)),     ADD1(temp)
  21864.  
  21865. /****** Query newsgroup. *********************************************/
  21866.  
  21867. void
  21868. NNMqng(np,gp)
  21869. Rstruc nncb         *np;
  21870. Rstruc newsgroup    *gp;
  21871. {
  21872.  struct newsarticle *ap;
  21873.  int                 i;
  21874.  VARK               *vp;
  21875.  VARK               *vpfirst;
  21876.  VARK               *vplast;
  21877.  VARK              **wp;
  21878.  VARK              **wpfirst;
  21879.  VARK              **wplast;
  21880.  char                stat[129];
  21881.  char                temp[129];
  21882.  
  21883.  if (!gp) return;
  21884.  
  21885.  NNMclrtx(np,NULL);
  21886.  
  21887.  OUT1("");
  21888.  OUT3("    Struct at %8.8X: Newsgroup '%s'", gp, gp->name);
  21889.  OUT1("");
  21890.  OUT2("next.......................%8.8X", gp->next);
  21891.  OUT2("next2......................%8.8X", gp->next2);
  21892.  OUT2("next3......................%8.8X", gp->next3);
  21893.  OUT2("saved_newsrc_line..........%8.8X", gp->saved_newsrc_line);
  21894.  OUT2("article_vector.............%8.8X", gp->article_vector);
  21895.  OUT2("sort_vector................%8.8X", gp->sort_vector);
  21896.  OUT2("low_number.................%d",    gp->low_number);
  21897.  OUT2("high_number................%d",    gp->high_number);
  21898.  OUT2("vector_first...............%d",    gp->vector_first);
  21899.  OUT2("vector_last................%d",    gp->vector_last);
  21900.  OUT2("article_count..............%d",    gp->article_count);
  21901.  OUT2("unread_count...............%d",    gp->unread_count);
  21902.  OUT2("sort_count.................%d",    gp->sort_count);
  21903.  OUT2("article_vector_len.........%d",    gp->article_vector_len);
  21904.  OUT2("registered.................%d",    gp->registered);
  21905.  OUT2("saved_newsrc_data..........%s",    gp->saved_newsrc_data);
  21906.  OUT2("status.....................%2.2X", gp->status);
  21907.  if (NoSuchGroup(gp))         OUT1(" NoSuchGroup"           );
  21908.  if (NewGroup(gp))            OUT1(" NewGroup"              );
  21909.  if (GroupFromNewsrc(gp))     OUT1(" GroupFromNewsrc"       );
  21910.  if (GroupListed(gp))         OUT1(" GroupListed"           );
  21911.  if (GroupSelectedUnread(gp)) OUT1(" GroupSelectedUnread"   );
  21912.  if (GroupSelectedRead(gp))   OUT1(" GroupSelectedRead"     );
  21913.  if (GroupError(gp))          OUT1(" GroupError"            );
  21914.  if (GroupInTable(gp))        OUT1(" GroupInTable"          );
  21915.  OUT2("name.......................%s",    gp->name);
  21916.  if (gp->saved_newsrc_line) {
  21917.    OUT1("");
  21918.    OUT1("Saved newsrc line follows:");
  21919.    OUT1("");
  21920.    OUT1(gp->saved_newsrc_line);
  21921.    OUT1("");
  21922.    OUT1("");
  21923.  }
  21924.  
  21925.  if (gp->article_vector) {
  21926.    OUT1("");
  21927.    OUT1("Article vector follows:");
  21928.    OUT1("");
  21929.    vpfirst = &GETVARKFIRST(gp);
  21930.    vplast  = &GETVARKLAST(gp);
  21931.    for (vp = vpfirst, i = gp->vector_first; vp <= vplast; vp++,i++) {
  21932.      sprintf(stat," %10d: %8.8X    ",i,*vp);
  21933.      ap = VARK2PARTICLE(*vp);
  21934.      if (ap == V_NULL_ARTICLE)         ADD1("Null     ");
  21935.      else if (ap == V_MISSING_ARTICLE) ADD1("Missing  ");
  21936.      else                              ADD2("%8.8X ",ap);
  21937.      if (IsKnown(*vp))                 ADD1("Known   ");
  21938.      else                              ADD1("Unknown ");
  21939.      if (IsEligible(*vp))              ADD1("Eligible   ");
  21940.      else                              ADD1("Ineligible ");
  21941.      if (IsRead(*vp))                  ADD1("Read   ");
  21942.      else                              ADD1("Unread ");
  21943.      OUT1(stat);
  21944.    }
  21945.  }
  21946.  if (gp->sort_vector) {
  21947.    OUT1("");
  21948.    OUT1("Sort vector follows:");
  21949.    OUT1("");
  21950.    wpfirst = gp->sort_vector;
  21951.    wplast  = gp->sort_vector + gp->sort_count;
  21952.    for (wp = wpfirst; wp < wplast; wp++) {
  21953.      OUT3("     %8.8X: %8.8X",*wp,**wp);
  21954.    }
  21955.  }
  21956.  
  21957.  NNMvtx(np,NULL,NULL);
  21958.  
  21959.  return;
  21960. }
  21961.  
  21962. ./ ADD NAME=NNMRARH
  21963.  
  21964.  /********************************************************************/
  21965.  /*                                                                  */
  21966.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  21967.  /*                                                                  */
  21968.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  21969.  /*                                                                  */
  21970.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  21971.  /* including the implied warranties of merchantability and fitness, */
  21972.  /* are expressly denied.                                            */
  21973.  /*                                                                  */
  21974.  /* Provided this copyright notice is included, this software may    */
  21975.  /* be freely distributed and not offered for sale.                  */
  21976.  /*                                                                  */
  21977.  /* Changes or modifications may be made and used only by the maker  */
  21978.  /* of same, and not further distributed.  Such modifications should */
  21979.  /* be mailed to the author for consideration for addition to the    */
  21980.  /* software and incorporation in subsequent releases.               */
  21981.  /*                                                                  */
  21982.  /********************************************************************/
  21983.  
  21984. #pragma  csect(code,  "NN@RARH ")
  21985. #pragma  csect(static,"NN$RARH ")
  21986. #include "nn.h"
  21987.  
  21988. /****** Get article. *************************************************/
  21989.  
  21990. static struct newsarticle *
  21991. get_article(np,gp,vp,anum,cdp)
  21992. Rstruc nncb          *np;
  21993. Rstruc newsgroup     *gp;
  21994. VARK                 *vp;
  21995. int                   anum;
  21996. struct countdown     *cdp;
  21997. {
  21998.  struct newsarticle  *ap;
  21999.  char                *lp;
  22000.  char                *cp;
  22001.  struct textline     *tp;
  22002.  int                  header_index;
  22003.  char                 header_name[INTERNET_SIZE];
  22004.  
  22005.  if (anum <= 0) anum = VARK2NUMBER(gp,vp);
  22006.  
  22007.  SetUnknown(*vp);
  22008.  
  22009.  /* Allocate a struct newsarticle for this article */
  22010.  
  22011.  GETMAIN(ap, struct newsarticle, 1, "news article");
  22012.  if (!ap) {
  22013.    ERR2("There is not enough memory to retrieve article %d.", anum);
  22014.    SetIneligible(*vp);
  22015.    return NULL;
  22016.  }
  22017.  
  22018.  *vp = ((VARK)ap | VARK2BITS(*vp));
  22019.  
  22020.  memset(ap,0,sizeof(struct newsarticle));
  22021.  ClearArticleStatus(ap);
  22022.  ap->action = ERROR;
  22023.  ap->number = anum;
  22024.  
  22025.  if (!NNMestng(np,NULL)) {                 /* Establish newsgroup */
  22026.    SetArticleError(ap);
  22027.    SetIneligible(*vp);
  22028.    return NULL;
  22029.  }
  22030.  
  22031.  tp = NULL;
  22032.  
  22033.  /* If user asked for screen updates, do them here. */
  22034.  
  22035.  NNMupdt(np,cdp,"NNMLART2");
  22036.  
  22037.  /* Ask for the head of the article by number. */
  22038.  /* (Is it better to ask by message-id? Dunno) */
  22039.  
  22040.  sprintf(np->nntp_command,"HEAD %d",ap->number);
  22041.  if (!NNMsockt(np)) return FALSE;  /* Send socket command to server */
  22042.  
  22043.  if (NNMgsrvl(np,&lp)) {           /* Get server line */
  22044.    switch (np->nntp_message_num) {
  22045.      case 221:          /* article retrieved, head follows         */
  22046.                SetArticleHeadRetrieved(ap);
  22047.                break;
  22048.      case 423:          /*    no such article number in this group */
  22049.                SetNoSuchArticle(ap);
  22050.                ap->action = MISSING;
  22051.                break;
  22052.      case 430:          /*    no such article found                */
  22053.                SetArticleAbsent(ap);
  22054.                ap->action = MISSING;
  22055.                break;
  22056.      default:
  22057.                SetArticleError(ap);
  22058.                NNMrperr(np);        /* Report protocol error */
  22059.                break;
  22060.    }
  22061.  }
  22062.  
  22063.  if (!ArticleHeadRetrieved(ap)) {
  22064.    if IsUnread(*vp) gp->unread_count--;
  22065.    SetMissingRead(*vp);
  22066.    return NULL;
  22067.  }
  22068.  
  22069.  /* Scan the text for headers and extract the subject and whatever. */
  22070.  
  22071.  ap->subject    = "";
  22072.  ap->from       = "";
  22073.  ap->message_id = "";
  22074.  ap->date       = "";
  22075.  
  22076.  np->sending_text = TRUE; /* Stuff following is header text */
  22077.  
  22078.  for (;;) {
  22079.  
  22080.    if (!NNMgsrvl(np,&lp))            break;  /* Get server line */
  22081.    if (lp == NULL)                   break;
  22082.    if (np->server_finished_replying) break;
  22083.    if (!(tp=NNMouttx(np,lp,ap)))     break;  /* Output text line */
  22084.  
  22085.    if (*(cp=tp->tab_expanded_text) == ' ') continue;
  22086.  
  22087.    header_name[0] = '\0';
  22088.    header_index = 0;
  22089.    while (*cp != ':') {
  22090.      if (*cp == '\0' || *cp == ' ') {
  22091.        NNMdump(np,"Warning, bad header line",lp,strlen(lp));
  22092.        SetArticleBadData(ap);
  22093.        break;
  22094.      }
  22095.      else header_name[header_index++] = toupper(*cp++);
  22096.    }
  22097.  
  22098.    header_name[header_index] = '\0';
  22099.    cp = skip_whitespace(cp+1);
  22100.    if      (EQUAL(header_name,"FROM")) {
  22101.            ap->from = cp;
  22102.    }
  22103.    else if (EQUAL(header_name,"SUBJECT")) {
  22104.            ap->subject = cp;
  22105.    }
  22106.    else if (EQUAL(header_name,"MESSAGE-ID")) {
  22107.            ap->message_id = cp;
  22108.    }
  22109.    else if (EQUAL(header_name,"DATE")) {
  22110.            cp = strpbrk(cp,"0123456789");
  22111.            if (!cp) cp = "*BAD DATE*";
  22112.            ap->date = cp;
  22113.    }
  22114.  }
  22115.  
  22116.  /* Prepare ISPF variables for possible panel or message processing. */
  22117.  
  22118.  if (!np->batch_mode) {
  22119.    (void)NNMivput(np,"NNTSUBJ " ,ap->subject,-1);
  22120.  }
  22121.  
  22122.  /* Since we retrieved the article, it can't be missing, can it? */
  22123.  
  22124.  SetKnown(*vp);
  22125.  ap->action = NO_ACTION;
  22126.  
  22127.  return ap;
  22128.  
  22129. }
  22130.  
  22131. /****** Retrieve article header. *************************************/
  22132.  
  22133. struct newsarticle *
  22134. NNMrarh(np,gp,vp,anum,cdp)
  22135. Rstruc nncb          *np;
  22136. Rstruc newsgroup     *gp;
  22137. VARK                 *vp;
  22138. int                   anum;
  22139. struct countdown     *cdp;
  22140. {
  22141.  Rstruc newsarticle  *ap;
  22142.  
  22143.  /* Note that either vp or anum may be null (zero), but NOT BOTH. */
  22144.  
  22145.  if (!vp) vp = &GETVARK(gp,anum);
  22146.  ap = VARK2PARTICLE(*vp);
  22147.  
  22148.  if (ap == V_NULL_ARTICLE)  return get_article(np,gp,vp,anum,cdp);
  22149.  else if (ap == V_MISSING_ARTICLE) return NULL;
  22150.  else                              return ap;
  22151.  
  22152. }
  22153.  
  22154. ./ ADD NAME=NNMRART
  22155.  
  22156.  /********************************************************************/
  22157.  /*                                                                  */
  22158.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  22159.  /*                                                                  */
  22160.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  22161.  /*                                                                  */
  22162.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  22163.  /* including the implied warranties of merchantability and fitness, */
  22164.  /* are expressly denied.                                            */
  22165.  /*                                                                  */
  22166.  /* Provided this copyright notice is included, this software may    */
  22167.  /* be freely distributed and not offered for sale.                  */
  22168.  /*                                                                  */
  22169.  /* Changes or modifications may be made and used only by the maker  */
  22170.  /* of same, and not further distributed.  Such modifications should */
  22171.  /* be mailed to the author for consideration for addition to the    */
  22172.  /* software and incorporation in subsequent releases.               */
  22173.  /*                                                                  */
  22174.  /********************************************************************/
  22175.  
  22176. #pragma  csect(code,  "NN@RART ")
  22177. #pragma  csect(static,"NN$RART ")
  22178. #include "nn.h"
  22179.  
  22180. /****** Retrieve all article titles. *********************************/
  22181.  
  22182. int
  22183. NNMrart(np,gp,not_just_unread,not_just_only)
  22184. Rstruc nncb         *np;
  22185. Rstruc newsgroup    *gp;
  22186. Fool                 not_just_unread;
  22187. Fool                 not_just_only;
  22188. {
  22189.  struct newsarticle *ap;
  22190.  VARK               *vp;
  22191.  VARK               *vpfirst;
  22192.  VARK               *vplast;
  22193.  VARK              **wp;
  22194.  VARK              **wpfirst;
  22195.  VARK              **wplast;
  22196.  int                 count;
  22197.  struct countdown    cd;
  22198.  Bool                save_show_all_articles;
  22199.  char                save_article_only_char;
  22200.  
  22201.  np->bypass_header_retrieval = FALSE;
  22202.  
  22203.  if (!gp->article_vector) return 0;
  22204.  
  22205.  vpfirst = &GETVARKFIRST(gp);
  22206.  vplast  = &GETVARKLAST(gp);
  22207.  
  22208.  if (np->updatefreq < 0) {
  22209.    cd.do_update = FALSE;
  22210.    cd.done      = 0;
  22211.    cd.to_do     = 0;
  22212.  }
  22213.  else {
  22214.    cd.do_update = TRUE;
  22215.    cd.done      = 0;
  22216.    cd.to_do     = 0;
  22217.    if (not_just_unread) {
  22218.      for (vp = vpfirst; vp <= vplast; vp++) {
  22219.        if (IsNull(*vp)) cd.to_do++;
  22220.      }
  22221.    }
  22222.    else {
  22223.      for (vp = vpfirst; vp <= vplast; vp++) {
  22224.        if (IsNull(*vp) && IsUnread(*vp)) cd.to_do++;
  22225.      }
  22226.    }
  22227.  }
  22228.  
  22229.  if (not_just_unread) {
  22230.    save_show_all_articles = np->show_all_articles;
  22231.    np->show_all_articles = TRUE;
  22232.  }
  22233.  if (not_just_only) {
  22234.    save_article_only_char = np->article_only_string[0];
  22235.    np->article_only_string[0] = '\0';
  22236.  }
  22237.  
  22238.  count = 0;
  22239.  
  22240.  if (gp->sort_vector) {
  22241.    wpfirst = gp->sort_vector;
  22242.    wplast  = gp->sort_vector + gp->sort_count - 1;
  22243.    for (wp = wpfirst; wp <= wplast; wp++) {
  22244.      SetUnknown(**wp);
  22245.      if (NNMcar(np,gp,0,*wp,NULL,&cd,RETRIEVE)) { /* Choose article */
  22246.        count++;
  22247.      }
  22248.    }
  22249.  }
  22250.  else {
  22251.    for (vp = vpfirst; vp <= vplast; vp++) {
  22252.      SetUnknown(*vp);
  22253.      if (NNMcar(np,gp,0,vp,NULL,&cd,RETRIEVE)) { /* Choose article */
  22254.        count++;
  22255.      }
  22256.    }
  22257.  }
  22258.  
  22259.  /*
  22260.   * IMPORTANT: On return, articles are set eligible if their titles
  22261.   * have been retrieved, even if we fudged the criteria.  We could
  22262.   * reset them all to unknown, but NNMsort needs this information,
  22263.   * so it is the responsibility of the caller of NNMrart to reset
  22264.   * all the statuses if it called NNMrart with fudging turned on.
  22265.   */
  22266.  
  22267.  if (not_just_unread) {
  22268.    np->show_all_articles = save_show_all_articles;
  22269.  }
  22270.  if (not_just_only) {
  22271.    np->article_only_string[0] = save_article_only_char;
  22272.  }
  22273.  
  22274.  return count; /* number of eligible and retrieved, for NNMsort */
  22275. }
  22276.  
  22277. ./ ADD NAME=NNMRBFM
  22278.  
  22279.  /********************************************************************/
  22280.  /*                                                                  */
  22281.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  22282.  /*                                                                  */
  22283.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  22284.  /* including the implied warranties of merchantability and fitness, */
  22285.  /* are expressly denied.                                            */
  22286.  /*                                                                  */
  22287.  /* Provided this copyright notice is included, this software may    */
  22288.  /* be freely distributed and not offered for sale.                  */
  22289.  /*                                                                  */
  22290.  /* Changes or modifications may be made and used only by the maker  */
  22291.  /* of same, and not further distributed.  Such modifications should */
  22292.  /* be mailed to the author for consideration for addition to the    */
  22293.  /* software and incorporation in subsequent releases.               */
  22294.  /*                                                                  */
  22295.  /********************************************************************/
  22296.  
  22297. #pragma  csect(code,  "NN@RBFM ")
  22298. #pragma  csect(static,"NN$RBFM ")
  22299. #include "nn.h"
  22300.  
  22301. /****** Report bad format message. ***********************************/
  22302.  
  22303. void
  22304. NNMrbfm(np)
  22305. Rstruc nncb  *np;
  22306. {
  22307.  
  22308.  NNMclrtx(np,NULL);                         /* Clear text */
  22309.  
  22310.  CRIT2("NNTP message from server %s has invalid format.", np->nnserver);
  22311.  
  22312.  (void)NNMouttx(np,np->server_buf,NULL);    /* Output text line */
  22313.  NNMvtx(np,NULL,NULL);                      /* View text */
  22314.  
  22315.  return;
  22316. }
  22317.  
  22318. ./ ADD NAME=NNMRECON
  22319.  
  22320.  /********************************************************************/
  22321.  /*                                                                  */
  22322.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  22323.  /*                                                                  */
  22324.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  22325.  /* including the implied warranties of merchantability and fitness, */
  22326.  /* are expressly denied.                                            */
  22327.  /*                                                                  */
  22328.  /* Provided this copyright notice is included, this software may    */
  22329.  /* be freely distributed and not offered for sale.                  */
  22330.  /*                                                                  */
  22331.  /* Changes or modifications may be made and used only by the maker  */
  22332.  /* of same, and not further distributed.  Such modifications should */
  22333.  /* be mailed to the author for consideration for addition to the    */
  22334.  /* software and incorporation in subsequent releases.               */
  22335.  /*                                                                  */
  22336.  /********************************************************************/
  22337.  
  22338. #pragma  csect(code,  "NN@RECON")
  22339. #pragma  csect(static,"NN$RECON")
  22340. #include "nn.h"
  22341.  
  22342. /****** Reconnect to server. *****************************************/
  22343.  
  22344. Bool
  22345. NNMrecon(np)
  22346. Rstruc nncb        *np;
  22347. {
  22348.  struct newsgroup  *gp;
  22349.  char               save_command[CLIENT_BUF_MSGSIZE+4];
  22350.  
  22351.  if (np->dont_reconnect) {
  22352.    CRIT2(
  22353.  "Disconnected from server %s.  Reconnection will not be attempted.",
  22354.          np->nnserver);
  22355.    return FALSE;
  22356.  }
  22357.  
  22358.  np->connected_to_server   = FALSE;
  22359.  np->reconnect_in_progress = TRUE;
  22360.  
  22361.  if (!np->batch_mode) {
  22362.    (void)NNMispf(np,"CONTROL DISPLAY LOCK");
  22363.    (void)NNMispf(np,"DISPLAY PANEL(NNMLRCON)");
  22364.  }
  22365.  
  22366.  /*
  22367.   * fprintf(stderr,"Lost connection, possible timeout.\n");
  22368.   * fprintf(stderr,"Attempting reconnection to news server %s (%s)\n",
  22369.   *                np->server_hostname,
  22370.   *                np->server_ip_addrstr);
  22371.   */
  22372.  
  22373.  if (!NNMconn(np)) {                 /* Connect to news server */
  22374.    CRIT2("Reconnection failed to server %s after disconnect.",
  22375.          np->nnserver);
  22376.    return FALSE;
  22377.  }
  22378.  
  22379.  /* If there is a current newsgroup and we're not currently trying
  22380.   * to issue a "GROUP" command, then reestablish server's state.
  22381.   */
  22382.  
  22383.  if ((gp=np->current_newsgroup)
  22384.      && memcmp(np->nntp_command,"GROUP ",6)) /* not "GROUP" */ {
  22385.  
  22386.    if (!np->batch_mode) {
  22387.      (void)NNMispf(np,"CONTROL DISPLAY LOCK");
  22388.      (void)NNMispf(np,"DISPLAY PANEL(NNMLRSNG)");
  22389.    }
  22390.  
  22391.    strcpy(save_command,np->nntp_command);
  22392.    /* Establish newsgroup */
  22393.    if (!NNMestng(np,gp->name)) {
  22394.      strcpy(np->nntp_command,save_command);
  22395.      CRIT3(
  22396.        "Reselect of newsgroup %s failed during reconnection to %s.",
  22397.        gp->name, np->nnserver);
  22398.      return FALSE;
  22399.    }
  22400.    strcpy(np->nntp_command,save_command);
  22401.  }
  22402.  np->reconnect_in_progress = FALSE;
  22403.  return TRUE;
  22404. }
  22405.  
  22406. ./ ADD NAME=NNMRPERR
  22407.  
  22408.  /********************************************************************/
  22409.  /*                                                                  */
  22410.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  22411.  /*                                                                  */
  22412.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  22413.  /* including the implied warranties of merchantability and fitness, */
  22414.  /* are expressly denied.                                            */
  22415.  /*                                                                  */
  22416.  /* Provided this copyright notice is included, this software may    */
  22417.  /* be freely distributed and not offered for sale.                  */
  22418.  /*                                                                  */
  22419.  /* Changes or modifications may be made and used only by the maker  */
  22420.  /* of same, and not further distributed.  Such modifications should */
  22421.  /* be mailed to the author for consideration for addition to the    */
  22422.  /* software and incorporation in subsequent releases.               */
  22423.  /*                                                                  */
  22424.  /********************************************************************/
  22425.  
  22426. #pragma  csect(code,  "NN@RPERR")
  22427. #pragma  csect(static,"NN$RPERR")
  22428. #include "nn.h"
  22429.  
  22430. /****** Report protocol error. ***************************************/
  22431.  
  22432. void
  22433. NNMrperr(np)
  22434. Rstruc nncb  *np;
  22435. {
  22436.  
  22437.  NNMclrtx(np,NULL);                         /* Clear text */
  22438.  
  22439.  CRIT2("NNTP protocol error.  Unexpected response by server %s.",
  22440.        np->nnserver);
  22441.  
  22442.  (void)NNMouttx(np,np->server_buf,NULL);    /* Output text line */
  22443.  NNMvtx(np,NULL,NULL);                      /* View text */
  22444.  
  22445.  return;
  22446. }
  22447.  
  22448. ./ ADD NAME=NNMSAVE
  22449.  
  22450.  /********************************************************************/
  22451.  /*                                                                  */
  22452.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  22453.  /*                                                                  */
  22454.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  22455.  /* including the implied warranties of merchantability and fitness, */
  22456.  /* are expressly denied.                                            */
  22457.  /*                                                                  */
  22458.  /* Provided this copyright notice is included, this software may    */
  22459.  /* be freely distributed and not offered for sale.                  */
  22460.  /*                                                                  */
  22461.  /* Changes or modifications may be made and used only by the maker  */
  22462.  /* of same, and not further distributed.  Such modifications should */
  22463.  /* be mailed to the author for consideration for addition to the    */
  22464.  /* software and incorporation in subsequent releases.               */
  22465.  /*                                                                  */
  22466.  /********************************************************************/
  22467.  
  22468. #pragma  csect(code,  "NN@SAVE ")
  22469. #pragma  csect(static,"NN$SAVE ")
  22470. #include "nn.h"
  22471. #include "nnbatch.h"
  22472.  
  22473. /****** Save NEWSRC file. ********************************************/
  22474.  
  22475. Bool
  22476. NNMsave(np,rest)
  22477. Rstruc nncb         *np;
  22478. char                *rest;
  22479. {
  22480.  Rstruc batch       *bp;
  22481.  
  22482.  if (np->batch_mode) {
  22483.    bp = np->batch_hook;
  22484.    if (GETB("CHECKPOINT") == FALSE) return TRUE;
  22485.  }
  22486.  
  22487.  NNMcnrf(np,NULL,TRUE);  /* Close NEWSRC file */
  22488.  
  22489.  /* Reopen the file for input.  Don't let anybody else sneak in. */
  22490.  
  22491.  if (!(np->newsrc_file = fopen(np->newsrc_to_open,"r"))) {
  22492.    perror("Cannot reopen NEWSRC file");
  22493.  }
  22494.  
  22495.  return TRUE;
  22496. }
  22497.  
  22498. ./ ADD NAME=NNMSOCKT
  22499.  
  22500.  /********************************************************************/
  22501.  /*                                                                  */
  22502.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  22503.  /*                                                                  */
  22504.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  22505.  /* including the implied warranties of merchantability and fitness, */
  22506.  /* are expressly denied.                                            */
  22507.  /*                                                                  */
  22508.  /* Provided this copyright notice is included, this software may    */
  22509.  /* be freely distributed and not offered for sale.                  */
  22510.  /*                                                                  */
  22511.  /* Changes or modifications may be made and used only by the maker  */
  22512.  /* of same, and not further distributed.  Such modifications should */
  22513.  /* be mailed to the author for consideration for addition to the    */
  22514.  /* software and incorporation in subsequent releases.               */
  22515.  /*                                                                  */
  22516.  /********************************************************************/
  22517.  
  22518. #pragma  csect(code,  "NN@SOCKT")
  22519. #pragma  csect(static,"NN$SOCKT")
  22520. #include "nn.h"
  22521.  
  22522. /****** Output one data line for the server. *************************/
  22523.  
  22524. Bool
  22525. NNMsockt(np)
  22526. Rstruc nncb    *np;
  22527. {
  22528.  int            nntp_bytes;
  22529.  int            writrc;
  22530.  char          *s_buf;
  22531.  
  22532.  nntp_bytes = strlen(np->nntp_command);
  22533.  
  22534.  /* Before sending a request to the server, do a cleanup operation
  22535.     to make sure that no more responses are coming from the server. */
  22536.  
  22537.  NNMesrvr(np);           /* End server read */
  22538.  
  22539.  memcpy(np->client_buf,np->nntp_command,nntp_bytes);
  22540.  np->client_buf[nntp_bytes  ] = CARRIAGE_RETURN;
  22541.  np->client_buf[nntp_bytes+1] = LINE_FEED;
  22542.  
  22543.  if (np->receiving_text &&
  22544.      nntp_bytes == 1    &&
  22545.      np->client_buf[0] == '.') {
  22546.    np->receiving_text = FALSE;
  22547.  }
  22548.  
  22549.  if (np->debug_mode)
  22550.     NNMdump(np,"Writing to server",np->client_buf,nntp_bytes+2);
  22551.  
  22552. #ifdef MVS
  22553.  EBCDIC_TO_ASCII(np->client_buf,nntp_bytes+2);
  22554. #endif
  22555.  
  22556.  writrc = write(np->socknum, np->client_buf, nntp_bytes+2);
  22557.  if (writrc < 0) {
  22558.    np->connection_broken = TRUE;
  22559.    if (!np->reconnect_in_progress) {
  22560.      GETMAIN(s_buf,char,CLIENT_BUF_MSGSIZE+4,"socket buffer");
  22561.      if (s_buf) {
  22562.        memcpy(s_buf,np->client_buf,nntp_bytes+2);
  22563.        if (NNMrecon(np)) {     /* Reconnect to server */
  22564.          writrc = write(np->socknum, s_buf, nntp_bytes+2);
  22565.        }
  22566.        FREEMAIN(s_buf, "old socket buffer");
  22567.      }
  22568.    }
  22569.  }
  22570.  if (writrc < 0) {
  22571.    CRIT2("TCP/IP error: write() failed to send data to server %s.",
  22572.          np->nnserver);
  22573.    return FALSE;
  22574.  }
  22575.  
  22576.  NNMssrvr(np);      /* Start server read */
  22577.  
  22578.  return TRUE;
  22579. }
  22580.  
  22581. ./ ADD NAME=NNMSOPT
  22582.  
  22583.  /********************************************************************/
  22584.  /*                                                                  */
  22585.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  22586.  /*                                                                  */
  22587.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  22588.  /*                                                                  */
  22589.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  22590.  /* including the implied warranties of merchantability and fitness, */
  22591.  /* are expressly denied.                                            */
  22592.  /*                                                                  */
  22593.  /* Provided this copyright notice is included, this software may    */
  22594.  /* be freely distributed and not offered for sale.                  */
  22595.  /*                                                                  */
  22596.  /* Changes or modifications may be made and used only by the maker  */
  22597.  /* of same, and not further distributed.  Such modifications should */
  22598.  /* be mailed to the author for consideration for addition to the    */
  22599.  /* software and incorporation in subsequent releases.               */
  22600.  /*                                                                  */
  22601.  /********************************************************************/
  22602.  
  22603. #pragma  csect(code,  "NN@SOPT ")
  22604. #pragma  csect(static,"NN$SOPT ")
  22605. #include "nn.h"
  22606.  
  22607. #define BOOLOPTSET(A,B,C) \
  22608.    switch (A[0]) { \
  22609.      case  'n': \
  22610.      case  'N':   B = FALSE; break; \
  22611.      case  'y': \
  22612.      case  'Y':   B = TRUE; break; \
  22613.      case '\0': \
  22614.      default:     B = C; break; \
  22615.    }
  22616.  
  22617. /****** Set options that are stored in ISPF profile. *****************/
  22618.  
  22619. void
  22620. NNMsopt(np,which)
  22621. Rstruc nncb        *np;
  22622. enum user_option    which;
  22623. {
  22624.  int                arrows;
  22625.  char               tempinc [256];
  22626.  char               tempexc [256];
  22627.  char               nnmupdtf[ 12];
  22628.  char               nnextpow[  4];
  22629.  char               nnextpap[  4];
  22630.  char               nnupan  [  4];
  22631.  char               nnuprn  [  4];
  22632.  char               nnupra  [  4];
  22633.  char               nnngscr [  4];
  22634.  char               nnngcsr [  4];
  22635.  char               nnarscr [  4];
  22636.  char               nnarcsr [  4];
  22637.  char               nnarrows[  2];
  22638.  
  22639.  if (which == OPTION_ALL) {
  22640.    NNMispf(np, "VGET \
  22641. (NNRFCOPT NNRFCINC NNRFCEXC\
  22642.  NNUPAN NNUPRN NNUPRA NNMUPDTF NNEXTPOW NNEXTPAP\
  22643.  NNNGSCR NNNGCSR NNARSCR NNARCSR NNARROWS)\
  22644.  PROFILE");
  22645.  }
  22646.  
  22647.  if (which == OPTION_ALL || which == OPTION_HEADER) {
  22648.  
  22649.    (void)NNMivget(np,"NNRFCOPT ", np->nnrfcopt, sizeof(np->nnrfcopt));
  22650.    (void)NNMivget(np,"NNRFCINC ", tempinc, sizeof(tempinc));
  22651.    (void)NNMivget(np,"NNRFCEXC ", tempexc, sizeof(tempexc));
  22652.  
  22653.    if (!*np->nnrfcopt) strcpy(np->nnrfcopt,"A");
  22654.    sprintf(np->nnrfcinc," %s ",tempinc);
  22655.    sprintf(np->nnrfcexc," %s ",tempexc);
  22656.  
  22657.  }
  22658.  
  22659.  if (which == OPTION_ALL || which == OPTION_OTHER) {
  22660.  
  22661.    (void)NNMivget(np,"NNUPAN ",   nnupan,   sizeof(nnupan  ));
  22662.    (void)NNMivget(np,"NNUPRN ",   nnuprn,   sizeof(nnuprn  ));
  22663.    (void)NNMivget(np,"NNUPRA ",   nnupra,   sizeof(nnupra  ));
  22664.    (void)NNMivget(np,"NNMUPDTF ", nnmupdtf, sizeof(nnmupdtf));
  22665.    (void)NNMivget(np,"NNEXTPOW ", nnextpow, sizeof(nnextpow));
  22666.    (void)NNMivget(np,"NNEXTPAP ", nnextpap, sizeof(nnextpap));
  22667.  
  22668.    /* 5 is a "reasonable" default, according to DDI */
  22669.  
  22670.    if      (nnmupdtf[0] == '\0')     np->updatefreq = 5;
  22671.    else if (EQUAL(nnmupdtf, "OFF"))  np->updatefreq = -1;
  22672.    else if (EQUAL(nnmupdtf, "ON"))   np->updatefreq = 0;
  22673.    else                              np->updatefreq = atoi(nnmupdtf);
  22674.  
  22675.    BOOLOPTSET(nnupan,   np->update_adding_newsgroups,    FALSE);
  22676.    BOOLOPTSET(nnuprn,   np->update_rewriting_newsrc,     TRUE);
  22677.    BOOLOPTSET(nnupra,   np->update_retrieving_articles,  TRUE);
  22678.    BOOLOPTSET(nnextpow, np->warn_overwrite,              TRUE);
  22679.    BOOLOPTSET(nnextpap, np->warn_append,                 TRUE);
  22680.  
  22681.    if (!np->update_retrieving_articles) np->updatefreq = -1;
  22682.  
  22683.  }
  22684.  
  22685.  if (which == OPTION_ALL || which == OPTION_VIEW) {
  22686.  
  22687.    (void)NNMivget(np,"NNNGSCR ",  nnngscr,  sizeof(nnngscr ));
  22688.    (void)NNMivget(np,"NNNGCSR ",  nnngcsr,  sizeof(nnngcsr ));
  22689.    (void)NNMivget(np,"NNARSCR ",  nnarscr,  sizeof(nnarscr ));
  22690.    (void)NNMivget(np,"NNARCSR ",  nnarcsr,  sizeof(nnarcsr ));
  22691.    (void)NNMivget(np,"NNARROWS ", nnarrows, sizeof(nnarrows));
  22692.  
  22693.    BOOLOPTSET(nnngscr,  np->newsgroup_autoscroll,        TRUE);
  22694.    BOOLOPTSET(nnngcsr,  np->newsgroup_autocursor,       FALSE);
  22695.    BOOLOPTSET(nnarscr,  np->article_autoscroll,          TRUE);
  22696.    BOOLOPTSET(nnarcsr,  np->article_autocursor,         FALSE);
  22697.  
  22698.    switch (nnarrows[0]) {
  22699.      case  '1':
  22700.      default:     arrows = 1;              break;
  22701.      case  '2':   arrows = 2;              break;
  22702.      case  '3':   arrows = 3;              break;
  22703.    }
  22704.  
  22705.    if (arrows != np->article_rows) {
  22706.      np->article_rows = arrows;
  22707.      np->article_criterion_changed = TRUE;
  22708.    }
  22709.  }
  22710.  
  22711.  return;
  22712. }
  22713.  
  22714. ./ ADD NAME=NNMSORT
  22715.  
  22716.  /********************************************************************/
  22717.  /*                                                                  */
  22718.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  22719.  /*                                                                  */
  22720.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  22721.  /*                                                                  */
  22722.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  22723.  /* including the implied warranties of merchantability and fitness, */
  22724.  /* are expressly denied.                                            */
  22725.  /*                                                                  */
  22726.  /* Provided this copyright notice is included, this software may    */
  22727.  /* be freely distributed and not offered for sale.                  */
  22728.  /*                                                                  */
  22729.  /* Changes or modifications may be made and used only by the maker  */
  22730.  /* of same, and not further distributed.  Such modifications should */
  22731.  /* be mailed to the author for consideration for addition to the    */
  22732.  /* software and incorporation in subsequent releases.               */
  22733.  /*                                                                  */
  22734.  /********************************************************************/
  22735.  
  22736. #pragma  csect(code,  "NN@SORT ")
  22737. #pragma  csect(static,"NN$SORT ")
  22738. #include "nn.h"
  22739.  
  22740. /****** Compare articles by number. **********************************/
  22741.  
  22742. static int
  22743. compare_articles_by_number(wp1,wp2)
  22744. register const void       *wp1;
  22745. register const void       *wp2;
  22746. {
  22747.  return
  22748.         (VARK2PARTICLE(**(VARK **)wp1))->number
  22749.       - (VARK2PARTICLE(**(VARK **)wp2))->number
  22750.        ;
  22751. }
  22752.  
  22753. /****** Compare articles by subject. *********************************/
  22754.  
  22755. static int
  22756. compare_articles_by_subject(wp1,wp2)
  22757. register const void       *wp1;
  22758. register const void       *wp2;
  22759. {
  22760.  int answer;
  22761.  
  22762.  answer = strcmp(
  22763.                  (VARK2PARTICLE(**(VARK **)wp1))->csubject,
  22764.                  (VARK2PARTICLE(**(VARK **)wp2))->csubject
  22765.                 );
  22766.  if (answer == 0) return compare_articles_by_number(wp1,wp2);
  22767.  else return answer;
  22768.  
  22769. }
  22770.  
  22771. /****** Make canonical subject. *************************************/
  22772.  
  22773. static char *
  22774. make_canonical_subject(spp,subject)
  22775. char                 **spp;
  22776. char                  *subject;
  22777. {
  22778.  char                 *ip;
  22779.  char                 *op;
  22780.  char                 *rp;
  22781.  int                   re_count;
  22782.  
  22783.  if (!*subject) return "";
  22784.  
  22785.  /* Scan past "re"s and count them up */
  22786.  
  22787.  rp = *spp;
  22788.  
  22789.  re_count = -1;
  22790.  ip = subject - 3;
  22791.  do {
  22792.    ip = ip + 3 + strspn(ip + 3," \t");
  22793.    re_count++;
  22794.  } while (!memcmp(ip,"Re:",3) ||
  22795.           !memcmp(ip,"re:",3) ||
  22796.        /* !memcmp(ip,"rE:",3) || - do you really expect this??? */
  22797.           !memcmp(ip,"RE:",3));
  22798.  
  22799.  /* Copy subject to buffer while lowercasing. Sets op to last nonblank
  22800.     character in buffer. */
  22801.  
  22802.  copy_lowercase_and_strip_trailing(rp,ip,op);
  22803.  
  22804.  /* Hack for prioritizing RE:'s.  Add a byte at the end to put
  22805.   * subjects in order.  e.g.:
  22806.   * Subject: Foo              --> "foo\0"
  22807.   * Subject: Re: Foo          --> "foo\001\0"
  22808.   * Subject: Re: Re: Foo      --> "foo\002\0"
  22809.   *
  22810.   * This algorithm will break if there are more than 255 "RE:"s,
  22811.   * but do you really think that's likely?
  22812.   */
  22813.  
  22814.  if (re_count > 0) {
  22815.    *op = (unsigned char) re_count;
  22816.    op++;
  22817.  }
  22818.  *op = '\0';
  22819.  
  22820.  *spp = op + 1;   /* Bump buffer pointer past our new end */
  22821.  
  22822.  return rp;
  22823.  
  22824. }
  22825.  
  22826. /****** Sort article table. *****************************************/
  22827.  
  22828. Bool
  22829. NNMsort(np,gp)
  22830. Rstruc nncb         *np;
  22831. Rstruc newsgroup    *gp;
  22832. {
  22833.  Rstruc newsarticle *ap;
  22834.  VARK               *vp;
  22835.  VARK               *vpfirst;
  22836.  VARK               *vplast;
  22837.  VARK              **wp;
  22838.  char               *sortbuf;
  22839.  char               *sp;
  22840.  int                 sortbufsize;
  22841.  int                 count;
  22842.  int                 i;
  22843.  
  22844.  if (!gp->article_vector) return TRUE;
  22845.  
  22846.  if (gp->sort_vector) {
  22847.    FREEMAIN(gp->sort_vector,"sort vector");
  22848.    gp->sort_vector = NULL;
  22849.    gp->sort_count  = 0;
  22850.  }
  22851.  
  22852.  /* Retrieve article titles, read or unread, but ignoring any
  22853.   * subject filtering.
  22854.   */
  22855.  count = NNMrart(np,gp,FALSE,TRUE); /* Retrieve article titles */
  22856.  if (count == 0) return TRUE;
  22857.  
  22858.  GETMAIN(gp->sort_vector, VARK **, count, "sort vector");
  22859.  if (!gp->sort_vector) {
  22860.    CRIT1("There is not enough memory to sort the newsgroup.");
  22861.    return FALSE;
  22862.  }
  22863.  
  22864.  gp->sort_count = count;
  22865.  
  22866.  vpfirst = &GETVARKFIRST(gp);
  22867.  vplast  = &GETVARKLAST(gp);
  22868.  wp = gp->sort_vector;
  22869.  sortbufsize = 0;
  22870.  for (vp = vpfirst; vp <= vplast; vp++) {
  22871.    if (IsEligible(*vp)) {     /* i.e. if NNMrart retrieved it */
  22872.      ap = VARK2PARTICLE(*vp);
  22873.      if (*ap->subject) sortbufsize += strlen(ap->subject) + 1;
  22874.      SetUnknown(*vp);         /* unfudge status as we go */
  22875.      *(wp++) = vp;
  22876.    }
  22877.  }
  22878.  
  22879.  if (sortbufsize > 0) {
  22880.    GETMAIN(sortbuf, char, sortbufsize, "sort-by-subject buffer");
  22881.    if (!sortbuf) {
  22882.      CRIT1("There is not enough memory to sort articles by subject.");
  22883.      FREEMAIN(gp->sort_vector,"sort vector");
  22884.      gp->sort_vector = NULL;
  22885.      gp->sort_count  = 0;
  22886.      return FALSE;
  22887.    }
  22888.  }
  22889.  
  22890.  sp = sortbuf;
  22891.  for (wp = gp->sort_vector, i = gp->sort_count; i > 0; wp++, i--) {
  22892.    ap = VARK2PARTICLE(**wp);
  22893.    ap->csubject = make_canonical_subject(&sp,ap->subject);
  22894.  }
  22895.  
  22896.  qsort(gp->sort_vector, gp->sort_count, sizeof(VARK **),
  22897.        compare_articles_by_subject);
  22898.  
  22899.  /* This isn't strictly necessary as long as no one tries to refer
  22900.   * to ap->csubject outside of this module.
  22901.   *
  22902.  for (wp = gp->sort_vector, i = gp->sort_count; i > 0; wp++, i--) {
  22903.    ap = VARK2PARTICLE(**wp);
  22904.    ap->csubject = NULL;
  22905.  }
  22906.   *
  22907.   */
  22908.  
  22909.  FREEMAIN(sortbuf,"sort-by-subject buffer");
  22910.  
  22911.  return TRUE;
  22912. }
  22913.  
  22914. ./ ADD NAME=NNMSSRVR
  22915.  
  22916.  /********************************************************************/
  22917.  /*                                                                  */
  22918.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  22919.  /*                                                                  */
  22920.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  22921.  /* including the implied warranties of merchantability and fitness, */
  22922.  /* are expressly denied.                                            */
  22923.  /*                                                                  */
  22924.  /* Provided this copyright notice is included, this software may    */
  22925.  /* be freely distributed and not offered for sale.                  */
  22926.  /*                                                                  */
  22927.  /* Changes or modifications may be made and used only by the maker  */
  22928.  /* of same, and not further distributed.  Such modifications should */
  22929.  /* be mailed to the author for consideration for addition to the    */
  22930.  /* software and incorporation in subsequent releases.               */
  22931.  /*                                                                  */
  22932.  /********************************************************************/
  22933.  
  22934. #pragma  csect(code,  "NN@SSRVR")
  22935. #pragma  csect(static,"NN$SSRVR")
  22936. #include "nn.h"
  22937.  
  22938. /****** Start server read. *******************************************/
  22939.  
  22940. void
  22941. NNMssrvr(np)
  22942. Rstruc nncb  *np;
  22943. {
  22944.  
  22945.  np->server_has_something_pending = TRUE;
  22946.  np->server_finished_replying     = FALSE;
  22947.  np->sending_text                 = FALSE;
  22948.  np->something_to_print           = FALSE;
  22949.  np->dont_read                    = FALSE;
  22950.  
  22951.  return;
  22952.  
  22953. }
  22954.  
  22955. ./ ADD NAME=NNMSTRLC
  22956.  
  22957.  /********************************************************************/
  22958.  /*                                                                  */
  22959.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  22960.  /*                                                                  */
  22961.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  22962.  /* including the implied warranties of merchantability and fitness, */
  22963.  /* are expressly denied.                                            */
  22964.  /*                                                                  */
  22965.  /* Provided this copyright notice is included, this software may    */
  22966.  /* be freely distributed and not offered for sale.                  */
  22967.  /*                                                                  */
  22968.  /* Changes or modifications may be made and used only by the maker  */
  22969.  /* of same, and not further distributed.  Such modifications should */
  22970.  /* be mailed to the author for consideration for addition to the    */
  22971.  /* software and incorporation in subsequent releases.               */
  22972.  /*                                                                  */
  22973.  /********************************************************************/
  22974.  
  22975. #pragma  csect(code,  "NN@STRLC")
  22976. #pragma  csect(static,"NN$STRLC")
  22977. #include "nn.h"
  22978.  
  22979. /****** Case-insensitive string search. ******************************/
  22980.  
  22981.   /* This differs from the Ustrstr function in NNMbbexp in that it only
  22982.    * has to lowercase the "b" argument, not both.  The "a" argument
  22983.    * is assumed to be all lower case already.
  22984.    */
  22985.  
  22986. char *
  22987. NNMstrlc(b,a)
  22988. register char  *b;
  22989. register char  *a;
  22990. {
  22991.  register char *aa;
  22992.  register char *bb;
  22993.  
  22994.  if (!*a) return strchr(b,'\0');
  22995.  
  22996.  for (;;) {
  22997.  
  22998.    while (*b && (*a != tolower(*b))) b++;
  22999.  
  23000.    if (!*b) return NULL;
  23001.  
  23002.    for (aa = a, bb = b;
  23003.         *aa && *bb && (*aa == tolower(*bb));
  23004.         aa++, bb++) ;
  23005.  
  23006.    if (!*aa) return a;
  23007.  
  23008.    b++;
  23009.  }
  23010.  
  23011. }
  23012.  
  23013. ./ ADD NAME=NNMSUMAT
  23014.  
  23015.  /********************************************************************/
  23016.  /*                                                                  */
  23017.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  23018.  /*                                                                  */
  23019.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  23020.  /* including the implied warranties of merchantability and fitness, */
  23021.  /* are expressly denied.                                            */
  23022.  /*                                                                  */
  23023.  /* Provided this copyright notice is included, this software may    */
  23024.  /* be freely distributed and not offered for sale.                  */
  23025.  /*                                                                  */
  23026.  /* Changes or modifications may be made and used only by the maker  */
  23027.  /* of same, and not further distributed.  Such modifications should */
  23028.  /* be mailed to the author for consideration for addition to the    */
  23029.  /* software and incorporation in subsequent releases.               */
  23030.  /*                                                                  */
  23031.  /********************************************************************/
  23032.  
  23033. #pragma  csect(code,  "NN@SUMAT")
  23034. #pragma  csect(static,"NN$SUMAT")
  23035. #include "nn.h"
  23036.  
  23037. /****** Subject matching code. ***************************************/
  23038.  
  23039. Bool
  23040. NNMsumat(a,b)
  23041. char        *a;
  23042. char        *b;
  23043. {
  23044.  char       *cp;
  23045.  char       *c1;
  23046.  char       *c2;
  23047.  char        bracket;
  23048.  char        s1[257];
  23049.  char        s2[257];
  23050.  
  23051.  strncpy(s1,a,256);
  23052.  strncpy(s2,b,256);
  23053.  
  23054.  lowercase_and_strip_trailing_in_place(s1);
  23055.  lowercase_and_strip_trailing_in_place(s2);
  23056.  
  23057.  c1 = skip_whitespace(s1);
  23058.  c2 = skip_whitespace(s2);
  23059.  
  23060.  if (!strcmp(c1,c2)) return TRUE;
  23061.  
  23062.  while (!memcmp(c1,"re:",3)) {
  23063.    c1 = skip_whitespace(c1+3);
  23064.    if (!strcmp(c1,c2)) return TRUE;
  23065.  }
  23066.  while (!memcmp(c2,"re:",3)) {
  23067.    c2 = skip_whitespace(c2+3);
  23068.    if (!strcmp(c1,c2)) return TRUE;
  23069.  }
  23070.  
  23071.  if ((cp=strstr(c1,"(was:" /*)*/ )) ||
  23072.      (cp=strstr(c1,"(was " /*)*/ )) ||
  23073.      (cp=strstr(c1,"[was " /*)*/ )) ||
  23074.      (cp=strstr(c1,"[was:" /*)*/ ))) {
  23075.    switch (*cp) {
  23076.      case '(':  bracket = ')';  break;
  23077.      case '[':  bracket = ']';  break;
  23078.      default:   bracket = '\0'; break;
  23079.    }
  23080.    c1 = skip_whitespace(cp+5);
  23081.    if (!memcmp(c1,"re:",3)) c1 = skip_whitespace(c1+3);
  23082.    if (!strcmp(c1,c2)) return TRUE;
  23083.    cp = c1 + strlen(c1) - 1;
  23084.    if (*cp == bracket) *cp = '\0';
  23085.    if (!strcmp(c1,c2)) return TRUE;
  23086.  }
  23087.  if ((cp=strstr(c2,"(was:" /*)*/ )) ||
  23088.      (cp=strstr(c2,"(was " /*)*/ )) ||
  23089.      (cp=strstr(c2,"[was " /*)*/ )) ||
  23090.      (cp=strstr(c2,"[was:" /*)*/ ))) {
  23091.    switch (*cp) {
  23092.      case '(':  bracket = ')';  break;
  23093.      case '[':  bracket = ']';  break;
  23094.      default:   bracket = '\0'; break;
  23095.    }
  23096.    c2 = skip_whitespace(cp+5);
  23097.    if (!memcmp(c2,"re:",3)) c2 = skip_whitespace(c2+3);
  23098.    if (!strcmp(c1,c2)) return TRUE;
  23099.    cp = c2 + strlen(c2) - 1;
  23100.    if (*cp == bracket) *cp = '\0';
  23101.    if (!strcmp(c1,c2)) return TRUE;
  23102.  }
  23103.  
  23104.  if (!strcmp(c1,c2)) return TRUE;
  23105.  
  23106.  return FALSE;
  23107.  
  23108. }
  23109.  
  23110. ./ ADD NAME=NNMTSO
  23111.  
  23112.  /********************************************************************/
  23113.  /*                                                                  */
  23114.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  23115.  /*                                                                  */
  23116.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  23117.  /* including the implied warranties of merchantability and fitness, */
  23118.  /* are expressly denied.                                            */
  23119.  /*                                                                  */
  23120.  /* Provided this copyright notice is included, this software may    */
  23121.  /* be freely distributed and not offered for sale.                  */
  23122.  /*                                                                  */
  23123.  /* Changes or modifications may be made and used only by the maker  */
  23124.  /* of same, and not further distributed.  Such modifications should */
  23125.  /* be mailed to the author for consideration for addition to the    */
  23126.  /* software and incorporation in subsequent releases.               */
  23127.  /*                                                                  */
  23128.  /********************************************************************/
  23129.  
  23130.  /********************************************************************/
  23131.  /*                                                                  */
  23132.  /* Thanks to Michael Van Norman for this code.                      */
  23133.  /*                                                                  */
  23134.  /********************************************************************/
  23135.  
  23136. #pragma  csect(code,  "NN@TSO  ")
  23137. #pragma  csect(static,"NN$TSO  ")
  23138. #include "nn.h"
  23139.  
  23140. #pragma linkage(ikjeftsr,OS)
  23141.  
  23142. #define _IKJEFTSR_FLAGS_AUTH        0x00000000
  23143. #define _IKJEFTSR_FLAGS_COMMAND     0x00000001
  23144. #define _IKJEFTSR_FLAGS_DUMP        0x00000100
  23145. #define _IKJEFTSR_FLAGS_NODUMP      0x00000000
  23146. #define _IKJEFTSR_FLAGS_PROGRAM     0x00000002
  23147. #define _IKJEFTSR_FLAGS_UNAUTH      0x00010000
  23148.  
  23149. /****** Issue TSO command. *******************************************/
  23150.  
  23151. int
  23152. NNMtso(command)
  23153. char        *command;
  23154. {
  23155.  int         flags         = _IKJEFTSR_FLAGS_COMMAND +
  23156.                              _IKJEFTSR_FLAGS_UNAUTH;
  23157.  int         commandLength = strlen(command);
  23158.  int         rc            = 0;
  23159.  int         returnCode    = 0;
  23160.  int         reasonCode    = 0;
  23161.  int         abendCode     = 0;
  23162.  
  23163.  static int (*ikjeftsr)() = NULL;
  23164.  
  23165.  if (!ikjeftsr) {
  23166.    /*
  23167.    ikjeftsr = (int (*)())fetch("ikjeftsr");
  23168.    if (!ikjeftsr) {
  23169.     */
  23170.      /* #pragma linkage( tsoServiceFacility, OS )
  23171.       * int (*tsoServiceFacility)( int *, char *, int *,
  23172.       *                            int *, int *, int * );
  23173.       */
  23174.      int tsoEntryAddress;
  23175.  
  23176.      tsoEntryAddress = 0x00000010;    /* Address of CVT */
  23177.      tsoEntryAddress = *(int *)(tsoEntryAddress);
  23178.      tsoEntryAddress += 0x9C;/*       /* Offset of TVT in CVT */
  23179.      tsoEntryAddress = *(int *)(tsoEntryAddress);
  23180.      tsoEntryAddress += 0x10;/*       /* TSVTASF-TSVT (from IKJTSVT) */
  23181.      tsoEntryAddress = *(int *)(tsoEntryAddress);
  23182. #ifndef SASC
  23183.      ikjeftsr = (int (*)())(tsoEntryAddress);
  23184. #else
  23185.      ikjeftsr = (__ibmos int (*)())(tsoEntryAddress);
  23186. #endif
  23187.    /*
  23188.    }
  23189.    */
  23190.  }
  23191.  
  23192.  if (!ikjeftsr) {
  23193.    fprintf(stderr,
  23194.            "Cannot execute TSO commands, can't fetch IKJEFTSR.\n");
  23195.    return -2;
  23196.  }
  23197.  
  23198.  rc = (*ikjeftsr)(&flags, command, &commandLength,
  23199.                           &returnCode, &reasonCode,
  23200.                           (int *)((int)(&abendCode) | 0x80000000));
  23201.  
  23202.  if (rc != 0) {
  23203.    if (rc > 4) {
  23204.      fprintf(stderr,"Command failed:%s\n",command);
  23205.      if (rc == 20 && reasonCode == 40)
  23206.           fprintf(stderr,"Command was not found.\n");
  23207.      else fprintf(stderr,
  23208.              "rc=%d,returncode=%d,reasoncode=%d,abendcode=%8.8x\n",
  23209.              rc, returnCode, reasonCode, abendCode);
  23210.    }
  23211.    if (abendCode != 0) rc = -1;
  23212.    else rc = returnCode;
  23213.  }
  23214.  
  23215.  return rc;
  23216. }
  23217.  
  23218. ./ ADD NAME=NNMUNALC
  23219.  
  23220.  /********************************************************************/
  23221.  /*                                                                  */
  23222.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  23223.  /*                                                                  */
  23224.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  23225.  /* including the implied warranties of merchantability and fitness, */
  23226.  /* are expressly denied.                                            */
  23227.  /*                                                                  */
  23228.  /* Provided this copyright notice is included, this software may    */
  23229.  /* be freely distributed and not offered for sale.                  */
  23230.  /*                                                                  */
  23231.  /* Changes or modifications may be made and used only by the maker  */
  23232.  /* of same, and not further distributed.  Such modifications should */
  23233.  /* be mailed to the author for consideration for addition to the    */
  23234.  /* software and incorporation in subsequent releases.               */
  23235.  /*                                                                  */
  23236.  /********************************************************************/
  23237.  
  23238. #pragma  csect(code,  "NN@UNALC")
  23239. #pragma  csect(static,"NN$UNALC")
  23240. #include "nn.h"
  23241.  
  23242. /****** Unallocate a data set. ***************************************/
  23243.  
  23244. Bool
  23245. NNMunalc(ddname)
  23246. char         *ddname;
  23247. {
  23248.  __S99parms   stuff99;   /* The manual has it wrong.  No "struct". */
  23249.  int          rc;
  23250.  TEXTUNIT    *tu [2];
  23251.  TEXTUNIT     tu_ddn;
  23252.  TEXTUNIT     tu_una;
  23253.  
  23254.  if (!ddname ||
  23255.      !*ddname) return TRUE;   /* if no ddname to free, do nothing */
  23256.  
  23257.  memset((char *)&stuff99,0,sizeof(__S99parms));
  23258.  
  23259.  stuff99.__S99RBLN   = 20;
  23260.  stuff99.__S99VERB   = S99VRBUN;
  23261.  stuff99.__S99FLAG1  = 0;
  23262.  stuff99.__S99ERROR  = 0;
  23263.  stuff99.__S99INFO   = 0;
  23264.  stuff99.__S99TXTPP  = tu;
  23265.  stuff99.__S99FLAG2  = 0;
  23266.  
  23267.  tu[0] = &tu_ddn;
  23268.  tu[1] = &tu_una;
  23269.  *(int *)&tu[1] |= 0x80000000;
  23270.  
  23271.  tu_ddn.key     = DUNDDNAM;
  23272.  tu_ddn.num     = 1;
  23273.  tu_ddn.ent.len = strlen(ddname);
  23274.  copy_uppercase(tu_ddn.ent.prm,ddname);
  23275.  
  23276.  tu_una.key     = DUNUNALC;
  23277.  tu_una.num     = 0;
  23278.  
  23279.  rc = svc99(&stuff99);
  23280.  
  23281.  if (rc == 0) return TRUE;
  23282.  else if (stuff99.__S99ERROR == 0x0438) /* not freed, is not allocated*/
  23283.          return TRUE;
  23284.  else {
  23285.    NNMdfail(rc,&stuff99);
  23286.    return FALSE;
  23287.  }
  23288. }
  23289.  
  23290. ./ ADD NAME=NNMUPDT
  23291.  
  23292.  /********************************************************************/
  23293.  /*                                                                  */
  23294.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  23295.  /*                                                                  */
  23296.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  23297.  /*                                                                  */
  23298.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  23299.  /* including the implied warranties of merchantability and fitness, */
  23300.  /* are expressly denied.                                            */
  23301.  /*                                                                  */
  23302.  /* Provided this copyright notice is included, this software may    */
  23303.  /* be freely distributed and not offered for sale.                  */
  23304.  /*                                                                  */
  23305.  /* Changes or modifications may be made and used only by the maker  */
  23306.  /* of same, and not further distributed.  Such modifications should */
  23307.  /* be mailed to the author for consideration for addition to the    */
  23308.  /* software and incorporation in subsequent releases.               */
  23309.  /*                                                                  */
  23310.  /********************************************************************/
  23311.  
  23312. #pragma  csect(code,  "NN@UPDT ")
  23313. #pragma  csect(static,"NN$UPDT ")
  23314. #include "nn.h"
  23315.  
  23316. /****** Update the screen as frequently as desired. ******************/
  23317.  
  23318. void
  23319. NNMupdt(np,cdp,screen)
  23320. Rstruc nncb           *np;
  23321. struct countdown      *cdp;
  23322. char                  *screen;
  23323. {
  23324.   int                  pct;
  23325.   int                  barsize;
  23326.   int                  l;
  23327.   int                  timediff;
  23328.   int                  h;
  23329.   int                  m;
  23330.   int                  s;
  23331.   time_t               thistime;
  23332.   char                 nnmbar[62];
  23333.   char                 nnmestm[9];
  23334.   char                 zhilite[9];
  23335.   char                 temp[8];
  23336.   char                 display_string[24];
  23337.  
  23338.   if (!cdp || !cdp->do_update || np->batch_mode) return;
  23339.  
  23340.   time(&thistime);
  23341.  
  23342.   if (cdp->done == 0) {
  23343.     if (cdp->to_do == 0) return;
  23344.     if (np->barchar == '\0') {
  23345.       (void)NNMivget(np,"ZHILITE ",zhilite,sizeof(zhilite));
  23346.       if (zhilite[0] == 'Y') np->barchar = ' ';
  23347.       else                   np->barchar = '@';
  23348.     }
  23349.     timediff = -1;                 /* don't display on initial call */
  23350.     np->lasttime = thistime;
  23351.     np->firstime = thistime;
  23352.     memset(nnmestm,' ',sizeof(nnmestm));
  23353.     (void)NNMivput(np, "NNMESTM ", nnmestm, 0);
  23354.   }
  23355.   else {
  23356.     timediff = (int)difftime(thistime, np->lasttime);
  23357.   }
  23358.  
  23359.   if (timediff >= np->updatefreq) {
  23360.     memset(nnmbar,' ',sizeof(nnmbar));
  23361.     nnmbar[0] = '^';
  23362.     if (cdp->to_do < 0) {
  23363.       pct = 0;
  23364.       barsize = 1;
  23365.     }
  23366.     else {
  23367.       if (cdp->to_do < cdp->done) cdp->to_do = cdp->done;
  23368.       pct = cdp->done * 100 / cdp->to_do;
  23369.       barsize = pct * (sizeof(nnmbar) - 2) / 100 + 1;
  23370.     }
  23371.     memset(nnmbar+1, np->barchar, barsize-1);
  23372.     nnmbar[barsize++] = '/';
  23373.  
  23374. #if 1
  23375.  
  23376.     /* This code adds the number of currently processed items to the  */
  23377.     /* right of the bar until it won't fit anymore, then puts it      */
  23378.     /* inside the bar.                                                */
  23379.  
  23380.     l = sprintf(temp, "%d", cdp->done);
  23381.     if (barsize + l < sizeof(nnmbar)) {
  23382.       memcpy(&nnmbar[barsize], temp, l);
  23383.     }
  23384.     else {
  23385.       memcpy(&nnmbar[barsize-l-3], temp, l);
  23386.       if (np->barchar != ' ') {
  23387.         nnmbar[barsize-l-4] = ' ';
  23388.         nnmbar[barsize-3]   = ' ';
  23389.       }
  23390.     }
  23391.  
  23392. #else
  23393.  
  23394.     /* This code adds the number of currently processed items to the  */
  23395.     /* right of the bar until it will fit inside, then puts it there. */
  23396.  
  23397.     l = sprintf(temp, "%d", cdp->done);
  23398.     if (barsize - 4 < l + 2) {
  23399.       memcpy(&nnmbar[barsize], temp, l);
  23400.     }
  23401.     else {
  23402.       memcpy(&nnmbar[barsize-l-3], temp, l);
  23403.       if (np->barchar != ' ') {
  23404.         nnmbar[barsize-l-4] = ' ';
  23405.         nnmbar[barsize-3]   = ' ';
  23406.       }
  23407.     }
  23408.  
  23409. #endif
  23410.  
  23411.     (void)NNMivput(np, "NNMBAR ",nnmbar,sizeof(nnmbar));
  23412.  
  23413.     l = sprintf(temp, "%d", cdp->to_do);
  23414.     (void)NNMivput(np, "NNMCOUNT", temp, l);
  23415.  
  23416.     s = (cdp->to_do - cdp->done) * difftime(thistime, np->firstime)
  23417.         / cdp->done;
  23418.     if (s > 0) {
  23419.       m = s / 60;  s = s % 60;
  23420.       h = m / 60;  m = m % 60;
  23421.       sprintf(nnmestm, "%2.2d:%2.2d:%2.2d", h, m, s);
  23422.       (void)NNMivput(np, "NNMESTM ", nnmestm, sizeof(nnmestm) - 1);
  23423.     }
  23424.  
  23425.     sprintf(display_string, "DISPLAY PANEL(%s)", screen);
  23426.     (void)NNMispf(np, "CONTROL DISPLAY LOCK");
  23427.     (void)NNMispf(np, display_string);
  23428.     np->lasttime = thistime;
  23429.   }
  23430.  
  23431.   cdp->done++;
  23432.  
  23433.   return;
  23434.  
  23435. }
  23436.  
  23437. ./ ADD NAME=NNMVAR
  23438.  
  23439.  /********************************************************************/
  23440.  /*                                                                  */
  23441.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  23442.  /*                                                                  */
  23443.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  23444.  /*                                                                  */
  23445.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  23446.  /* including the implied warranties of merchantability and fitness, */
  23447.  /* are expressly denied.                                            */
  23448.  /*                                                                  */
  23449.  /* Provided this copyright notice is included, this software may    */
  23450.  /* be freely distributed and not offered for sale.                  */
  23451.  /*                                                                  */
  23452.  /* Changes or modifications may be made and used only by the maker  */
  23453.  /* of same, and not further distributed.  Such modifications should */
  23454.  /* be mailed to the author for consideration for addition to the    */
  23455.  /* software and incorporation in subsequent releases.               */
  23456.  /*                                                                  */
  23457.  /********************************************************************/
  23458.  
  23459. #pragma  csect(code,  "NN@VAR  ")
  23460. #pragma  csect(static,"NN$VAR  ")
  23461. #include "nn.h"
  23462.  
  23463. #define ROWCPY(A,B,C) {\
  23464.                        name_length = strlen(B); \
  23465.                        if (name_length > C) name_length = C; \
  23466.                        memcpy(&rowp[A], B, name_length); \
  23467.                       }
  23468.  
  23469. struct ntdynarray {
  23470.                    struct newsarticle    *article;
  23471.                    VARK                 **sortvark;
  23472.                    int                    number;
  23473.                    char                   numstr [6];
  23474.                   };
  23475.  
  23476. /****** Format screen line. ******************************************/
  23477.  
  23478. static void
  23479. format_screen_line(ap,vp,ndp,wp)
  23480. Rstruc newsarticle    *ap;
  23481. VARK                  *vp;
  23482. Rstruc ntdynarray     *ndp;
  23483. VARK                 **wp;
  23484. {
  23485.  ndp->sortvark = wp;
  23486.  ndp->article  = ap;
  23487.  ndp->number   = ap->number;
  23488.  sprintf(ndp->numstr, "%5d", ndp->number);
  23489.  if (ap->action == NO_ACTION) {
  23490.   if (IsRead(*vp)) ap->action = READ;
  23491.   else             ap->action = UNREAD;
  23492.  }
  23493.  return;
  23494. }
  23495.  
  23496. /****** View articles. ***********************************************/
  23497.  
  23498. static Bool
  23499. view_articles(np,gp,dynarray,nntdyna,depth,dynsize)
  23500. Rstruc nncb           *np;
  23501. Rstruc newsgroup      *gp;
  23502. struct ntdynarray     *dynarray;
  23503. char                  *nntdyna;
  23504. int                    depth;
  23505. int                    dynsize;
  23506. {
  23507.  struct newsarticle   *ap;
  23508.  Rstruc ntdynarray    *ndp;
  23509.  Rstruc tabledesc     *tdp;
  23510.  Rstruc seldesc       *sdp;
  23511.  Rstruc cmddesc       *cdp;
  23512.  struct ntdynarray    *ntdynarray_start;
  23513.  struct ntdynarray    *ntdynarray_end;
  23514.  char                 *cp;
  23515.  char                 *rowp;
  23516.  char                 *act;
  23517.  VARK                 *vp;
  23518.  VARK                 *vpfirst;
  23519.  VARK                 *vplast;
  23520.  VARK                **wp;
  23521.  VARK                **wpfirst;
  23522.  VARK                **wplast;
  23523.  VARK                **save_top_sorted_article;
  23524.  int                   save_top_article;
  23525.  int                   display_total;
  23526.  int                   command_index;
  23527.  int                   prc;
  23528.  int                   nntlvl;
  23529.  int                   articles_per_screen;
  23530.  int                   scroll;
  23531.  int                   zscrolln;
  23532.  int                   rowincr;
  23533.  int                   rowbump;
  23534.  int                   actlen;
  23535.  int                   anum;
  23536.  int                   artcursor;
  23537.  int                   last_article_selected;
  23538.  short                 name_length;
  23539.  Bool                  is_max;
  23540.  Bool                  is_scroll_word;
  23541.  Bool                  rebuild_dynamic_array;
  23542.  Bool                  selection_processed_ok;
  23543.  Bool                  command_processed_ok;
  23544.  char                  aattr;
  23545.  char                  sel;
  23546.  struct countdown      cd;
  23547.  char                  tcmd        [72];
  23548.  char                  nnthead     [81];
  23549.  char                  nntcsr      [12];
  23550.  char                  command      [COMMANDSIZE];
  23551.  char                  zverb        [9];
  23552.  char                  zscrolla     [9];
  23553.  char                  rowmessage  [81];
  23554.  
  23555.  ntdynarray_start        = dynarray;
  23556.  rebuild_dynamic_array   = TRUE;
  23557.  scroll                  = 0;
  23558.  artcursor               = 0;
  23559.  last_article_selected   = -1;
  23560.  save_top_article        = 0;
  23561.  save_top_sorted_article = NULL;
  23562.  tdp = np->display_table_vector->article_display_table;
  23563.  strcpy(tcmd,"");
  23564.  strcpy(np->article_only_string,"");
  23565.  
  23566.  cd.do_update = (np->updatefreq >= 0);
  23567.  cd.done      = 0;
  23568.  cd.to_do     = -1;
  23569.  
  23570.  /* Loop displaying article titles until END. */
  23571.  
  23572.  do {
  23573.  
  23574.   /* The very first time, all articles have a not-known-yet status.
  23575.    * The normal article collections set knownness on the fly.
  23576.    * When the article criterion changes (e.g. ONLY command),
  23577.    * all articles are set to unknown.  This could also be done
  23578.    * in processing for the ONLY command itself.
  23579.    * If status has been changed (read->unread or vice versa),
  23580.    * alter it here.  But do not change it if the status is read
  23581.    * and the displayed status has been set to one of those
  23582.    * funny values like "Extracted".
  23583.    * This is needed because the newsgroup mark and unmark
  23584.    * operations do not go through the ap actions.
  23585.    */
  23586.  
  23587.    if (np->article_criterion_changed) {
  23588.      if (gp->sort_vector) (void)NNMsort(np,gp);
  23589.      np->article_criterion_changed = FALSE;
  23590.      rebuild_dynamic_array = TRUE;
  23591.      if (gp->article_vector) {
  23592.        vpfirst = &GETVARKFIRST(gp);
  23593.        vplast  = &GETVARKLAST(gp);
  23594.        for (vp = vpfirst; vp <= vplast; vp++) {
  23595.          SetUnknown(*vp);
  23596.          if (IsPresent(*vp) && (ap=VARK2PARTICLE(*vp))) {
  23597.            if (IsRead(*vp)) {
  23598.              if (ap->action == UNREAD
  23599.               || ap->action == MISSING
  23600.               || ap->action == ERROR
  23601.               || ap->action == NO_ACTION) ap->action = READ;
  23602.              else;
  23603.            }
  23604.            else ap->action = UNREAD;
  23605.          }
  23606.        }
  23607.      }
  23608.    } /* end if article criterion changed */
  23609.  
  23610.    /*
  23611.     * If necessary, rebuild the array of newsarticle pointers.
  23612.     */
  23613.  
  23614.    if (rebuild_dynamic_array) {
  23615.      rebuild_dynamic_array = FALSE;
  23616.      rowincr               = np->article_rows;
  23617.      if (rowincr < 1) rowincr = 1;
  23618.      rowbump               = 80 * rowincr;
  23619.      articles_per_screen   = (depth-1)/rowincr + 1;
  23620.      cd.do_update          = (np->updatefreq >= 0);
  23621.      cd.done               = 0;
  23622.      cd.to_do              = articles_per_screen;
  23623.      if (cd.do_update && gp->article_vector
  23624.                       && *np->article_only_string) {
  23625.        cd.to_do = 0;
  23626.        vpfirst = &GETVARKFIRST(gp);
  23627.        vplast  = &GETVARKLAST(gp);
  23628.        for (vp = vpfirst; vp <= vplast; vp++) {
  23629.          if (IsNull(*vp))  cd.to_do++;
  23630.        }
  23631.      }
  23632.      display_total         = articles_per_screen;
  23633.      ndp                   = ntdynarray_start;
  23634.  
  23635.      /* Process scroll, collecting (abs(scroll)) articles
  23636.       * until the new top-of-display article is found.  Logic:
  23637.       * If top article is logically past end, then OK.
  23638.       * If top article is not eligible, move back up until we find
  23639.       * an eligible one.
  23640.       * If top article is first but still not eligible, move down
  23641.       * until we find an eligible one.
  23642.       * Then collect enough articles to fill the screen.
  23643.       */
  23644.  
  23645.      if (gp->sort_vector) {
  23646.  
  23647.        wpfirst = gp->sort_vector;
  23648.        wplast  = gp->sort_vector + gp->sort_count;
  23649.  
  23650.        wp = np->top_sorted_article;
  23651.  
  23652.        if (wp < wplast) {
  23653.          for (; wp >= wpfirst; wp--)
  23654.              if (NNMcar(np,gp,0,*wp,NULL,&cd,RETRIEVE)) break;
  23655.        }
  23656.  
  23657.        if (wp < wpfirst) {
  23658.          for (wp = wpfirst; wp < wplast; wp++)
  23659.              if (NNMcar(np,gp,0,*wp,NULL,&cd,RETRIEVE)) break;
  23660.        }
  23661.  
  23662.        if (scroll > 0) {
  23663.          while (scroll > 0 && ++wp < wplast) {
  23664.            if (NNMcar(np,gp,0,*wp,NULL,&cd,RETRIEVE)) scroll--;
  23665.          }
  23666.        }
  23667.        else if (scroll < 0) {
  23668.          while (scroll < 0 && --wp >= wpfirst) {
  23669.            if (NNMcar(np,gp,0,*wp,NULL,&cd,RETRIEVE)) scroll++;
  23670.          }
  23671.          if (wp < wpfirst) wp = wpfirst;
  23672.        }
  23673.        np->top_sorted_article = wp;
  23674.  
  23675.        for (; display_total > 0 && wp < wplast; wp++) {
  23676.          if (NNMcar(np,gp,0,*wp,&ap,&cd,RETRIEVE)) {
  23677.            format_screen_line(ap,*wp,ndp,wp);
  23678.            display_total--;
  23679.            ndp++;
  23680.          }
  23681.        }
  23682.        ntdynarray_end = ndp;
  23683.  
  23684.      }
  23685.  
  23686.      else if (gp->article_vector) { /* not sorted */
  23687.  
  23688.        anum = np->top_article;
  23689.  
  23690.        if (anum <= gp->vector_last) {
  23691.          for (; anum >= gp->vector_first; anum--)
  23692.              if (NNMcar(np,gp,anum,NULL,NULL,&cd,RETRIEVE)) break;
  23693.        }
  23694.  
  23695.        if (anum < gp->vector_first) {
  23696.          for (anum = gp->vector_first; anum <= gp->vector_last; anum++)
  23697.              if (NNMcar(np,gp,anum,NULL,NULL,&cd,RETRIEVE)) break;
  23698.        }
  23699.  
  23700.        if (scroll > 0) {
  23701.          while (scroll > 0 && ++anum <= gp->vector_last) {
  23702.            if (NNMcar(np,gp,anum,NULL,NULL,&cd,RETRIEVE)) scroll--;
  23703.          }
  23704.        }
  23705.        else if (scroll < 0) {
  23706.          while (scroll < 0 && --anum >= gp->vector_first) {
  23707.            if (NNMcar(np,gp,anum,NULL,NULL,&cd,RETRIEVE)) scroll++;
  23708.          }
  23709.          if (anum < gp->vector_first) anum = gp->vector_first;
  23710.        }
  23711.        np->top_article = anum;
  23712.  
  23713.        for (; display_total > 0 && anum <= gp->vector_last; anum++) {
  23714.          if (NNMcar(np,gp,anum,NULL,&ap,&cd,RETRIEVE)) {
  23715.            vp = &GETVARK(gp,anum);
  23716.            format_screen_line(ap,vp,ndp,NULL);
  23717.            display_total--;
  23718.            ndp++;
  23719.          }
  23720.        }
  23721.        ntdynarray_end = ndp;
  23722.  
  23723.      } /* end not sorted */
  23724.  
  23725.      else { /* no article vector */
  23726.  
  23727.        ntdynarray_end = ndp;
  23728.        np->top_article = 0;
  23729.  
  23730.      }
  23731.  
  23732.    } /* end if rebuild_dynamic_array */
  23733.  
  23734.    save_top_article = np->top_article;
  23735.    save_top_sorted_article = np->top_sorted_article;
  23736.    artcursor = 0;
  23737.  
  23738.    /* Fill dynamic area with data for groups satisfying criterion. */
  23739.  
  23740.    memset(nntdyna, ' ', dynsize);
  23741.  
  23742.    for (ndp = ntdynarray_start, rowp = nntdyna;
  23743.         ndp < ntdynarray_end;
  23744.         ndp++) {
  23745.      ap = ndp->article;
  23746.      if (np->article_autocursor
  23747.       && ndp->number == last_article_selected) {
  23748.        artcursor = rowp + 2 - nntdyna;
  23749.      }
  23750.      rowp[ 0]        = DATAIN_HIGH;     /* selection code attribute */
  23751.      rowp[ 1]        = ' ';             /* selection code field     */
  23752.      rowp[ 2]        = DATAOUT_BLUE;    /* article number attribute */
  23753.      memcpy(&rowp[ 3], ndp->numstr, 5); /* article number           */
  23754.      rowp[ 8]        = DATAOUT_GREEN;   /* article title attribute  */
  23755.      ROWCPY(9,ap->subject,60);          /* article title            */
  23756.  
  23757.      switch (ap->action) {
  23758.        case NO_ACTION: act = "No action"; aattr = DATAOUT_TURQ;   break;
  23759.        case READ:      act = "Read   "  ; aattr = DATAOUT_BLUE;   break;
  23760.        case RETRIEVED: act = "Retrieved"; aattr = DATAOUT_BLUE;   break;
  23761.        case EXTRACTED: act = "Extracted"; aattr = DATAOUT_BLUE;   break;
  23762.        case PRINTED:   act = "Printed"  ; aattr = DATAOUT_BLUE;   break;
  23763.        case UNREAD:    act = "Unread "  ; aattr = DATAOUT_YELLOW; break;
  23764.        case MISSING:   act = "Missing"  ; aattr = DATAOUT_TURQ;   break;
  23765.        case ERROR:     act = "Error  "  ; aattr = DATAOUT_TURQ;   break;
  23766.        case CANCELLED: act = "Cancelled"; aattr = DATAOUT_BLUE;   break;
  23767.        default:        act = "???????"  , aattr = DATAOUT_TURQ;   break;
  23768.      }
  23769.      actlen = strlen(act);
  23770.      memcpy(&rowp[68-actlen],act,actlen);
  23771.      rowp[68-actlen-1] = aattr;
  23772.  
  23773.      if (rowincr == 1) {
  23774.        rowp[68] = DATAOUT_GREEN;           /* article date attribute */
  23775.        ROWCPY(69,ap->date,11);                      /* article date  */
  23776.      }
  23777.      else {
  23778.        memset(&rowp[68],' ',12);
  23779.      }
  23780.  
  23781.      if ((rowp+=80) >= nntdyna + dynsize) break;
  23782.      if (rowincr >= 2) {
  23783.        rowp[0] = DATAOUT_GREEN;          /* article author attribute */
  23784.        ROWCPY(9,ap->from,58);                    /* article author   */
  23785.        rowp[59] = DATAOUT_GREEN;           /* article date attribute */
  23786.        ROWCPY(60,ap->date,20);                      /* article date  */
  23787.        if ((rowp+=80) >= nntdyna + dynsize) break;
  23788.        if (rowincr >= 3) {
  23789.          rowp[0] = DATAOUT_BLUE;
  23790.          ROWCPY(9,ap->message_id,70);
  23791.          if ((rowp+=80) >= nntdyna + dynsize) break;
  23792.        }
  23793.      }
  23794.    } /* end for */
  23795.  
  23796.    if (rowp < nntdyna + dynsize) {
  23797.      rowp[0] = DATAOUT_HIGH;
  23798.      memset(&rowp[1], '-',79);
  23799.    }
  23800.  
  23801.  /* Format the heading line for the title display.
  23802.   * Row message is "Range mmmm-nnnn", not "m-n of p", because
  23803.   * we don't always know if we can get to all the articles.
  23804.   */
  23805.  
  23806.    if (!gp->article_vector) strcpy(rowmessage, "");
  23807.    else sprintf(rowmessage, " Range %d-%d",
  23808.                             gp->vector_first, gp->vector_last);
  23809.  
  23810.    memset(nnthead, '-', 80);
  23811.    *(nnthead+80) = '\0';
  23812.    strcpy(nnthead, "Newsgroup: ");
  23813.    name_length = strlen(gp->name);
  23814.    if (name_length > 40) name_length = 40;
  23815.    strncat(nnthead, gp->name, name_length);
  23816.    *(strchr(nnthead,'\0')) = ' ';
  23817.    strcpy(nnthead + 79 - strlen(rowmessage), rowmessage);
  23818.  
  23819.    if (artcursor > 0) {
  23820.      sprintf(nntcsr,"%d",artcursor);
  23821.      (void)NNMivput(np,"NNTCSR ", nntcsr, -1);
  23822.    }
  23823.    else {
  23824.      (void)NNMivput(np,"NNTCSR ", "0", 1);
  23825.    }
  23826.  
  23827.    (void)NNMivput(np,"NNTCMD " , tcmd,    -1);
  23828.    (void)NNMivput(np,"NNTHEAD ", nnthead, -1);
  23829.    (void)NNMivput(np,"NNTDYNA ", nntdyna, dynsize);
  23830.    (void)NNMivput(np,"YRFIND "  ,"ALIAS FIND",-1);
  23831.  
  23832.    prc = NNMdispl(np,"NNMDAR  ");
  23833.    if (prc > 8) break;
  23834.  
  23835.    (void)NNMivput(np,"YRFIND "  ,"",-1);
  23836.    (void)NNMivget(np,"NNTDYNA " , nntdyna,  dynsize);
  23837.    (void)NNMivget(np,"ZVERB "   , zverb,    sizeof(zverb));
  23838.    (void)NNMivget(np,"ZSCROLLA ", zscrolla, sizeof(zscrolla));
  23839.    zscrolln = NNMiget(np,"ZSCROLLN ");
  23840.    nntlvl   = NNMiget(np,"NNTLVL ");
  23841.    scroll   = 0;
  23842.  
  23843.    /* Process selections. */
  23844.  
  23845.    save_top_article = np->top_article;
  23846.    save_top_sorted_article = np->top_sorted_article;
  23847.    np->top_article = 0;
  23848.    np->top_sorted_article = NULL;
  23849.    last_article_selected = -1;
  23850.  
  23851.    for (ndp = ntdynarray_start, rowp = nntdyna;
  23852.         ndp < ntdynarray_end && !np->quit;
  23853.         ndp++,                  rowp += rowbump) {
  23854.      sel = toupper(rowp[1]);
  23855.      if (sel == ' ') continue;
  23856.      for (sdp = tdp->first_seldesc; sdp->selection_code != ' '; sdp++) {
  23857.        if (sel == sdp->selection_code) {
  23858.          ap = ndp->article;
  23859.          np->current_sortvark = ndp->sortvark;
  23860.          selection_processed_ok = (sdp->selection_processor)(np,ap);
  23861.          last_article_selected = ap->number;
  23862.          sdp = NULL;
  23863.          break;
  23864.        }
  23865.      }
  23866.      if (sdp) {
  23867.        ERR1("Unknown selection code.  Type one of the listed codes.");
  23868.        selection_processed_ok = FALSE;
  23869.      }
  23870.    }
  23871.  
  23872.    if (np->quit) break;
  23873.  
  23874.    if (np->top_article != 0 && np->article_autocursor)
  23875.        last_article_selected = np->top_article;
  23876.    if (np->top_article == 0 || !np->article_autoscroll)
  23877.        np->top_article = save_top_article;
  23878.    if (np->top_sorted_article == NULL || !np->article_autoscroll)
  23879.        np->top_sorted_article = save_top_sorted_article;
  23880.  
  23881.    /* Process command if any. */
  23882.  
  23883.    strcpy(tcmd,"");
  23884.  
  23885.    (void)NNMivget(np,tdp->command_variable,tcmd,sizeof(tcmd));
  23886.  
  23887.    if (strcmp(tcmd,"") != 0) {
  23888.  
  23889.      last_article_selected = -1;
  23890.      memset(command,' ',COMMANDSIZE);
  23891.      command_index = 0;
  23892.      for (cp = tcmd; *cp && !isspace(*cp); cp++) {
  23893.        if (cp >= tcmd+COMMANDSIZE) {
  23894.          ERR1("Unknown command name.");
  23895.          command_processed_ok = FALSE;
  23896.        }
  23897.        command[command_index++] = toupper(*cp);
  23898.      }
  23899.      while (*cp && isspace(*cp)) cp++;
  23900.  
  23901.      for (cdp = tdp->first_cmddesc; *cdp->command_name != ' '; cdp++) {
  23902.        if (!memcmp(command,cdp->command_name,COMMANDSIZE-1)) {
  23903.          command_processed_ok = (cdp->command_processor)(np,gp,cp);
  23904.          cdp = NULL;
  23905.          break;
  23906.        }
  23907.      }
  23908.      if (cdp) {
  23909.        for (cdp=tdp->next_cmddesc; *cdp->command_name != ' '; cdp++) {
  23910.          if (!memcmp(command,cdp->command_name,COMMANDSIZE-1)) {
  23911.            command_processed_ok = (cdp->command_processor)(np,gp,cp);
  23912.            cdp = NULL;
  23913.            break;
  23914.          }
  23915.        }
  23916.      }
  23917.      if (cdp) {
  23918.        ERR1("Unknown command name.");
  23919.        command_processed_ok = FALSE;
  23920.      }
  23921.  
  23922.      if (command_processed_ok) strcpy(tcmd,"");
  23923.  
  23924.    }
  23925.  
  23926.    if (np->quit) break;
  23927.  
  23928.    if (np->top_article != save_top_article
  23929.     || np->top_sorted_article != save_top_sorted_article)
  23930.        rebuild_dynamic_array = TRUE;
  23931.  
  23932.    /* Process scroll request if any. */
  23933.  
  23934.    switch (zscrolla[0]) {
  23935.      case 'P':
  23936.      case 'H':
  23937.      case 'C':
  23938.      case 'D':  is_max = FALSE;
  23939.                 is_scroll_word = TRUE;
  23940.                 break;
  23941.      case 'M':  is_max = TRUE;
  23942.                 break;
  23943.      default:   is_max = FALSE;
  23944.                 is_scroll_word = FALSE;
  23945.                 break;
  23946.    }
  23947.  
  23948.    if      (EQUAL(zverb,"DOWN")) {
  23949.      if (is_max)         {
  23950.                           np->top_article = gp->vector_last;
  23951.                           np->top_sorted_article = wplast - 1;
  23952.                           scroll = -((nntlvl-1)/np->article_rows);
  23953.                          }
  23954.      else
  23955.      if (is_scroll_word)  scroll = zscrolln/rowincr;
  23956.      else                 scroll = zscrolln;
  23957.    }
  23958.    else if (EQUAL(zverb,"UP")) {
  23959.      if (is_max)         {
  23960.                           np->top_article = gp->vector_first;
  23961.                           np->top_sorted_article = wpfirst;
  23962.                           scroll = 0;
  23963.                           rebuild_dynamic_array = TRUE;
  23964.                          }
  23965.      else
  23966.      if (is_scroll_word)  scroll = -zscrolln/rowincr;
  23967.      else                 scroll = -zscrolln;
  23968.    }
  23969.    else scroll = 0;
  23970.  
  23971.    if (scroll != 0) rebuild_dynamic_array = TRUE;
  23972.  
  23973.  } while (prc == 0);
  23974.  
  23975.  return TRUE;
  23976.  
  23977. }
  23978.  
  23979. /****** View articles. ***********************************************/
  23980.  
  23981. Bool
  23982. NNMvar(np,gp)
  23983. Rstruc nncb           *np;
  23984. Rstruc newsgroup      *gp;
  23985. {
  23986.  struct ntdynarray    *dynarray;
  23987.  char                 *nntdyna;
  23988.  int                   depth;
  23989.  int                   dynsize;
  23990.  
  23991.  /* Get depth of dynamic area (number of rows to display on screen) */
  23992.  
  23993.  (void)NNMispf(np,
  23994.        "PQUERY PANEL(NNMDAR) AREANAME(NNTDYNA) DEPTH(NNTDEPTH)");
  23995.  if (np->ispfrc != 0) return FALSE;
  23996.  depth = NNMiget(np,"NNTDEPTH ");
  23997.  
  23998.  /* Allocate a block of "ntdynarray" article pointers, one element
  23999.   * for each article currently being displayed.  This must be big
  24000.   * enough to fill up the screen.  It is rebuilt every time the
  24001.   * display changes, through scrolling or selection activity.
  24002.   */
  24003.  
  24004.  GETMAIN(dynarray, struct ntdynarray, depth,
  24005.          "newsarticle dynamic array");
  24006.  if (!dynarray) return FALSE;
  24007.  
  24008.  /* Get storage for ISPF dynamic area variable to be constructed. */
  24009.  
  24010.  dynsize = 80*depth;
  24011.  GETMAIN(nntdyna, char, dynsize+1, "NNTDYNA buffer");
  24012.  if (!nntdyna) return FALSE;
  24013.  
  24014.  np->top_article               = 0;
  24015.  np->top_sorted_article        = NULL;
  24016.  np->repeat_find               = FALSE;
  24017.  np->article_criterion_changed = TRUE;
  24018.  *np->selsubj                  = '\0';
  24019.  
  24020.  if (!view_articles(np,gp,dynarray,nntdyna,depth,dynsize)) return FALSE;
  24021.  
  24022.  FREEMAIN(nntdyna,"NNTDYNA buffer");
  24023.  FREEMAIN(dynarray,"newsarticle dynamic area");
  24024.  
  24025.  return TRUE;
  24026.  
  24027. }
  24028. ./ ADD NAME=NNMVIEW
  24029.  
  24030.  /********************************************************************/
  24031.  /*                                                                  */
  24032.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1993    */
  24033.  /*                                                                  */
  24034.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  24035.  /*                                                                  */
  24036.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  24037.  /* including the implied warranties of merchantability and fitness, */
  24038.  /* are expressly denied.                                            */
  24039.  /*                                                                  */
  24040.  /* Provided this copyright notice is included, this software may    */
  24041.  /* be freely distributed and not offered for sale.                  */
  24042.  /*                                                                  */
  24043.  /* Changes or modifications may be made and used only by the maker  */
  24044.  /* of same, and not further distributed.  Such modifications should */
  24045.  /* be mailed to the author for consideration for addition to the    */
  24046.  /* software and incorporation in subsequent releases.               */
  24047.  /*                                                                  */
  24048.  /********************************************************************/
  24049.  
  24050. #pragma  csect(code,  "NN@VIEW ")
  24051. #pragma  csect(static,"NN$VIEW ")
  24052. #include "nn.h"
  24053.  
  24054. struct browser {
  24055.    struct newsgroup     *gp;
  24056.    struct newsarticle   *ap;
  24057.    struct texthdr       *thp;            /* text header pointer      */
  24058.    struct textline     **tv;             /* text vector              */
  24059.                char     *bda;            /* dynamic area address     */
  24060.                char     *work;           /* find work area address   */
  24061.                char     *firstpos;       /* beginning of actual data */
  24062.                char     *lastpos;        /* end of actual data       */
  24063.                int       depth;          /* dynamic area depth       */
  24064.                int       lvl;            /* last visible line        */
  24065.                int       size;           /* dynamic area size        */
  24066.                int       more_rows;      /* Scroll request row count */
  24067.                int       rowfactor;      /* # physical rows per line */
  24068.                int       screenbump;     /* # physical rows * width  */
  24069.                int       top;            /* top row number           */
  24070.                int       total;          /* total number of rows     */
  24071.                int       coloff;         /* offset from LEFT/RIGHT   */
  24072.                int       cols;           /* 1 if COLS done, else 0   */
  24073.                int       maxlen;         /* maximum text length      */
  24074.                int       maxcoloff;      /* maximum right scroll     */
  24075.                Bool      override_scroll;/* set by some commands     */
  24076.                Bool      highlighted;    /* set if FIND highlights   */
  24077.                Bool      reinit_browse;  /* set if text changed      */
  24078.                Bool      exit_browse;    /* set if browse must exit  */
  24079.                Bool      find_hit_end;   /* top/bottom of data reach */
  24080.                int       find_count;     /* used by FIND ALL         */
  24081.                int       find_row;       /* row where last found     */
  24082.                int       find_col;       /* col where last found     */
  24083.                int       found_row;      /* row where last found     */
  24084.                int       found_col;      /* col where last found     */
  24085.                int       csrpos;         /* cursor position          */
  24086.                int       find_csrpos;    /* col where last found     */
  24087.                int       found_left;     /* pos left of found string */
  24088.                int       found_right;    /* pos right of found string*/
  24089.                char      cursor     [9]; /* cursor field name        */
  24090.                char      find_cursor[9]; /* row where last found     */
  24091.                char      title     [81]; /* title                    */
  24092.                char      cols_line [81]; /* cols line                */
  24093.                char      zcmd      [81]; /* command input            */
  24094.               };
  24095.  
  24096. /******* torot13 ******************************************************/
  24097.  
  24098. static char
  24099. torot13(c)
  24100. char    c;
  24101. {
  24102.  char   d;
  24103.  if (!isalpha(c)) d = c;
  24104.  else switch (c) {
  24105.    case 'a':   d = 'n'; break;
  24106.    case 'b':   d = 'o'; break;
  24107.    case 'c':   d = 'p'; break;
  24108.    case 'd':   d = 'q'; break;
  24109.    case 'e':   d = 'r'; break;
  24110.    case 'f':   d = 's'; break;
  24111.    case 'g':   d = 't'; break;
  24112.    case 'h':   d = 'u'; break;
  24113.    case 'i':   d = 'v'; break;
  24114.    case 'j':   d = 'w'; break;
  24115.    case 'k':   d = 'x'; break;
  24116.    case 'l':   d = 'y'; break;
  24117.    case 'm':   d = 'z'; break;
  24118.    case 'n':   d = 'a'; break;
  24119.    case 'o':   d = 'b'; break;
  24120.    case 'p':   d = 'c'; break;
  24121.    case 'q':   d = 'd'; break;
  24122.    case 'r':   d = 'e'; break;
  24123.    case 's':   d = 'f'; break;
  24124.    case 't':   d = 'g'; break;
  24125.    case 'u':   d = 'h'; break;
  24126.    case 'v':   d = 'i'; break;
  24127.    case 'w':   d = 'j'; break;
  24128.    case 'x':   d = 'k'; break;
  24129.    case 'y':   d = 'l'; break;
  24130.    case 'z':   d = 'm'; break;
  24131.    case 'A':   d = 'N'; break;
  24132.    case 'B':   d = 'O'; break;
  24133.    case 'C':   d = 'P'; break;
  24134.    case 'D':   d = 'Q'; break;
  24135.    case 'E':   d = 'R'; break;
  24136.    case 'F':   d = 'S'; break;
  24137.    case 'G':   d = 'T'; break;
  24138.    case 'H':   d = 'U'; break;
  24139.    case 'I':   d = 'V'; break;
  24140.    case 'J':   d = 'W'; break;
  24141.    case 'K':   d = 'X'; break;
  24142.    case 'L':   d = 'Y'; break;
  24143.    case 'M':   d = 'Z'; break;
  24144.    case 'N':   d = 'A'; break;
  24145.    case 'O':   d = 'B'; break;
  24146.    case 'P':   d = 'C'; break;
  24147.    case 'Q':   d = 'D'; break;
  24148.    case 'R':   d = 'E'; break;
  24149.    case 'S':   d = 'F'; break;
  24150.    case 'T':   d = 'G'; break;
  24151.    case 'U':   d = 'H'; break;
  24152.    case 'V':   d = 'I'; break;
  24153.    case 'W':   d = 'J'; break;
  24154.    case 'X':   d = 'K'; break;
  24155.    case 'Y':   d = 'L'; break;
  24156.    case 'Z':   d = 'M'; break;
  24157.  }
  24158.  
  24159.  return d;
  24160. }
  24161.  
  24162. /******* EXTRACT command **********************************************/
  24163.  
  24164. static Bool
  24165. process_extract_command(np,bp,operands)
  24166. Rstruc nncb         *np;
  24167. Rstruc browser      *bp;
  24168. char                *operands;
  24169. {
  24170.  Rstruc newsarticle *ap = bp->ap;
  24171.  
  24172.  if (!ap) (void)NNMivput(np,"NNTNUM ","",-1);
  24173.  np->extract_file = NULL;
  24174.  np->printing     = FALSE;
  24175.  (void)NNMispf(np,"CONTROL DISPLAY SAVE");
  24176.  (void)NNMxtx(np,ap,TRUE);                   /* Extract text */
  24177.  (void)NNMispf(np,"CONTROL DISPLAY RESTORE");
  24178.  
  24179.  return TRUE;
  24180. }
  24181.  
  24182. /******* PRINT command ************************************************/
  24183.  
  24184. static Bool
  24185. process_print_command(np,bp,operands)
  24186. Rstruc nncb         *np;
  24187. Rstruc browser      *bp;
  24188. char                *operands;
  24189. {
  24190.  Rstruc newsarticle *ap = bp->ap;
  24191.  
  24192.  if (!ap) (void)NNMivput(np,"NNTNUM ","",-1);
  24193.  np->extract_file = NULL;
  24194.  np->printing     = TRUE;
  24195.  (void)NNMispf(np,"CONTROL DISPLAY SAVE");
  24196.  (void)NNMxtx(np,ap,TRUE);                   /* Print text */
  24197.  (void)NNMispf(np,"CONTROL DISPLAY RESTORE");
  24198.  
  24199.  return TRUE;
  24200. }
  24201.  
  24202. /******* UNREAD command ***********************************************/
  24203.  
  24204. static Bool
  24205. process_unread_command(np,bp,operands)
  24206. Rstruc nncb         *np;
  24207. Rstruc browser      *bp;
  24208. char                *operands;
  24209. {
  24210.  
  24211.  np->another_article = UNREAD_THIS_ARTICLE;
  24212.  bp->exit_browse = TRUE;
  24213.  
  24214.  return TRUE;
  24215. }
  24216.  
  24217. /******* ROT13 command ************************************************/
  24218.  
  24219. static Bool
  24220. process_rot13_command(np,bp,operands)
  24221. Rstruc nncb         *np;
  24222. Rstruc browser      *bp;
  24223. char                *operands;
  24224. {
  24225.  struct textline    *tp;
  24226.  char               *cp;
  24227.  char               *cpe;
  24228.  
  24229.  for (tp=bp->thp->text_body_line; tp; tp=tp->next) {
  24230.    for (cp=tp->tab_expanded_text, cpe=cp+tp->tab_expanded_text_length;
  24231.         cp < cpe;
  24232.         cp++) {
  24233.      *cp = torot13(*cp);
  24234.    }
  24235.  }
  24236.  
  24237.  bp->reinit_browse = TRUE;
  24238.  
  24239.  return TRUE;
  24240. }
  24241.  
  24242. /******* REPLY command ************************************************/
  24243.  
  24244. static Bool
  24245. process_reply_command(np,bp,operands)
  24246. Rstruc nncb         *np;
  24247. Rstruc browser      *bp;
  24248. char                *operands;
  24249. {
  24250.  
  24251.  (void)NNMispf(np,"CONTROL DISPLAY SAVE");
  24252.  NNMdmail(np,bp->gp,bp->ap);       /* Send mail message */
  24253.  (void)NNMispf(np,"CONTROL DISPLAY RESTORE");
  24254.  return TRUE;
  24255. }
  24256.  
  24257. /******* FOLLOWUP command *********************************************/
  24258.  
  24259. static Bool
  24260. process_followup_command(np,bp,operands)
  24261. Rstruc nncb         *np;
  24262. Rstruc browser      *bp;
  24263. char                *operands;
  24264. {
  24265.  
  24266.  (void)NNMispf(np,"CONTROL DISPLAY SAVE");
  24267.  NNMdpost(np,bp->gp,bp->ap);       /* Post followup */
  24268.  (void)NNMispf(np,"CONTROL DISPLAY RESTORE");
  24269.  return TRUE;
  24270. }
  24271.  
  24272. /******* NEXT command *************************************************/
  24273.  
  24274. static Bool
  24275. process_next_command(np,bp,operands)
  24276. Rstruc nncb         *np;
  24277. Rstruc browser      *bp;
  24278. char                *operands;
  24279. {
  24280.  
  24281.  np->another_article = NEXT_ARTICLE;
  24282.  bp->exit_browse = TRUE;
  24283.  return TRUE;
  24284. }
  24285.  
  24286. /******* PREV command *************************************************/
  24287.  
  24288. static Bool
  24289. process_prev_command(np,bp,operands)
  24290. Rstruc nncb         *np;
  24291. Rstruc browser      *bp;
  24292. char                *operands;
  24293. {
  24294.  
  24295.  np->another_article = PREV_ARTICLE;
  24296.  bp->exit_browse = TRUE;
  24297.  return TRUE;
  24298. }
  24299.  
  24300. /******* NEXTU command ************************************************/
  24301.  
  24302. static Bool
  24303. process_nextu_command(np,bp,operands)
  24304. Rstruc nncb         *np;
  24305. Rstruc browser      *bp;
  24306. char                *operands;
  24307. {
  24308.  
  24309.  np->another_article = NEXT_UNREAD_ARTICLE;
  24310.  bp->exit_browse = TRUE;
  24311.  return TRUE;
  24312. }
  24313.  
  24314. /******* PREVU command ************************************************/
  24315.  
  24316. static Bool
  24317. process_prevu_command(np,bp,operands)
  24318. Rstruc nncb         *np;
  24319. Rstruc browser      *bp;
  24320. char                *operands;
  24321. {
  24322.  
  24323.  np->another_article = PREV_UNREAD_ARTICLE;
  24324.  bp->exit_browse = TRUE;
  24325.  return TRUE;
  24326. }
  24327.  
  24328. /******* NEXTT command ************************************************/
  24329.  
  24330. static Bool
  24331. process_nextt_command(np,bp,operands)
  24332. Rstruc nncb         *np;
  24333. Rstruc browser      *bp;
  24334. char                *operands;
  24335. {
  24336.  
  24337.  np->another_article = NEXT_TABLED_ARTICLE;
  24338.  bp->exit_browse = TRUE;
  24339.  return TRUE;
  24340. }
  24341.  
  24342. /******* PREVT command ************************************************/
  24343.  
  24344. static Bool
  24345. process_prevt_command(np,bp,operands)
  24346. Rstruc nncb         *np;
  24347. Rstruc browser      *bp;
  24348. char                *operands;
  24349. {
  24350.  
  24351.  np->another_article = PREV_TABLED_ARTICLE;
  24352.  bp->exit_browse = TRUE;
  24353.  return TRUE;
  24354. }
  24355.  
  24356. /******* NEXTSUBJ command *********************************************/
  24357.  
  24358. static Bool
  24359. process_nextsubj_command(np,bp,operands)
  24360. Rstruc nncb         *np;
  24361. Rstruc browser      *bp;
  24362. char                *operands;
  24363. {
  24364.  
  24365.  np->another_article = NEXT_THREAD_ARTICLE;
  24366.  bp->exit_browse = TRUE;
  24367.  return TRUE;
  24368. }
  24369.  
  24370. /******* PREVSUBJ command *********************************************/
  24371.  
  24372. static Bool
  24373. process_prevsubj_command(np,bp,operands)
  24374. Rstruc nncb         *np;
  24375. Rstruc browser      *bp;
  24376. char                *operands;
  24377. {
  24378.  
  24379.  np->another_article = PREV_THREAD_ARTICLE;
  24380.  bp->exit_browse = TRUE;
  24381.  return TRUE;
  24382. }
  24383.  
  24384. /******* FIRSTSUBJ command ********************************************/
  24385.  
  24386. static Bool
  24387. process_firstsubj_command(np,bp,operands)
  24388. Rstruc nncb         *np;
  24389. Rstruc browser      *bp;
  24390. char                *operands;
  24391. {
  24392.  
  24393.  np->another_article = FIRST_THREAD_ARTICLE;
  24394.  bp->exit_browse = TRUE;
  24395.  return TRUE;
  24396. }
  24397.  
  24398. /******* LASTSUBJ command *********************************************/
  24399.  
  24400. static Bool
  24401. process_lastsubj_command(np,bp,operands)
  24402. Rstruc nncb         *np;
  24403. Rstruc browser      *bp;
  24404. char                *operands;
  24405. {
  24406.  
  24407.  np->another_article = LAST_THREAD_ARTICLE;
  24408.  bp->exit_browse = TRUE;
  24409.  return TRUE;
  24410. }
  24411.  
  24412. /******* NEWSUBJ command **********************************************/
  24413.  
  24414. static Bool
  24415. process_newsubj_command(np,bp,operands)
  24416. Rstruc nncb         *np;
  24417. Rstruc browser      *bp;
  24418. char                *operands;
  24419. {
  24420.  
  24421.  np->another_article = NEW_THREAD_ARTICLE;
  24422.  bp->exit_browse = TRUE;
  24423.  return TRUE;
  24424. }
  24425.  
  24426. /******* SUBJECT command **********************************************/
  24427.  
  24428. static Bool
  24429. process_subject_command(np,bp,operands)
  24430. Rstruc nncb         *np;
  24431. Rstruc browser      *bp;
  24432. char                *operands;
  24433. {
  24434.  
  24435.  /* If anything remaining on the command line, make it the new    */
  24436.  /* subject, otherwise just display the current subject.          */
  24437.  
  24438.  if (*operands) {
  24439.    memset(np->selsubj,0,sizeof(np->selsubj));
  24440.    strncpy(np->selsubj,operands,sizeof(np->selsubj)-1);
  24441.  WARN1(
  24442.   "Subject changed.  All subject searches will use the new subject.");
  24443.  }
  24444.  else if (!*np->selsubj) {
  24445.    WARN1(
  24446.     "No current subject has been set by a subject-related command.");
  24447.  }
  24448.  else {
  24449.    WARN2("Current subject: %s", np->selsubj);
  24450.  }
  24451.  return TRUE;
  24452. }
  24453.  
  24454. /******* OPTIONS command **********************************************/
  24455.  
  24456. static Bool
  24457. process_options_command(np,bp,operands)
  24458. Rstruc nncb         *np;
  24459. Rstruc browser      *bp;
  24460. char                *operands;
  24461. {
  24462.  
  24463.  NNMdsopt(np,operands);         /* Do "set options" function */
  24464.  np->another_article = REDISPLAY_ARTICLE;
  24465.  bp->exit_browse = TRUE;
  24466.  return TRUE;
  24467. }
  24468.  
  24469. /******* HEADERS command **********************************************/
  24470.  
  24471. static Bool
  24472. process_headers_command(np,bp,operands)
  24473. Rstruc nncb         *np;
  24474. Rstruc browser      *bp;
  24475. char                *operands;
  24476. {
  24477.  
  24478.  NNMdsopt(np,"1");              /* Do "set options 1" function */
  24479.  np->another_article = REDISPLAY_ARTICLE;
  24480.  bp->exit_browse = TRUE;
  24481.  return TRUE;
  24482. }
  24483.  
  24484.  
  24485. /******* COLS command *************************************************/
  24486.  
  24487. static Bool
  24488. process_cols_command(np,bp,operands)
  24489. Rstruc nncb         *np;
  24490. Rstruc browser      *bp;
  24491. char                *operands;
  24492. {
  24493.  
  24494.  bp->cols = 1;
  24495.  *bp->cols_line = '\0';
  24496.  bp->reinit_browse = TRUE;
  24497.  return TRUE;
  24498. }
  24499.  
  24500. /******* RESET command ************************************************/
  24501.  
  24502. static Bool
  24503. process_reset_command(np,bp,operands)
  24504. Rstruc nncb         *np;
  24505. Rstruc browser      *bp;
  24506. char                *operands;
  24507. {
  24508.  
  24509.  bp->cols = 0;
  24510.  *bp->cols_line = '\0';
  24511.  bp->reinit_browse = TRUE;
  24512.  return TRUE;
  24513. }
  24514.  
  24515. /******* DISPLAY command **********************************************/
  24516.  
  24517. static Bool
  24518. process_display_command(np,bp,operands)
  24519. Rstruc nncb         *np;
  24520. Rstruc browser      *bp;
  24521. char                *operands;
  24522. {
  24523.  unsigned int        u;
  24524.  
  24525.  switch (strlen(operands)) {
  24526.    case 1: np->text_dispchar = operands[0];
  24527.            break;
  24528.    case 2: if (1 != sscanf(operands,"%x",&u)) {
  24529.              ERR1("Invalid hex character representation.");
  24530.              return FALSE;
  24531.            }
  24532.            np->text_dispchar = u;
  24533.            break;
  24534.    default:
  24535.            ERR1("A single character must be specified.");
  24536.            return FALSE;
  24537.  }
  24538.  bp->reinit_browse = TRUE;
  24539.  return TRUE;
  24540. }
  24541.  
  24542. /******* LOCATE command ***********************************************/
  24543.  
  24544. static Bool
  24545. process_locate_command(np,bp,operands)
  24546. Rstruc nncb         *np;
  24547. Rstruc browser      *bp;
  24548. char                *operands;
  24549. {
  24550.  int                 locnum;
  24551.  char                junk[72];
  24552.  
  24553.  if (1 != sscanf(operands, "%d %s", &locnum, junk)) {
  24554.    ERR1("The LOCATE command requires a line number.");
  24555.    return FALSE;
  24556.  }
  24557.  
  24558.  bp->top = locnum;
  24559.  bp->more_rows = 0;
  24560.  bp->override_scroll = TRUE;
  24561.  bp->reinit_browse = TRUE;
  24562.  return TRUE;
  24563. }
  24564.  
  24565. /***** Helper functions for FIND **************************************/
  24566.  
  24567. /*--------------------------------------------------------------------*
  24568.  * Get quoted FIND string.                                            *
  24569.  *--------------------------------------------------------------------*/
  24570.  
  24571. static char *
  24572. get_quoted_find_string(np,cp,qform)
  24573. Rstruc nncb         *np;
  24574. char                *cp;
  24575. char                *qform;
  24576. {
  24577.  char                quote     = *cp;
  24578.  char                termchar  = '\0';
  24579.  
  24580.  for (cp++;;cp++) {
  24581.    if (*cp == quote) {
  24582.      switch (*(cp+1)) {
  24583.        case '\0':
  24584.        case ' ':  termchar = '\0'; break;
  24585.        case 'c':
  24586.        case 'C':  termchar = 'C' ; break;
  24587.        case 't':
  24588.        case 'T':  termchar = 'T' ; break;
  24589.        case 'x':
  24590.        case 'X':  termchar = 'X' ; break;
  24591.        case 'p':
  24592.        case 'P':  termchar = 'P' ; break;
  24593.        default:   continue;
  24594.      }
  24595.      if (termchar) {
  24596.        switch (*(cp+2)) {
  24597.          case '\0':
  24598.          case ' ':  break;
  24599.          default:   continue;
  24600.        }
  24601.        if (*qform != FIND_QUOTED) {
  24602.          ERR1(
  24603.       "Invalid string; Do not surround a quoted string with letters.");
  24604.          *qform = FIND_BADFORM;
  24605.          return NULL;
  24606.        }
  24607.        else {
  24608.          switch (termchar) {
  24609.            case 'C': *qform = FIND_C; break;
  24610.            case 'T': *qform = FIND_T; break;
  24611.            case 'X': *qform = FIND_X; break;
  24612.            case 'P': *qform = FIND_P; break;
  24613.          }
  24614.          *cp = '\0'; /* kill the quote because it's the character */
  24615.          cp++;       /* that the caller will kill, not the quote  */
  24616.        }
  24617.      }
  24618.      break;
  24619.    }
  24620.    else if (!*cp) {
  24621.      ERR1(
  24622.      "Missing quote; The FIND command requires balanced quote marks.");
  24623.      *qform = FIND_BADFORM;
  24624.      return NULL;
  24625.    }
  24626.  }
  24627.  return cp;
  24628. }
  24629.  
  24630. /*--------------------------------------------------------------------*
  24631.  * Get FIND operand.                                                  *
  24632.  *--------------------------------------------------------------------*/
  24633.  
  24634. static char *
  24635. get_find_operand(np,opp,qform)
  24636. Rstruc nncb     *np;
  24637. char           **opp;
  24638. char            *qform;
  24639. {
  24640.  char           *cp    = *opp;
  24641.  char           *start = NULL;
  24642.  
  24643.  cp = skip_ISPF_whitespace(cp);
  24644.  
  24645.  if (!*cp) return NULL;
  24646.  if (*cp == '\'' || *cp == '"') {
  24647.    start = cp+1;
  24648.    *qform = FIND_QUOTED;
  24649.    if (!(cp = get_quoted_find_string(np,cp,qform))) return NULL;
  24650.  }
  24651.  else if ((*(cp+1) == '\'' || *(cp+1) == '"')) {
  24652.    switch (*cp) {
  24653.      case 'c':
  24654.      case 'C': *qform = FIND_C; break;
  24655.      case 't':
  24656.      case 'T': *qform = FIND_T; break;
  24657.      case 'x':
  24658.      case 'X': *qform = FIND_X; break;
  24659.      case 'p':
  24660.      case 'P': *qform = FIND_P; break;
  24661.      default:  *qform = FIND_UNQUOTED; break;
  24662.    }
  24663.    if (*qform != FIND_UNQUOTED) {
  24664.      cp++;
  24665.      start = cp+1;
  24666.      if (!(cp = get_quoted_find_string(np,cp,qform))) return NULL;
  24667.    }
  24668.    else {
  24669.      start = cp;
  24670.      find_ISPF_whitespace(cp,start);
  24671.    }
  24672.  }
  24673.  else {
  24674.    start = cp;
  24675.    *qform = FIND_UNQUOTED;
  24676.    find_ISPF_whitespace(cp,start);
  24677.  }
  24678.  if (*cp) {
  24679.    *cp  = '\0';
  24680.    *opp = cp+1;
  24681.  }
  24682.  else {
  24683.    *opp = cp;
  24684.  }
  24685.  return start;
  24686. }
  24687.  
  24688. /*--------------------------------------------------------------------*
  24689.  * Find it.                                                           *
  24690.  *--------------------------------------------------------------------*/
  24691.  
  24692. #define REND                 (r+(*tpp)->tab_expanded_text_length)
  24693. #define PRECEDED_BY_VERBIAGE (q>r && isalnum(*(q-1)))
  24694. #define FOLLOWED_BY_VERBIAGE (q+findlen<REND && isalnum(*(q+findlen)))
  24695.  
  24696. static Bool
  24697. find_it(np,bp,find_string,findlen,
  24698.                           find_type,find_what,find_trans,
  24699.                           find_left_bound,find_right_bound)
  24700. Rstruc nncb       *np;
  24701. Rstruc browser    *bp;
  24702. char              *find_string;
  24703. int                findlen;
  24704. char               find_type;      /* chars word prefix suffix */
  24705. char               find_what;      /* next prev first last all */
  24706. char               find_trans;     /* caps asis generic        */
  24707. int                find_left_bound;
  24708. int                find_right_bound;
  24709. {
  24710.  struct textline **tpp;
  24711.  char             *p;
  24712.  char             *q;
  24713.  char             *r;
  24714.  int               row;
  24715.  int               col;
  24716.  int               complen;
  24717.  int               lcol;
  24718.  int               rcol;
  24719.  int               ecol;
  24720.  Bool              backward_find;
  24721.  
  24722.  lcol = find_left_bound - 1;
  24723.  rcol = find_right_bound - 1;
  24724.  row  = bp->find_row;
  24725.  col  = bp->find_col;
  24726.  
  24727.  switch (find_what) {
  24728.    case FIND_NEXT:
  24729.                     if (bp->find_hit_end) {
  24730.                       bp->find_hit_end = FALSE;
  24731.                       row = 0;
  24732.                       col = lcol;
  24733.                     }
  24734.                     else if (EQUAL(bp->find_cursor,"NNBDYNA")) {
  24735.                       row = bp->top+((bp->find_csrpos-1)/80)-bp->cols-1;
  24736.                       col = (bp->find_csrpos-1) % 80 + bp->coloff;
  24737.                       if (++col >= bp->maxlen) {
  24738.                         row++;
  24739.                         col = lcol;
  24740.                       }
  24741.                     }
  24742.                     else {
  24743.                       row = bp->top - 1;
  24744.                       if (row < 0) row = 0;
  24745.                       col = lcol;
  24746.                     }
  24747.                     backward_find = FALSE;
  24748.                     break;
  24749.    case FIND_PREV:
  24750.                     if (bp->find_hit_end) {
  24751.                       bp->find_hit_end = FALSE;
  24752.                       row = bp->total - 1;
  24753.                       col = rcol;
  24754.                     }
  24755.                     else if (EQUAL(bp->find_cursor,"NNBDYNA")) {
  24756.                       row = bp->top+((bp->find_csrpos-1)/80)-bp->cols-1;
  24757.                       col = (bp->find_csrpos-1) % 80 + bp->coloff;
  24758.                       if (--col < 0) {
  24759.                         row--;
  24760.                         col = rcol;
  24761.                       }
  24762.                     }
  24763.                     else {
  24764.                       row = bp->total - 1;
  24765.                       col = rcol;
  24766.                     }
  24767.                     backward_find = TRUE;
  24768.                     break;
  24769.    case FIND_FIRST:
  24770.                     if (bp->find_hit_end) {
  24771.                       bp->find_hit_end = FALSE;
  24772.                     }
  24773.                     row = 0;
  24774.                     col = lcol;
  24775.                     backward_find = FALSE;
  24776.                     break;
  24777.    case FIND_LAST:
  24778.                     if (bp->find_hit_end) {
  24779.                       bp->find_hit_end = FALSE;
  24780.                     }
  24781.                     row = bp->total - 1;
  24782.                     col = rcol;
  24783.                     backward_find = TRUE;
  24784.                     break;
  24785.    case FIND_ALL:
  24786.                     col++;
  24787.                     backward_find = FALSE;
  24788.                     break;
  24789.  }
  24790.  
  24791.  if (backward_find == FALSE) {
  24792.    /* forward find */
  24793.    if (col < lcol) col = lcol;
  24794.    else if (col > rcol) {
  24795.      col = lcol;
  24796.      row++;
  24797.    }
  24798.    for (tpp = &bp->tv[row]; row < bp->total; tpp++, col=lcol, row++) {
  24799.      ecol = (*tpp)->tab_expanded_text_length - 1;
  24800.      if (ecol > rcol) ecol = rcol;
  24801.      if (col > ecol) continue;
  24802.      p = (*tpp)->tab_expanded_text;
  24803.      if (find_trans == FIND_CAPS) {
  24804.        copy_uppercase(bp->work,p);
  24805.        r = bp->work;
  24806.      }
  24807.      else r = p;
  24808.      complen = ecol-col+1;
  24809.      for (q = r + col;;q++) {
  24810.        q = memchr(q,find_string[0],complen);
  24811.        if (!q) break;
  24812.        col = q - r;
  24813.        complen = ecol-col+1;
  24814.        if (complen < findlen) break;
  24815.        if (!memcmp(q,find_string,findlen)) {
  24816.          switch (find_type) {
  24817.            case FIND_CHARS:  break;
  24818.            case FIND_WORD:
  24819.                 if (PRECEDED_BY_VERBIAGE || FOLLOWED_BY_VERBIAGE)
  24820.                     continue;
  24821.                 break;
  24822.            case FIND_PREFIX:
  24823.                 if (PRECEDED_BY_VERBIAGE || !FOLLOWED_BY_VERBIAGE)
  24824.                     continue;
  24825.                 break;
  24826.            case FIND_SUFFIX:
  24827.                 if (!PRECEDED_BY_VERBIAGE || FOLLOWED_BY_VERBIAGE)
  24828.                    continue;
  24829.                 break;
  24830.          }
  24831.          bp->find_row = row;
  24832.          bp->find_col = col;
  24833.          return TRUE;
  24834.        }
  24835.      }
  24836.    }
  24837.    bp->find_row = 0;
  24838.    bp->find_col = 0;
  24839.    bp->find_hit_end = TRUE;
  24840.    return FALSE;
  24841.  }
  24842.  else {
  24843.    /* backward find */
  24844.    if (row >= bp->total) row = bp->total - 1;
  24845.    if (col > rcol-findlen+1) col = rcol-findlen+1;
  24846.    else if (col < lcol) {
  24847.      col = rcol-findlen+1;
  24848.      row--;
  24849.    }
  24850.    for (tpp=&bp->tv[row]; row >= 0; tpp--, col=rcol-findlen+1, row--) {
  24851.      ecol = (*tpp)->tab_expanded_text_length - 1;
  24852.      if (ecol > rcol) ecol = rcol;
  24853.      if (col > ecol) col = ecol;
  24854.      p = (*tpp)->tab_expanded_text;
  24855.      if (find_trans == FIND_CAPS) {
  24856.        copy_uppercase(bp->work,p);
  24857.        r = bp->work;
  24858.      }
  24859.      else r = p;
  24860.      for (q = r + col; q >= r; q--) {
  24861.        if (!memcmp(q,find_string,findlen)) {
  24862.          switch (find_type) {
  24863.            case FIND_CHARS:  break;
  24864.            case FIND_WORD:
  24865.                 if (PRECEDED_BY_VERBIAGE || FOLLOWED_BY_VERBIAGE)
  24866.                     continue;
  24867.                 break;
  24868.            case FIND_PREFIX:
  24869.                 if (PRECEDED_BY_VERBIAGE || !FOLLOWED_BY_VERBIAGE)
  24870.                     continue;
  24871.                 break;
  24872.            case FIND_SUFFIX:
  24873.                 if (!PRECEDED_BY_VERBIAGE || FOLLOWED_BY_VERBIAGE)
  24874.                    continue;
  24875.                 break;
  24876.          }
  24877.          col = q - r;
  24878.          bp->find_row = row;
  24879.          bp->find_col = col;
  24880.          return TRUE;
  24881.        }
  24882.      }
  24883.    }
  24884.    bp->find_row = bp->total - 1;
  24885.    bp->find_col = bp->maxlen;
  24886.    bp->find_hit_end = TRUE;
  24887.    return FALSE;
  24888.  }
  24889.  
  24890. }
  24891.  
  24892. /********* FIND command ***********************************************/
  24893.  
  24894. static Bool
  24895. process_find_command(np,bp,operands)
  24896. Rstruc nncb         *np;
  24897. Rstruc browser      *bp;
  24898. char                *operands;
  24899. {
  24900.  char        *find_operand [64];
  24901.  char        *show_type;
  24902.  char        *cp;
  24903.  char        *opcopy;
  24904.  char        *op;
  24905.  char        *p;
  24906.  char        *q;
  24907.  char         find_qform   [64];
  24908.  Bool         finderror = FALSE;
  24909.  Bool         out_of_bounds = FALSE;
  24910.  int          find_operand_count;
  24911.  int          ox;
  24912.  int          find_left_bound;
  24913.  int          find_right_bound;
  24914.  int          n;
  24915.  int          len;
  24916.  int          findlen;
  24917.  char         find_what;      /* next prev first last all */
  24918.  char         find_type;      /* chars word prefix suffix */
  24919.  char         find_trans;     /* caps asis generic        */
  24920.  char         find_form;      /* unquoted quoted c x t p  */
  24921.  char         ff;             /* unquoted quoted c x t p  */
  24922.  Bool         hit_end                = FALSE;
  24923.  Bool         find_string_given      = FALSE;
  24924.  Bool         find_what_given        = FALSE;
  24925.  Bool         find_type_given        = FALSE;
  24926.  Bool         find_left_bound_given  = FALSE;
  24927.  Bool         find_right_bound_given = FALSE;
  24928.  char         operand_copy [81];
  24929.  char         find_string  [81];
  24930.  char         temp         [81];
  24931.  char         show_string [129];
  24932.  char         shortmsg    [129];
  24933.  char         longmsg     [129];
  24934.  
  24935.  strcpy(operand_copy,operands);
  24936.  
  24937.  find_operand_count = 0;
  24938.  for (ox = 0, opcopy = operand_copy; ox < 64; ox++) {
  24939.    ff = FIND_UNQUOTED;
  24940.    op = get_find_operand(np,&opcopy,&ff);
  24941.    if (ff == FIND_BADFORM) return FALSE;
  24942.    if (!op) break;
  24943.    find_operand[ox] = op;
  24944.    find_qform[ox] = ff;
  24945.    find_operand_count++;
  24946.  }
  24947.  
  24948.  if (find_operand_count == 0) {
  24949.    if (!*np->text_find_string) {
  24950.      ERR1("The first FIND command requires an operand.");
  24951.      return FALSE;
  24952.    }
  24953.    strcpy(find_string,np->text_find_string);
  24954.    find_what        = np->text_find_what;
  24955.    find_type        = np->text_find_type;
  24956.    find_trans       = np->text_find_trans;
  24957.    find_left_bound  = np->text_find_left_bound;
  24958.    find_right_bound = np->text_find_right_bound;
  24959.  }
  24960.  else {
  24961.    find_what        = FIND_NEXT;
  24962.    find_type        = FIND_CHARS;
  24963.    find_trans       = FIND_CAPS;
  24964.    find_left_bound  = 1;
  24965.    find_right_bound = bp->maxlen;
  24966.    for (ox = 0; ox < find_operand_count; ox++) {
  24967.      op = find_operand[ox];
  24968.      ff = find_qform[ox];
  24969.      if (ff != FIND_UNQUOTED) {
  24970.        if (find_string_given) finderror = TRUE;
  24971.        else {
  24972.          strcpy(find_string,op);
  24973.          find_form = ff;
  24974.          find_string_given = TRUE;
  24975.        }
  24976.      }
  24977.      else {
  24978.        copy_uppercase(temp,op);
  24979.        if (EQUAL(temp,"*")) {
  24980.          if (find_string_given) finderror = TRUE;
  24981.          else {
  24982.            strcpy(find_string,np->text_find_string);
  24983.            find_form = ff;
  24984.            find_string_given = TRUE;
  24985.          }
  24986.        }
  24987.        else if (find_operand_count == 1) {
  24988.          strcpy(find_string,op);
  24989.          find_form = ff;
  24990.          find_string_given = TRUE;
  24991.        }
  24992.        else if (EQUAL(temp,"NEXT")) {
  24993.          if (find_what_given) finderror = TRUE;
  24994.          else {
  24995.            find_what = FIND_NEXT;
  24996.            find_what_given = TRUE;
  24997.          }
  24998.        }
  24999.        else if (EQUAL(temp,"PREV")) {
  25000.          if (find_what_given) finderror = TRUE;
  25001.          else {
  25002.            find_what = FIND_PREV;
  25003.            find_what_given = TRUE;
  25004.          }
  25005.        }
  25006.        else if (EQUAL(temp,"FIRST")) {
  25007.          if (find_what_given) finderror = TRUE;
  25008.          else {
  25009.            find_what = FIND_FIRST;
  25010.            find_what_given = TRUE;
  25011.          }
  25012.        }
  25013.        else if (EQUAL(temp,"LAST")) {
  25014.          if (find_what_given) finderror = TRUE;
  25015.          else {
  25016.            find_what = FIND_LAST;
  25017.            find_what_given = TRUE;
  25018.          }
  25019.        }
  25020.        else if (EQUAL(temp,"ALL")) {
  25021.          if (find_what_given) finderror = TRUE;
  25022.          else {
  25023.            find_what = FIND_ALL;
  25024.            find_what_given = TRUE;
  25025.          }
  25026.        }
  25027.        else if (EQUAL(temp,"CHARS")) {
  25028.          if (find_type_given) finderror = TRUE;
  25029.          else {
  25030.            find_type = FIND_CHARS;
  25031.            find_type_given = TRUE;
  25032.          }
  25033.        }
  25034.        else if (EQUAL(temp,"WORD")) {
  25035.          if (find_type_given) finderror = TRUE;
  25036.          else {
  25037.            find_type = FIND_WORD;
  25038.            find_type_given = TRUE;
  25039.          }
  25040.        }
  25041.        else if (EQUAL(temp,"PREFIX") || EQUAL(temp,"PRE")) {
  25042.          if (find_type_given) finderror = TRUE;
  25043.          else {
  25044.            find_type = FIND_PREFIX;
  25045.            find_type_given = TRUE;
  25046.          }
  25047.        }
  25048.        else if (EQUAL(temp,"SUFFIX") || EQUAL(temp,"SUF")) {
  25049.          if (find_type_given) finderror = TRUE;
  25050.          else {
  25051.            find_type = FIND_SUFFIX;
  25052.            find_type_given = TRUE;
  25053.          }
  25054.        }
  25055.        else if (*(temp+strspn(temp,"0123456789")) == '\0') {
  25056.          if (find_left_bound_given) {
  25057.            if (find_right_bound_given) finderror = TRUE;
  25058.            else {
  25059.              find_right_bound = atoi(temp);
  25060.              if (find_right_bound > bp->maxlen) out_of_bounds = TRUE;
  25061.              find_right_bound_given = TRUE;
  25062.            }
  25063.          }
  25064.          else {
  25065.            find_left_bound  = atoi(temp);
  25066.              if (find_right_bound < 1) out_of_bounds = TRUE;
  25067.            find_left_bound_given = TRUE;
  25068.          }
  25069.        }
  25070.        else {
  25071.          if (find_string_given) finderror = TRUE;
  25072.          else {
  25073.            strcpy(find_string,op);
  25074.            find_form = ff;
  25075.            find_string_given = TRUE;
  25076.          }
  25077.        }
  25078.      }
  25079.    }
  25080.  }
  25081.  
  25082.  if (out_of_bounds) {
  25083.    ERR2("Invalid bound; Bounds must lie between 1 and %d", bp->maxlen);
  25084.    return FALSE;
  25085.  }
  25086.  
  25087.  if (finderror) {
  25088.    ERR1("Put string in quotes; Conflicting or unknown parameter.");
  25089.    return FALSE;
  25090.  }
  25091.  
  25092.  len = strlen(find_string);
  25093.  
  25094.  if (find_string_given) bp->find_hit_end = FALSE;
  25095.  
  25096.  if (find_left_bound_given && find_right_bound_given
  25097.      && find_left_bound > find_right_bound) {
  25098.    n = find_left_bound;
  25099.    find_left_bound = find_right_bound;
  25100.    find_right_bound = n;
  25101.  }
  25102.  else if (find_left_bound_given && !find_right_bound_given) {
  25103.    find_right_bound = find_left_bound + len - 1;
  25104.  }
  25105.  
  25106.  if (find_string_given) {
  25107.    switch (find_form) {
  25108.      case FIND_UNQUOTED:  find_trans = FIND_CAPS;    break;
  25109.      case FIND_QUOTED:    find_trans = FIND_CAPS;    break;
  25110.      case FIND_C:         find_trans = FIND_ASIS;    break;
  25111.      case FIND_T:         find_trans = FIND_CAPS;    break;
  25112.      case FIND_P:         find_trans = FIND_GENERIC; break;
  25113.      case FIND_X:         find_trans = FIND_HEX;
  25114.         if (len % 2 != 0) {
  25115.           ERR1("Odd number of characters in hex string.");
  25116.           return FALSE;
  25117.         }
  25118.         if (len != strspn(find_string,"0123456789abcdefABCDEF")) {
  25119.           ERR1("Invalid (non-hex) characters in hex string.");
  25120.           return FALSE;
  25121.         }
  25122.         for (p = find_string, q = find_string; *p; p += 2, *q++) {
  25123.           sprintf(temp,"0x%2.2s",p);
  25124.           sscanf(temp,"%x",&n);
  25125.           *q = (char)n;
  25126.         }
  25127.         *q = '\0';
  25128.         len = strlen(find_string);
  25129.         break;
  25130.    }
  25131.  }
  25132.  
  25133.  /* Store parameters for next Repeat Find operation. */
  25134.  
  25135.  strcpy(np->text_find_string,find_string);
  25136.  switch (find_what) {
  25137.    case FIND_PREV:
  25138.    case FIND_LAST:  np->text_find_what = FIND_PREV; break;
  25139.    default:         np->text_find_what = FIND_NEXT; break;
  25140.  }
  25141.  np->text_find_type        = find_type;
  25142.  np->text_find_trans       = find_trans;
  25143.  np->text_find_left_bound  = find_left_bound;
  25144.  np->text_find_right_bound = find_right_bound;
  25145.  
  25146.  if (!*find_string) {
  25147.    ERR1("A null string is not allowed for the FIND command.");
  25148.    return FALSE;
  25149.  }
  25150.  
  25151.  if (bp->total == 0) {
  25152.    ERR1("There is no text to search.");
  25153.    return FALSE;
  25154.  }
  25155.  
  25156.  strcpy(bp->zcmd,"");
  25157.  
  25158.  switch (find_type) {
  25159.    case FIND_CHARS:   show_type = "Chars";  break;
  25160.    case FIND_WORD:    show_type = "Word";   break;
  25161.    case FIND_PREFIX:  show_type = "Prefix"; break;
  25162.    case FIND_SUFFIX:  show_type = "Suffix"; break;
  25163.    default:           show_type = "Text";   break;
  25164.  }
  25165.  
  25166.  switch (find_trans) {
  25167.    case FIND_ASIS:    strcpy(show_string+0,"C'");
  25168.                       strcpy(show_string+2,find_string);
  25169.                       strcat(show_string,"'");
  25170.                       break;
  25171.    case FIND_GENERIC: strcpy(show_string+0,"P'");
  25172.                       strcpy(show_string+2,find_string);
  25173.                       strcat(show_string,"'");
  25174.                       break;
  25175.    case FIND_HEX:     strcpy(show_string+0,"X'");
  25176.                       for (p=find_string,q=show_string+2;*p;p++,q+=2) {
  25177.                         sprintf(q,"%2.2X",*p);
  25178.                       }
  25179.                       strcat(show_string,"'");
  25180.                       break;
  25181.    case FIND_CAPS:
  25182.    default:           strcpy(show_string+0,"'");
  25183.                       strcpy(show_string+1,find_string);
  25184.                       strcat(show_string,"'");
  25185.                       break;
  25186.  }
  25187.  
  25188.  switch (find_trans) {
  25189.    case FIND_CAPS:
  25190.         uppercase_in_place(find_string);
  25191.         break;
  25192.    case FIND_GENERIC:
  25193.         ERR1("The P'string' generic format is not supported.");
  25194.         return FALSE;
  25195.  }
  25196.  
  25197.  hit_end = bp->find_hit_end;
  25198.  findlen = strlen(find_string);
  25199.  
  25200.  if (find_what == FIND_ALL) {
  25201.    bp->find_count = 0;
  25202.    if (!find_it(np,bp,find_string,findlen,
  25203.                                   find_type,FIND_FIRST,find_trans,
  25204.                                   find_left_bound, find_right_bound)) {
  25205.      sprintf(shortmsg,"No %s %s found",show_type,show_string);
  25206.      sprintf(longmsg,
  25207.              "%s %s - not found within columns %d to %d",
  25208.              show_type,show_string,find_left_bound,find_right_bound);
  25209.      ERR3("%24s;%s",shortmsg,longmsg);
  25210.      return FALSE;
  25211.    }
  25212.    bp->found_row = bp->find_row;
  25213.    bp->found_col = bp->find_col;
  25214.    bp->find_count = 1;
  25215.    while (find_it(np,bp,find_string,findlen,
  25216.                         find_type,FIND_ALL,find_trans,
  25217.                         find_left_bound, find_right_bound)) {
  25218.          bp->find_count++;
  25219.    }
  25220.    bp->find_hit_end = FALSE;
  25221.  }
  25222.  else {
  25223.    if (!find_it(np,bp,find_string,findlen,
  25224.                                   find_type,find_what,find_trans,
  25225.                                   find_left_bound, find_right_bound)) {
  25226.      if (hit_end) {
  25227.        sprintf(shortmsg,"No %s %s found",show_type,show_string);
  25228.        sprintf(longmsg,
  25229.                "%s %s - not found within columns %d to %d",
  25230.                show_type,show_string,find_left_bound,find_right_bound);
  25231.        ERR3("%24s;%s",shortmsg,longmsg);
  25232.        return FALSE;
  25233.      }
  25234.      else if (np->text_find_what == FIND_PREV) {
  25235.        sprintf(shortmsg,"Top of data reached");
  25236.        sprintf(longmsg,
  25237.             "%s %s not found.  Use RFIND to continue from bottom.",
  25238.              show_type, show_string);
  25239.        ERR3("%24s;%s",shortmsg,longmsg);
  25240.      }
  25241.      else {
  25242.        sprintf(shortmsg,"Bottom of data reached");
  25243.        sprintf(longmsg,
  25244.                "%s %s not found.  Use RFIND to continue from top.",
  25245.              show_type, show_string);
  25246.        ERR3("%24s;%s",shortmsg,longmsg);
  25247.      }
  25248.      return FALSE;
  25249.    }
  25250.    bp->found_row = bp->find_row;
  25251.    bp->found_col = bp->find_col;
  25252.  }
  25253.  
  25254.  if (bp->found_row + 1 < bp->top
  25255.   || bp->found_row + 1 >= bp->top + bp->lvl - bp->cols) {
  25256.    bp->top = bp->found_row + 1 - 1;
  25257.    if (bp->top < 0) bp->top = 0;
  25258.  }
  25259.  
  25260.  if (bp->found_col < bp->coloff) {
  25261.    bp->coloff = bp->found_col;
  25262.    *bp->cols_line = '\0';
  25263.  }
  25264.  else if (bp->found_col+len > bp->coloff+80) {
  25265.    bp->coloff = bp->found_col + len - 80;
  25266.    if (bp->coloff < 0) bp->coloff = 0;
  25267.    *bp->cols_line = '\0';
  25268.  }
  25269.  
  25270.  strcpy(bp->cursor, "NNBDYNA");
  25271.  bp->csrpos = 80 * (bp->found_row - bp->top+bp->cols + 1)
  25272.               + bp->found_col - bp->coloff + 1;
  25273.  
  25274.  bp->found_left = bp->csrpos;
  25275.  bp->found_right = bp->found_left + len;
  25276.  bp->reinit_browse = TRUE;
  25277.  
  25278.  if (find_what == FIND_ALL) {
  25279.    sprintf(shortmsg,"%d %s %s",bp->find_count,show_type,show_string);
  25280.    sprintf(longmsg,
  25281.            "%s %s found %d times within columns %d to %d",
  25282.            show_type,show_string,bp->find_count,
  25283.            find_left_bound,find_right_bound);
  25284.    WARN3("%24s;%s",shortmsg,longmsg);
  25285.  }
  25286.  else {
  25287.    sprintf(shortmsg,"%s %s found",show_type,show_string);
  25288.    sprintf(longmsg,
  25289.            "Search for %s %s within columns %d to %d was successful",
  25290.            show_type,show_string, find_left_bound,find_right_bound);
  25291.    WARN3("%24s;%s",shortmsg,longmsg);
  25292.  }
  25293.  
  25294.  bp->find_row = bp->found_row;
  25295.  bp->find_col = bp->found_col;
  25296.  return TRUE;
  25297. }
  25298.  
  25299. /************ Fill browse dynamic area. *******************************/
  25300.  
  25301. static void
  25302. fill_browse_dynamic_area(np,bp)
  25303. Rstruc nncb        *np;
  25304. Rstruc browser     *bp;
  25305. {
  25306.  struct textline  **tpp  = NULL;
  25307.  register char     *cp   = NULL;
  25308.  register char     *p;
  25309.  char              *q;
  25310.  char              *r;
  25311.  int                i;
  25312.  int                j;
  25313.  char               temp[12];
  25314.  
  25315.  static char  top_of_data_line[81] = "\
  25316. ********************************* Top of data \
  25317. **********************************";
  25318.  
  25319.  static char  bottom_of_data_line[81] = "\
  25320. ******************************** Bottom of data \
  25321. ********************************";
  25322.  
  25323.  bp->lastpos = bp->bda + bp->size;
  25324.  bp->total = bp->thp->text_line_count;
  25325.  
  25326.  memset(bp->bda,' ',bp->size);
  25327.  
  25328.  if      (bp->more_rows == -MAX_INT)
  25329.          bp->top = 0;
  25330.  else if (bp->more_rows == MAX_INT)
  25331.          bp->top = bp->total + 2 - bp->lvl + bp->cols;
  25332.  else    bp->top += bp->more_rows;
  25333.  
  25334.  if (bp->top < 0) bp->top = 0;
  25335.  if (bp->top > bp->total) bp->top = bp->total + 1;
  25336.  
  25337.  i  = bp->top;
  25338.  p  = bp->bda;
  25339.  
  25340.  if (bp->cols > 0) {
  25341.    if (!*bp->cols_line) {
  25342.      for (j=bp->coloff+1,r=bp->cols_line; j<=bp->coloff+80; j++,r++) {
  25343.        if (j%10 == 0) {
  25344.          sprintf(temp,"%d",j%100);
  25345.          *r = temp[0];
  25346.        }
  25347.        else if (j%5 == 0) *r = '+';
  25348.        else *r = '-';
  25349.      }
  25350.    }
  25351.    memcpy(p,bp->cols_line,80);
  25352.    p += 80;
  25353.  }
  25354.  
  25355.  if (i == 0) {
  25356.    memcpy(p,top_of_data_line,80);
  25357.    p += 80;
  25358.    i++;
  25359.  }
  25360.  
  25361.  bp->firstpos = p;
  25362.  
  25363.  for (tpp=&bp->tv[i-1];i<=bp->total && p<bp->lastpos;i++,tpp++,p+=80) {
  25364.    if ((*tpp)->tab_expanded_text_length > bp->coloff) {
  25365.      cp = (*tpp)->tab_expanded_text + bp->coloff;
  25366.      for (j = 0, q = p; *cp && j < 80; j++, q++, cp++) {
  25367.        if (*cp > 0xf9 || *cp < 0x40) *q = np->text_dispchar;
  25368.        else *q = *cp;
  25369.      }
  25370.    }
  25371.  }
  25372.  
  25373.  if (p < bp->lastpos) {
  25374.    memcpy(p,bottom_of_data_line,80);
  25375.  }
  25376.  
  25377.  return;
  25378. }
  25379.  
  25380. /************ Highlight browse text. **********************************/
  25381.  
  25382. static void
  25383. highlight_browse_text(np,bp)
  25384. Rstruc nncb        *np;
  25385. Rstruc browser     *bp;
  25386. {
  25387.  char              *p;
  25388.  
  25389.  bp->highlighted = FALSE;
  25390.  
  25391.  if (bp->found_left) {
  25392.    if (EQUAL(bp->cursor,"NNBDYNA")) {
  25393.      for (p = bp->bda + bp->found_left - 1; p >= bp->firstpos; p--) {
  25394.        if (*p == ' ') {
  25395.          *p = DATAOUT_HIGH;
  25396.          bp->highlighted = TRUE;
  25397.          break;
  25398.        }
  25399.      }
  25400.      for (p = bp->bda + bp->found_right - 1; p <= bp->lastpos; p++) {
  25401.       if (*p == ' ') {
  25402.         *p = DATAOUT_LOW;
  25403.          bp->highlighted = TRUE;
  25404.          break;
  25405.        }
  25406.      }
  25407.    }
  25408.  }
  25409.  
  25410.  bp->found_left = 0;
  25411.  bp->found_right = 0;
  25412.  
  25413.  return;
  25414. }
  25415.  
  25416. /************ Display browse data. ************************************/
  25417.  
  25418. static void
  25419. display_browse_data(np,bp,tdp)
  25420. Rstruc nncb        *np;
  25421. Rstruc browser     *bp;
  25422. Rstruc tabledesc   *tdp;
  25423. {
  25424.  Rstruc cmddesc    *cdp;
  25425.  char              *cp;
  25426.  char              *operands;
  25427.  int                displayrc;
  25428.  int                zscrolln;
  25429.  int                leftcol;
  25430.  int                rightcol;
  25431.  int                command_index;
  25432.  Bool               command_processed_ok;
  25433.  Bool               is_max;
  25434.  Bool               is_scroll_word;
  25435.  Bool               is_scroll_cursor;
  25436.  SCROLL             scroll_amount;
  25437.  char               command    [COMMANDSIZE+1];
  25438.  char               zverb      [16];
  25439.  char               zscrolla   [16];
  25440.  char               longmsg    [73];
  25441.  char               nnbtitle   [81];
  25442.  char               nnbmsg     [81];
  25443.  char               temp1      [81];
  25444.  char               temp2      [81];
  25445.  
  25446.  bp->more_rows = 0;
  25447.  bp->override_scroll = FALSE;
  25448.  bp->exit_browse     = FALSE;
  25449.  
  25450.  memset (nnbtitle, '-', 80);
  25451.  strcpy (nnbtitle, "Browse - ");
  25452.  memcpy (nnbtitle + 9, bp->title, strlen(bp->title));
  25453.  
  25454.  if (!np->setmsg) {
  25455.    leftcol = bp->coloff + 1;
  25456.    rightcol = bp->coloff + 80;
  25457.    if (bp->top > bp->total) strcpy(temp1,"");
  25458.    else sprintf(temp1, " Line %d of %d,", bp->top, bp->total);
  25459.    if (bp->maxlen <= 80)
  25460.         sprintf(temp2," Cols %d-%d",leftcol,rightcol);
  25461.    else sprintf(temp2," Cols %d-%d of %d",leftcol,rightcol,bp->maxlen);
  25462.    strcpy(nnbmsg,temp1);
  25463.    strcat(nnbmsg,temp2);
  25464.    strcpy (nnbtitle + 79 - strlen(nnbmsg), nnbmsg);
  25465.  }
  25466.  
  25467.  (void)NNMivput(np,"NNBTITLE ",nnbtitle    ,-1);
  25468.  (void)NNMivput(np,"ZCMD "    ,bp->zcmd    ,-1);
  25469.  (void)NNMivput(np,"NNBDYNA " ,bp->bda     ,bp->size);
  25470.  (void)NNMivput(np,"NNBCUR "  ,bp->cursor  ,-1);
  25471.  sprintf(temp1,"%d",bp->csrpos);
  25472.  (void)NNMivput(np,"NNBPOS  " ,temp1       ,-1);
  25473.  (void)NNMivput(np,"YRFIND "  ,"ALIAS FIND",-1);
  25474.  
  25475.  displayrc = NNMdispl(np,"NNMVIEW ");
  25476.  
  25477.  if (displayrc > 0) bp->exit_browse = TRUE;
  25478.  
  25479.  (void)NNMivput(np,"YRFIND "  ,"",-1);
  25480.  (void)NNMivget(np,"NNBCUR  " ,bp->cursor  , 8);
  25481.  (void)NNMivget(np,"ZCMD    " ,bp->zcmd     ,sizeof(bp->zcmd));
  25482.  bp->lvl    = NNMiget(np,"NNBLVL  ");
  25483.  bp->csrpos = NNMiget(np,"NNBPOS  ");
  25484.  
  25485.  strip_trailing_in_place(bp->cursor); /* try to fix UCLA find bug */
  25486.  
  25487.  strcpy(bp->find_cursor, bp->cursor);
  25488.  bp->find_csrpos = bp->csrpos;
  25489.  strcpy(bp->cursor,"");
  25490.  bp->csrpos = 1;
  25491.  if (bp->highlighted) bp->reinit_browse = TRUE;
  25492.  else                 bp->reinit_browse = FALSE;
  25493.  
  25494.  if (*bp->zcmd) {
  25495.  
  25496.    memset(command,' ',COMMANDSIZE);
  25497.    command_index = 0;
  25498.    for (cp = bp->zcmd; *cp && !isspace(*cp); cp++) {
  25499.      if (cp >= bp->zcmd+COMMANDSIZE) {
  25500.        ERR1("Unknown command name.");
  25501.        command_processed_ok = FALSE;
  25502.      }
  25503.      command[command_index++] = toupper(*cp);
  25504.    }
  25505.    while (*cp && isspace(*cp)) cp++;
  25506.  
  25507.    for (cdp=tdp->first_cmddesc; *cdp->command_name != ' '; cdp++) {
  25508.      if (!memcmp(command,cdp->command_name,COMMANDSIZE-1)) {
  25509.        command_processed_ok = (cdp->command_processor)(np,bp,cp);
  25510.        cdp = NULL;
  25511.        break;
  25512.      }
  25513.      #define LASTAPCMD "OPT "
  25514.      #define LASTAPLEN 4
  25515.      else if (!bp->ap
  25516.            && !memcmp(cdp->command_name,LASTAPCMD,LASTAPLEN))
  25517.               break;
  25518.    }
  25519.    if (cdp) {
  25520.      for (cdp=tdp->next_cmddesc; *cdp->command_name != ' '; cdp++) {
  25521.        if (!memcmp(command,cdp->command_name,COMMANDSIZE-1)) {
  25522.          command_processed_ok = (cdp->command_processor)(np,bp,cp);
  25523.          cdp = NULL;
  25524.          break;
  25525.        }
  25526.      }
  25527.    }
  25528.    if (cdp) {
  25529.      ERR1("Unknown command name.");
  25530.      command_processed_ok = FALSE;
  25531.    }
  25532.  
  25533.    if (command_processed_ok) strcpy(bp->zcmd,"");
  25534.  
  25535.  }
  25536.  
  25537.  if (np->quit || bp->exit_browse) return;
  25538.  
  25539.  /* Check scroll request (ZSCROLLA direction, ZSCROLLN number).
  25540.   * Skip this if something was done by a command which causes
  25541.   * its own pseudo-scrolling to happen (like LOCATE).
  25542.   */
  25543.  
  25544.  if (!bp->override_scroll) {
  25545.  
  25546.    zscrolln = 0;
  25547.  
  25548.    (void)NNMivget(np,"ZVERB    " ,  zverb    ,sizeof(zverb));
  25549.    (void)NNMivget(np,"ZSCROLLA " ,  zscrolla ,sizeof(zscrolla));
  25550.    zscrolln = NNMiget(np,"ZSCROLLN ");
  25551.  
  25552.    is_max = FALSE;
  25553.    is_scroll_word = FALSE;
  25554.    is_scroll_cursor = FALSE;
  25555.  
  25556.    switch (zscrolla[0]) {
  25557.      case 'P':
  25558.      case 'H':
  25559.      case 'D':  is_scroll_word = TRUE;
  25560.                 break;
  25561.      case 'C':  is_scroll_word = TRUE;
  25562.                 is_scroll_cursor = TRUE;
  25563.                 break;
  25564.      case 'M':  is_max = TRUE;
  25565.                 break;
  25566.    }
  25567.  
  25568.    if      (EQUAL(zverb,"DOWN"))  scroll_amount = DOWN;
  25569.    else if (EQUAL(zverb,"UP"))    scroll_amount = UP;
  25570.    else if (EQUAL(zverb,"LEFT"))  scroll_amount = LEFT;
  25571.    else if (EQUAL(zverb,"RIGHT")) scroll_amount = RIGHT;
  25572.    else                           scroll_amount = NO_SCROLL;
  25573.  
  25574.  
  25575.    switch (scroll_amount) {
  25576.      case NO_SCROLL:
  25577.           bp->more_rows = 0;
  25578.           break;
  25579.      case DOWN:
  25580.           if (is_max) bp->more_rows = MAX_INT;
  25581.           else if (is_scroll_word)
  25582.                       bp->more_rows = zscrolln - bp->cols;
  25583.           else        bp->more_rows = zscrolln;
  25584.           bp->reinit_browse = TRUE;
  25585.           break;
  25586.      case UP:
  25587.           if (is_max) bp->more_rows = -MAX_INT;
  25588.           else if (is_scroll_cursor)
  25589.                       bp->more_rows = -zscrolln;
  25590.           else if (is_scroll_word)
  25591.                       bp->more_rows = -zscrolln - bp->cols;
  25592.           else        bp->more_rows = -zscrolln;
  25593.           bp->reinit_browse = TRUE;
  25594.           break;
  25595.      case LEFT:
  25596.           if (is_max) bp->coloff = 0;
  25597.           else        bp->coloff -= zscrolln;
  25598.           if (bp->coloff < 0) bp->coloff = 0;
  25599.           *bp->cols_line = '\0';
  25600.           bp->more_rows = 0;
  25601.           bp->reinit_browse = TRUE;
  25602.           break;
  25603.      case RIGHT:
  25604.           if (is_max) bp->coloff = bp->maxcoloff;
  25605.           else        bp->coloff += zscrolln;
  25606.           if (bp->coloff > bp->maxcoloff) bp->coloff = bp->maxcoloff;
  25607.           *bp->cols_line = '\0';
  25608.           bp->more_rows = 0;
  25609.           bp->reinit_browse = TRUE;
  25610.           break;
  25611.    }
  25612.  }
  25613.  
  25614.  return;
  25615. }
  25616.  
  25617. /*---*/
  25618.  
  25619. static struct cmddesc browse_commands[] = {
  25620.                           {"L          ",process_locate_command   },
  25621.                           {"LOC        ",process_locate_command   },
  25622.                           {"LOCATE     ",process_locate_command   },
  25623.                           {"F          ",process_find_command     },
  25624.                           {"FIND       ",process_find_command     },
  25625.                           {"RFIND      ",process_find_command     },
  25626.                           {"YRFIND     ",process_find_command     },
  25627.                           {"COL        ",process_cols_command     },
  25628.                           {"COLS       ",process_cols_command     },
  25629.                           {"RES        ",process_reset_command    },
  25630.                           {"RESET      ",process_reset_command    },
  25631.                           {"NOCOL      ",process_reset_command    },
  25632.                           {"NOCOLS     ",process_reset_command    },
  25633.                           {"DISP       ",process_display_command  },
  25634.                           {"DISPL      ",process_display_command  },
  25635.                           {"DISPLAY    ",process_display_command  },
  25636.                           {"EXT        ",process_extract_command  },
  25637.                           {"EXTR       ",process_extract_command  },
  25638.                           {"EXTRACT    ",process_extract_command  },
  25639.                           {"PRT        ",process_print_command    },
  25640.                           {"PRNT       ",process_print_command    },
  25641.                           {"PRINT      ",process_print_command    },
  25642.                           {"ROT13      ",process_rot13_command    },
  25643.  /* overrides general */  {"OPTIONS    ",process_options_command  },
  25644.  /* overrides general */  {"OPT        ",process_options_command  },
  25645.  /* overrides general */  {"HEADERS    ",process_headers_command  },
  25646.  /* overrides general */  {"HEADER     ",process_headers_command  },
  25647.                           {"UNREAD     ",process_unread_command   },
  25648.                           {"REPLY      ",process_reply_command    },
  25649.                           {"FOLLOWUP   ",process_followup_command },
  25650.                           {"NEXT       ",process_next_command     },
  25651.                           {"PREV       ",process_prev_command     },
  25652.                           {"NEXTU      ",process_nextu_command    },
  25653.                           {"NU         ",process_nextu_command    },
  25654.                           {"PREVU      ",process_prevu_command    },
  25655.                           {"PU         ",process_prevu_command    },
  25656.                           {"NEXTT      ",process_nextt_command    },
  25657.                           {"NT         ",process_nextt_command    },
  25658.                           {"PREVT      ",process_prevt_command    },
  25659.                           {"PT         ",process_prevt_command    },
  25660.                           {"NEXTS      ",process_nextsubj_command },
  25661.                           {"NEXTSUBJ   ",process_nextsubj_command },
  25662.                           {"NS         ",process_nextsubj_command },
  25663.                           {"PREVS      ",process_prevsubj_command },
  25664.                           {"PREVSUBJ   ",process_prevsubj_command },
  25665.                           {"PS         ",process_prevsubj_command },
  25666.                           {"FIRSTS     ",process_firstsubj_command},
  25667.                           {"FIRSTSUBJ  ",process_firstsubj_command},
  25668.                           {"FS         ",process_firstsubj_command},
  25669.                           {"LASTS      ",process_lastsubj_command },
  25670.                           {"LASTSUBJ   ",process_lastsubj_command },
  25671.                           {"LS         ",process_lastsubj_command },
  25672.                           {"NEWSUBJ    ",process_newsubj_command  },
  25673.                           {"SUBJECT    ",process_subject_command  },
  25674.                           {"SUBJ       ",process_subject_command  },
  25675.                           {"           ",NULL}
  25676.                          };
  25677.  
  25678.  
  25679. /****** View text in full screen mode (BROWSE replacement) ***********/
  25680.  
  25681. void
  25682. NNMview(np,gp,ap,texthdrp,title)
  25683. Rstruc nncb         *np;
  25684. Rstruc newsgroup    *gp;
  25685. Rstruc newsarticle  *ap;
  25686. struct texthdr      *texthdrp;
  25687. char                *title;
  25688. {
  25689.  Rstruc tabledesc   *tdp;
  25690.  struct textline    *tp;
  25691.  struct textline   **tv;
  25692.  struct textline   **textvector;
  25693.  struct browser     *bp;
  25694.  struct browser      browserstruct;
  25695.  
  25696.  GETMAIN(textvector, struct textline *,
  25697.          texthdrp->text_line_count, "text vector");
  25698.  if (!textvector) {
  25699.    ERR1("Not enough memory to display text.");
  25700.    return;
  25701.  }
  25702.  
  25703.  bp = &browserstruct;
  25704.  memset(bp,0,sizeof(struct browser));
  25705.  bp->gp = gp;
  25706.  bp->ap = ap;
  25707.  bp->thp = texthdrp;
  25708.  bp->tv = textvector;
  25709.  strcpy(bp->title,title);
  25710.  bp->more_rows = -MAX_INT;   /* set initial request to scroll up max */
  25711.  bp->top       = 0;
  25712.  bp->find_row  = -1;
  25713.  bp->find_col  = -1;
  25714.  bp->csrpos    = 1;
  25715.  strcpy(bp->cursor,"");
  25716.  bp->reinit_browse = TRUE;
  25717.  
  25718.  /* Collect text line pointers, skipping suppressed lines. */
  25719.  
  25720.  bp->maxlen = 0;
  25721.  for (tp=texthdrp->first_text_line, tv=textvector; tp; tp=tp->next) {
  25722.    if (tp->text_length >= 0) {
  25723.      *(tv++) = tp;
  25724.      if (bp->maxlen < tp->tab_expanded_text_length)
  25725.          bp->maxlen = tp->tab_expanded_text_length;
  25726.    }
  25727.  }
  25728.  bp->maxcoloff = bp->maxlen - 80;
  25729.  if (bp->maxcoloff < 0) bp->maxcoloff = 0;
  25730.  
  25731.  GETMAIN(bp->work, char *, bp->maxlen+1, "browse work string");
  25732.  if (!bp->work) return;
  25733.  
  25734.  (void)NNMispf(np,
  25735.          "PQUERY PANEL(NNMVIEW) AREANAME(NNBDYNA) DEPTH(NNBDEPTH)");
  25736.  if (np->ispfrc != 0) return;
  25737.  bp->depth = NNMiget(np,"NNBDEPTH ");
  25738.  bp->size = bp->depth * 80;
  25739.  GETMAIN(bp->bda, char *, bp->size+1, "browse dynamic area");
  25740.  if (!bp->bda) return;
  25741.  
  25742.  if (!np->text_dispchar) np->text_dispchar = '.';
  25743.  
  25744.  tdp = np->display_table_vector->text_display_table;
  25745.  tdp->first_cmddesc = browse_commands;
  25746.  
  25747.  for (;;) {
  25748.    if (bp->reinit_browse) {
  25749.      fill_browse_dynamic_area(np,bp);
  25750.      highlight_browse_text(np,bp);
  25751.    }
  25752.    display_browse_data(np,bp,tdp);
  25753.    if (np->quit || bp->exit_browse) break;
  25754.  }
  25755.  
  25756.  FREEMAIN(bp->work,"browse work string");
  25757.  FREEMAIN(bp->bda,"browse dynamic area");
  25758.  FREEMAIN(textvector, "text vector");
  25759.  
  25760.  return;
  25761. }
  25762.  
  25763. ./ ADD NAME=NNMVNG
  25764.  
  25765.  /********************************************************************/
  25766.  /*                                                                  */
  25767.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  25768.  /*                                                                  */
  25769.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  25770.  /*                                                                  */
  25771.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  25772.  /* including the implied warranties of merchantability and fitness, */
  25773.  /* are expressly denied.                                            */
  25774.  /*                                                                  */
  25775.  /* Provided this copyright notice is included, this software may    */
  25776.  /* be freely distributed and not offered for sale.                  */
  25777.  /*                                                                  */
  25778.  /* Changes or modifications may be made and used only by the maker  */
  25779.  /* of same, and not further distributed.  Such modifications should */
  25780.  /* be mailed to the author for consideration for addition to the    */
  25781.  /* software and incorporation in subsequent releases.               */
  25782.  /*                                                                  */
  25783.  /********************************************************************/
  25784.  
  25785. #pragma  csect(code,  "NN@VNG  ")
  25786. #pragma  csect(static,"NN$VNG  ")
  25787. #include "nn.h"
  25788.  
  25789. struct ngdynarray {
  25790.                    struct newsgroup      *newsgroup;
  25791.                   };
  25792.  
  25793. /****** Display newsgroups via ISPF dynamic area. ********************/
  25794.  
  25795. Bool
  25796. NNMvng(np)
  25797. Rstruc nncb           *np;
  25798. {
  25799.  Rstruc newsgroup     *gp;
  25800.  Rstruc ngdynarray    *ndp;
  25801.  struct ngdynarray    *ngdynarray_address;
  25802.  Rstruc tabledesc     *tdp;
  25803.  Rstruc seldesc       *sdp;
  25804.  Rstruc cmddesc       *cdp;
  25805.  char                 *cp;
  25806.  int                   next_offset;
  25807.  int                   command_index;
  25808.  int                   newsgroup_count;
  25809.  int                   display_total;
  25810.  int                   dti;
  25811.  int                   ngi;
  25812.  int                   prc;
  25813.  int                   nnglvl;
  25814.  int                   depth;
  25815.  int                   topgroup;
  25816.  int                   bottomgroup;
  25817.  int                   save_topgroup;
  25818.  int                   last_group_located;
  25819.  int                   last_group_selected;
  25820.  int                   groupcursor;
  25821.  int                   zscrolln;
  25822.  int                   dynsize;
  25823.  int                   framelength;
  25824.  int                   findbump;
  25825.  short                 name_length;
  25826.  Bool                  is_max;
  25827.  Bool                  selection_processed_ok;
  25828.  Bool                  command_processed_ok;
  25829.  Bool                  text_not_found;
  25830.  char                 *rowp;
  25831.  char                 *nngdyna;
  25832.  char                  sel;
  25833.  char                  tcmd     [72];
  25834.  char                  nnghead  [81];
  25835.  char                  nngline  [81];
  25836.  char                  nngcsr   [12];
  25837.  char                  command  [COMMANDSIZE];
  25838.  char                  zverb     [9];
  25839.  char                  zscrolla  [9];
  25840.  char                  rowmessage[81];
  25841.  
  25842.  static char           dashes[65] =
  25843.     "----------------------------------------------------------------";
  25844.  
  25845.  tdp = np->display_table_vector->newsgroup_display_table;
  25846.  
  25847.  np->current_newsgroup           = NULL;
  25848.  np->newsgroup_selected          = FALSE;
  25849.  np->newsgroup_criterion_changed = TRUE;
  25850.  np->newsgroup_order_changed     = TRUE;
  25851.  text_not_found                  = FALSE;
  25852.  strcpy(np->newsgroup_only_string,"");
  25853.  
  25854.  /* Determine how many TOTAL newsgroups we have. */
  25855.  
  25856.  newsgroup_count = 0;
  25857.  for (gp = np->first_newsgroup; gp; gp = gp->next) newsgroup_count++;
  25858.  
  25859.  /* Allocate a block of "ngdynarray" newsgroup pointers, one element
  25860.   * for each newsgroup that is currently displayed.  This must be
  25861.   * big enough to hold all known newsgroups at maximum.
  25862.   */
  25863.  
  25864.  if (newsgroup_count == 0) {
  25865.    ERR1(
  25866.      "No newsgroups to display.  Use L option to get list from server."
  25867.        );
  25868.    return FALSE;
  25869.  }
  25870.  
  25871.  GETMAIN(ngdynarray_address, struct ngdynarray,
  25872.          newsgroup_count, "newsgroup dynamic array");
  25873.  if (!ngdynarray_address) return FALSE;
  25874.  
  25875.  /* Get depth of dynamic area (number of rows to display on screen) */
  25876.  
  25877.  (void)NNMispf(np,
  25878.        "PQUERY PANEL(NNMDNG) AREANAME(NNGDYNA) DEPTH(NNGDEPTH)");
  25879.  if (np->ispfrc != 0) return FALSE;
  25880.  depth = NNMiget(np,"NNGDEPTH ");
  25881.  
  25882.  /* Get storage for ISPF dynamic area variable to be constructed. */
  25883.  
  25884.  dynsize = 80*depth;
  25885.  GETMAIN(nngdyna, char, dynsize+1, "NNGDYNA buffer");
  25886.  if (!nngdyna) return FALSE;
  25887.  memset(nngdyna,' ',dynsize);
  25888.  
  25889.  topgroup = 0;
  25890.  groupcursor = 0;
  25891.  last_group_located  = -1;
  25892.  last_group_selected = -1;
  25893.  
  25894.  strcpy(tcmd,"");
  25895.  
  25896.  memset(nngline,' ',80);
  25897.  nngline[ 0] = DATAOUT_HIGH;
  25898.  nngline[ 1] = 'S';
  25899.  nngline[ 2] = DATAOUT_LOW;
  25900.  memcpy(&nngline[ 3],"select",6);
  25901.  nngline[ 9] = DATAOUT_HIGH;
  25902.  nngline[10] = 'A';
  25903.  nngline[11] = DATAOUT_LOW;
  25904.  memcpy(&nngline[12],"all",   3);
  25905.  nngline[15] = DATAOUT_HIGH;
  25906.  nngline[16] = 'R';
  25907.  nngline[17] = DATAOUT_LOW;
  25908.  memcpy(&nngline[18],"reg",   3);
  25909.  nngline[21] = DATAOUT_HIGH;
  25910.  nngline[22] = 'D';
  25911.  nngline[23] = DATAOUT_LOW;
  25912.  memcpy(&nngline[24],"dereg", 5);
  25913.  nngline[29] = DATAOUT_HIGH;
  25914.  nngline[30] = 'M';
  25915.  nngline[31] = DATAOUT_LOW;
  25916.  memcpy(&nngline[32],"mark",  4);
  25917.  nngline[36] = DATAOUT_HIGH;
  25918.  nngline[37] = 'U';
  25919.  nngline[38] = DATAOUT_LOW;
  25920.  memcpy(&nngline[39],"unmark",6);
  25921.  nngline[48] = DATAOUT_HIGH;
  25922.  strcpy(&nngline[49],"Unread   Count   Range");
  25923.  
  25924.  /* The last line above may be variable some day if we have to vary
  25925.     the width of the numbers...  */
  25926.  
  25927.  /* Loop displaying newsgroups until END or criterion changed. */
  25928.  
  25929.  do {
  25930.  
  25931.    /* If the newsgroup display criteria have changed, or this is the
  25932.       first time through, build the array of newsgroup pointers.  */
  25933.  
  25934.    if (np->newsgroup_criterion_changed || np->newsgroup_order_changed) {
  25935.      ndp = ngdynarray_address;
  25936.      display_total = 0;
  25937.      topgroup = 0;
  25938.      switch (np->newsgroup_order) {
  25939.        case NNTP_LIST_ORDER:
  25940.             gp = np->first_newsgroup_alt;
  25941.             next_offset = (char *)&gp->next2 - (char *)gp;
  25942.             break;
  25943.        case ALPHABETICAL_ORDER:
  25944.        default:
  25945.             gp = np->first_newsgroup;
  25946.             next_offset = (char *)&gp->next - (char *)gp;
  25947.             break;
  25948.      }
  25949.      for (; gp; gp = *(struct newsgroup **)((int)gp + next_offset)) {
  25950.        if (np->newsgroup_criterion_changed) {
  25951.          OffGroupInTable(gp);   /* guilty until proven innocent */
  25952.          if ((np->show_all_newsgroups && !NoSuchGroup(gp))
  25953.           || gp->registered) {
  25954.            if (!*np->newsgroup_only_string
  25955.             || strstr(gp->name,np->newsgroup_only_string)) {
  25956.              SetGroupInTable(gp);
  25957.            }
  25958.          }
  25959.        }
  25960.        if (GroupInTable(gp)) {
  25961.          display_total++;
  25962.          ndp->newsgroup = gp;
  25963.          ndp++;
  25964.        }
  25965.      }
  25966.    }
  25967.  
  25968.    np->newsgroup_criterion_changed = FALSE;
  25969.    np->newsgroup_order_changed     = FALSE;
  25970.  
  25971.    /* Fill dynamic area with data for groups satisfying criterion. */
  25972.  
  25973.    memset(nngdyna, ' ', dynsize);
  25974.  
  25975.    for (dti = 0,       ngi = topgroup,        rowp = nngdyna;
  25976.         dti < depth && ngi < display_total;
  25977.         dti++,         ngi++,                 rowp += 80) {
  25978.      ndp = &ngdynarray_address[ngi];
  25979.      gp  = ndp->newsgroup;
  25980.      rowp[ 0]  = DATAIN_HIGH;     /* selection code attribute */
  25981.      rowp[ 1]  = ' ';             /* selection code field     */
  25982.      rowp[ 2]  = gp->registered
  25983.                  ? (gp->unread_count ? DATAOUT_YELLOW : DATAOUT_TURQ)
  25984.                  : (gp->unread_count ? DATAOUT_GREEN  : DATAOUT_BLUE);
  25985.                                       /* newsgroup name attribute */
  25986.      memset(&rowp[3], '.', 40);
  25987.      name_length = strlen(gp->name);
  25988.      if (name_length > 40) name_length = 40;
  25989.      memcpy(&rowp[3], gp->name, name_length);
  25990.      rowp[3+name_length] = DATAOUT_BLUE;
  25991.      rowp[43] = DATAOUT_PINK;
  25992.      rowp[44] = gp->registered ? 'R' : ' ';
  25993.      rowp[45] = DATAOUT_HIGH;
  25994.      if (gp->unread_count != 0)
  25995.         sprintf(&rowp[46], "  %7d", gp->unread_count);
  25996.      rowp[55] = DATAOUT_LOW;
  25997.      if (gp->article_count == 0)
  25998.         strcpy(&rowp[56],"      0                ");
  25999.      else
  26000.         sprintf(&rowp[56], "%7d %7d -%7d",
  26001.                 gp->article_count, gp->low_number, gp->high_number);
  26002.      rowp[strlen(rowp)] = ' ';
  26003.  
  26004.      if (NoSuchGroup(gp)) {
  26005.        memcpy(&rowp[46],"******* No such newsgroup *******",33);
  26006.      }
  26007.  
  26008.    }
  26009.  
  26010.    if (rowp < nngdyna + dynsize) {
  26011.      rowp[0] = DATAOUT_HIGH;
  26012.      memset(&rowp[1], '-',79);
  26013.    }
  26014.  
  26015.    bottomgroup = ngi - 1;
  26016.  
  26017.    if (topgroup > bottomgroup) strcpy(rowmessage,"");
  26018.    else sprintf(rowmessage, "%d-%d of %d",
  26019.                        topgroup + 1, bottomgroup + 1, display_total);
  26020.  
  26021.  
  26022.    framelength = (79 - strlen(rowmessage) - sizeof("Newsgroup Listing")
  26023.                  - 3) / 2;
  26024.  
  26025.    sprintf(nnghead, "%*.*s Newsgroup Listing %*.*s %s",
  26026.                     framelength, framelength, dashes,
  26027.                     framelength, framelength, dashes,
  26028.                     rowmessage);
  26029.  
  26030.    if (last_group_selected >= 0 && np->newsgroup_autocursor) {
  26031.      groupcursor = (last_group_selected - topgroup) * 80 + 2;
  26032.    }
  26033.  
  26034.    if (groupcursor > 0) {
  26035.      sprintf(nngcsr,"%d",groupcursor);
  26036.      (void)NNMivput(np,"NNGCSR ", nngcsr, -1);
  26037.    }
  26038.    else {
  26039.      (void)NNMivput(np,"NNGCSR ", "0", 1);
  26040.    }
  26041.  
  26042.    (void)NNMivput(np,"NNGCMD ",  tcmd,    -1);
  26043.    (void)NNMivput(np,"NNGHEAD ", nnghead, -1);
  26044.    (void)NNMivput(np,"NNGLINE ", nngline, -1);
  26045.    (void)NNMivput(np,"NNGDYNA ", nngdyna, dynsize);
  26046.    (void)NNMivput(np,"YRFIND " , "ALIAS FIND",-1);
  26047.  
  26048.    prc = NNMdispl(np,"NNMDNG  ");
  26049.    if (prc > 8) break;
  26050.  
  26051.    /* (void)NNMispf(np,"VGET (ZVERB ZSCROLLA ZSCROLLN)"); */
  26052.  
  26053.    (void)NNMivput(np,"YRFIND "  ,"",-1);
  26054.    (void)NNMivget(np,"NNGDYNA " , nngdyna,  dynsize);
  26055.    (void)NNMivget(np,"ZVERB "   , zverb,    sizeof(zverb));
  26056.    (void)NNMivget(np,"ZSCROLLA ", zscrolla, sizeof(zscrolla));
  26057.    zscrolln = NNMiget(np,"ZSCROLLN ");
  26058.    nnglvl   = NNMiget(np,"NNGLVL ");
  26059.  
  26060.    /* Initialize what may be set by selection/command processors. */
  26061.  
  26062.    strcpy(np->nngroup,"");
  26063.    last_group_selected = -1;
  26064.    last_group_located  = -1;
  26065.    groupcursor = 0;
  26066.    np->please_locate_group = FALSE;
  26067.    np->please_find_group   = FALSE;
  26068.  
  26069.    /* Process selections. */
  26070.  
  26071.    for (ngi = topgroup,        rowp = nngdyna;
  26072.         ngi <= bottomgroup  && !np->quit;
  26073.         ngi++,                 rowp += 80) {
  26074.      ndp = &ngdynarray_address[ngi];
  26075.      gp = ndp->newsgroup;
  26076.      sel = toupper(rowp[1]);
  26077.      if (sel == ' ') continue;
  26078.      for (sdp = tdp->first_seldesc; sdp->selection_code != ' '; sdp++) {
  26079.        if (sel == sdp->selection_code) {
  26080.          (void)NNMivput(np,"NNGNAME ",gp->name, -1);
  26081.          selection_processed_ok = (sdp->selection_processor)(np,gp);
  26082.          sdp = NULL;
  26083.          break;
  26084.        }
  26085.      }
  26086.      if (sdp) {
  26087.        ERR1("Unknown selection code.  Type one of the listed codes.");
  26088.        selection_processed_ok = FALSE;
  26089.      }
  26090.      else if (selection_processed_ok) {
  26091.        if (*np->nngroup) last_group_located = ngi;
  26092.        if (np->newsgroup_autocursor) last_group_selected = ngi;
  26093.      }
  26094.    }
  26095.  
  26096.    if (np->quit) break;
  26097.  
  26098.    /* Process command if any. */
  26099.  
  26100.    strcpy(tcmd,"");
  26101.  
  26102.    (void)NNMivget(np,tdp->command_variable,tcmd,sizeof(tcmd));
  26103.  
  26104.    if (strcmp(tcmd,"") != 0) {
  26105.  
  26106.      memset(command,' ',COMMANDSIZE);
  26107.      command_index = 0;
  26108.      for (cp = tcmd; *cp && !isspace(*cp); cp++) {
  26109.        if (cp >= tcmd+COMMANDSIZE) {
  26110.          ERR1("Unknown command name.");
  26111.          command_processed_ok = FALSE;
  26112.        }
  26113.        command[command_index++] = toupper(*cp);
  26114.      }
  26115.      while (*cp && isspace(*cp)) cp++;
  26116.  
  26117.      for (cdp=tdp->first_cmddesc; cdp->command_name[0] != ' '; cdp++) {
  26118.        if (!memcmp(command,cdp->command_name,COMMANDSIZE-1)) {
  26119.          command_processed_ok = (cdp->command_processor)(np,NULL,cp);
  26120.          cdp = NULL;
  26121.          break;
  26122.        }
  26123.      }
  26124.      if (cdp) {
  26125.        for (cdp=tdp->next_cmddesc; cdp->command_name[0] != ' '; cdp++) {
  26126.          if (!memcmp(command,cdp->command_name,COMMANDSIZE-1)) {
  26127.            command_processed_ok = (cdp->command_processor)(np,NULL,cp);
  26128.            cdp = NULL;
  26129.            break;
  26130.          }
  26131.        }
  26132.      }
  26133.  
  26134.      if (cdp) {
  26135.        ERR1("Unknown command name.");
  26136.        command_processed_ok = FALSE;
  26137.      }
  26138.  
  26139.      if (command_processed_ok) strcpy(tcmd,"");
  26140.  
  26141.    }
  26142.  
  26143.    if (np->quit) break;
  26144.  
  26145.    /* If locate to a specific group name was requested,
  26146.       process before any scroll request.  */
  26147.  
  26148.    if (last_group_located >= 0 && np->newsgroup_autoscroll) {
  26149.      text_not_found = FALSE;
  26150.      topgroup = last_group_located;
  26151.    }
  26152.    else if (np->please_locate_group) {
  26153.      text_not_found = FALSE;
  26154.      for (topgroup = 0, ndp = ngdynarray_address;
  26155.           topgroup < display_total;
  26156.           topgroup++,   ndp++) {
  26157.        gp = ndp->newsgroup;
  26158.        if (strcmp(gp->name,np->newsgroup_locate_string) >= 0) break;
  26159.      }
  26160.      if (topgroup == display_total) topgroup--;
  26161.    }
  26162.    else if (np->please_find_group) {
  26163.      save_topgroup = topgroup;
  26164.      switch (np->newsgroup_find_option) {
  26165.        case FIND_NEXT:
  26166.                        findbump = 1;
  26167.                        if (np->repeat_find) {
  26168.                          if (text_not_found) topgroup = 0;
  26169.                          else topgroup++;
  26170.                        }
  26171.                        break;
  26172.        case FIND_PREV:
  26173.                        findbump = -1;
  26174.                        if (np->repeat_find) {
  26175.                          if (text_not_found) topgroup = bottomgroup;
  26176.                          else topgroup--;
  26177.                        }
  26178.                        break;
  26179.        case FIND_FIRST:
  26180.                        topgroup = 0;
  26181.                        findbump = 1;
  26182.                        break;
  26183.        case FIND_LAST:
  26184.                        topgroup = display_total - 1;
  26185.                        findbump = -1;
  26186.                        break;
  26187.      }
  26188.      gp = NULL;
  26189.      for (ndp = &ngdynarray_address[topgroup];
  26190.           topgroup < display_total && topgroup >= 0;
  26191.           topgroup += findbump, ndp += findbump) {
  26192.        if (GroupInTable(ndp->newsgroup)
  26193.         && strstr(ndp->newsgroup->name,np->newsgroup_find_string)) {
  26194.          gp = ndp->newsgroup;
  26195.          break;
  26196.        }
  26197.      }
  26198.      if (!gp) {
  26199.        topgroup = save_topgroup;
  26200.        text_not_found = TRUE;
  26201.        ERR3("No %s newsgroups with '%s' in name.",
  26202.             (findbump > 0 ? "more" : "previous"),
  26203.             np->newsgroup_find_string);
  26204.      }
  26205.      else {
  26206.        text_not_found = FALSE;
  26207.    WARN1("Newsgroup found;\
  26208. The newsgroup whose name contains the desired text tops the display.");
  26209.      }
  26210.    }
  26211.    else text_not_found = FALSE;
  26212.  
  26213.    /* Process scroll request if any. */
  26214.  
  26215.    is_max = EQUAL(zscrolla,"MAX");
  26216.    if      (EQUAL(zverb,"DOWN")) {
  26217.      if (is_max) topgroup = display_total - nnglvl + 1;
  26218.      else        topgroup += zscrolln;
  26219.    }
  26220.    else if (EQUAL(zverb,"UP")) {
  26221.      if (is_max) topgroup = 0;
  26222.      else        topgroup -= zscrolln;
  26223.    }
  26224.    if (topgroup < 0)
  26225.        topgroup = 0;
  26226.    if (topgroup > display_total)
  26227.        topgroup = display_total;
  26228.  
  26229.  } while (prc == 0);
  26230.  
  26231.  FREEMAIN(nngdyna,"NNGDYNA buffer");
  26232.  FREEMAIN(ngdynarray_address,"newsgroup dynamic area");
  26233.  
  26234.  return TRUE;
  26235.  
  26236. }
  26237.  
  26238. ./ ADD NAME=NNMVTX
  26239.  
  26240.  /********************************************************************/
  26241.  /*                                                                  */
  26242.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  26243.  /*                                                                  */
  26244.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  26245.  /*                                                                  */
  26246.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  26247.  /* including the implied warranties of merchantability and fitness, */
  26248.  /* are expressly denied.                                            */
  26249.  /*                                                                  */
  26250.  /* Provided this copyright notice is included, this software may    */
  26251.  /* be freely distributed and not offered for sale.                  */
  26252.  /*                                                                  */
  26253.  /* Changes or modifications may be made and used only by the maker  */
  26254.  /* of same, and not further distributed.  Such modifications should */
  26255.  /* be mailed to the author for consideration for addition to the    */
  26256.  /* software and incorporation in subsequent releases.               */
  26257.  /*                                                                  */
  26258.  /********************************************************************/
  26259.  
  26260. #pragma  csect(code,  "NN@VTX  ")
  26261. #pragma  csect(static,"NN$VTX  ")
  26262. #include "nn.h"
  26263.  
  26264. /****** View the lines of text retrieved from the server. ************/
  26265.  
  26266. void
  26267. NNMvtx(np,gp,ap)
  26268. Rstruc nncb         *np;
  26269. Rstruc newsgroup    *gp;
  26270. Rstruc newsarticle  *ap;
  26271. {
  26272.  struct texthdr    *texthdrp;
  26273.  char               title     [81];
  26274.  
  26275.  /* If article is not specified, use main nncb, else article's text */
  26276.  
  26277.  texthdrp = (ap ? &ap->thdr : &np->thdr);
  26278.  
  26279.  if (np->batch_mode) {
  26280.    NNMbtext(np,texthdrp,NULL);
  26281.    return;
  26282.  }
  26283.  
  26284.  if (ap) sprintf(title, "%s:%d ",        gp->name, ap->number);
  26285.  else    sprintf(title, "NewsServer:%s ",np->nnserver);
  26286.  
  26287.  NNMview(np,gp,ap,texthdrp,title);
  26288.  return;
  26289. }
  26290.  
  26291. ./ ADD NAME=NNMXARTT
  26292.  
  26293.  /********************************************************************/
  26294.  /*                                                                  */
  26295.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  26296.  /*                                                                  */
  26297.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  26298.  /*                                                                  */
  26299.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  26300.  /* including the implied warranties of merchantability and fitness, */
  26301.  /* are expressly denied.                                            */
  26302.  /*                                                                  */
  26303.  /* Provided this copyright notice is included, this software may    */
  26304.  /* be freely distributed and not offered for sale.                  */
  26305.  /*                                                                  */
  26306.  /* Changes or modifications may be made and used only by the maker  */
  26307.  /* of same, and not further distributed.  Such modifications should */
  26308.  /* be mailed to the author for consideration for addition to the    */
  26309.  /* software and incorporation in subsequent releases.               */
  26310.  /*                                                                  */
  26311.  /********************************************************************/
  26312.  
  26313. #pragma  csect(code,  "NN@XARTT")
  26314. #pragma  csect(static,"NN$XARTT")
  26315. #include "nn.h"
  26316.  
  26317. #define FORCE_DISPLAY_TO_TOP_AFTER_EXTRACT
  26318.  
  26319. /****** Emit an article title. ***************************************/
  26320.  
  26321. static Bool
  26322. emit_title(np,vp,xfp)
  26323. Rstruc nncb         *np;
  26324. VARK                *vp;
  26325. FILE                *xfp;
  26326. {
  26327.  Rstruc newsarticle *ap = VARK2PARTICLE(*vp);
  26328.  char               *stat;
  26329.  
  26330.  if      IsMissing(*vp)  stat = "Missing";
  26331.  else if IsUnread(*vp)   stat = "Unread";
  26332.  else if IsRead(*vp)     stat = "Read";
  26333.  else                    stat = "?";
  26334.  
  26335.  if (np->article_rows == 1) {
  26336.    fprintf(xfp,"%7d %-51.51s %-8.8s %11.11s\n",
  26337.                 ap->number, ap->subject, stat, ap->date);
  26338.  }
  26339.  else {
  26340.    fprintf(xfp,"%7d %-51.51s %-8.8s\n",
  26341.                ap->number, ap->subject, stat);
  26342.  }
  26343.  if (np->article_rows >= 2) {
  26344.    fprintf(xfp,"        %-51.51s %11.11s\n", ap->from, ap->date);
  26345.  }
  26346.  if (np->article_rows >= 3) {
  26347.    fprintf(xfp,"        %-51.51s\n", ap->message_id);
  26348.  }
  26349.  if (ferror(xfp)) return FALSE;
  26350.  else return TRUE;
  26351. }
  26352.  
  26353. /****** Extract article titles. **************************************/
  26354.  
  26355. Bool
  26356. NNMxartt(np,gp,mode)
  26357. Rstruc nncb         *np;
  26358. Rstruc newsgroup    *gp;
  26359. enum data_set_type   mode;
  26360. {
  26361.  FILE               *xfp;
  26362.  int                 count;
  26363.  VARK               *vp;
  26364.  VARK               *vpfirst;
  26365.  VARK               *vplast;
  26366.  VARK              **wp;
  26367.  VARK              **wpfirst;
  26368.  VARK              **wplast;
  26369.  struct extraction  *ep;
  26370.  struct extraction   the_extraction;
  26371.  
  26372.  if (!gp->article_vector) {
  26373.    ERR2("Newsgroup %s contains no articles.",gp->name);
  26374.    return FALSE;
  26375.  }
  26376.  
  26377.  /* Display panel asking for data set name into which to extract. */
  26378.  
  26379.  ep = &the_extraction;
  26380.  memset(ep,0,sizeof(struct extraction));
  26381.  ep->mode = mode;
  26382.  if (ep->mode == JES)
  26383.       strcpy(ep->panelname,"NNMPPRN1");
  26384.  else strcpy(ep->panelname,"NNMPEXN1");
  26385.  
  26386.  if (!((xfp=NNMgetds(np,ep)))) return TRUE;
  26387.  
  26388.  /* If append mode, and a separator line was specified, use it. */
  26389.  
  26390.  if (ep->appending && *ep->separator) {
  26391.    fprintf(xfp,"%s\n",ep->separator);
  26392.    if (ep->blanking) fprintf(xfp,"\n");
  26393.  }
  26394.  
  26395.  fprintf(xfp," Newsgroup: %-43.43s     Status   Date\n\n", gp->name);
  26396.  
  26397.  count = NNMrart(np,gp,FALSE,FALSE);  /* Retrieve article titles */
  26398.  
  26399.  if (gp->sort_vector) {
  26400.    wpfirst = gp->sort_vector;
  26401.    wplast  = gp->sort_vector + gp->sort_count - 1;
  26402.    for (wp = wpfirst; wp <= wplast; wp++) {
  26403.      if (IsEligible(**wp)) {
  26404.        if (!emit_title(np,*wp,xfp)) break;
  26405.      }
  26406.    }
  26407. #ifdef FORCE_DISPLAY_TO_TOP_AFTER_EXTRACT
  26408.    np->top_sorted_article = gp->sort_vector;
  26409. #endif
  26410.  }
  26411.  else {
  26412.    vpfirst = &GETVARKFIRST(gp);
  26413.    vplast  = &GETVARKLAST(gp);
  26414.    for (vp = vpfirst; vp <= vplast; vp++) {
  26415.      if (IsEligible(*vp)) {
  26416.        if (!emit_title(np,vp,xfp)) break;
  26417.      }
  26418.    }
  26419. #ifdef FORCE_DISPLAY_TO_TOP_AFTER_EXTRACT
  26420.    np->top_article = gp->vector_first;
  26421. #endif
  26422.  }
  26423.  
  26424.  fprintf(xfp,"\n");
  26425.  
  26426.  if (ferror(xfp)) {
  26427.    ERR2("An output error occurred writing to %s.", ep->dsname);
  26428.  }
  26429.  else {
  26430.    WARN2("A list of titles has been written to %s.", ep->dsname);
  26431.  }
  26432.  
  26433.  (ep->closer)(np,ep,xfp,TRUE);   /* Close the file */
  26434.  
  26435.  return TRUE;
  26436. }
  26437.  
  26438. ./ ADD NAME=NNMXARTX
  26439.  
  26440.  /********************************************************************/
  26441.  /*                                                                  */
  26442.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  26443.  /*                                                                  */
  26444.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  26445.  /*                                                                  */
  26446.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  26447.  /* including the implied warranties of merchantability and fitness, */
  26448.  /* are expressly denied.                                            */
  26449.  /*                                                                  */
  26450.  /* Provided this copyright notice is included, this software may    */
  26451.  /* be freely distributed and not offered for sale.                  */
  26452.  /*                                                                  */
  26453.  /* Changes or modifications may be made and used only by the maker  */
  26454.  /* of same, and not further distributed.  Such modifications should */
  26455.  /* be mailed to the author for consideration for addition to the    */
  26456.  /* software and incorporation in subsequent releases.               */
  26457.  /*                                                                  */
  26458.  /********************************************************************/
  26459.  
  26460. #pragma  csect(code,  "NN@XARTX")
  26461. #pragma  csect(static,"NN$XARTX")
  26462. #include "nn.h"
  26463.  
  26464. /****** Extract an article. ******************************************/
  26465.  
  26466. static Bool
  26467. extract_it(np,gp,ep,vp,xfpp,newtopp)
  26468. Rstruc nncb         *np;
  26469. Rstruc newsgroup    *gp;
  26470. struct extraction   *ep;
  26471. VARK                *vp;
  26472. FILE               **xfpp;
  26473. int                 *newtopp;
  26474. {
  26475.  struct newsarticle *ap;
  26476.  char               *cp1;
  26477.  char               *cp2;
  26478.  int                 anum;
  26479.  char                pdspec [32];
  26480.  
  26481.  if (np->extract_write_error || np->extract_close_error) return FALSE;
  26482.  anum = VARK2NUMBER(gp,vp);
  26483.  if (anum > ep->to_article_number)                       return FALSE;
  26484.  if (anum < ep->from_article_number)                     return TRUE;
  26485.  if (!(NNMcar(np,gp,anum,vp,&ap,NULL,RETRIEVE)))         return TRUE;
  26486.  
  26487.  if (ep->mode == PDS) {
  26488.    sprintf(ep->member,"%8.8d",anum);
  26489.    for (cp1 = ep->member, cp2 = ep->member_prefix;
  26490.         *cp1 == '0' && *cp2;
  26491.         cp1++, cp2++) {
  26492.      *cp1 = *cp2;
  26493.    }
  26494.    (void)NNMivput(np,"NNEXMEM ",ep->member,-1);
  26495.    sprintf(pdspec,"dd:%s(%s)",ep->ddname,ep->member);
  26496.  }
  26497.  else {
  26498.    (void)NNMivput(np,"NNEXMEM "," ",-1);
  26499.  }
  26500.  
  26501.  if (*newtopp == 0) *newtopp = anum;
  26502.  
  26503.  if (!NNMpick(np,ap)) {       /* Pick article to process */
  26504.    fprintf(stderr,"\n*** Error accessing article %d\n",ap->number);
  26505.    return TRUE;
  26506.  }
  26507.  
  26508.  if (ep->mode == PDS) {
  26509.    (*xfpp) = OPEN_TEXT_FILE_FOR_WRITE(pdspec);
  26510.    if (!(*xfpp)) {
  26511.      perror(pdspec);
  26512.      ERR3("Cannot open member %s of PDS %s.", ep->member, ep->dsname);
  26513.      return FALSE;
  26514.    }
  26515.  }
  26516.  
  26517.  np->extract_file = (*xfpp);
  26518.  np->extractionp  = ep;
  26519.  
  26520.  NNMdoit(np,ap, ep->mode==JES ? 'P' : 'E'); /* Process article picked*/
  26521.  
  26522.  if (np->extract_write_error || np->extract_close_error) {
  26523.    /*
  26524.     * if (ep->mode == PDS) {
  26525.     *   if (fclose((*xfpp)) < 0) {
  26526.     *     /* perror(ep->dsname); */
  26527.    /*   ERR2("An error occurred closing data set %s.", ep->dsname);
  26528.     *     np->extract_close_error = TRUE;
  26529.     *   }
  26530.     * }
  26531.     */
  26532.    *newtopp = ap->number;
  26533.    return FALSE;
  26534.  }
  26535.  
  26536.  /* If not appending (always true for PDS), close was done in NNMxtx.*/
  26537.  
  26538.  if (ep->mode == SEQ) {
  26539.    if (!ep->appending) {
  26540.      (ep->closer)(np,ep,*xfpp,FALSE);   /* Close the file */
  26541.      if (np->extract_close_error) {
  26542.        *newtopp = ap->number;
  26543.        return FALSE;
  26544.      }
  26545.      (*xfpp) = OPEN_TEXT_FILE_FOR_APPEND(ep->dsname);
  26546.      if (!(*xfpp)) {
  26547.        perror(ep->dsname);
  26548.        ERR2("Unable to open file %s.", ep->dsname);
  26549.        np->extract_write_error = TRUE;
  26550.        *newtopp = ap->number;
  26551.        return FALSE;
  26552.      }
  26553.      ep->appending = TRUE;
  26554.    }
  26555.  }
  26556.  return TRUE;
  26557.  
  26558. }
  26559.  
  26560. /****** Extract article text. ****************************************/
  26561.  
  26562. Bool
  26563. NNMxartx(np,gp,mode)
  26564. Rstruc nncb         *np;
  26565. Rstruc newsgroup    *gp;
  26566. enum data_set_type   mode;
  26567. {
  26568.  Rstruc newsarticle *ap;
  26569.  FILE               *xfp;
  26570.  struct extraction  *ep;
  26571.  VARK               *vp;
  26572.  VARK               *vpfirst;
  26573.  VARK               *vplast;
  26574.  VARK              **wp;
  26575.  VARK              **wpfirst;
  26576.  VARK              **wplast;
  26577.  int                 new_top_article = 0;
  26578.  struct extraction   the_extraction;
  26579.  
  26580.  if (!gp->article_vector) {
  26581.    ERR2("Newsgroup %s contains no articles.",gp->name);
  26582.    return FALSE;
  26583.  }
  26584.  
  26585.  /* Display panel asking for data set name into which to extract. */
  26586.  
  26587.  ep = &the_extraction;
  26588.  memset(ep,0,sizeof(struct extraction));
  26589.  ep->mode = mode;
  26590.  ep->article_count = gp->article_count;
  26591.  switch (ep->mode) {
  26592.    case PDS: strcpy(ep->panelname,"NNMPEXNP"); break;
  26593.    case JES: strcpy(ep->panelname,"NNMPPRNS"); break;
  26594.    case SEQ: strcpy(ep->panelname,"NNMPEXNS"); break;
  26595.  }
  26596.  
  26597.  if (!((xfp=NNMgetds(np,ep)))) return TRUE;
  26598.  
  26599.  np->extract_tab_expanding          = ep->tab_expanding;
  26600.  np->extract_appending              = ep->mode == PDS ? FALSE : TRUE;
  26601.  np->extract_ejecting               = ep->ejecting;
  26602.  np->extract_blank_before_separator = ep->blanking;
  26603.  np->extract_separator_line         = ep->separator;
  26604.  np->extract_write_error            = FALSE;
  26605.  np->extract_close_error            = FALSE;
  26606.  
  26607.  /* for each article (subject to range option), write */
  26608.  
  26609.  if (gp->sort_vector) {
  26610.    wpfirst = gp->sort_vector;
  26611.    wplast  = gp->sort_vector + gp->sort_count - 1;
  26612.    for (wp = wpfirst; wp <= wplast; wp++) {
  26613.      if (!extract_it(np,gp,ep,*wp,&xfp,&new_top_article)) break;
  26614.    }
  26615.  }
  26616.  else {
  26617.    vpfirst = &GETVARKFIRST(gp);
  26618.    vplast  = &GETVARKLAST(gp);
  26619.    for (vp = vpfirst; vp <= vplast; vp++) {
  26620.      if (!extract_it(np,gp,ep,vp,&xfp,&new_top_article)) break;
  26621.    }
  26622.  }
  26623.  
  26624.  if (np->extract_write_error || np->extract_close_error)
  26625.     np->top_article = new_top_article;
  26626.  else if (new_top_article)
  26627.     np->top_article = new_top_article;
  26628.  
  26629.  if (xfp) {
  26630.    if      (np->extract_write_error) {
  26631.      ERR2("An error occurred writing to %s.", ep->dsname);
  26632.    }
  26633.    else if (np->extract_close_error) {
  26634.      if (ep->mode == PDS) {
  26635.      ERR3("Cannot store member %s in %s.  Check directory space.",
  26636.           ep->member, ep->dsname);
  26637.      }
  26638.      else ERR2("An error occurred closing %s.", ep->dsname);
  26639.    }
  26640.    else {
  26641.      WARN3("Articles from %s have been written to %s.",
  26642.            gp->name, ep->dsname);
  26643.    }
  26644.  }
  26645.  
  26646.  (ep->closer)(np,ep,xfp,TRUE);   /* "Close" the PDS or the file */
  26647.  
  26648.  return TRUE;
  26649. }
  26650.  
  26651. ./ ADD NAME=NNMXLIST
  26652.  
  26653.  /********************************************************************/
  26654.  /*                                                                  */
  26655.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  26656.  /*                                                                  */
  26657.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  26658.  /* including the implied warranties of merchantability and fitness, */
  26659.  /* are expressly denied.                                            */
  26660.  /*                                                                  */
  26661.  /* Provided this copyright notice is included, this software may    */
  26662.  /* be freely distributed and not offered for sale.                  */
  26663.  /*                                                                  */
  26664.  /* Changes or modifications may be made and used only by the maker  */
  26665.  /* of same, and not further distributed.  Such modifications should */
  26666.  /* be mailed to the author for consideration for addition to the    */
  26667.  /* software and incorporation in subsequent releases.               */
  26668.  /*                                                                  */
  26669.  /********************************************************************/
  26670.  
  26671. #pragma  csect(code,  "NN@XLIST")
  26672. #pragma  csect(static,"NN$XLIST")
  26673. #include "nn.h"
  26674.  
  26675. /****** Extract newsgroup listing. ***********************************/
  26676.  
  26677. static void
  26678. output_newsgroup_line(np,gp,xfp)
  26679. Rstruc nncb         *np;
  26680. Rstruc newsgroup    *gp;
  26681. FILE                *xfp;
  26682. {
  26683.  char                temp   [81];
  26684.  
  26685.  if (gp->article_count == 0) strcpy(temp,"");
  26686.  else sprintf(temp,"%7d - %7d", gp->low_number, gp->high_number);
  26687.  
  26688.  fprintf(xfp,"%*.*s %*.*s %c %7d %7d %s\n",
  26689.          strlen(gp->name),
  26690.          39,
  26691.          gp->name,
  26692.          39-strlen(gp->name),
  26693.          39-strlen(gp->name),
  26694.          ".........................................",
  26695.          (gp->registered ? 'R' : ' '),
  26696.          gp->unread_count,
  26697.          gp->article_count,
  26698.          temp);
  26699.  
  26700.  return;
  26701.  
  26702. }
  26703.  
  26704. /****** Extract newsgroup listing. ***********************************/
  26705.  
  26706. Bool
  26707. NNMxlist(np,mode)
  26708. Rstruc nncb         *np;
  26709. enum data_set_type   mode;
  26710. {
  26711.  Rstruc newsgroup   *gp;
  26712.  FILE               *xfp;
  26713.  struct extraction  *ep;
  26714.  char                temp   [72];
  26715.  struct extraction   the_extraction;
  26716.  
  26717.  /* Display panel asking for data set name into which to extract. */
  26718.  
  26719.  ep = &the_extraction;
  26720.  memset(ep,0,sizeof(struct extraction));
  26721.  ep->mode = mode;
  26722.  if (ep->mode == JES)
  26723.       strcpy(ep->panelname, "NNMPPRNG");
  26724.  else strcpy(ep->panelname, "NNMPEXNG");
  26725.  
  26726.  if (!((xfp=NNMgetds(np,ep)))) return TRUE;
  26727.  
  26728.  /* If append mode, and a separator line was specified, use it. */
  26729.  
  26730.  if (ep->appending && *ep->separator) {
  26731.    fprintf(xfp,"%s\n",ep->separator);
  26732.    if (ep->blanking) fprintf(xfp,"\n");
  26733.  }
  26734.  
  26735.  fprintf(xfp,"\
  26736.   Newsgroup Listing                          Unread   Count      \
  26737.   Range\n\n");
  26738.  
  26739.  switch (np->newsgroup_order) {
  26740.    case NNTP_LIST_ORDER:
  26741.         for (gp = np->first_newsgroup_alt; gp; gp = gp->next2) {
  26742.           if (GroupInTable(gp)) {
  26743.             output_newsgroup_line(np,gp,xfp);
  26744.           }
  26745.         }
  26746.         break;
  26747.  
  26748.    case NEWSRC_ORDER:        /* not implemented - fall through */
  26749.    case ALPHABETICAL_ORDER:
  26750.    default:                  /* default is alphabetical order */
  26751.         for (gp = np->first_newsgroup; gp; gp = gp->next) {
  26752.           if (GroupInTable(gp)) {
  26753.             output_newsgroup_line(np,gp,xfp);
  26754.           }
  26755.         }
  26756.         break;
  26757.  }
  26758.  
  26759.  fprintf(xfp,"\n");
  26760.  
  26761.  if (ferror(xfp)){
  26762.    ERR2("An error occurred writing to %s.", ep->dsname);
  26763.  }
  26764.  else {
  26765.    WARN2("A list of titles has been written to %s.", ep->dsname);
  26766.  }
  26767.  
  26768.  (ep->closer)(np,ep,xfp,TRUE);     /* Close the file */
  26769.  
  26770.  return TRUE;
  26771.  
  26772. }
  26773.  
  26774. ./ ADD NAME=NNMXTX
  26775.  
  26776.  /********************************************************************/
  26777.  /*                                                                  */
  26778.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  26779.  /*                                                                  */
  26780.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  26781.  /* including the implied warranties of merchantability and fitness, */
  26782.  /* are expressly denied.                                            */
  26783.  /*                                                                  */
  26784.  /* Provided this copyright notice is included, this software may    */
  26785.  /* be freely distributed and not offered for sale.                  */
  26786.  /*                                                                  */
  26787.  /* Changes or modifications may be made and used only by the maker  */
  26788.  /* of same, and not further distributed.  Such modifications should */
  26789.  /* be mailed to the author for consideration for addition to the    */
  26790.  /* software and incorporation in subsequent releases.               */
  26791.  /*                                                                  */
  26792.  /********************************************************************/
  26793.  
  26794. #pragma  csect(code,  "NN@XTX  ")
  26795. #pragma  csect(static,"NN$XTX  ")
  26796. #include "nn.h"
  26797.  
  26798. #define XFPUTC(A)     np->extract_write_error = (fputc((A),xfp) == EOF)
  26799.  
  26800. #define XFWRITE(A,B)  fwrite((A),(B),1,xfp), \
  26801.                       np->extract_write_error = (ferror(xfp) != 0)
  26802.  
  26803. /****** Extract the lines of server text into a data set. ************/
  26804.  
  26805. Bool
  26806. NNMxtx(np,ap,headerstoo)
  26807. Rstruc nncb         *np;
  26808. Rstruc newsarticle  *ap;
  26809. Fool                 headerstoo;
  26810. {
  26811.  FILE               *xfp;
  26812.  struct texthdr     *thp;
  26813.  struct textline    *tp;
  26814.  struct extraction  *ep;
  26815.  int                 l;
  26816.  int                 linelen;
  26817.  char               *cp;
  26818.  Bool                printing;
  26819.  char                formatted_number [11];
  26820.  struct extraction   the_extraction;
  26821.  
  26822.  /* If article is not specified, use main nncb, else article's text */
  26823.  
  26824.  thp = (ap ? &ap->thdr : &np->thdr);
  26825.  
  26826.  printing = np->printing;
  26827.  np->printing = FALSE;
  26828.  
  26829.  /* Set article data for message. */
  26830.  
  26831.  if (ap) {
  26832.    sprintf(formatted_number,"%d",ap->number);
  26833.    (void)NNMivput(np,"NNTNUM ",  formatted_number, -1);
  26834.    (void)NNMivput(np,"NNTSUBJ ", ap->subject,      -1);
  26835.  }
  26836.  else {
  26837.    (void)NNMivput(np,"NNTNUM ",  "", -1);
  26838.    (void)NNMivput(np,"NNTSUBJ ", "", -1);
  26839.  }
  26840.  
  26841.  if (np->extract_file) {
  26842.    if (!np->following_up) {
  26843.      (void)NNMispf(np,"CONTROL DISPLAY LOCK");
  26844.      if (printing)
  26845.         (void)NNMispf(np,"DISPLAY PANEL(NNMLPRN2)");
  26846.      else
  26847.         (void)NNMispf(np,"DISPLAY PANEL(NNMLEXN2)");
  26848.    }
  26849.    xfp = np->extract_file;
  26850.    ep = np->extractionp;
  26851.  }
  26852.  else {
  26853.  
  26854.    ep = &the_extraction;
  26855.    memset(ep,0,sizeof(struct extraction));
  26856.    if (printing) {
  26857.      ep->mode = JES;
  26858.      strcpy(ep->panelname,"NNMPPRDS");
  26859.    }
  26860.    else {
  26861.      ep->mode = SEQ;
  26862.      strcpy(ep->panelname,"NNMPEXDS");
  26863.    }
  26864.  
  26865.    if (!((xfp=NNMgetds(np,ep)))) return FALSE;
  26866.  
  26867.    np->extract_tab_expanding          = ep->tab_expanding;
  26868.    np->extract_appending              = ep->appending;
  26869.    np->extract_ejecting               = ep->ejecting;
  26870.    np->extract_blank_before_separator = ep->blanking;
  26871.    np->extract_separator_line         = ep->separator;
  26872.  }
  26873.  
  26874.  /* If append mode, and a separator line was specified, use it. */
  26875.  
  26876.  np->extract_write_error = FALSE;
  26877.  np->extract_close_error = FALSE;
  26878.  
  26879.  if (np->extract_ejecting) {
  26880.    XFPUTC('\f');
  26881.  }
  26882.  
  26883.  if (np->extract_appending) {
  26884.    XFPUTC('\n');
  26885.    if (np->extract_separator_line && *np->extract_separator_line) {
  26886.      XFWRITE(np->extract_separator_line,
  26887.              strlen(np->extract_separator_line));
  26888.      XFPUTC('\n');
  26889.      if (np->extract_blank_before_separator) XFPUTC('\n');
  26890.    }
  26891.  }
  26892.  
  26893.  if      (headerstoo)               tp = thp->first_text_line;
  26894.  else if ((tp=thp->text_body_line)) tp = tp->next;
  26895.  
  26896.  linelen = (printing ? 120 : 251);
  26897.  
  26898.  for (; tp && !np->extract_write_error; tp = tp->next) {
  26899.    if (tp->text_length == 0) {
  26900.      if (np->following_up) XFPUTC('>');
  26901.      XFPUTC('\n');
  26902.    }
  26903.    else if (tp->text_length > 0) {
  26904.      if (np->extract_tab_expanding) {
  26905.        cp = tp->tab_expanded_text;
  26906.        l  = tp->tab_expanded_text_length;
  26907.      }
  26908.      else {
  26909.        cp = tp->text;
  26910.        l  = tp->text_length;
  26911.      }
  26912.      for (; l>0 && !np->extract_write_error; cp+=linelen, l-=linelen) {
  26913.        if (np->following_up) XFPUTC('>');
  26914.        XFWRITE(cp,(l > linelen ? linelen : l));
  26915.        XFPUTC('\n');
  26916.      }
  26917.    }
  26918.  }
  26919.  
  26920.  if (!np->extract_write_error && ferror(xfp))
  26921.     np->extract_write_error = TRUE;
  26922.  
  26923.  if (!np->following_up) {
  26924.    if (!np->extract_appending || !np->extract_file) {
  26925.      (ep->closer)(np,ep,xfp,printing);   /* Close the file */
  26926.      if (np->extract_close_error) return FALSE;
  26927.    }
  26928.  }
  26929.  if (!np->extract_file) {
  26930.    if (np->extract_write_error) {
  26931.      ERR2("An error occurred writing to %s.",ep->dsname);
  26932.      np->extract_write_error = TRUE;
  26933.    }
  26934.    else if (ap) {
  26935.      WARN3("Article %d has been written to %s.",ap->number,ep->dsname);
  26936.    }
  26937.    else {
  26938.      WARN2("Displayed text has been written to %s.",ep->dsname);
  26939.    }
  26940.  }
  26941.  if (np->extract_write_error) return FALSE;
  26942.  else return TRUE;
  26943. }
  26944.  
  26945. ./ ENDUP
  26946. ?!
  26947. //PANELS   EXEC MDLOAD,BS='6160',TRK1='10',TRK2='1',TO='PANELS'
  26948. //SYSIN    DD   DATA,DLM='?!'
  26949. ./ ADD NAME=NNL
  26950. )ATTR
  26951.  ~ TYPE(INPUT)  INTENS(HIGH) PAD('_')
  26952.  # TYPE(INPUT)  INTENS(LOW)  CAPS(OFF)
  26953.  $ TYPE(INPUT)  INTENS(LOW)  CAPS(ON)
  26954. )BODY
  26955. %---------------  NETNEWS SERVER SELECTION MENU  -------------------------------
  26956. %Command ===>_ZCMD                                            %Scroll ===>_AMT +
  26957. %
  26958. +Line commands:    %D+(Delete) %I+(Insert) %R+(Replicate) %S+(Select)
  26959. %
  26960. %    Server                                       NEWSRC dsname
  26961. %    -------------------------------------------- ------------------------------
  26962. )MODEL
  26963. %~Z%#SERVER                                      $NEWSRC
  26964. )INIT
  26965.   .ZVARS = '(NNSEL)'
  26966.   &AMT = &ZSCML
  26967. )PROC
  26968.   IF (&ZCMD ^= &Z) .MSG = ISPZ001
  26969.   &ZSCML = &AMT
  26970.   VPUT (ZSCML) PROFILE
  26971. )END
  26972.  /* Panel due to Leonard D. Woren <ldw@mvsa.usc.edu>. */
  26973. ./ ADD NAME=NNM
  26974. )ATTR
  26975. /*                                                                   /*
  26976. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  26977. /*                                                                   /*
  26978. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  26979. /*                                                                   /*
  26980. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  26981. /* including the implied warranties of merchantability and fitness,  /*
  26982. /* are expressly denied.                                             /*
  26983. /*                                                                   /*
  26984. /* Provided this copyright notice is included, this software may     /*
  26985. /* be freely distributed and not offered for sale.                   /*
  26986. /*                                                                   /*
  26987. /* Changes or modifications may be made and used only by the maker   /*
  26988. /* of same, and not further distributed.  Such modifications should  /*
  26989. /* be mailed to the author for consideration for addition to the     /*
  26990. /* software and incorporation in subsequent releases.                /*
  26991. /*                                                                   /*
  26992.  ^ TYPE(INPUT) INTENS(HIGH) COLOR(GREEN) CAPS(OFF)
  26993.  ! TYPE(TEXT)  INTENS(HIGH) COLOR(RED)
  26994. )BODY EXPAND(``)
  26995. %-`-`-  MVS Network News Viewer -`-`-
  26996. %COMMAND ===>_ZCMD
  26997. +
  26998. +Select one of the following options:
  26999. +
  27000. + %L+or%blank+   - List all newsgroups from server
  27001. + %N +NEWGROUPS  - List new newsgroups from server since last N or L
  27002. + %A +ALL        - Select items from all newsgroups listed in NEWSRC file
  27003. + %R +REGISTERED - Select items from registered newsgroups in NEWSRC file
  27004. + %G +GROUP      - Go directly to the newsgroup named below
  27005. + %NNTP+         - Enter native NNTP protocol commands
  27006. + %OPTions+      - Specify NNMVS defaults
  27007. + %X +EXIT       - Bye
  27008. +
  27009. %Newsgroup name +(if option G selected)%===>^NNGROUPI
  27010. +
  27011. %News server host name+(or IP address) %===>_NNSERVER
  27012. +
  27013. %Name of NEWSRC data set               %===>_NNNEWSRF
  27014. +
  27015. +Press!END+key to leave this menu.
  27016. )INIT
  27017.  .HELP = TNNM
  27018.  IF (&NNCURSOR = &Z)
  27019.   IF (&NNSERVER = &Z)
  27020.    .CURSOR = NNSERVER
  27021.   ELSE
  27022.    .CURSOR = ZCMD
  27023.  ELSE
  27024.   .CURSOR = &NNCURSOR
  27025.  &ZCMD = &Z
  27026.  IF (&NNREGNNG = &Z) &NNREGNNG = PROMPT
  27027.  IF (&NNNEWSRF = &Z) &NNNEWSRF = NEWSRC
  27028. )PROC
  27029.  IF   (&NNGROUPI ^= &Z) VER(&ZCMD,NB)
  27030.  IF   (&ZCMD = ' ')  &ZCMD = 'L'      /* remove if you hate BLANK */
  27031.  &ZCMD = TRANS(&ZCMD A,A R,R L,L G,G N,N
  27032.                      O,O OPT,O OPTIONS,O NNTP,P P,P X,X LD,Z *,?)
  27033.  IF   (&ZCMD ^= 'X') VER (&NNSERVER,NB)
  27034.  IF   (&ZCMD = 'G')  VER (&NNGROUPI,NB)
  27035.  &NNREGNNG = TRUNC(&NNREGNNG,1)
  27036.  VER  (&NNREGNNG,NB,LIST,Y,N,P)
  27037.  VER  (&NNNEWSRF,NB,DSNAME)
  27038.  &TEMP1 = TRUNC(&NNNEWSRF,1)
  27039.  &TEMP2 = .TRAIL
  27040.  IF (&TEMP1 = '''')
  27041.   &NNNEWSRC = TRUNC(&TEMP2,'''')
  27042.  ELSE
  27043.   &NNNEWSRC = '&ZPREFIX..&NNNEWSRF'
  27044.  VPUT (NNGROUPI NNSERVER NNREGNNG NNNEWSRF) PROFILE
  27045. )END
  27046. ./ ADD NAME=NNMDAR
  27047. )ATTR DEFAULT(%+\)
  27048. /*                                                                   /*
  27049. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27050. /*                                                                   /*
  27051. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27052. /* including the implied warranties of merchantability and fitness,  /*
  27053. /* are expressly denied.                                             /*
  27054. /*                                                                   /*
  27055. /* Provided this copyright notice is included, this software may     /*
  27056. /* be freely distributed and not offered for sale.                   /*
  27057. /*                                                                   /*
  27058. /* Changes or modifications may be made and used only by the maker   /*
  27059. /* of same, and not further distributed.  Such modifications should  /*
  27060. /* be mailed to the author for consideration for addition to the     /*
  27061. /* software and incorporation in subsequent releases.                /*
  27062. /*                                                                   /*
  27063.  ~ TYPE(INPUT) INTENS(HIGH)  CAPS(OFF) JUST(LEFT)
  27064.  ^ TYPE(INPUT) INTENS(HIGH)  CAPS(OFF) JUST(LEFT)
  27065.  |  AREA(DYNAMIC) EXTEND(ON) SCROLL(ON)
  27066.  01 TYPE(DATAOUT) INTENS(LOW)
  27067.  02 TYPE(DATAOUT) INTENS(HIGH)
  27068.  03 TYPE(DATAIN)  INTENS(LOW)
  27069.  04 TYPE(DATAIN)  INTENS(HIGH)
  27070.  05 TYPE(DATAOUT) COLOR(GREEN)
  27071.  06 TYPE(DATAOUT) COLOR(PINK)
  27072.  07 TYPE(DATAOUT) COLOR(RED)
  27073.  08 TYPE(DATAOUT) COLOR(TURQ)
  27074.  09 TYPE(DATAOUT) COLOR(YELLOW)
  27075.  0A TYPE(DATAIN)  COLOR(BLUE)
  27076.  0B TYPE(DATAIN)  COLOR(PINK)
  27077.  0C TYPE(DATAIN)  COLOR(TURQ)
  27078.  0D TYPE(DATAIN)  COLOR(WHITE)
  27079.  0E TYPE(DATAIN)  COLOR(YELLOW)
  27080. )BODY EXPAND(``)
  27081. %&NNTHEAD
  27082. %COMMAND ===>~NNTCMD                                          %SCROLL ===>^NNTS+
  27083. +                                                                              %
  27084. Article:%S+select%E+extract%P+print%M+mark%U+unmark%C+cancel%Status   Date
  27085.  _______________________________________________________________________________
  27086. |NNTDYNA                                                                       |
  27087. )INIT
  27088.  .HELP = TNNMT
  27089.  IF (&NNTS = &Z) &NNTS = CSR
  27090.  IF (&NNTCSR ^= 0)
  27091.   .CURSOR=NNTDYNA
  27092.   .CSRPOS=&NNTCSR
  27093. )PROC
  27094.  &NNTLVL = LVLINE(NNTDYNA)
  27095.  VPUT (NNTS) PROFILE
  27096. )END
  27097. ./ ADD NAME=NNMDBOGG
  27098. )ATTR DEFAULT(%+_)
  27099. /*                                                                   /*
  27100. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27101. /*                                                                   /*
  27102. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27103. /* including the implied warranties of merchantability and fitness,  /*
  27104. /* are expressly denied.                                             /*
  27105. /*                                                                   /*
  27106. /* Provided this copyright notice is included, this software may     /*
  27107. /* be freely distributed and not offered for sale.                   /*
  27108. /*                                                                   /*
  27109. /* Changes or modifications may be made and used only by the maker   /*
  27110. /* of same, and not further distributed.  Such modifications should  /*
  27111. /* be mailed to the author for consideration for addition to the     /*
  27112. /* software and incorporation in subsequent releases.                /*
  27113. /*                                                                   /*
  27114.  ^  TYPE(INPUT)  INTENS(HIGH) CAPS(ON) JUST(LEFT)
  27115.  |  AREA(DYNAMIC) EXTEND(ON) SCROLL(ON)
  27116.  01 TYPE(DATAOUT) INTENS(LOW)
  27117.  02 TYPE(DATAOUT) INTENS(HIGH)
  27118.  03 TYPE(DATAIN)  INTENS(LOW)
  27119.  04 TYPE(DATAIN)  INTENS(HIGH)
  27120. )BODY EXPAND(``)
  27121. %-`-`- Unknown Newsgroups (found in NEWSRC but not by server) -`-`-
  27122. %COMMAND ===>^ZCMD                                            %SCROLL ===>_AMT +
  27123.  
  27124. +Groups displayed will be deleted from NEWSRC.  Scroll up/down to see all.
  27125. +Type%K+to keep a group,%D+to delete. %&END+to accept. %QUIT+or%CANCEL+to abort.
  27126. -------------------------------------------------------------------------------+
  27127. |NNDYNA                                                                        |
  27128. )INIT
  27129.  .HELP = TNNM
  27130.  &END = PFK(END)
  27131.  IF (&AMT = &Z) &AMT = CSR
  27132.  IF (&NNDB1ST = &Z)
  27133.   &NNDB1ST = NO
  27134.   .ALARM = YES
  27135. )PROC
  27136.  VER (&ZCMD,LIST,QUIT,CAN,CANCEL)
  27137.  &NNLVL = LVLINE(NNDYNA)
  27138. )END
  27139. ./ ADD NAME=NNMDNEWG
  27140. )ATTR DEFAULT(%+_)
  27141. /*                                                                   /*
  27142. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27143. /*                                                                   /*
  27144. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27145. /* including the implied warranties of merchantability and fitness,  /*
  27146. /* are expressly denied.                                             /*
  27147. /*                                                                   /*
  27148. /* Provided this copyright notice is included, this software may     /*
  27149. /* be freely distributed and not offered for sale.                   /*
  27150. /*                                                                   /*
  27151. /* Changes or modifications may be made and used only by the maker   /*
  27152. /* of same, and not further distributed.  Such modifications should  /*
  27153. /* be mailed to the author for consideration for addition to the     /*
  27154. /* software and incorporation in subsequent releases.                /*
  27155. /*                                                                   /*
  27156.  ^  TYPE(INPUT)  INTENS(HIGH) CAPS(ON) JUST(LEFT)
  27157.  |  AREA(DYNAMIC) EXTEND(ON) SCROLL(ON)
  27158.  01 TYPE(DATAOUT) INTENS(LOW)
  27159.  02 TYPE(DATAOUT) INTENS(HIGH)
  27160.  03 TYPE(DATAIN)  INTENS(LOW)
  27161.  04 TYPE(DATAIN)  INTENS(HIGH)
  27162. )BODY EXPAND(``)
  27163. %-`-`- New Newsgroups -`-`-
  27164. %COMMAND ===>^ZCMD                                            %SCROLL ===>_AMT +
  27165.  
  27166. +Type%R+to register a newsgroup; %D+to deregister. Scroll up/down to see all.
  27167. +Registered group names highlighted. %&END+to accept. %QUIT+or%CANCEL+to abort.
  27168. -------------------------------------------------------------------------------+
  27169. |NNDYNA                                                                        |
  27170. )INIT
  27171.  .HELP = TNNM
  27172.  &END = PFK(END)
  27173.  IF (&AMT = &Z) &AMT = CSR
  27174.  IF (&NNDN1ST = &Z)
  27175.   &NNDN1ST = NO
  27176.   .ALARM = YES
  27177. )PROC
  27178.  VER (&ZCMD,LIST,QUIT,CAN,CANCEL)
  27179.  &NNLVL = LVLINE(NNDYNA)
  27180. )END
  27181. ./ ADD NAME=NNMDNG
  27182. )ATTR
  27183. /*                                                                   /*
  27184. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27185. /*                                                                   /*
  27186. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27187. /* including the implied warranties of merchantability and fitness,  /*
  27188. /* are expressly denied.                                             /*
  27189. /*                                                                   /*
  27190. /* Provided this copyright notice is included, this software may     /*
  27191. /* be freely distributed and not offered for sale.                   /*
  27192. /*                                                                   /*
  27193. /* Changes or modifications may be made and used only by the maker   /*
  27194. /* of same, and not further distributed.  Such modifications should  /*
  27195. /* be mailed to the author for consideration for addition to the     /*
  27196. /* software and incorporation in subsequent releases.                /*
  27197. /*                                                                   /*
  27198.  ~ TYPE(INPUT) INTENS(HIGH)  CAPS(OFF) JUST(LEFT)
  27199.  ^ TYPE(INPUT) INTENS(HIGH)  CAPS(OFF) JUST(LEFT)
  27200.  ! TYPE(OUTPUT) INTENS(LOW)  CAPS(OFF) JUST(RIGHT) COLOR(YELLOW)
  27201.  # TYPE(OUTPUT) INTENS(LOW)  CAPS(OFF) JUST(RIGHT) COLOR(BLUE)
  27202.  @ TYPE(OUTPUT) INTENS(HIGH) CAPS(OFF) JUST(RIGHT) COLOR(PINK)
  27203.  ? TYPE(OUTPUT) INTENS(LOW)  CAPS(OFF) JUST(LEFT)  COLOR(TURQ) PAD('.')
  27204.  |  AREA(DYNAMIC) EXTEND(ON) SCROLL(ON)
  27205.  \  AREA(DYNAMIC) EXTEND(OFF) SCROLL(OFF)
  27206.  01 TYPE(DATAOUT) INTENS(LOW)
  27207.  02 TYPE(DATAOUT) INTENS(HIGH)
  27208.  03 TYPE(DATAIN)  INTENS(LOW)
  27209.  04 TYPE(DATAIN)  INTENS(HIGH)
  27210.  05 TYPE(DATAOUT) COLOR(GREEN)
  27211.  06 TYPE(DATAOUT) COLOR(PINK)
  27212.  07 TYPE(DATAOUT) COLOR(RED)
  27213.  08 TYPE(DATAOUT) COLOR(TURQ)
  27214.  09 TYPE(DATAOUT) COLOR(YELLOW)
  27215.  0A TYPE(DATAIN)  COLOR(BLUE)
  27216.  0B TYPE(DATAIN)  COLOR(PINK)
  27217.  0C TYPE(DATAIN)  COLOR(TURQ)
  27218.  0D TYPE(DATAIN)  COLOR(WHITE)
  27219.  0E TYPE(DATAIN)  COLOR(YELLOW)
  27220. )BODY EXPAND(``)
  27221. %&NNGHEAD
  27222. %COMMAND ===>~NNGCMD                                          %SCROLL ===>^NNGS+
  27223. +
  27224. \NNGLINE                                                                       \
  27225.  -------------------------------------------------------------------------------
  27226. |NNGDYNA                                                                       |
  27227. )INIT
  27228.  .HELP = TNNMG
  27229.  IF (&NNGS = &Z) &NNGS = CSR
  27230.  IF (&NNGCSR ^= 0)
  27231.   .CURSOR=NNGDYNA
  27232.   .CSRPOS=&NNGCSR
  27233. )PROC
  27234.  &NNGLVL = LVLINE(NNGDYNA)
  27235.  VPUT (NNGS) PROFILE
  27236. )END
  27237. ./ ADD NAME=NNMLADDG
  27238. )ATTR
  27239. /*                                                                   /*
  27240. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27241. /*                                                                   /*
  27242. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27243. /* including the implied warranties of merchantability and fitness,  /*
  27244. /* are expressly denied.                                             /*
  27245. /*                                                                   /*
  27246. /* Provided this copyright notice is included, this software may     /*
  27247. /* be freely distributed and not offered for sale.                   /*
  27248. /*                                                                   /*
  27249. /* Changes or modifications may be made and used only by the maker   /*
  27250. /* of same, and not further distributed.  Such modifications should  /*
  27251. /* be mailed to the author for consideration for addition to the     /*
  27252. /* software and incorporation in subsequent releases.                /*
  27253. /*                                                                   /*
  27254.  @ TYPE(OUTPUT) INTENS(LOW)
  27255. )BODY EXPAND(``)
  27256. %-`-`-  MVS Network News Connection -`-`-
  27257. +
  27258. +
  27259.          Adding newsgroup:
  27260. %        &NNLGROUP
  27261. +
  27262.          (Estimated number of articles...&NNLCOUNT)
  27263. +        @NNDUMMY
  27264. +
  27265.                                  % Please wait.
  27266. +
  27267. +
  27268. )INIT
  27269. )PROC
  27270. )END
  27271. ./ ADD NAME=NNMLADD2
  27272. )ATTR DEFAULT(|+_)
  27273. /*                                                                   /*
  27274. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27275. /*                                                                   /*
  27276. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  27277. /*                                                                   /*
  27278. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27279. /* including the implied warranties of merchantability and fitness,  /*
  27280. /* are expressly denied.                                             /*
  27281. /*                                                                   /*
  27282. /* Provided this copyright notice is included, this software may     /*
  27283. /* be freely distributed and not offered for sale.                   /*
  27284. /*                                                                   /*
  27285. /* Changes or modifications may be made and used only by the maker   /*
  27286. /* of same, and not further distributed.  Such modifications should  /*
  27287. /* be mailed to the author for consideration for addition to the     /*
  27288. /* software and incorporation in subsequent releases.                /*
  27289. /*                                                                   /*
  27290.  ^ TYPE(DATAOUT) INTENS(HIGH) COLOR(TURQ) HILITE(REVERSE)
  27291.  / TYPE(DATAOUT) INTENS(HIGH) COLOR(TURQ)
  27292.  * AREA(DYNAMIC)
  27293. )BODY EXPAND(``)
  27294. |-`-`-  MVS Network News Connection -`-`-
  27295. +
  27296.  
  27297.          Now adding newsgroups
  27298.  
  27299. +
  27300.          Percentage of news groups processed:
  27301.          ------------------------------------------------------------
  27302.         *NNMBAR                                                     *|&NNMCOUNT
  27303. +        ------------------------------------------------------------
  27304.         0%                          50%                              100%
  27305.  
  27306.      This may take a long time, depending on the number of newsgroups.
  27307.  
  27308.  
  27309. |                                  Please wait.
  27310.  
  27311. )INIT
  27312. )PROC
  27313. )END
  27314. ./ ADD NAME=NNMLADD3
  27315. )ATTR DEFAULT(|+_)
  27316. /*                                                                   /*
  27317. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27318. /*                                                                   /*
  27319. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  27320. /*                                                                   /*
  27321. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27322. /* including the implied warranties of merchantability and fitness,  /*
  27323. /* are expressly denied.                                             /*
  27324. /*                                                                   /*
  27325. /* Provided this copyright notice is included, this software may     /*
  27326. /* be freely distributed and not offered for sale.                   /*
  27327. /*                                                                   /*
  27328. /* Changes or modifications may be made and used only by the maker   /*
  27329. /* of same, and not further distributed.  Such modifications should  /*
  27330. /* be mailed to the author for consideration for addition to the     /*
  27331. /* software and incorporation in subsequent releases.                /*
  27332. /*                                                                   /*
  27333.  ^ TYPE(DATAOUT) INTENS(HIGH) COLOR(TURQ) HILITE(REVERSE)
  27334.  / TYPE(DATAOUT) INTENS(HIGH) COLOR(TURQ)
  27335.  * AREA(DYNAMIC)
  27336. )BODY EXPAND(``)
  27337. |-`-`-  MVS Network News Connection -`-`-
  27338. +
  27339.  
  27340.          Now adding newsgroup:
  27341.         |&NNLGROUP
  27342. +
  27343.          Percentage of news groups processed:
  27344.          ------------------------------------------------------------
  27345.         *NNMBAR                                                     *|&NNMCOUNT
  27346. +        ------------------------------------------------------------
  27347.         0%                          50%                              100%
  27348.  
  27349.      This may take a long time, depending on the number of newsgroups.
  27350.  
  27351.  
  27352. |                                  Please wait.
  27353.  
  27354. )INIT
  27355. )PROC
  27356. )END
  27357. ./ ADD NAME=NNMLARTS
  27358. )ATTR
  27359. /*                                                                   /*
  27360. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27361. /*                                                                   /*
  27362. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27363. /* including the implied warranties of merchantability and fitness,  /*
  27364. /* are expressly denied.                                             /*
  27365. /*                                                                   /*
  27366. /* Provided this copyright notice is included, this software may     /*
  27367. /* be freely distributed and not offered for sale.                   /*
  27368. /*                                                                   /*
  27369. /* Changes or modifications may be made and used only by the maker   /*
  27370. /* of same, and not further distributed.  Such modifications should  /*
  27371. /* be mailed to the author for consideration for addition to the     /*
  27372. /* software and incorporation in subsequent releases.                /*
  27373. /*                                                                   /*
  27374.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  27375.  @ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
  27376.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  27377.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  27378.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  27379.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  27380.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  27381. )BODY EXPAND(``)
  27382. %-`-`-  MVS Network News Connection -`-`-
  27383. +
  27384. +
  27385.          Now retrieving the titles of the articles in newsgroup:
  27386. %        &NNGROUP
  27387. +
  27388.      This may take a long time, depending on the number of articles.
  27389. +
  27390. +
  27391.                                  % Please wait.
  27392. +
  27393. +
  27394. )INIT
  27395. )PROC
  27396. )END
  27397. ./ ADD NAME=NNMLART2
  27398. )ATTR DEFAULT(|+_)
  27399. /*                                                                   /*
  27400. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27401. /*                                                                   /*
  27402. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  27403. /*                                                                   /*
  27404. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27405. /* including the implied warranties of merchantability and fitness,  /*
  27406. /* are expressly denied.                                             /*
  27407. /*                                                                   /*
  27408. /* Provided this copyright notice is included, this software may     /*
  27409. /* be freely distributed and not offered for sale.                   /*
  27410. /*                                                                   /*
  27411. /* Changes or modifications may be made and used only by the maker   /*
  27412. /* of same, and not further distributed.  Such modifications should  /*
  27413. /* be mailed to the author for consideration for addition to the     /*
  27414. /* software and incorporation in subsequent releases.                /*
  27415. /*                                                                   /*
  27416.  ^ TYPE(DATAOUT) INTENS(HIGH) COLOR(TURQ) HILITE(REVERSE)
  27417.  / TYPE(DATAOUT) INTENS(HIGH) COLOR(TURQ)
  27418.  * AREA(DYNAMIC)
  27419.  $ TYPE(TEXT) INTENS(LOW)
  27420.  # TYPE(OUTPUT) INTENS(HIGH)
  27421. )BODY EXPAND(``)
  27422. |-`-`-  MVS Network News Connection -`-`-
  27423. +
  27424.  
  27425.          Now retrieving the titles of the articles in newsgroup:
  27426.         |&NNGROUP
  27427. +
  27428.          &MSG
  27429. +        ------------------------------------------------------------
  27430.         *NNMBAR                                                     *|&TODO
  27431. +        ------------------------------------------------------------
  27432.         0%                          50%                              100%
  27433.  
  27434.         $Estimated time to completion:#NNMESTM +
  27435.  
  27436.      This may take a long time, depending on the number of articles.
  27437.  
  27438.  
  27439. |                                  Please wait.
  27440.  
  27441. )INIT
  27442.  IF (&NNMESTM = &Z)
  27443.    .ATTRCHAR($) = 'INTENS(NON)'
  27444.    .ATTRCHAR(#) = 'INTENS(NON)'
  27445.  IF (&NNMCOUNT = -1)
  27446.   &TODO = &Z
  27447.   &MSG = 'Articles processed so far while searching:'
  27448.  ELSE
  27449.   &TODO = &NNMCOUNT
  27450.   &MSG = 'Percentage of articles processed so far:'
  27451. )PROC
  27452. )END
  27453. ./ ADD NAME=NNMLCONN
  27454. )ATTR
  27455. /*                                                                   /*
  27456. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27457. /*                                                                   /*
  27458. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27459. /* including the implied warranties of merchantability and fitness,  /*
  27460. /* are expressly denied.                                             /*
  27461. /*                                                                   /*
  27462. /* Provided this copyright notice is included, this software may     /*
  27463. /* be freely distributed and not offered for sale.                   /*
  27464. /*                                                                   /*
  27465. /* Changes or modifications may be made and used only by the maker   /*
  27466. /* of same, and not further distributed.  Such modifications should  /*
  27467. /* be mailed to the author for consideration for addition to the     /*
  27468. /* software and incorporation in subsequent releases.                /*
  27469. /*                                                                   /*
  27470.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  27471.  @ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
  27472.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  27473.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  27474.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  27475.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  27476.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  27477. )BODY EXPAND(``)
  27478. %-`-`-  MVS Network News Connection -`-`-
  27479. +
  27480. +             Client name: &NNCLIENT    Client IP address:  &NNCLIEIP
  27481. +
  27482. +
  27483. +             Connection is in progress for news server at:
  27484.               &NNSERVER (&NNSERVIP)
  27485. +
  27486. +
  27487.                                  % Please wait.
  27488. +
  27489. +
  27490. )INIT
  27491. )PROC
  27492. )END
  27493. ./ ADD NAME=NNMLDISC
  27494. )ATTR
  27495. /*                                                                   /*
  27496. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27497. /*                                                                   /*
  27498. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27499. /* including the implied warranties of merchantability and fitness,  /*
  27500. /* are expressly denied.                                             /*
  27501. /*                                                                   /*
  27502. /* Provided this copyright notice is included, this software may     /*
  27503. /* be freely distributed and not offered for sale.                   /*
  27504. /*                                                                   /*
  27505. /* Changes or modifications may be made and used only by the maker   /*
  27506. /* of same, and not further distributed.  Such modifications should  /*
  27507. /* be mailed to the author for consideration for addition to the     /*
  27508. /* software and incorporation in subsequent releases.                /*
  27509. /*                                                                   /*
  27510.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  27511.  @ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
  27512.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  27513.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  27514.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  27515.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  27516.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  27517. )BODY EXPAND(``)
  27518. %-`-`-  MVS Network News Connection -`-`-
  27519. +
  27520. +
  27521. +         Disconnection is in progress from the news server at:
  27522.           &NNSOLDER (&NNSOLDIP)
  27523. +
  27524. +
  27525.                                  % Please wait.
  27526. +
  27527. +
  27528. )INIT
  27529. )PROC
  27530. )END
  27531. ./ ADD NAME=NNMLEXN2
  27532. )ATTR
  27533. /*                                                                   /*
  27534. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27535. /*                                                                   /*
  27536. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27537. /* including the implied warranties of merchantability and fitness,  /*
  27538. /* are expressly denied.                                             /*
  27539. /*                                                                   /*
  27540. /* Provided this copyright notice is included, this software may     /*
  27541. /* be freely distributed and not offered for sale.                   /*
  27542. /*                                                                   /*
  27543. /* Changes or modifications may be made and used only by the maker   /*
  27544. /* of same, and not further distributed.  Such modifications should  /*
  27545. /* be mailed to the author for consideration for addition to the     /*
  27546. /* software and incorporation in subsequent releases.                /*
  27547. /*                                                                   /*
  27548.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  27549.  @ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
  27550.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  27551.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  27552.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  27553.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  27554. )BODY EXPAND(``)
  27555. %-`-`-  MVS Network News Connection -`-`-
  27556. +
  27557. +Newsgroup: &NNLGROUP
  27558. +
  27559. +Article #:%&NNTNUM
  27560. +Subject:   &NNTSUBJ
  27561. +
  27562. +Extracting to: &NNEXDSN
  27563. +&MEMSTUFF
  27564. +
  27565.                                  % Please wait.
  27566. +
  27567. )INIT
  27568.  IF (&NNEXMEM = &Z) &MEMSTUFF = &Z
  27569.  ELSE               &MEMSTUFF = 'Member: &NNEXMEM'
  27570. )PROC
  27571. )END
  27572. ./ ADD NAME=NNMLLIST
  27573. )ATTR
  27574. /*                                                                   /*
  27575. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27576. /*                                                                   /*
  27577. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27578. /* including the implied warranties of merchantability and fitness,  /*
  27579. /* are expressly denied.                                             /*
  27580. /*                                                                   /*
  27581. /* Provided this copyright notice is included, this software may     /*
  27582. /* be freely distributed and not offered for sale.                   /*
  27583. /*                                                                   /*
  27584. /* Changes or modifications may be made and used only by the maker   /*
  27585. /* of same, and not further distributed.  Such modifications should  /*
  27586. /* be mailed to the author for consideration for addition to the     /*
  27587. /* software and incorporation in subsequent releases.                /*
  27588. /*                                                                   /*
  27589.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  27590.  @ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
  27591.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  27592.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  27593.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  27594.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  27595.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  27596. )BODY EXPAND(``)
  27597. %-`-`-  MVS Network News Connection -`-`-
  27598. +
  27599. +
  27600.        A list of all newsgroups is being retrieved from the news server at:
  27601.        &NNSERVER (&NNSERVIP)
  27602. +
  27603.      This may take a long time, depending on the number of newsgroups known.
  27604. +
  27605. +
  27606.                                  % Please wait.
  27607. +
  27608. +
  27609. )INIT
  27610. )PROC
  27611. )END
  27612. ./ ADD NAME=NNMLNEWG
  27613. )ATTR
  27614. /*                                                                   /*
  27615. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27616. /*                                                                   /*
  27617. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  27618. /*                                                                   /*
  27619. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27620. /* including the implied warranties of merchantability and fitness,  /*
  27621. /* are expressly denied.                                             /*
  27622. /*                                                                   /*
  27623. /* Provided this copyright notice is included, this software may     /*
  27624. /* be freely distributed and not offered for sale.                   /*
  27625. /*                                                                   /*
  27626. /* Changes or modifications may be made and used only by the maker   /*
  27627. /* of same, and not further distributed.  Such modifications should  /*
  27628. /* be mailed to the author for consideration for addition to the     /*
  27629. /* software and incorporation in subsequent releases.                /*
  27630. /*                                                                   /*
  27631.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  27632.  @ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
  27633.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  27634.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  27635.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  27636.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  27637.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  27638. )BODY EXPAND(``)
  27639. %-`-`-  MVS Network News Connection -`-`-
  27640. +
  27641. +
  27642.        A list of new newsgroups since &NNNGDT &NNNGTM is being retrieved
  27643. +      from the news server at:  &NNSERVER (&NNSERVIP)
  27644. +
  27645.      This may take a long time, depending on the number of newsgroups known.
  27646. +
  27647. +
  27648.                                  % Please wait.
  27649. +
  27650. +
  27651. )INIT
  27652. )PROC
  27653. )END
  27654. ./ ADD NAME=NNMLPRN2
  27655. )ATTR
  27656. /*                                                                   /*
  27657. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1993     /*
  27658. /*                                                                   /*
  27659. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27660. /* including the implied warranties of merchantability and fitness,  /*
  27661. /* are expressly denied.                                             /*
  27662. /*                                                                   /*
  27663. /* Provided this copyright notice is included, this software may     /*
  27664. /* be freely distributed and not offered for sale.                   /*
  27665. /*                                                                   /*
  27666. /* Changes or modifications may be made and used only by the maker   /*
  27667. /* of same, and not further distributed.  Such modifications should  /*
  27668. /* be mailed to the author for consideration for addition to the     /*
  27669. /* software and incorporation in subsequent releases.                /*
  27670. /*                                                                   /*
  27671.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  27672.  @ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
  27673.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  27674.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  27675.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  27676.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  27677. )BODY EXPAND(``)
  27678. %-`-`-  MVS Network News Connection -`-`-
  27679. +
  27680. +Newsgroup: &NNLGROUP
  27681. +
  27682. +Article #:%&NNTNUM
  27683. +Subject:   &NNTSUBJ
  27684. +
  27685. +Printing to SYSOUT class: &NNEXSCL
  27686. +&MEMSTUFF
  27687. +
  27688.                                  % Please wait.
  27689. +
  27690. )INIT
  27691.  IF (&NNEXMEM = &Z) &MEMSTUFF = &Z
  27692.  ELSE               &MEMSTUFF = 'Member: &NNEXMEM'
  27693. )PROC
  27694. )END
  27695. ./ ADD NAME=NNMLRCON
  27696. )ATTR
  27697. /*                                                                   /*
  27698. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27699. /*                                                                   /*
  27700. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27701. /* including the implied warranties of merchantability and fitness,  /*
  27702. /* are expressly denied.                                             /*
  27703. /*                                                                   /*
  27704. /* Provided this copyright notice is included, this software may     /*
  27705. /* be freely distributed and not offered for sale.                   /*
  27706. /*                                                                   /*
  27707. /* Changes or modifications may be made and used only by the maker   /*
  27708. /* of same, and not further distributed.  Such modifications should  /*
  27709. /* be mailed to the author for consideration for addition to the     /*
  27710. /* software and incorporation in subsequent releases.                /*
  27711. /*                                                                   /*
  27712.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  27713.  @ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
  27714.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  27715.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  27716.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  27717.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  27718.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  27719. )BODY EXPAND(``)
  27720. %-`-`-  MVS Network News Connection -`-`-
  27721. +
  27722.         +Connection has apparently been lost to the news server at:
  27723.         &NNSERVER (&NNSERVIP)
  27724. +
  27725.                 +Reconnection to the server is in progress.
  27726. +
  27727.                                  % Please wait.
  27728. +
  27729. +
  27730. )INIT
  27731. )PROC
  27732. )END
  27733. ./ ADD NAME=NNMLRETG
  27734. )ATTR
  27735. /*                                                                   /*
  27736. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27737. /*                                                                   /*
  27738. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27739. /* including the implied warranties of merchantability and fitness,  /*
  27740. /* are expressly denied.                                             /*
  27741. /*                                                                   /*
  27742. /* Provided this copyright notice is included, this software may     /*
  27743. /* be freely distributed and not offered for sale.                   /*
  27744. /*                                                                   /*
  27745. /* Changes or modifications may be made and used only by the maker   /*
  27746. /* of same, and not further distributed.  Such modifications should  /*
  27747. /* be mailed to the author for consideration for addition to the     /*
  27748. /* software and incorporation in subsequent releases.                /*
  27749. /*                                                                   /*
  27750.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  27751.  @ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
  27752.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  27753.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  27754.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  27755.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  27756.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  27757. )BODY EXPAND(``)
  27758. %-`-`-  MVS Network News Connection -`-`-
  27759. +
  27760. +
  27761.          Retrieving current status of newsgroup:
  27762. %        &NNLGROUP
  27763. +
  27764. +
  27765.                                  % Please wait.
  27766. +
  27767. +
  27768. )INIT
  27769. )PROC
  27770. )END
  27771. ./ ADD NAME=NNMLRET2
  27772. )ATTR DEFAULT(|+_)
  27773. /*                                                                   /*
  27774. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27775. /*                                                                   /*
  27776. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  27777. /*                                                                   /*
  27778. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27779. /* including the implied warranties of merchantability and fitness,  /*
  27780. /* are expressly denied.                                             /*
  27781. /*                                                                   /*
  27782. /* Provided this copyright notice is included, this software may     /*
  27783. /* be freely distributed and not offered for sale.                   /*
  27784. /*                                                                   /*
  27785. /* Changes or modifications may be made and used only by the maker   /*
  27786. /* of same, and not further distributed.  Such modifications should  /*
  27787. /* be mailed to the author for consideration for addition to the     /*
  27788. /* software and incorporation in subsequent releases.                /*
  27789. /*                                                                   /*
  27790.  ^ TYPE(DATAOUT) INTENS(HIGH) COLOR(TURQ) HILITE(REVERSE)
  27791.  / TYPE(DATAOUT) INTENS(HIGH) COLOR(TURQ)
  27792.  * AREA(DYNAMIC)
  27793.  $ TYPE(TEXT) INTENS(LOW)
  27794.  # TYPE(OUTPUT) INTENS(HIGH)
  27795. )BODY EXPAND(``)
  27796. |-`-`-  MVS Network News Connection -`-`-
  27797. +
  27798. +
  27799. +        Retrieving current status of registered newsgroups
  27800. +
  27801. +
  27802. +        Percentage of registered newsgroups processed:
  27803. +        ------------------------------------------------------------
  27804. +       *NNMBAR                                                     *|&NNMCOUNT
  27805. +        ------------------------------------------------------------
  27806. +       0%                          50%                              100%
  27807. +
  27808. +       $Estimated time to completion:#NNMESTM +
  27809. +
  27810. )INIT
  27811.  IF (&NNMESTM = &Z)
  27812.    .ATTRCHAR($) = 'INTENS(NON)'
  27813.    .ATTRCHAR(#) = 'INTENS(NON)'
  27814. )PROC
  27815. )END
  27816. ./ ADD NAME=NNMLRET3
  27817. )ATTR DEFAULT(|+_)
  27818. /*                                                                   /*
  27819. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27820. /*                                                                   /*
  27821. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  27822. /*                                                                   /*
  27823. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27824. /* including the implied warranties of merchantability and fitness,  /*
  27825. /* are expressly denied.                                             /*
  27826. /*                                                                   /*
  27827. /* Provided this copyright notice is included, this software may     /*
  27828. /* be freely distributed and not offered for sale.                   /*
  27829. /*                                                                   /*
  27830. /* Changes or modifications may be made and used only by the maker   /*
  27831. /* of same, and not further distributed.  Such modifications should  /*
  27832. /* be mailed to the author for consideration for addition to the     /*
  27833. /* software and incorporation in subsequent releases.                /*
  27834. /*                                                                   /*
  27835.  ^ TYPE(DATAOUT) INTENS(HIGH) COLOR(TURQ) HILITE(REVERSE)
  27836.  / TYPE(DATAOUT) INTENS(HIGH) COLOR(TURQ)
  27837.  * AREA(DYNAMIC)
  27838.  $ TYPE(TEXT) INTENS(LOW)
  27839.  # TYPE(OUTPUT) INTENS(HIGH)
  27840. )BODY EXPAND(``)
  27841. |-`-`-  MVS Network News Connection -`-`-
  27842. +
  27843. +
  27844. +        Retrieving current status of newsgroup:
  27845. |        &NNLGROUP
  27846. +
  27847. +        Percentage of registered newsgroups processed:
  27848. +        ------------------------------------------------------------
  27849. +       *NNMBAR                                                     *|&NNMCOUNT
  27850. +        ------------------------------------------------------------
  27851. +       0%                          50%                              100%
  27852. +
  27853. +       $Estimated time to completion:#NNMESTM +
  27854. +
  27855. )INIT
  27856.  IF (&NNMESTM = &Z)
  27857.    .ATTRCHAR($) = 'INTENS(NON)'
  27858.    .ATTRCHAR(#) = 'INTENS(NON)'
  27859. )PROC
  27860. )END
  27861. ./ ADD NAME=NNMLRSNG
  27862. )ATTR
  27863. /*                                                                   /*
  27864. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27865. /*                                                                   /*
  27866. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27867. /* including the implied warranties of merchantability and fitness,  /*
  27868. /* are expressly denied.                                             /*
  27869. /*                                                                   /*
  27870. /* Provided this copyright notice is included, this software may     /*
  27871. /* be freely distributed and not offered for sale.                   /*
  27872. /*                                                                   /*
  27873. /* Changes or modifications may be made and used only by the maker   /*
  27874. /* of same, and not further distributed.  Such modifications should  /*
  27875. /* be mailed to the author for consideration for addition to the     /*
  27876. /* software and incorporation in subsequent releases.                /*
  27877. /*                                                                   /*
  27878.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  27879.  @ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
  27880.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  27881.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  27882.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  27883.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  27884.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  27885. )BODY EXPAND(``)
  27886. %-`-`-  MVS Network News Connection -`-`-
  27887. +
  27888. +         Reconnection has been established to the news server at:
  27889.           &NNSERVER (&NNSERVIP)
  27890. +
  27891.           Now reestablishing current newsgroup:
  27892. %         &NNGROUP
  27893. +
  27894.                                  % Please wait.
  27895. +
  27896. +
  27897. )INIT
  27898. )PROC
  27899. )END
  27900. ./ ADD NAME=NNMLUNRC
  27901. )ATTR
  27902. /*                                                                   /*
  27903. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27904. /*                                                                   /*
  27905. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  27906. /*                                                                   /*
  27907. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27908. /* including the implied warranties of merchantability and fitness,  /*
  27909. /* are expressly denied.                                             /*
  27910. /*                                                                   /*
  27911. /* Provided this copyright notice is included, this software may     /*
  27912. /* be freely distributed and not offered for sale.                   /*
  27913. /*                                                                   /*
  27914. /* Changes or modifications may be made and used only by the maker   /*
  27915. /* of same, and not further distributed.  Such modifications should  /*
  27916. /* be mailed to the author for consideration for addition to the     /*
  27917. /* software and incorporation in subsequent releases.                /*
  27918. /*                                                                   /*
  27919.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  27920.  @ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
  27921.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  27922.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  27923.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  27924.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  27925.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  27926. )BODY EXPAND(``)
  27927. %-`-`-  MVS Network News Connection -`-`-
  27928. +
  27929. +
  27930. +                       Updating NEWSRC file &NNNEWSRF ...
  27931. +
  27932. +
  27933. +
  27934. %                                  Please wait.
  27935. +
  27936. +
  27937. )INIT
  27938. )PROC
  27939. )END
  27940. ./ ADD NAME=NNMOPTS
  27941. )ATTR
  27942. /*                                                                   /*
  27943. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27944. /*                                                                   /*
  27945. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  27946. /*                                                                   /*
  27947. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27948. /* including the implied warranties of merchantability and fitness,  /*
  27949. /* are expressly denied.                                             /*
  27950. /*                                                                   /*
  27951. /* Provided this copyright notice is included, this software may     /*
  27952. /* be freely distributed and not offered for sale.                   /*
  27953. /*                                                                   /*
  27954. /* Changes or modifications may be made and used only by the maker   /*
  27955. /* of same, and not further distributed.  Such modifications should  /*
  27956. /* be mailed to the author for consideration for addition to the     /*
  27957. /* software and incorporation in subsequent releases.                /*
  27958. /*                                                                   /*
  27959. )BODY EXPAND(``)
  27960. %-`-`- NNMVS - Article Retrieval Options -`-`-
  27961. %Command ===>_ZCMD
  27962. +
  27963. %General options:
  27964.  
  27965. +In-progress screen for adding newsgroups?  (YES/NO)%==>_Z  +
  27966. +In-progress screen for rewriting NEWSRC?   (YES/NO)%==>_Z  +
  27967. +In-progress screen for retrieving articles?(YES/NO)%==>_Z  +
  27968.  
  27969. +Screen update frequency   %==>_Z       + (Enter%ON, OFF,+or%number+of seconds)
  27970.  
  27971. %EXTRACT prompting options:
  27972.  
  27973. +Warning panel before writing over an existing dataset?%==>_Z  +
  27974. +Warning panel before appending to an existing dataset?%==>_Z  +
  27975.  
  27976. +Press%ENTER+to change options.  Press%&END+(or type%END+command) when done.
  27977. )INIT
  27978.  .ZVARS  = '(NNUPAN NNUPRN NNUPRA NNMUPDTF NNEXTPOW NNEXTPAP)'
  27979.  .HELP   = TNNMOPT
  27980.  .CURSOR = ZCMD
  27981.  &END = PFK(END)
  27982.  &ZCMD = &Z
  27983.  VGET (NNUPAN NNUPRN NNUPRA NNMUPDTF NNEXTPOW NNEXTPAP) PROFILE
  27984.  IF (&NNMUPDTF = &Z) &NNMUPDTF = '5'
  27985.  &NNUPAN   = TRANS(TRUNC(&NNUPAN,1)   Y,YES N,NO *,NO )
  27986.  &NNUPRN   = TRANS(TRUNC(&NNUPRN,1)   Y,YES N,NO *,YES)
  27987.  &NNUPRA   = TRANS(TRUNC(&NNUPRA,1)   Y,YES N,NO *,YES)
  27988.  &NNEXTPOW = TRANS(TRUNC(&NNEXTPOW,1) Y,YES N,NO *,YES)
  27989.  &NNEXTPAP = TRANS(TRUNC(&NNEXTPAP,1) Y,YES N,NO *,YES)
  27990. )PROC
  27991.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  27992.  IF (.RESP = ENTER)
  27993.   VER(&NNMUPDTF,NB)
  27994.   IF (&NNMUPDTF = '0')  &NNMUPDTF = 'ON'
  27995.   IF (&NNMUPDTF = 'ON','OFF')
  27996.   ELSE
  27997.     VER(&NNMUPDTF,NUM)
  27998.   &NNUPAN   = TRUNC(&NNUPAN,1)
  27999.   &NNUPRN   = TRUNC(&NNUPRN,1)
  28000.   &NNUPRA   = TRUNC(&NNUPRA,1)
  28001.   &NNEXTPOW = TRUNC(&NNEXTPOW,1)
  28002.   &NNEXTPAP = TRUNC(&NNEXTPAP,1)
  28003.   VER(&NNUPAN  ,NB,LIST,Y,N)
  28004.   VER(&NNUPRN  ,NB,LIST,Y,N)
  28005.   VER(&NNUPRA  ,NB,LIST,Y,N)
  28006.   VER(&NNEXTPOW,NB,LIST,Y,N)
  28007.  VPUT (NNUPAN NNUPRN NNUPRA NNMUPDTF NNEXTPOW NNEXTPAP) PROFILE
  28008. )END
  28009. ./ ADD NAME=NNMOPTT
  28010. )ATTR
  28011. /*                                                                   /*
  28012. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28013. /*                                                                   /*
  28014. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  28015. /*                                                                   /*
  28016. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28017. /* including the implied warranties of merchantability and fitness,  /*
  28018. /* are expressly denied.                                             /*
  28019. /*                                                                   /*
  28020. /* Provided this copyright notice is included, this software may     /*
  28021. /* be freely distributed and not offered for sale.                   /*
  28022. /*                                                                   /*
  28023. /* Changes or modifications may be made and used only by the maker   /*
  28024. /* of same, and not further distributed.  Such modifications should  /*
  28025. /* be mailed to the author for consideration for addition to the     /*
  28026. /* software and incorporation in subsequent releases.                /*
  28027. /*                                                                   /*
  28028. )BODY EXPAND(``)
  28029. %-`-`- NNMVS - Table Viewing Options -`-`-
  28030. %Command ===>_ZCMD
  28031. +
  28032. %Newsgroup table options:
  28033.  
  28034. +Scroll last selected newsgroup to top? (YES/NO)%==>_Z  +
  28035. +Put cursor at last selected newsgroup? (YES/NO)%==>_Z  +
  28036.  
  28037. %Article table options:
  28038.  
  28039. +Scroll last selected article to top?   (YES/NO)%==>_Z  +
  28040. +Put cursor at last selected article?   (YES/NO)%==>_Z  +
  28041.  
  28042. +Number of heading rows to display per article  %==>_Z+  (Enter%1, 2+or%3+only)
  28043.  
  28044.  
  28045. +Press%ENTER+to change options.  Press%&END+(or type%END+command) when done.
  28046. )INIT
  28047.  .ZVARS  = '(NNNGSCR NNNGCSR NNARSCR NNARCSR NNARROWS)'
  28048.  .HELP   = TNNMOPT
  28049.  .CURSOR = ZCMD
  28050.  &END = PFK(END)
  28051.  &ZCMD = &Z
  28052.  VGET (NNNGSCR NNNGCSR NNARSCR NNARCSR NNARROWS) PROFILE
  28053.  &NNNGSCR  = TRANS(TRUNC(&NNNGSCR,1)  Y,YES N,NO *,YES)
  28054.  &NNNGCSR  = TRANS(TRUNC(&NNNGCSR,1)  Y,YES N,NO *,NO)
  28055.  &NNARSCR  = TRANS(TRUNC(&NNARSCR,1)  Y,YES N,NO *,YES)
  28056.  &NNARCSR  = TRANS(TRUNC(&NNARCSR,1)  Y,YES N,NO *,NO)
  28057.  &NNARROWS = TRANS(&NNARROWS 1,1 2,2 3,3 *,1)
  28058. )PROC
  28059.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  28060.  IF (.RESP = ENTER)
  28061.   &NNNGSCR  = TRUNC(&NNNGSCR,1)
  28062.   &NNNGCSR  = TRUNC(&NNNGCSR,1)
  28063.   &NNARSCR  = TRUNC(&NNARSCR,1)
  28064.   &NNARCSR  = TRUNC(&NNARCSR,1)
  28065.   VER(&NNNGSCR,NB,LIST,Y,N)
  28066.   VER(&NNNGCSR,NB,LIST,Y,N)
  28067.   VER(&NNARSCR,NB,LIST,Y,N)
  28068.   VER(&NNARCSR,NB,LIST,Y,N)
  28069.   VER(&NNARROWS,NB,LIST,1,2,3)
  28070.  VPUT (NNNGSCR NNNGCSR NNARSCR NNARCSR NNARROWS) PROFILE
  28071. )END
  28072. ./ ADD NAME=NNMPAUTH
  28073. )ATTR
  28074. /*                                                                   /*
  28075. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28076. /*                                                                   /*
  28077. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28078. /* including the implied warranties of merchantability and fitness,  /*
  28079. /* are expressly denied.                                             /*
  28080. /*                                                                   /*
  28081. /* Provided this copyright notice is included, this software may     /*
  28082. /* be freely distributed and not offered for sale.                   /*
  28083. /*                                                                   /*
  28084. /* Changes or modifications may be made and used only by the maker   /*
  28085. /* of same, and not further distributed.  Such modifications should  /*
  28086. /* be mailed to the author for consideration for addition to the     /*
  28087. /* software and incorporation in subsequent releases.                /*
  28088. /*                                                                   /*
  28089. )BODY WINDOW(62,14)
  28090. +
  28091. %Command ===>_ZCMD
  28092. +
  28093.  NNMVS could not obtain authorization from the NNTP server.
  28094.  You may proceed, but you should be aware that some news
  28095.  reading or posting operations may fail.
  28096.  
  28097.  The response from server &NNSERVER was:
  28098.  
  28099. %&NNSRVRSP
  28100. +
  28101.  Press%ENTER+to proceed.
  28102.  Press%END  +to return to the NNMVS primary menu.
  28103. )INIT
  28104.  .HELP = TNNM
  28105.  &ZWINTTL = 'Server authorization failed'
  28106.  &END = PFK(END)
  28107.  &ZCMD = &Z
  28108. )PROC
  28109.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  28110. )END
  28111. ./ ADD NAME=NNMPCAN
  28112. )ATTR
  28113. /*                                                                   /*
  28114. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28115. /*                                                                   /*
  28116. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28117. /* including the implied warranties of merchantability and fitness,  /*
  28118. /* are expressly denied.                                             /*
  28119. /*                                                                   /*
  28120. /* Provided this copyright notice is included, this software may     /*
  28121. /* be freely distributed and not offered for sale.                   /*
  28122. /*                                                                   /*
  28123. /* Changes or modifications may be made and used only by the maker   /*
  28124. /* of same, and not further distributed.  Such modifications should  /*
  28125. /* be mailed to the author for consideration for addition to the     /*
  28126. /* software and incorporation in subsequent releases.                /*
  28127. /*                                                                   /*
  28128.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28129. )BODY WINDOW(64,14)
  28130. +
  28131. %Command ===>^ZCMD
  28132. +
  28133. +Newsgroup :%&NNCGROUP
  28134. +Article:   %&NNCNUM
  28135. +Message-ID:%&NNCMSGID
  28136. +Subject:   %&NNCSUBJ
  28137.  
  28138.  
  28139. +This action will forward a CANCEL request to the news server.
  28140. +
  28141. +Press%ENTER+to proceed to cancel this article.
  28142. +
  28143. +Press%&END (END)+to abandon the request and leave the article.
  28144. )INIT
  28145.  .HELP = TNNM
  28146.  &ZWINTTL = 'Confirm Article Cancellation'
  28147.  &END = PFK(END)
  28148. )PROC
  28149.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  28150. )END
  28151. ./ ADD NAME=NNMPCONM
  28152. )ATTR
  28153. /*                                                                   /*
  28154. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28155. /*                                                                   /*
  28156. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28157. /* including the implied warranties of merchantability and fitness,  /*
  28158. /* are expressly denied.                                             /*
  28159. /*                                                                   /*
  28160. /* Provided this copyright notice is included, this software may     /*
  28161. /* be freely distributed and not offered for sale.                   /*
  28162. /*                                                                   /*
  28163. /* Changes or modifications may be made and used only by the maker   /*
  28164. /* of same, and not further distributed.  Such modifications should  /*
  28165. /* be mailed to the author for consideration for addition to the     /*
  28166. /* software and incorporation in subsequent releases.                /*
  28167. /*                                                                   /*
  28168. )BODY WINDOW(49,10)
  28169. +
  28170. %Command ===>_ZCMD
  28171.  
  28172. +To:     %&NNMAILTO
  28173. +Subject:%&NNMAILSJ
  28174.  
  28175. +Press%ENTER     +to mail this message.
  28176. +Press%&END (END)+to return to the mail menu.
  28177. +Enter%CANCEL    +to cancel the message.
  28178. )INIT
  28179.  .HELP = TNNM
  28180.  &ZWINTTL = 'Confirm mailing'
  28181.  &END = PFK(END)
  28182.  &ZCMD = &Z
  28183. )PROC
  28184.  VER(&ZCMD,LIST,CAN,CANCEL)
  28185. )END
  28186. ./ ADD NAME=NNMPCONP
  28187. )ATTR
  28188. /*                                                                   /*
  28189. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28190. /*                                                                   /*
  28191. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28192. /* including the implied warranties of merchantability and fitness,  /*
  28193. /* are expressly denied.                                             /*
  28194. /*                                                                   /*
  28195. /* Provided this copyright notice is included, this software may     /*
  28196. /* be freely distributed and not offered for sale.                   /*
  28197. /*                                                                   /*
  28198. /* Changes or modifications may be made and used only by the maker   /*
  28199. /* of same, and not further distributed.  Such modifications should  /*
  28200. /* be mailed to the author for consideration for addition to the     /*
  28201. /* software and incorporation in subsequent releases.                /*
  28202. /*                                                                   /*
  28203. )BODY WINDOW(49,10)
  28204. +
  28205. %Command ===>_ZCMD
  28206.  
  28207. +Newsgroups:%&NNPOSTNG
  28208. +Subject:   %&NNPOSTSJ
  28209.  
  28210. +Press%ENTER     +to post this article.
  28211. +Press%&END (END)+to return to the posting menu.
  28212. +Enter%CANCEL    +to cancel the post.
  28213. )INIT
  28214.  .HELP = TNNM
  28215.  &ZWINTTL = 'Confirm posting'
  28216.  &END = PFK(END)
  28217.  &ZCMD = &Z
  28218. )PROC
  28219.  VER(&ZCMD,LIST,CAN,CANCEL)
  28220. )END
  28221. ./ ADD NAME=NNMPEXDS
  28222. )ATTR
  28223. /*                                                                   /*
  28224. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28225. /*                                                                   /*
  28226. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28227. /* including the implied warranties of merchantability and fitness,  /*
  28228. /* are expressly denied.                                             /*
  28229. /*                                                                   /*
  28230. /* Provided this copyright notice is included, this software may     /*
  28231. /* be freely distributed and not offered for sale.                   /*
  28232. /*                                                                   /*
  28233. /* Changes or modifications may be made and used only by the maker   /*
  28234. /* of same, and not further distributed.  Such modifications should  /*
  28235. /* be mailed to the author for consideration for addition to the     /*
  28236. /* software and incorporation in subsequent releases.                /*
  28237. /*                                                                   /*
  28238.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28239. )BODY WINDOW(77,16)
  28240. +
  28241. %Command ===>^ZCMD
  28242. +
  28243. +&NUMBER       %&SUBJECT
  28244. +
  28245. +Save to data set ===>_NNEXDSN
  28246. +Expand tab characters?       ===>_Z  +
  28247.  
  28248. +(Note: Data set will be RECFM=VB, LRECL=259, BLKSIZE=6233.)
  28249.  
  28250. +Append to end of data set?   ===>_Z  +
  28251. +Blank line after separator?  ===>_Z  +
  28252. +Separator line between articles (append mode only...blank for none):
  28253. +>^Z                                                                       +<
  28254.  
  28255. +Press%&END (END)+to cancel the extract request.
  28256. )INIT
  28257.  .HELP = TNNM
  28258.  .ZVARS = '(NNEXTAB NNEXAPP NNEXBLK NNEXSEP)'
  28259.  .CURSOR = NNEXDSN
  28260.  IF (&NNTNUM ^= &Z)
  28261.   &ZWINTTL = 'Extract from &NNGROUP'
  28262.   &NUMBER  = 'Article &NNTNUM: '
  28263.   &SUBJECT = '&NNTSUBJ'
  28264.  ELSE
  28265.   &ZWINTTL = 'Extract text'
  28266.   &NUMBER  = ' '
  28267.   &SUBJECT = ' '
  28268.  &END = PFK(END)
  28269.  &ZCMD = &Z
  28270.  VGET (NNEXDSN NNEXTAB NNEXAPP NNEXBLK NNEXSEP) PROFILE
  28271.  &NNEXTAB = TRANS(&NNEXTAB Y,YES N,NO ' ',NO)
  28272.  &NNEXAPP = TRANS(&NNEXAPP Y,YES N,NO ' ',NO)
  28273.  &NNEXBLK = TRANS(&NNEXBLK Y,YES N,NO ' ',NO)
  28274. )PROC
  28275.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  28276.  VER(&NNEXDSN,NB,DSNAME)
  28277.  &NNEXTAB = TRUNC(&NNEXTAB,1)
  28278.  VER(&NNEXTAB,NB,LIST,Y,N)
  28279.  &NNEXAPP = TRUNC(&NNEXAPP,1)
  28280.  VER(&NNEXAPP,NB,LIST,Y,N)
  28281.  &NNEXBLK = TRUNC(&NNEXBLK,1)
  28282.  VER(&NNEXBLK,NB,LIST,Y,N)
  28283.  VPUT (NNEXDSN NNEXTAB NNEXAPP NNEXBLK NNEXSEP) PROFILE
  28284. )END
  28285. ./ ADD NAME=NNMPEXNG
  28286. )ATTR
  28287. /*                                                                   /*
  28288. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28289. /*                                                                   /*
  28290. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28291. /* including the implied warranties of merchantability and fitness,  /*
  28292. /* are expressly denied.                                             /*
  28293. /*                                                                   /*
  28294. /* Provided this copyright notice is included, this software may     /*
  28295. /* be freely distributed and not offered for sale.                   /*
  28296. /*                                                                   /*
  28297. /* Changes or modifications may be made and used only by the maker   /*
  28298. /* of same, and not further distributed.  Such modifications should  /*
  28299. /* be mailed to the author for consideration for addition to the     /*
  28300. /* software and incorporation in subsequent releases.                /*
  28301. /*                                                                   /*
  28302.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28303. )BODY WINDOW(77,14)
  28304. +
  28305. %Command ===>^ZCMD
  28306. +
  28307. +Save to data set ===>_NNEXDSN
  28308.  
  28309. +(Note: Data set will be RECFM=VB, LRECL=259, BLKSIZE=6233.)
  28310.  
  28311. +Append to end of data set?   ===>_Z  +
  28312. +Blank line after separator?  ===>_Z  +
  28313. +Separator line between articles (append mode only...blank for none):
  28314. +>^Z                                                                       +<
  28315.  
  28316. +Press%&END (END)+to cancel the extract request.
  28317. )INIT
  28318.  .HELP = TNNM
  28319.  .ZVARS = '(NNEXAPP NNEXBLK NNEXSEP)'
  28320.  .CURSOR = NNEXDSN
  28321.  &ZWINTTL = 'Extract newsgroup listing'
  28322.  &END = PFK(END)
  28323.  &ZCMD = &Z
  28324.  VGET (NNEXDSN NNEXAPP NNEXBLK NNEXSEP) PROFILE
  28325.  &NNEXAPP = TRANS(&NNEXAPP Y,YES N,NO ' ',NO)
  28326.  &NNEXBLK = TRANS(&NNEXBLK Y,YES N,NO ' ',NO)
  28327. )PROC
  28328.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  28329.  VER(&NNEXDSN,NB,DSNAME)
  28330.  &NNEXAPP = TRUNC(&NNEXAPP,1)
  28331.  VER(&NNEXAPP,NB,LIST,Y,N)
  28332.  &NNEXBLK = TRUNC(&NNEXBLK,1)
  28333.  VER(&NNEXBLK,NB,LIST,Y,N)
  28334.  VPUT (NNEXDSN NNEXAPP NNEXBLK NNEXSEP) PROFILE
  28335. )END
  28336. ./ ADD NAME=NNMPEXNP
  28337. )ATTR
  28338. /*                                                                   /*
  28339. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28340. /*                                                                   /*
  28341. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28342. /* including the implied warranties of merchantability and fitness,  /*
  28343. /* are expressly denied.                                             /*
  28344. /*                                                                   /*
  28345. /* Provided this copyright notice is included, this software may     /*
  28346. /* be freely distributed and not offered for sale.                   /*
  28347. /*                                                                   /*
  28348. /* Changes or modifications may be made and used only by the maker   /*
  28349. /* of same, and not further distributed.  Such modifications should  /*
  28350. /* be mailed to the author for consideration for addition to the     /*
  28351. /* software and incorporation in subsequent releases.                /*
  28352. /*                                                                   /*
  28353.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28354. )BODY EXPAND(``) WINDOW(77,14)
  28355. +
  28356. %Command ===>^ZCMD
  28357. +
  28358. +Data set name%===>_NNEXPDS
  28359. +Member prefix%===>_NNEXPMP + (article number appended - default is%#+)
  28360.  
  28361. +Note: The dataset must be a PDS (old or new) with RECFM=VB and LRECL=259.
  28362.  
  28363. +Expand tab characters?      %===>_Z  +
  28364.  
  28365. +From article number%===>_NNEXAN1      + (blank for first article in table)
  28366. +To   article number%===>_NNEXAN2      + (blank for last article in table)
  28367.  
  28368. +Press%&END (END)+to cancel the extract request.
  28369. )INIT
  28370.  .HELP = TNNM
  28371.  .ZVARS = '(NNEXTAB)'
  28372.  .CURSOR = ZCMD
  28373.  &ZWINTTL = 'Log text of articles in &NNGROUP to PDS members'
  28374.  &NUMBER = ' &NNTNUM: '
  28375.  &END = PFK(END)
  28376.  &ZCMD = &Z
  28377.  VGET (NNEXPDS NNEXPMP NNEXTAB) PROFILE
  28378.  &NNEXTAB = TRANS(&NNEXTAB Y,YES N,NO ' ',NO)
  28379.  IF (&NNEXPMP = &Z) &NNEXPMP = '#'
  28380.  &NNEXAN1 = &Z
  28381.  &NNEXAN2 = &Z
  28382. )PROC
  28383.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  28384.  &NNEXTAB = TRUNC(&NNEXTAB,1)
  28385.  VER(&NNEXTAB,NB,LIST,Y,N)
  28386.  VER(&NNEXPDS,NB,DSNAME)
  28387.  &TEMP1 = TRUNC(&NNEXPDS,1)
  28388.  &TEMP2 = .TRAIL
  28389.  IF (&TEMP1 = '''')
  28390.   &NNEXDSN = TRUNC(&TEMP2,'''')
  28391.  ELSE
  28392.   &NNEXDSN = '&ZPREFIX..&NNEXPDS'
  28393.   VER(&NNEXPMP,NB,NAME)
  28394.  VER(&NNEXAN1,NUM)
  28395.  VER(&NNEXAN2,NUM)
  28396.  VPUT (NNEXPDS NNEXPMP NNEXTAB) PROFILE
  28397. )END
  28398. ./ ADD NAME=NNMPEXNS
  28399. )ATTR
  28400. /*                                                                   /*
  28401. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28402. /*                                                                   /*
  28403. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28404. /* including the implied warranties of merchantability and fitness,  /*
  28405. /* are expressly denied.                                             /*
  28406. /*                                                                   /*
  28407. /* Provided this copyright notice is included, this software may     /*
  28408. /* be freely distributed and not offered for sale.                   /*
  28409. /*                                                                   /*
  28410. /* Changes or modifications may be made and used only by the maker   /*
  28411. /* of same, and not further distributed.  Such modifications should  /*
  28412. /* be mailed to the author for consideration for addition to the     /*
  28413. /* software and incorporation in subsequent releases.                /*
  28414. /*                                                                   /*
  28415.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28416. )BODY EXPAND(``) WINDOW(77,17)
  28417. +
  28418. %Command ===>^ZCMD
  28419. +
  28420. +Data set name%===>_NNEXSEQ
  28421. +(Note: Data set will be RECFM=VB, LRECL=259, BLKSIZE=6233.)
  28422. +
  28423. +Expand tab characters?      %===>_Z  +
  28424. +
  28425. +Append to end of data set?  %===>_Z  +
  28426. +Blank line after separator? %===>_Z  +
  28427. +Separator line before each article (leave blank for none):
  28428. +>^Z                                                                       +<
  28429.  
  28430. +From article number%===>_NNEXAN1      + (blank for first article in table)
  28431. +To   article number%===>_NNEXAN2      + (blank for last article in table)
  28432.  
  28433. +Press%&END (END)+to cancel the extract request.
  28434. )INIT
  28435.  .HELP = TNNM
  28436.  .ZVARS = '(NNEXTAB NNEXAPP NNEXBLK NNEXSEP)'
  28437.  .CURSOR = ZCMD
  28438.  &ZWINTTL = 'Log text of articles in &NNGROUP to sequential file'
  28439.  &NUMBER = ' &NNTNUM: '
  28440.  &END = PFK(END)
  28441.  &ZCMD = &Z
  28442.  VGET (NNEXSEQ NNEXTAB NNEXAPP NNEXBLK NNEXSEP) PROFILE
  28443.  &NNEXTAB = TRANS(&NNEXTAB Y,YES N,NO ' ',NO)
  28444.  &NNEXAPP = TRANS(&NNEXAPP Y,YES N,NO ' ',NO)
  28445.  &NNEXBLK = TRANS(&NNEXBLK Y,YES N,NO ' ',NO)
  28446.  &NNEXAN1 = &Z
  28447.  &NNEXAN2 = &Z
  28448. )PROC
  28449.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  28450.  VER(&NNEXSEQ,NB,DSNAME)
  28451.  &NNEXDSN = &NNEXSEQ
  28452.  &NNEXTAB = TRUNC(&NNEXTAB,1)
  28453.  VER(&NNEXTAB,NB,LIST,Y,N)
  28454.  &NNEXAPP = TRUNC(&NNEXAPP,1)
  28455.  VER(&NNEXAPP,NB,LIST,Y,N)
  28456.  &NNEXBLK = TRUNC(&NNEXBLK,1)
  28457.  VER(&NNEXBLK,NB,LIST,Y,N)
  28458.  VER(&NNEXAN1,NUM)
  28459.  VER(&NNEXAN2,NUM)
  28460.  VPUT (NNEXSEQ NNEXTAB NNEXAPP NNEXBLK NNEXSEP) PROFILE
  28461. )END
  28462. ./ ADD NAME=NNMPEXNT
  28463. )ATTR
  28464. /*                                                                   /*
  28465. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28466. /*                                                                   /*
  28467. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28468. /* including the implied warranties of merchantability and fitness,  /*
  28469. /* are expressly denied.                                             /*
  28470. /*                                                                   /*
  28471. /* Provided this copyright notice is included, this software may     /*
  28472. /* be freely distributed and not offered for sale.                   /*
  28473. /*                                                                   /*
  28474. /* Changes or modifications may be made and used only by the maker   /*
  28475. /* of same, and not further distributed.  Such modifications should  /*
  28476. /* be mailed to the author for consideration for addition to the     /*
  28477. /* software and incorporation in subsequent releases.                /*
  28478. /*                                                                   /*
  28479.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28480. )BODY WINDOW(77,10)
  28481. +
  28482. %Command ===>^ZCMD
  28483. +
  28484. +Move cursor to choice (or type%S+next to choice) and press%ENTER+to select:
  28485. +
  28486. _A%1+- List%titles+of articles in table
  28487. _B%2+- Log %text  +of articles to%sequential file+
  28488. _C%3+- Log %text  +of articles to%members of PDS+
  28489. +
  28490. +Press%&END (END)+to cancel the extract request.
  28491. )INIT
  28492.  .HELP = TNNM
  28493.  .CURSOR = ZCMD
  28494.  &ZWINTTL = 'Extract news articles - titles or text'
  28495.  &END = PFK(END)
  28496.  &ZCMD = &Z
  28497.  &A = &Z
  28498.  &B = &Z
  28499.  &C = &Z
  28500. )PROC
  28501.  VER(&ZCMD,LIST,1,2,3)
  28502.  IF (&ZCMD ^= &Z)
  28503.   &NNCHOICE = TRANS(&ZCMD 1 1 2 2 3 3 * ?)
  28504.  ELSE
  28505.   &TEMP = '&A/&B/&C'
  28506.   IF (&TEMP = '//')
  28507.    &NNCHOICE = TRANS(.CURSOR A 1 B 2 C 3 * ?)
  28508.   ELSE
  28509.    &NNCHOICE = TRANS(&TEMP  'S//' 1
  28510.                             '1//' 1
  28511.                             '/S/' 2
  28512.                             '/2/' 2
  28513.                             '//S' 3
  28514.                             '//3' 3
  28515.                                * ?
  28516.                    )
  28517. )END
  28518. ./ ADD NAME=NNMPEXN1
  28519. )ATTR
  28520. /*                                                                   /*
  28521. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28522. /*                                                                   /*
  28523. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28524. /* including the implied warranties of merchantability and fitness,  /*
  28525. /* are expressly denied.                                             /*
  28526. /*                                                                   /*
  28527. /* Provided this copyright notice is included, this software may     /*
  28528. /* be freely distributed and not offered for sale.                   /*
  28529. /*                                                                   /*
  28530. /* Changes or modifications may be made and used only by the maker   /*
  28531. /* of same, and not further distributed.  Such modifications should  /*
  28532. /* be mailed to the author for consideration for addition to the     /*
  28533. /* software and incorporation in subsequent releases.                /*
  28534. /*                                                                   /*
  28535.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28536. )BODY WINDOW(77,14)
  28537. +
  28538. %Command ===>^ZCMD
  28539. +
  28540. +Save to data set ===>_NNEXDSN
  28541.  
  28542. +(Note: Data set will be RECFM=VB, LRECL=259, BLKSIZE=6233.)
  28543.  
  28544. +Append to end of data set?   ===>_Z  +
  28545. +Blank line after separator?  ===>_Z  +
  28546. +Separator line between articles (append mode only...blank for none):
  28547. +>^Z                                                                       +<
  28548.  
  28549. +Press%&END (END)+to cancel the extract request.
  28550. )INIT
  28551.  .HELP = TNNM
  28552.  .ZVARS = '(NNEXAPP NNEXBLK NNEXSEP)'
  28553.  .CURSOR = NNEXDSN
  28554.  &ZWINTTL = 'Extract news article listing'
  28555.  &END = PFK(END)
  28556.  &ZCMD = &Z
  28557.  VGET (NNEXDSN NNEXAPP NNEXBLK NNEXSEP) PROFILE
  28558.  &NNEXAPP = TRANS(&NNEXAPP Y,YES N,NO ' ',NO)
  28559.  &NNEXBLK = TRANS(&NNEXBLK Y,YES N,NO ' ',NO)
  28560. )PROC
  28561.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  28562.  VER(&NNEXDSN,NB,DSNAME)
  28563.  &NNEXAPP = TRUNC(&NNEXAPP,1)
  28564.  VER(&NNEXAPP,NB,LIST,Y,N)
  28565.  &NNEXBLK = TRUNC(&NNEXBLK,1)
  28566.  VER(&NNEXBLK,NB,LIST,Y,N)
  28567.  VPUT (NNEXDSN NNEXAPP NNEXBLK NNEXSEP) PROFILE
  28568. )END
  28569. ./ ADD NAME=NNMPEXOW
  28570. )ATTR
  28571. /*                                                                   /*
  28572. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28573. /*                                                                   /*
  28574. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28575. /* including the implied warranties of merchantability and fitness,  /*
  28576. /* are expressly denied.                                             /*
  28577. /*                                                                   /*
  28578. /* Provided this copyright notice is included, this software may     /*
  28579. /* be freely distributed and not offered for sale.                   /*
  28580. /*                                                                   /*
  28581. /* Changes or modifications may be made and used only by the maker   /*
  28582. /* of same, and not further distributed.  Such modifications should  /*
  28583. /* be mailed to the author for consideration for addition to the     /*
  28584. /* software and incorporation in subsequent releases.                /*
  28585. /*                                                                   /*
  28586.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28587. )BODY WINDOW(58,10)
  28588. +
  28589. %Command ===>^ZCMD
  28590. +
  28591. +Dataset already exists:
  28592. +
  28593. %&NNEXDSN
  28594. +
  28595. +Press%ENTER+to%&ACTION
  28596. +Press%&END (END)+to cancel the request.
  28597. +
  28598. )INIT
  28599.  .HELP = TNNM
  28600.  .ALARM = YES
  28601.  &ZWINTTL = 'Extract To Existing Data Set'
  28602.  &END = PFK(END)
  28603.  &APP = TRUNC(&NNEXAPP,1)
  28604.  IF (&APP = Y) &ACTION = 'append to the end of the data set.'
  28605.  ELSE          &ACTION = 'overwrite the current data set.'
  28606. )PROC
  28607.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  28608. )END
  28609. ./ ADD NAME=NNMPEXPW
  28610. )ATTR
  28611. /*                                                                   /*
  28612. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28613. /*                                                                   /*
  28614. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28615. /* including the implied warranties of merchantability and fitness,  /*
  28616. /* are expressly denied.                                             /*
  28617. /*                                                                   /*
  28618. /* Provided this copyright notice is included, this software may     /*
  28619. /* be freely distributed and not offered for sale.                   /*
  28620. /*                                                                   /*
  28621. /* Changes or modifications may be made and used only by the maker   /*
  28622. /* of same, and not further distributed.  Such modifications should  /*
  28623. /* be mailed to the author for consideration for addition to the     /*
  28624. /* software and incorporation in subsequent releases.                /*
  28625. /*                                                                   /*
  28626.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28627. )BODY WINDOW(58,13)
  28628. +
  28629. %Command ===>^ZCMD
  28630. +
  28631. +Partitioned dataset already exists:
  28632. +
  28633. %&NNEXDSN
  28634. +
  28635. +If member names are generated that match existing members
  28636. +of this PDS, they will be%overwritten.+
  28637. +
  28638. +Press%ENTER+to proceed to use this PDS.
  28639. +Press%&END (END)+to cancel the request.
  28640. +
  28641. )INIT
  28642.  .HELP = TNNM
  28643.  .ALARM = YES
  28644.  &ZWINTTL = 'Extract To Members of Existing PDS'
  28645.  &END = PFK(END)
  28646. )PROC
  28647.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  28648. )END
  28649. ./ ADD NAME=NNMPGAUT
  28650. )ATTR
  28651. /*                                                                   /*
  28652. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28653. /*                                                                   /*
  28654. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28655. /* including the implied warranties of merchantability and fitness,  /*
  28656. /* are expressly denied.                                             /*
  28657. /*                                                                   /*
  28658. /* Provided this copyright notice is included, this software may     /*
  28659. /* be freely distributed and not offered for sale.                   /*
  28660. /*                                                                   /*
  28661. /* Changes or modifications may be made and used only by the maker   /*
  28662. /* of same, and not further distributed.  Such modifications should  /*
  28663. /* be mailed to the author for consideration for addition to the     /*
  28664. /* software and incorporation in subsequent releases.                /*
  28665. /*                                                                   /*
  28666.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28667.        @   TYPE(INPUT) INTENS(NON)  CAPS(OFF) JUST(LEFT)
  28668. )BODY WINDOW(64,14)
  28669. +
  28670. %Command ===>^ZCMD
  28671. +
  28672. +The NNTP server at &NNSERVER
  28673. +requires authorization to perform this operation.
  28674. +
  28675. +Username (as known to NNTP server) ===>^NNAUSER
  28676. +Password (as known to NNTP server) ===>@NNAPASS
  28677. +
  28678.  
  28679. +Press%&END (END)+to abort the current request.
  28680. )INIT
  28681.  .HELP = TNNM
  28682.  &ZWINTTL = 'Server Authorization Required'
  28683.  &NNAPASS = &Z
  28684.  &END = PFK(END)
  28685. )PROC
  28686.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  28687.  VER(&NNAUSER,NB)
  28688.  VER(&NNAPASS,NB)
  28689.  VPUT (NNAUSER) PROFILE
  28690. )END
  28691. ./ ADD NAME=NNMPGREG
  28692. )ATTR
  28693. /*                                                                   /*
  28694. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28695. /*                                                                   /*
  28696. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28697. /* including the implied warranties of merchantability and fitness,  /*
  28698. /* are expressly denied.                                             /*
  28699. /*                                                                   /*
  28700. /* Provided this copyright notice is included, this software may     /*
  28701. /* be freely distributed and not offered for sale.                   /*
  28702. /*                                                                   /*
  28703. /* Changes or modifications may be made and used only by the maker   /*
  28704. /* of same, and not further distributed.  Such modifications should  /*
  28705. /* be mailed to the author for consideration for addition to the     /*
  28706. /* software and incorporation in subsequent releases.                /*
  28707. /*                                                                   /*
  28708.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28709. )BODY WINDOW(58,10)
  28710. +
  28711. %Command ===>^ZCMD
  28712. +
  28713. +Get current status of each newsgroup in your list?
  28714. +(If you answer YES, it will take longer to start up.)
  28715. +(If you answer NO, displayed status will be incomplete.)
  28716. +
  28717. %===>_Z  +
  28718.  
  28719. +Press%&END (END)+to return to the previous panel.
  28720. )INIT
  28721.  .HELP = TNNM
  28722.  .ZVARS = '(NNRGANS)'
  28723.  .CURSOR = NNRGANS
  28724.  &ZWINTTL = ''
  28725.  &END = PFK(END)
  28726.  &NNRGANS = Y
  28727. )PROC
  28728.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  28729.  &NNRGANS = TRUNC(&NNRGANS,1)
  28730.  VER(&NNRGANS,NB,LIST,Y,N)
  28731. )END
  28732. ./ ADD NAME=NNMPMALL
  28733. )ATTR
  28734. /*                                                                   /*
  28735. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28736. /*                                                                   /*
  28737. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28738. /* including the implied warranties of merchantability and fitness,  /*
  28739. /* are expressly denied.                                             /*
  28740. /*                                                                   /*
  28741. /* Provided this copyright notice is included, this software may     /*
  28742. /* be freely distributed and not offered for sale.                   /*
  28743. /*                                                                   /*
  28744. /* Changes or modifications may be made and used only by the maker   /*
  28745. /* of same, and not further distributed.  Such modifications should  /*
  28746. /* be mailed to the author for consideration for addition to the     /*
  28747. /* software and incorporation in subsequent releases.                /*
  28748. /*                                                                   /*
  28749.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28750. )BODY WINDOW(76,14)
  28751. +
  28752. %Command ===>^ZCMD
  28753. +
  28754. +Newsgroup:%&NNGNAME
  28755. +
  28756. +What exactly do you want to do?
  28757. +
  28758. _Z%*+Mark%all+articles in the newsgroup &NNMARK
  28759. _Z%*+Mark%currently displayed+articles &NNMARK
  28760. _Z%*+Cancel this request and return to previous panel
  28761.  
  28762. +Move cursor to choice (or type%S+next to choice) and press%ENTER+to do it.
  28763. +
  28764. +Press%&END (END)+to cancel the request.
  28765. )INIT
  28766.  .HELP = TNNM
  28767.  .ZVARS = '(S1 S2 S3)'
  28768.  .CURSOR = ZCMD
  28769.  &ZWINTTL = 'Confirm Marking All Articles in Newsgroup'
  28770.  &END = PFK(END)
  28771.  &ZCMD = &Z
  28772.  &S1   = &Z
  28773.  &S2   = &Z
  28774.  &S3   = &Z
  28775. )PROC
  28776.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  28777.  &TEMP = '&S1/&S2/&S3'
  28778.  IF (&TEMP = '//')
  28779.   &NNCHOICE = TRANS(.CURSOR S1 1 S2 2 S3 3 * ?)
  28780.  ELSE
  28781.   &NNCHOICE = TRANS(&TEMP  'S//' 1
  28782.                            '1//' 1
  28783.                            '/S/' 2
  28784.                            '/2/' 2
  28785.                            '//S' 3
  28786.                            '//3' 3
  28787.                                * ?
  28788.                   )
  28789. )END
  28790. ./ ADD NAME=NNMPMARK
  28791. )ATTR
  28792. /*                                                                   /*
  28793. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28794. /*                                                                   /*
  28795. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28796. /* including the implied warranties of merchantability and fitness,  /*
  28797. /* are expressly denied.                                             /*
  28798. /*                                                                   /*
  28799. /* Provided this copyright notice is included, this software may     /*
  28800. /* be freely distributed and not offered for sale.                   /*
  28801. /*                                                                   /*
  28802. /* Changes or modifications may be made and used only by the maker   /*
  28803. /* of same, and not further distributed.  Such modifications should  /*
  28804. /* be mailed to the author for consideration for addition to the     /*
  28805. /* software and incorporation in subsequent releases.                /*
  28806. /*                                                                   /*
  28807.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28808. )BODY WINDOW(58,10)
  28809. +
  28810. %Command ===>^ZCMD
  28811. +
  28812. +Newsgroup:%&NNGNAME
  28813. +
  28814. +Be sure you really want to mark all articles%&NNMARK..
  28815. +
  28816. +Press%ENTER+to proceed with marking all articles.
  28817. +
  28818. +Press%&END (END)+to cancel the request.
  28819. )INIT
  28820.  .HELP = TNNM
  28821.  &ZWINTTL = 'Confirm Marking All Articles in Newsgroup'
  28822.  &END = PFK(END)
  28823. )PROC
  28824.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  28825. )END
  28826. ./ ADD NAME=NNMPOPT
  28827. )ATTR
  28828. /*                                                                   /*
  28829. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28830. /*                                                                   /*
  28831. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28832. /* including the implied warranties of merchantability and fitness,  /*
  28833. /* are expressly denied.                                             /*
  28834. /*                                                                   /*
  28835. /* Provided this copyright notice is included, this software may     /*
  28836. /* be freely distributed and not offered for sale.                   /*
  28837. /*                                                                   /*
  28838. /* Changes or modifications may be made and used only by the maker   /*
  28839. /* of same, and not further distributed.  Such modifications should  /*
  28840. /* be mailed to the author for consideration for addition to the     /*
  28841. /* software and incorporation in subsequent releases.                /*
  28842. /*                                                                   /*
  28843.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28844. )BODY WINDOW(77,11)
  28845. +
  28846. %Command ===>^ZCMD
  28847. +
  28848. +Move cursor to choice (or type%S+next to choice) and press%ENTER+to select:
  28849. +
  28850. _Z%1+- RFC822 header display options
  28851. _Z%2+- Article retrieval options
  28852. _Z%3+- Table processing options
  28853. +
  28854. +Press%&END (END)+to return to the previous panel.
  28855. )INIT
  28856.  .HELP = TNNMOPT
  28857.  .ZVARS = '(S1 S2 S3)'
  28858.  .CURSOR = ZCMD
  28859.  &ZWINTTL = 'Customize user options'
  28860.  &END = PFK(END)
  28861.  &ZCMD = &Z
  28862.  &S1   = &Z
  28863.  &S2   = &Z
  28864.  &S3   = &Z
  28865. )PROC
  28866.  IF (&ZCMD ^= &Z)
  28867.   &NNCHOICE = TRANS(&ZCMD 1 1 2 2 3 3 * ?)
  28868.  ELSE
  28869.   &TEMP = '&S1/&S2/&S3'
  28870.   IF (&TEMP = '//')
  28871.    &NNCHOICE = TRANS(.CURSOR S1 1 S2 2 S3 3 * ?)
  28872.   ELSE
  28873.    &NNCHOICE = TRANS(&TEMP  'S//' 1
  28874.                             '1//' 1
  28875.                             '/S/' 2
  28876.                             '/2/' 2
  28877.                             '//S' 3
  28878.                             '//3' 3
  28879.                                 * ?
  28880.                    )
  28881. )END
  28882. ./ ADD NAME=NNMPPRNT
  28883. )ATTR
  28884. /*                                                                   /*
  28885. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1993     /*
  28886. /*                                                                   /*
  28887. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28888. /* including the implied warranties of merchantability and fitness,  /*
  28889. /* are expressly denied.                                             /*
  28890. /*                                                                   /*
  28891. /* Provided this copyright notice is included, this software may     /*
  28892. /* be freely distributed and not offered for sale.                   /*
  28893. /*                                                                   /*
  28894. /* Changes or modifications may be made and used only by the maker   /*
  28895. /* of same, and not further distributed.  Such modifications should  /*
  28896. /* be mailed to the author for consideration for addition to the     /*
  28897. /* software and incorporation in subsequent releases.                /*
  28898. /*                                                                   /*
  28899.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28900. )BODY WINDOW(77,9)
  28901. +
  28902. %Command ===>^ZCMD
  28903. +
  28904. +Move cursor to choice (or type%S+next to choice) and press%ENTER+to select:
  28905. +
  28906. _A%1+- Print%titles+of articles in table
  28907. _B%2+- Print%text  +of articles
  28908. +
  28909. +Press%&END (END)+to cancel the print request.
  28910. )INIT
  28911.  .HELP = TNNM
  28912.  .CURSOR = ZCMD
  28913.  &ZWINTTL = 'Print news articles - titles or text'
  28914.  &END = PFK(END)
  28915.  &ZCMD = &Z
  28916.  &A = &Z
  28917.  &B = &Z
  28918. )PROC
  28919.  VER(&ZCMD,LIST,1,2)
  28920.  IF (&ZCMD ^= &Z)
  28921.   &NNCHOICE = TRANS(&ZCMD 1 1 2 2 * ?)
  28922.  ELSE
  28923.   &TEMP = '&A/&B'
  28924.   IF (&TEMP = '/')
  28925.    &NNCHOICE = TRANS(.CURSOR A 1 B 2 * ?)
  28926.   ELSE
  28927.    &NNCHOICE = TRANS(&TEMP  'S/' 1
  28928.                             '1/' 1
  28929.                             '/S' 2
  28930.                             '/2' 2
  28931.                               * ?
  28932.                    )
  28933. )END
  28934. ./ ADD NAME=NNMPPRT
  28935. )ATTR
  28936. /*                                                                   /*
  28937. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28938. /*                                                                   /*
  28939. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  28940. /*                                                                   /*
  28941. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28942. /* including the implied warranties of merchantability and fitness,  /*
  28943. /* are expressly denied.                                             /*
  28944. /*                                                                   /*
  28945. /* Provided this copyright notice is included, this software may     /*
  28946. /* be freely distributed and not offered for sale.                   /*
  28947. /*                                                                   /*
  28948. /* Changes or modifications may be made and used only by the maker   /*
  28949. /* of same, and not further distributed.  Such modifications should  /*
  28950. /* be mailed to the author for consideration for addition to the     /*
  28951. /* software and incorporation in subsequent releases.                /*
  28952. /*                                                                   /*
  28953.  ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28954.  ~   TYPE(TEXT)  INTENS(HIGH)
  28955.  \   TYPE(TEXT)  INTENS(LOW)
  28956.  {   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28957.  }   TYPE(INPUT) INTENS(HIGH) CAPS(ON)  JUST(LEFT)
  28958.  #   TYPE(TEXT)  INTENS(LOW)
  28959.  @   TYPE(INPUT) INTENS(HIGH) CAPS(ON)  JUST(LEFT)
  28960. )BODY WINDOW(77,19)
  28961. +
  28962. %Command ===>^ZCMD
  28963. +
  28964. +&NUMBER       %&SUBJECT
  28965. +
  28966. +SYSOUT class ===>_Z+   Number of copies ===>_Z  +
  28967. #Destination  ===>@Z       #  Forms ===>@Z   #   UCS ===>@Z   +
  28968.  
  28969. +(Note: Print data will be released to SYSOUT immediately.)
  28970. +
  28971. \Page eject between articles?     ~===>}Z  +
  28972. \Blank line after separator?      ~===>}Z  +
  28973. \Separator line before each article (leave blank for none):
  28974. \>{Z                                                                       \<
  28975.  
  28976. \From article number~===>}NNEXAN1      \ (blank for first article in table)
  28977. \To   article number~===>}NNEXAN2      \ (blank for last article in table)
  28978.  
  28979. +Press%&END (END)+to cancel the print request.
  28980. )INIT
  28981.  .HELP = TNNM
  28982.  .ZVARS =
  28983.    '(NNEXSCL NNEXSCO NNEXSDE NNEXSFO NNEXSUC NNEXSPA NNEXBLK NNEXSEP)'
  28984.  .CURSOR = NNEXSCL
  28985.  &END = PFK(END)
  28986.  &ZCMD = &Z
  28987.  &NNEXSCO = 1
  28988.  &PVARS = 'NNEXSCL'
  28989.  IF (&NNALLPR ^= &Z)
  28990.   &PVARS = '&PVARS NNEXSDE NNEXSFO NNEXSUC'
  28991.   .ATTRCHAR('#') = 'TYPE(TEXT)   INTENS(LOW)'
  28992.   .ATTRCHAR('@') = 'TYPE(INPUT)  INTENS(HIGH) CAPS(ON)  JUST(LEFT)'
  28993.  ELSE
  28994.   .ATTRCHAR('#') = 'TYPE(TEXT)   INTENS(NON)'
  28995.   .ATTRCHAR('@') = 'TYPE(OUTPUT) INTENS(NON)'
  28996.  IF (&NNWHICH = NNMPPRNS)
  28997.   .ATTRCHAR('~') = 'TYPE(TEXT)   INTENS(HIGH)'
  28998.   .ATTRCHAR('\') = 'TYPE(TEXT)   INTENS(LOW)'
  28999.   .ATTRCHAR('{') = 'TYPE(INPUT)  INTENS(HIGH) CAPS(OFF) JUST(LEFT)'
  29000.   .ATTRCHAR('}') = 'TYPE(INPUT)  INTENS(HIGH) CAPS(ON)  JUST(LEFT)'
  29001.  ELSE
  29002.   .ATTRCHAR('~') = 'TYPE(TEXT)   INTENS(NON)'
  29003.   .ATTRCHAR('\') = 'TYPE(TEXT)   INTENS(NON)'
  29004.   .ATTRCHAR('{') = 'TYPE(OUTPUT) INTENS(NON)'
  29005.   .ATTRCHAR('}') = 'TYPE(OUTPUT) INTENS(NON)'
  29006.  IF (&NNWHICH = NNMPPRNG)
  29007.   &ZWINTTL = 'Print newsgroup listing'
  29008.  IF (&NNWHICH = NNMPPRN1)
  29009.   &ZWINTTL = 'Print news article listing'
  29010.  IF (&NNWHICH = NNMPPRDS)
  29011.   IF (&NNTNUM ^= &Z)
  29012.    &ZWINTTL = 'Print from &NNGROUP'
  29013.    &NUMBER  = 'Article &NNTNUM: '
  29014.    &SUBJECT = '&NNTSUBJ'
  29015.   ELSE
  29016.    &ZWINTTL = 'Print text'
  29017.    &NUMBER  = &Z
  29018.    &SUBJECT = &Z
  29019.  ELSE
  29020.   &NUMBER  = &Z
  29021.   &SUBJECT = &Z
  29022.  IF (&NNWHICH = NNMPPRNS)
  29023.   &PVARS = '&PVARS NNEXSPA NNEXBLK NNEXSEP'
  29024.   &ZWINTTL = 'Print text of articles in &NNGROUP'
  29025.   &NNEXSPA = TRANS(TRUNC(&NNEXSPA,1) Y,YES N,NO ' ',NO)
  29026.   &NNEXBLK = TRANS(TRUNC(&NNEXBLK,1) Y,YES N,NO ' ',NO)
  29027.   &NNEXSCO = 1
  29028.   &NNEXAN1 = &Z
  29029.   &NNEXAN2 = &Z
  29030.  VGET (&PVARS) PROFILE
  29031. )PROC
  29032.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  29033.  VER(&NNEXSCL,NB)
  29034.  IF (&NNEXSCO = &Z) &NNEXSCO = 1
  29035.  VER(&NNEXSCO,NUM)
  29036.  VER(&NNEXSCO,RANGE,1,255)
  29037.  IF (&NNWHICH = NNMPPRNS)
  29038.   &NNEXSPA = TRUNC(&NNEXSPA,1)
  29039.   &NNEXBLK = TRUNC(&NNEXBLK,1)
  29040.   VER(&NNEXSPA,NB,LIST,Y,N)
  29041.   VER(&NNEXBLK,NB,LIST,Y,N)
  29042.   VER(&NNEXAN1,NUM)
  29043.   VER(&NNEXAN2,NUM)
  29044.  VPUT (&PVARS) PROFILE
  29045. )END
  29046. ./ ADD NAME=NNMQMAIL
  29047. )ATTR
  29048. /*                                                                   /*
  29049. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  29050. /*                                                                   /*
  29051. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  29052. /* including the implied warranties of merchantability and fitness,  /*
  29053. /* are expressly denied.                                             /*
  29054. /*                                                                   /*
  29055. /* Provided this copyright notice is included, this software may     /*
  29056. /* be freely distributed and not offered for sale.                   /*
  29057. /*                                                                   /*
  29058. /* Changes or modifications may be made and used only by the maker   /*
  29059. /* of same, and not further distributed.  Such modifications should  /*
  29060. /* be mailed to the author for consideration for addition to the     /*
  29061. /* software and incorporation in subsequent releases.                /*
  29062. /*                                                                   /*
  29063.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  29064. )BODY EXPAND(``)
  29065. -`-`- Send a mail message or reply -`-`-
  29066. %Command ===>^ZCMD
  29067. +
  29068. %Note:+This sends private mail to the individual sender named below.
  29069.       +To transmit to the newsgroup, use the%POST+command, or use
  29070.       +the%F (FOLLOWUP)+selection code.+
  29071. +
  29072. +&HEADING
  29073.  
  29074. %Required Header Fields+
  29075.  
  29076. +Mail to ===>^NNMAILTO
  29077. +Subject ===>^NNMAILSJ
  29078.  
  29079. %Optional Header Fields+
  29080.  
  29081. +Reply to ==>^NNMAILRT
  29082.  
  29083. +Your human name ==>^NNMAILFR
  29084. +Signature file  ==>_NNMAILSF
  29085. +Edit profile    ==>_NNEDPROF+
  29086.  
  29087. +Press%ENTER+to proceed to the editor to compose the message.
  29088. +Press%&END (END)+to cancel the mailing request.
  29089. )INIT
  29090.  .HELP = TNNM
  29091.  IF (&NNMAILOT = &Z) &HEADING = 'New mail message'
  29092.  ELSE                &HEADING = 'Reply to message from &NNMAILOT'
  29093.  IF (&NNMAILTO = &Z) .CURSOR = NNMAILTO
  29094.  ELSE                .CURSOR = NNMAILSJ
  29095.  &ZWINTTL = 'Send a mail message or reply'
  29096.  &END = PFK(END)
  29097.  &ZCMD = &Z
  29098.  IF (&NNEDPROF = &Z) &NNEDPROF = TEXT
  29099.  /* IF (&NNMAILSF = &Z) &NNMAILSF = &NNPOSTSF */
  29100. )PROC
  29101.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  29102.  VER(&NNMAILTO,NB)
  29103.  VER(&NNMAILSJ,NB)
  29104.  VER(&NNMAILSF,DSNAME)
  29105.  VER(&NNEDPROF,NAME)
  29106.  IF (&NNEDPROF = &Z) &NNEDPROF = TEXT
  29107.  VPUT (NNMAILRT NNMAILFR NNMAILSF NNEDPROF) PROFILE
  29108. )END
  29109. ./ ADD NAME=NNMQPOST
  29110. )ATTR
  29111. /*                                                                   /*
  29112. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  29113. /*                                                                   /*
  29114. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  29115. /* including the implied warranties of merchantability and fitness,  /*
  29116. /* are expressly denied.                                             /*
  29117. /*                                                                   /*
  29118. /* Provided this copyright notice is included, this software may     /*
  29119. /* be freely distributed and not offered for sale.                   /*
  29120. /*                                                                   /*
  29121. /* Changes or modifications may be made and used only by the maker   /*
  29122. /* of same, and not further distributed.  Such modifications should  /*
  29123. /* be mailed to the author for consideration for addition to the     /*
  29124. /* software and incorporation in subsequent releases.                /*
  29125. /*                                                                   /*
  29126.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  29127. /*                                                                   /*
  29128. /* There seems to be some kind of bug in ISPF 3.3.  Substitution of  /*
  29129. /* variables is not done before the first input field, so I could    /*
  29130. /* not put the panel heading where I wanted it. ???                  /*
  29131. /*                                                                   /*
  29132. )BODY EXPAND(``)
  29133.  -`-`- Post to news server -`-`-
  29134. %Command ===>^ZCMD
  29135.  
  29136. %Note:+The fate of a posted news article is determined by the%news server+
  29137.       %(&NNSERVER).
  29138.  
  29139. +Posting:  &HEADING
  29140.  
  29141. %Required Header Fields+
  29142.  
  29143. +Newsgroups  ===>^NNPOSTNG
  29144. +Subject     ===>^NNPOSTSJ
  29145.  
  29146. %Optional Header Fields+
  29147.  
  29148. +Reply To     ==>^NNPOSTRT
  29149. +Followup To  ==>^NNPOSTFO
  29150.  
  29151. +Your human name ==>^NNPOSTFR
  29152. +Signature file  ==>_NNPOSTSF
  29153. +Edit profile    ==>_NNEDPROF+
  29154.  
  29155. +Press%ENTER+to proceed to the editor to compose the article.
  29156. +Press%&END (END)+to cancel the posting request.
  29157. )INIT
  29158.  .HELP = TNNM
  29159.  IF (&NNPOSTHA = &Z)
  29160.   &HEADING = 'New Article'
  29161.  ELSE
  29162.   &HEADING = 'Followup to Article &NNPOSTHA in group &NNPOSTHG'
  29163.  IF (&NNPOSTNG = &Z) .CURSOR = NNPOSTNG
  29164.  ELSE                .CURSOR = NNPOSTSJ
  29165.  &END = PFK(END)
  29166.  &ZCMD = &Z
  29167.  IF (&NNEDPROF = &Z) &NNEDPROF = TEXT
  29168.  /* IF (&NNPOSTSF = &Z) &NNPOSTSF = &NNMAILSF */
  29169. )PROC
  29170.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  29171.  VER(&NNPOSTNG,NB)
  29172.  VER(&NNPOSTSJ,NB)
  29173.  VER(&NNPOSTSF,DSNAME)
  29174.  VER(&NNEDPROF,NAME)
  29175.  IF (&NNEDPROF = &Z) &NNEDPROF = TEXT
  29176.  VPUT (NNPOSTRT NNPOSTFR NNPOSTSF NNEDPROF) PROFILE
  29177. )END
  29178. ./ ADD NAME=NNMRCERR
  29179. )ATTR
  29180. /*                                                                   /*
  29181. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  29182. /*                                                                   /*
  29183. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  29184. /* including the implied warranties of merchantability and fitness,  /*
  29185. /* are expressly denied.                                             /*
  29186. /*                                                                   /*
  29187. /* Provided this copyright notice is included, this software may     /*
  29188. /* be freely distributed and not offered for sale.                   /*
  29189. /*                                                                   /*
  29190. /* Changes or modifications may be made and used only by the maker   /*
  29191. /* of same, and not further distributed.  Such modifications should  /*
  29192. /* be mailed to the author for consideration for addition to the     /*
  29193. /* software and incorporation in subsequent releases.                /*
  29194. /*                                                                   /*
  29195.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  29196.  @ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
  29197.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  29198.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  29199.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  29200.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  29201.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  29202. )BODY EXPAND(``)
  29203. %-`-`-  MVS Network News Viewer -`-`-
  29204. %COMMAND ===>_ZCMD
  29205. +
  29206. %  ` `  *** ERROR ***  ` ` +
  29207. +
  29208. % ` ` Unable to access the NEWSRC file, which is required. ` ` +
  29209. +
  29210. + ` ` This file must be allocated to DDname%NNNEWSRC. ` ` +
  29211. +
  29212. + ` ` The News Viewer cannot continue. ` ` +
  29213. +
  29214. +
  29215. + ` ` Press!ENTER+or!END+key to leave this panel. ` ` +
  29216. )INIT
  29217.  .HELP = TNNM
  29218. )PROC
  29219.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  29220. )END
  29221. ./ ADD NAME=NNMRFCH
  29222. )ATTR
  29223. /*                                                                   /*
  29224. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  29225. /*                                                                   /*
  29226. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  29227. /* including the implied warranties of merchantability and fitness,  /*
  29228. /* are expressly denied.                                             /*
  29229. /*                                                                   /*
  29230. /* Provided this copyright notice is included, this software may     /*
  29231. /* be freely distributed and not offered for sale.                   /*
  29232. /*                                                                   /*
  29233. /* Changes or modifications may be made and used only by the maker   /*
  29234. /* of same, and not further distributed.  Such modifications should  /*
  29235. /* be mailed to the author for consideration for addition to the     /*
  29236. /* software and incorporation in subsequent releases.                /*
  29237. /*                                                                   /*
  29238.  ! TYPE(TEXT) INTENS(LOW)
  29239.  ? TYPE(TEXT) INTENS(LOW)
  29240.  { TYPE(TEXT) INTENS(LOW)
  29241.  } TYPE(TEXT) INTENS(LOW)
  29242. )BODY EXPAND(``)
  29243. %-`-`- NNMVS - RFC822 Header Viewing Options -`-`-
  29244. %Command ===>_ZCMD
  29245. +
  29246. +The current RFC822 header viewing option is highlighted.
  29247. +Move cursor to choice (or type%S+next to choice) and press%ENTER+to change:
  29248. +
  29249. _A!Show all RFC822 headers
  29250. _B?Show all RFC822 headers except those in Exclude List
  29251. _C{Show the RFC822 headers in Include List only
  29252. _D}Suppress RFC822 headers entirely
  29253. +
  29254. +Lists are header names separated by blanks.  Do%not+put%:+in header names.
  29255. +
  29256. %Include List ==>_NNRFCINC
  29257.  
  29258.  
  29259. %Exclude List ==>_NNRFCEXC
  29260.  
  29261.  
  29262. +Press%ENTER+to change options.  Press%&END+(or type%END+command) when done.
  29263. )INIT
  29264.  .HELP = TNNMOPT
  29265.  .CURSOR = ZCMD
  29266.  &END = PFK(END)
  29267.  &ZCMD = &Z
  29268.  &A = &Z
  29269.  &B = &Z
  29270.  &C = &Z
  29271.  &D = &Z
  29272.  VGET (NNRFCOPT NNRFCINC NNRFCEXC) PROFILE
  29273.  IF (&NNRFCOPT = &Z) &NNRFCOPT = A
  29274.  IF (&NNRFCOPT = A) .ATTRCHAR(!) = 'INTENS(HIGH)'
  29275.  IF (&NNRFCOPT = B) .ATTRCHAR(?) = 'INTENS(HIGH)'
  29276.  IF (&NNRFCOPT = C) .ATTRCHAR({) = 'INTENS(HIGH)'
  29277.  IF (&NNRFCOPT = D) .ATTRCHAR(}) = 'INTENS(HIGH)'
  29278.  IF (&NNRFCOPT = B) .ATTR(NNRFCEXC) = 'INTENS(HIGH)'
  29279.  ELSE               .ATTR(NNRFCEXC) = 'INTENS(LOW)'
  29280.  IF (&NNRFCOPT = C) .ATTR(NNRFCINC) = 'INTENS(HIGH)'
  29281.  ELSE               .ATTR(NNRFCINC) = 'INTENS(LOW)'
  29282. )PROC
  29283.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  29284.  IF (.RESP = ENTER)
  29285.   &TEMP = '&A/&B/&C/&D'
  29286.   IF (&TEMP = '///')
  29287.    &NNCHOICE = TRANS(.CURSOR A A B B C C D D * ' ')
  29288.   ELSE
  29289.    &NNCHOICE = TRANS(&TEMP  'S///' A
  29290.                             '/S//' B
  29291.                             '//S/' C
  29292.                             '///S' D
  29293.                                * ?  )
  29294.   IF (&NNCHOICE = '?')
  29295.    &ZERRSM   = 'Invalid choice'
  29296.    &ZERRLM   = 'Make exactly one selection with the cursor or type only one S.'
  29297.    &ZERRALRM = YES
  29298.    &ZERRHM   = '*'
  29299.    .MSG = ISRZ002
  29300.   ELSE
  29301.    IF (&NNCHOICE ^= &Z)
  29302.     &NNRFCOPT = &NNCHOICE
  29303.   VPUT (NNRFCOPT NNRFCINC NNRFCEXC) PROFILE
  29304. )END
  29305. ./ ADD NAME=NNMVIEW
  29306. )ATTR DEFAULT(%+_)
  29307. /*                                                                   */
  29308. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1993     */
  29309. /*                                                                   */
  29310. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           */
  29311. /*                                                                   */
  29312. /* This software is provided on an "AS IS" basis.  All warranties,   */
  29313. /* including the implied warranties of merchantability and fitness,  */
  29314. /* are expressly denied.                                             */
  29315. /*                                                                   */
  29316. /* Provided this copyright notice is included, this software may     */
  29317. /* be freely distributed and not offered for sale.                   */
  29318. /*                                                                   */
  29319. /* Changes or modifications may be made and used only by the maker   */
  29320. /* of same, and not further distributed.  Such modifications should  */
  29321. /* be mailed to the author for consideration for addition to the     */
  29322. /* software and incorporation in subsequent releases.                */
  29323. /*                                                                   */
  29324.  ^  TYPE(INPUT)  INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  29325.  #  TYPE(OUTPUT) INTENS(HIGH) CAPS(OFF) JUST(RIGHT)
  29326.  \  TYPE(OUTPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  29327.  |  AREA(DYNAMIC) EXTEND(ON) SCROLL(ON) USERMOD(05)
  29328.  01 TYPE(DATAOUT) INTENS(LOW)
  29329.  02 TYPE(DATAOUT) INTENS(HIGH)
  29330.  03 TYPE(DATAIN)  INTENS(LOW)
  29331.  04 TYPE(DATAIN)  INTENS(HIGH)
  29332. )BODY
  29333. \NNBTITLE
  29334. %COMMAND ===>^ZCMD                                            %SCROLL ===>_Z   +
  29335. |NNBDYNA                                                                       |
  29336. )INIT
  29337.  .ZVARS = NNMARTSC
  29338.  IF (&NNMARTSC = &Z) &NNMARTSC = CSR
  29339.  &TNNMTHR = 'NNMVIEW'
  29340.  .HELP = TNNMB1
  29341.  .CURSOR = &NNBCUR
  29342.  .CSRPOS = &NNBPOS
  29343. )PROC
  29344.  &NNBCUR = .CURSOR
  29345.  &NNBPOS = .CSRPOS
  29346.  &NNBLVL = LVLINE(NNBDYNA)
  29347.  VPUT (NNMARTSC) PROFILE
  29348. )END
  29349. ./ ADD NAME=NNM0
  29350. )ATTR
  29351. /*                                                                   /*
  29352. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  29353. /*                                                                   /*
  29354. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  29355. /* including the implied warranties of merchantability and fitness,  /*
  29356. /* are expressly denied.                                             /*
  29357. /*                                                                   /*
  29358. /* Provided this copyright notice is included, this software may     /*
  29359. /* be freely distributed and not offered for sale.                   /*
  29360. /*                                                                   /*
  29361. /* Changes or modifications may be made and used only by the maker   /*
  29362. /* of same, and not further distributed.  Such modifications should  /*
  29363. /* be mailed to the author for consideration for addition to the     /*
  29364. /* software and incorporation in subsequent releases.                /*
  29365. /*                                                                   /*
  29366.  _ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  29367.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  29368.  @ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
  29369.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  29370.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  29371.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  29372.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  29373.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  29374. )BODY EXPAND(``)
  29375. %-`-`-  MVS Network News Client: NNTP Native Protocol Mode  -`-`-
  29376. %COMMAND ===>_ZCMD
  29377. +
  29378. %NNTP command ===>_NNCMD
  29379.  
  29380.  
  29381. +Press!END+key to leave this menu.
  29382. )INIT
  29383.  .HELP = TNNM
  29384.  .CURSOR = NNCMD
  29385.  &ZCMD = &Z
  29386. )PROC
  29387.  IF (&ZCMD ^= &Z) .MSG=ISPZ001
  29388. )END
  29389. ./ ADD NAME=TNNM
  29390. )ATTR
  29391. /*                                                                   /*
  29392. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  29393. /*                                                                   /*
  29394. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  29395. /*                                                                   /*
  29396. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  29397. /* including the implied warranties of merchantability and fitness,  /*
  29398. /* are expressly denied.                                             /*
  29399. /*                                                                   /*
  29400. /* Provided this copyright notice is included, this software may     /*
  29401. /* be freely distributed and not offered for sale.                   /*
  29402. /*                                                                   /*
  29403. /* Changes or modifications may be made and used only by the maker   /*
  29404. /* of same, and not further distributed.  Such modifications should  /*
  29405. /* be mailed to the author for consideration for addition to the     /*
  29406. /* software and incorporation in subsequent releases.                /*
  29407. /*                                                                   /*
  29408.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  29409.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  29410.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  29411.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  29412.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  29413.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  29414. )BODY EXPAND(``)
  29415. %TUTORIAL -`-`-  MVS Network News Viewer -`-`- TUTORIAL
  29416. %SELECTION ===>_ZCMD                                                           +
  29417. %
  29418. +NNMVS is an NNTP (network news transfer protocol)%news client+that runs on the
  29419.  IBM mainframe using ISPF services.  It retrieves news articles from an NNTP
  29420. %news server+executing on a host machine elsewhere on your network.  You must
  29421.  tell NNMVS where this news server is; it does not know otherwise.
  29422.  
  29423. +NNMVS remembers which articles you have read in a%"newsrc"+file, whose name
  29424.  defaults to%&ZPREFIX..NEWSRC+.  If you are a new user, you use the%L+or%blank+
  29425. +option to build your NEWSRC file with a list retrieved from the server.  To
  29426.  limit the list to your favorite newsgroups, you can register (subscribe to)
  29427.  the ones you want while viewing the newsgroup list.  Once you have used NNMVS
  29428.  and built a NEWSRC file, you may wish to use a different entry option to reduce
  29429.  startup time.  You can avoid retrieving the whole list by using the%R+option to
  29430.  view only%registered+(subscribed) newsgroups, or the%A+option to view%all+
  29431.  newsgroups listed in your NEWSRC file.  You can use the%N+option to get a list
  29432.  of newsgroups added since the last time you retrieved the newsgroup list (i.e.
  29433.  used%L+or%N+).  The%G+option always goes directly to a specific newsgroup.
  29434.  
  29435. +Press%ENTER+to proceed with the tutorial, or enter a selection code:
  29436.     %1+- Information on news servers
  29437.     %2+- Information on NNTP, as described by RFC 977
  29438. )INIT
  29439. )PROC
  29440.  &ZSEL = TRANS(&ZCMD,1,TNNMSERV,2,TNNMNNTP,*,?)
  29441.  &ZCONT = TNNM001
  29442. )END
  29443. ./ ADD NAME=TNNMB1
  29444. )ATTR
  29445. /*                                                                   /*
  29446. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  29447. /*                                                                   /*
  29448. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  29449. /*                                                                   /*
  29450. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  29451. /* including the implied warranties of merchantability and fitness,  /*
  29452. /* are expressly denied.                                             /*
  29453. /*                                                                   /*
  29454. /* Provided this copyright notice is included, this software may     /*
  29455. /* be freely distributed and not offered for sale.                   /*
  29456. /*                                                                   /*
  29457. /* Changes or modifications may be made and used only by the maker   /*
  29458. /* of same, and not further distributed.  Such modifications should  /*
  29459. /* be mailed to the author for consideration for addition to the     /*
  29460. /* software and incorporation in subsequent releases.                /*
  29461. /*                                                                   /*
  29462.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  29463.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  29464.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  29465.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  29466.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  29467.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  29468. )BODY EXPAND(``)
  29469. %TUTORIAL -`-`-  MVS Network News Viewer -`-`- TUTORIAL
  29470. %SELECTION ===>_ZCMD                                                           +
  29471. +When you select an article for viewing, you are placed in browse mode.
  29472. +You can use most NNMVS and ISPF BROWSE commands, plus the following commands:
  29473. %NEXT+           - proceed directly to the next article in the newsgroup
  29474. %NEXTSubj+ or%NS+- proceed directly to the next article on the same subject
  29475. %NEXTT+    or%NT+- proceed directly to the next article in the current table
  29476. %NEXTU+    or%NU+- proceed directly to the next unread article in the newsgroup
  29477. %PREV+           - proceed directly to the previous article in the newsgroup
  29478. %PREVSubj+ or%PS+- proceed directly to the previous article on the same subject
  29479. %PREVT+    or%PT+- proceed directly to the previous article in the current table
  29480. %PREVU+    or%PU+- proceed directly to the previous unread article in the group
  29481. %FIRSTSubj+or%FS+- proceed directly to first unread article on the same subject
  29482. %LASTSubj +or%LS+- proceed directly to last unread article on the same subject
  29483. %NEWSUBJ+        - proceed directly to first unread article on different subject
  29484. %SUBJECT+or%SUBJ+- display or change the current subject for subject searches
  29485. %UNREAD+         - stop reading this article and mark it unread
  29486. %EXTRACT+or%EXT+ - copy the article into a data set
  29487. %PRT+or%PRNT+    - print the article to SYSOUT
  29488. %ROT13+          - display "ROT13"-encoded text (toggle, do it again to reverse)
  29489. %FOLLOWUP+       - post a follow-up news article, news server permitting
  29490. %REPLY+          - send private mail to the originator of the news article
  29491. %HEADERs+        - customize article header line display (same as OPTIONS 1)
  29492.                           %(continued on next page)+
  29493. )INIT
  29494.  IF (&TNNMTHR = NNMBROBF) &ZUP = ISR10000
  29495.  ELSE                     &ZUP = TNNM001
  29496.  &ZCONT = TNNMB2
  29497. )PROC
  29498. )END
  29499. ./ ADD NAME=TNNMB2
  29500. )ATTR
  29501. /*                                                                   /*
  29502. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  29503. /*                                                                   /*
  29504. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  29505. /*                                                                   /*
  29506. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  29507. /* including the implied warranties of merchantability and fitness,  /*
  29508. /* are expressly denied.                                             /*
  29509. /*                                                                   /*
  29510. /* Provided this copyright notice is included, this software may     /*
  29511. /* be freely distributed and not offered for sale.                   /*
  29512. /*                                                                   /*
  29513. /* Changes or modifications may be made and used only by the maker   /*
  29514. /* of same, and not further distributed.  Such modifications should  /*
  29515. /* be mailed to the author for consideration for addition to the     /*
  29516. /* software and incorporation in subsequent releases.                /*
  29517. /*                                                                   /*
  29518.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  29519.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  29520.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  29521.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  29522.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  29523.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  29524. )BODY EXPAND(``)
  29525. %TUTORIAL -`-`-  MVS Network News Viewer -`-`- TUTORIAL
  29526. %SELECTION ===>_ZCMD                                                           +
  29527. %
  29528. +All the commands of ISPF BROWSE are supported under NNMVS browse, except for:
  29529.  
  29530.  %HEX+
  29531.  %BROWSE+
  29532.  %SUBMIT+
  29533.  %LOCATE .label+
  29534.  %.<string>+(to assign a label)
  29535.  %FIND P'generic-string'+
  29536.  %DISPLAY CC/NOCC+
  29537.  
  29538. +For NEXTSUBJ, PREVSUBJ, FIRSTSUBJ and LASTSUBJ, the current subject is that
  29539.  of the article being displayed.   Alphabetic case is ignored, and subjects
  29540.  with RE: and WAS: wrappers are taken into account.
  29541.  
  29542. +Note that NNTP protocol displays also use browse mode.  When you are browsing
  29543.  such output, commands relevant to article selection or sending are not
  29544.  available.  This means that EXTRACT and PRT are the only commands other
  29545.  than browse and general NNMVS commands that you can use at such a time.
  29546. )INIT
  29547. )PROC
  29548. )END
  29549. ./ ADD NAME=TNNMC
  29550. )ATTR
  29551. /*                                                                   /*
  29552. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1993     /*
  29553. /*                                                                   /*
  29554. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  29555. /* including the implied warranties of merchantability and fitness,  /*
  29556. /* are expressly denied.                                             /*
  29557. /*                                                                   /*
  29558. /* Provided this copyright notice is included, this software may     /*
  29559. /* be freely distributed and not offered for sale.                   /*
  29560. /*                                                                   /*
  29561. /* Changes or modifications may be made and used only by the maker   /*
  29562. /* of same, and not further distributed.  Such modifications should  /*
  29563. /* be mailed to the author for consideration for addition to the     /*
  29564. /* software and incorporation in subsequent releases.                /*
  29565. /*                                                                   /*
  29566.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  29567.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  29568.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  29569.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  29570.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  29571.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  29572. )BODY EXPAND(``)
  29573. %TUTORIAL -`-`-  MVS Network News Viewer -`-`- TUTORIAL
  29574. %SELECTION ===>_ZCMD                                                           +
  29575.  
  29576. +The following commands are available from any of the display modes:
  29577.  
  29578.  %OPTIONS+or%OPT+- set user options (e.g. for display of message headers)
  29579.  %SAVE          +- checkpoint%newsrc+(otherwise, will not be updated until exit)
  29580.  %POST          +- compose a news article for sending, news server permitting
  29581.  %MAIL          +- compose a mail message for sending to an individual user
  29582.  %NNTP          +- enter native NNTP protocol mode (for debugging only)
  29583.  %DISCONNECT    +- force disconnection from news server (reconnect automatic)
  29584.  %QUIT          +- leave NNMVS, saving changes in NEWSRC file
  29585.  %CRASHNNMVS    +- terminate NNMVS immediately, saving nothing
  29586.  %DEBUG         +- enable NNMVS debug mode (ddname NNDEBUG must be allocated)
  29587.  %NODEBUG       +- deactivate NNMVS debug mode
  29588.  %TEST          +- enter C/370 test mode (INSPECT)
  29589.  
  29590. +The following topics will be displayed next, or may be selected by number:
  29591.  
  29592. %   1 + - The Newsgroup Display (Available Selection Codes and Commands)
  29593. %   2 + - The Article Display   (Available Selection Codes and Commands)
  29594. %   3 + - The Text Display      (Available Commands)
  29595. %   4 + - Specifying User Options
  29596. )INIT
  29597. )PROC
  29598.  &ZSEL = TRANS(&ZCMD 1,TNNMG 2,TNNMT 3,TNNMB1 4,TNNMOPT *,?)
  29599.  &ZUP = TNNM
  29600. )END
  29601. ./ ADD NAME=TNNMG
  29602. )ATTR
  29603. /*                                                                   /*
  29604. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  29605. /*                                                                   /*
  29606. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  29607. /* including the implied warranties of merchantability and fitness,  /*
  29608. /* are expressly denied.                                             /*
  29609. /*                                                                   /*
  29610. /* Provided this copyright notice is included, this software may     /*
  29611. /* be freely distributed and not offered for sale.                   /*
  29612. /*                                                                   /*
  29613. /* Changes or modifications may be made and used only by the maker   /*
  29614. /* of same, and not further distributed.  Such modifications should  /*
  29615. /* be mailed to the author for consideration for addition to the     /*
  29616. /* software and incorporation in subsequent releases.                /*
  29617. /*                                                                   /*
  29618.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  29619.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  29620.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  29621.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  29622.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  29623.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  29624. )BODY EXPAND(``)
  29625. %TUTORIAL -`-`-  MVS Network News Viewer -`-`- TUTORIAL
  29626. %SELECTION ===>_ZCMD                                                           +
  29627. +In the%newsgroup+display, you may type a code in front of a newsgroup name:
  29628.  %S+ - select:      display articles, initially just those you haven't seen yet
  29629.  %N+ - new:         display unseen articles, removing seen ones from display
  29630.  %A+ - all:         display all articles, seen or unseen
  29631.  %R+ - register:    mark the newsgroup as one of your "subscribed" groups
  29632.  %D+ - deregister:  remove the newsgroup from your "subscribed" list
  29633.  %M+ - mark read:   tell the News Viewer you've seen everything in this group
  29634.  %U+ - mark unread: tell the News Viewer you haven't seen anything in this group
  29635.  %Q+ - query:       display newsgroup status (for debugging only)
  29636.  %&A+- &SELEC:      display unseen articles, sorted by subject
  29637.  %&B+- &AL:         display all articles, sorted by subject
  29638. +You may type one of the following commands on the newsgroup command line:
  29639.  %EXTRACT+or%EXT+    - copy the current list of newsgroups into a data set
  29640.  %PRT+or%PRNT+       - print the current list of newsgroups to SYSOUT
  29641.  %LOCATE+or%LOC+or%L+- position display at or near given newsgroup name
  29642.  %FIND string option+- find NEXT, PREV, FIRST or LAST group containing string
  29643.  %ONLY string+       - show only groups containing string (null string for all)
  29644.  %REGISTER+or%REG+   - show registered (subscribed) newsgroups only
  29645.  %ALL+               - show all newsgroups (registered and unregistered)
  29646.  %ORDER Alpha/List+  - order groups alphabetically or by server's active file
  29647.  %RESCAN+            - update the status with the latest items from the server
  29648. )INIT
  29649.  &A = '$'
  29650.  &B = '@'
  29651.  &SELEC  = '$elect'
  29652.  &AL     = '@ll'
  29653. )PROC
  29654.  &ZUP   = TNNM001
  29655. )END
  29656. ./ ADD NAME=TNNMNNTP
  29657. )ATTR
  29658. /*                                                                   /*
  29659. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  29660. /*                                                                   /*
  29661. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  29662. /* including the implied warranties of merchantability and fitness,  /*
  29663. /* are expressly denied.                                             /*
  29664. /*                                                                   /*
  29665. /* Provided this copyright notice is included, this software may     /*
  29666. /* be freely distributed and not offered for sale.                   /*
  29667. /*                                                                   /*
  29668. /* Changes or modifications may be made and used only by the maker   /*
  29669. /* of same, and not further distributed.  Such modifications should  /*
  29670. /* be mailed to the author for consideration for addition to the     /*
  29671. /* software and incorporation in subsequent releases.                /*
  29672. /*                                                                   /*
  29673.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  29674.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  29675.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  29676.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  29677.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  29678.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  29679. )BODY EXPAND(``)
  29680. %TUTORIAL -`-`-  MVS Network News Viewer -`-`- TUTORIAL
  29681. %SELECTION ===>_ZCMD                                                           +
  29682. %
  29683. % ` `  NNTP (Network News Transfer Protocol)  ` `
  29684. %
  29685. +RFC 977, "A Proposed Standard for the Stream-Based Transmission of News",
  29686.  is the document that describes the Network News Transfer Protocol.
  29687.  
  29688.  You may also wish to read:
  29689.  
  29690.  RFC 1036, "Standard for Interchange of USENET Messages"
  29691.  
  29692.  The%NNTP+option from the main NNMVS menu, or the%NNTP+command from any
  29693.  NNMVS display command line, allows you to communicate directly with
  29694.  the NNTP server using the protocol language defined in RFC 977, subject
  29695.  to the support provided by the news server to which you are connected.
  29696. )INIT
  29697. )PROC
  29698.  &ZUP = TNNM
  29699. )END
  29700. ./ ADD NAME=TNNMOPT
  29701. )ATTR
  29702. /*                                                                   /*
  29703. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  29704. /*                                                                   /*
  29705. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  29706. /*                                                                   /*
  29707. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  29708. /* including the implied warranties of merchantability and fitness,  /*
  29709. /* are expressly denied.                                             /*
  29710. /*                                                                   /*
  29711. /* Provided this copyright notice is included, this software may     /*
  29712. /* be freely distributed and not offered for sale.                   /*
  29713. /*                                                                   /*
  29714. /* Changes or modifications may be made and used only by the maker   /*
  29715. /* of same, and not further distributed.  Such modifications should  /*
  29716. /* be mailed to the author for consideration for addition to the     /*
  29717. /* software and incorporation in subsequent releases.                /*
  29718. /*                                                                   /*
  29719.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  29720.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  29721.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  29722.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  29723.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  29724.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  29725. )BODY EXPAND(``)
  29726. %TUTORIAL -`-`-  MVS Network News Viewer -`-`- TUTORIAL
  29727. %SELECTION ===>_ZCMD                                                           +
  29728. %
  29729. % ` `  Options  ` `
  29730. %
  29731. +The user options you set when you enter the OPTIONS command are remembered in
  29732.  your ISPF profile, as is typical of ISPF dialogs.  This is in contrast to
  29733.  newsgroup and article status information, which is stored in your NEWSRC file
  29734.  and not in your ISPF profile.
  29735.  
  29736.  The first set of options specifies handling of the message headers that appear
  29737.  in all news articles.  You may specify whether you want all header lines to be
  29738.  displayed, or just certain ones to be displayed, or certain ones NOT to be
  29739.  displayed, or none to be displayed.  The setting affects article extraction
  29740.  into files as well as viewing.
  29741.  
  29742. +You may specify the frequency at which the News Viewer will update the screen
  29743.  for long-running processes, such as retrieving articles from large newsgroups.
  29744.  
  29745.   %(continued on next page)+
  29746. )INIT
  29747. )PROC
  29748.  &ZUP = TNNM
  29749.  &ZCONT = TNNMOPT2
  29750. )END
  29751. ./ ADD NAME=TNNMOPT2
  29752. )ATTR
  29753. /*                                                                   /*
  29754. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  29755. /*                                                                   /*
  29756. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  29757. /*                                                                   /*
  29758. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  29759. /* including the implied warranties of merchantability and fitness,  /*
  29760. /* are expressly denied.                                             /*
  29761. /*                                                                   /*
  29762. /* Provided this copyright notice is included, this software may     /*
  29763. /* be freely distributed and not offered for sale.                   /*
  29764. /*                                                                   /*
  29765. /* Changes or modifications may be made and used only by the maker   /*
  29766. /* of same, and not further distributed.  Such modifications should  /*
  29767. /* be mailed to the author for consideration for addition to the     /*
  29768. /* software and incorporation in subsequent releases.                /*
  29769. /*                                                                   /*
  29770.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  29771.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  29772.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  29773.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  29774.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  29775.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  29776. )BODY EXPAND(``)
  29777. %TUTORIAL -`-`-  MVS Network News Viewer -`-`- TUTORIAL
  29778. %SELECTION ===>_ZCMD                                                           +
  29779. %
  29780. % ` `  Options - Screen Update Frequency ` `
  29781. %
  29782. +You may specify the frequency at which the News Viewer will update the screen
  29783.  for long-running processes.  These include:
  29784.  
  29785.    fetching the list of all newsgroups
  29786.    fetching the headers for unread articles in a newsgroup
  29787.    fetching the current status of registered newsgroup
  29788.  
  29789.  Specifying%ON+is the same as specifying a frequency of zero.  The initial
  29790.  default is%OFF,+but you may want to set it to%ON+or a number to experiment.
  29791.  
  29792.  When you use the%L+or%blank+option to fetch the list of all newsgroups, since
  29793.  the total number is not known, every newsgroup name will flash on the screen as
  29794.  it is read if the Update option is not%OFF.+ For slow terminals, this can
  29795.  greatly slow down the News Viewer; you should always specify%OFF+for slow
  29796.  terminals if you intend to do this.  While article titles are being fetched, if
  29797.  Update is%OFF,+nothing is displayed until all titles are retrieved.  Otherwise,
  29798.  a bar graph showing the progress will be displayed at the indicated interval;
  29799.  if Update is%ON+(the same as zero), the bar graph will be updated as every
  29800.  title is read.  An estimated time to completion will be displayed as well.
  29801. )INIT
  29802. )PROC
  29803.  &ZUP = TNNM
  29804. )END
  29805. ./ ADD NAME=TNNMSERV
  29806. )ATTR
  29807. /*                                                                   /*
  29808. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  29809. /*                                                                   /*
  29810. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  29811. /* including the implied warranties of merchantability and fitness,  /*
  29812. /* are expressly denied.                                             /*
  29813. /*                                                                   /*
  29814. /* Provided this copyright notice is included, this software may     /*
  29815. /* be freely distributed and not offered for sale.                   /*
  29816. /*                                                                   /*
  29817. /* Changes or modifications may be made and used only by the maker   /*
  29818. /* of same, and not further distributed.  Such modifications should  /*
  29819. /* be mailed to the author for consideration for addition to the     /*
  29820. /* software and incorporation in subsequent releases.                /*
  29821. /*                                                                   /*
  29822.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  29823.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  29824.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  29825.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  29826.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  29827.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  29828. )BODY EXPAND(``)
  29829. %TUTORIAL -`-`-  MVS Network News Viewer -`-`- TUTORIAL
  29830. %SELECTION ===>_ZCMD                                                           +
  29831. %
  29832. % ` `  News Servers  ` `
  29833. %
  29834. +Your NNMVS installation may already be configured to start you up with
  29835.  a default news server host.  If so, then you need do nothing special
  29836.  to tell NNMVS to connect to it.  Otherwise, you will need to provide the
  29837.  name of the host running an NNTP news server.
  29838.  
  29839. +Ask your system administrator to tell you the hostname of the machine
  29840.  where an available news server is running.  You may need to ask the
  29841.  administrator of that host to grant you permission to access the news server
  29842.  from the MVS system where the News Viewer will be running as a client.
  29843.  
  29844. +If NNMVS does not recognize the hostname, you may specify an IP address
  29845.  (four numbers separated by periods in the format nn.nn.nn.nn).
  29846. )INIT
  29847. )PROC
  29848.  &ZUP = TNNM
  29849. )END
  29850. ./ ADD NAME=TNNMT
  29851. )ATTR
  29852. /*                                                                   /*
  29853. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  29854. /*                                                                   /*
  29855. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  29856. /*                                                                   /*
  29857. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  29858. /* including the implied warranties of merchantability and fitness,  /*
  29859. /* are expressly denied.                                             /*
  29860. /*                                                                   /*
  29861. /* Provided this copyright notice is included, this software may     /*
  29862. /* be freely distributed and not offered for sale.                   /*
  29863. /*                                                                   /*
  29864. /* Changes or modifications may be made and used only by the maker   /*
  29865. /* of same, and not further distributed.  Such modifications should  /*
  29866. /* be mailed to the author for consideration for addition to the     /*
  29867. /* software and incorporation in subsequent releases.                /*
  29868. /*                                                                   /*
  29869.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  29870.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  29871.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  29872.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  29873.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  29874.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  29875. )BODY EXPAND(``)
  29876. %TUTORIAL -`-`-  MVS Network News Viewer -`-`- TUTORIAL
  29877. %SELECTION ===>_ZCMD                                                           +
  29878. +In the%article+display, you may type these codes in front of an article number:
  29879.  %S+ - select:      browse the article text
  29880.  %E+ - extract:     copy the article into a data set
  29881.  %P+ - print:       print the article to SYSOUT
  29882.  %M+ - mark read:   tell the News Viewer you've already seen this article
  29883.  %U+ - mark unread: tell the News Viewer you haven't seen this article
  29884.  %F+ - followup:    post a follow-up news article, news server permitting
  29885.  %R+ - reply:       send private mail to the originator of the news article
  29886.  %C+ - cancel:      send article cancel request to server (author must be you)
  29887.  %Q+ - query:       display article status (for debugging only)
  29888. +You may type one of the following commands on the article display command line:
  29889. %LOCATE+or%LOC+or%L+  - position display at or near given article number
  29890. %EXTRACT+or%EXT+      - copy titles or text of all articles into a data set
  29891. %PRT+or%PRNT+         - print titles or text of all articles to SYSOUT
  29892. %TITLES+or%TITLE+     - retrieve titles of all articles in table from the server
  29893. %QUERY+               - display newsgroup status (for debugging only)
  29894. %FIND string option+  - find NEXT, PREV, FIRST or LAST article with "string"
  29895. %ONLY string       +  - limit display to articles with "string" in the subject
  29896. %MARKALL+or%UNMARKALL+- mark all articles in this newsgroup read or unread
  29897. %SORT Subject/Number +- sort article display by subject or by article number
  29898. %RESCAN+              - update the status with the latest items from the server
  29899. )INIT
  29900. )PROC
  29901.  &ZUP   = TNNM001
  29902.  &TNNMTHR = &Z
  29903. )END
  29904. ./ ADD NAME=TNNM001
  29905. )ATTR
  29906. /*                                                                   /*
  29907. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  29908. /*                                                                   /*
  29909. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  29910. /* including the implied warranties of merchantability and fitness,  /*
  29911. /* are expressly denied.                                             /*
  29912. /*                                                                   /*
  29913. /* Provided this copyright notice is included, this software may     /*
  29914. /* be freely distributed and not offered for sale.                   /*
  29915. /*                                                                   /*
  29916. /* Changes or modifications may be made and used only by the maker   /*
  29917. /* of same, and not further distributed.  Such modifications should  /*
  29918. /* be mailed to the author for consideration for addition to the     /*
  29919. /* software and incorporation in subsequent releases.                /*
  29920. /*                                                                   /*
  29921.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  29922.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  29923.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  29924.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  29925.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  29926.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  29927. )BODY EXPAND(``)
  29928. %TUTORIAL -`-`-  MVS Network News Viewer -`-`- TUTORIAL
  29929. %SELECTION ===>_ZCMD                                                           +
  29930. %
  29931. +There are three kinds of displays created by the News Viewer:
  29932.  
  29933. %   Newsgroups+ - which allows you to select newsgroups by name
  29934. %   Articles  + - which allows you to select articles by name
  29935. %   Text      + - which allows you to browse article text or NNTP output
  29936.  
  29937. +Additional commands are available specific to each of the above modes.
  29938.  
  29939. +The following topics will be displayed next, or may be selected by number:
  29940.  
  29941. %   1 + - Commands Available From All Displays
  29942. %   2 + - The Newsgroup Display (Available Selection Codes and Commands)
  29943. %   3 + - The Article Display   (Available Selection Codes and Commands)
  29944. %   4 + - The Text Display      (Available Commands)
  29945. %   5 + - Specifying User Options
  29946. )INIT
  29947. )PROC
  29948.  &ZSEL = TRANS(&ZCMD 1,TNNMC 2,TNNMG 3,TNNMT 4,TNNMB1 5,TNNMOPT *,?)
  29949.  &ZUP = TNNM
  29950. )END
  29951. ./ ENDUP
  29952. ?!
  29953.