home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume36 / unpost / part05 / unpost.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-18  |  12.0 KB  |  412 lines

  1. /******************************************************************************
  2. * Module    :   Unpost --- Extract a binary file from a multi-part, uuencoded
  3. *               USENET News posting.
  4. *
  5. * Author    :   John W. M. Stevens
  6. *
  7. * Notes     :   See the file unpost.doc for information.
  8. ******************************************************************************/
  9.  
  10. #include    "compiler.h"
  11.  
  12. #include    "unpost.h"
  13. #include    "parse.h"
  14. #include    "segment.h"
  15.  
  16. /*********************************** Globals *********************************/
  17. char    *Version = "UNPOST V2.1.2";
  18. int     LineNumber = 0;
  19.  
  20. /*  Binary switches.  See file compiler.h to change default settings.   */
  21. int     MsDosFileNms = MUNGE_FILE_NMS;
  22. int     DumpDesc = DUMP_DESC_FILES;
  23. int     SepIncomps = SEP_INCOMPLETES;
  24.  
  25. /*  File pointers.  */
  26. FILE    *ErrFile = NULL;        /*  Error file.                             */
  27. FILE    *TextFile = NULL;       /*  Write non-binary to file.               */
  28. FILE    *IncompFile = NULL;     /*  Incompletes file.                       */
  29. /*****************************************************************************/
  30.  
  31. /*-----------------------------------------------------------------------------
  32. | Routine   :   ReadLine() --- Get a line from the file.
  33. |
  34. | Inputs    :   FlPtr   - Pointer to file to read from.
  35. |               InBfr   - Pointer to buffer to read into.
  36. |               BfrMax  - Max buffer size.
  37. |
  38. | Returns   :   Returns EOF or OK.
  39. -----------------------------------------------------------------------------*/
  40.  
  41. int     ReadLine(FILE   *FlPtr,
  42.                  char   *InBfr,
  43.                  int    BfrMax)
  44. {
  45.     register    int     i;
  46.     extern      FILE    *ErrFile;
  47.  
  48.     /*  Get a line from the file.   */
  49.     if (fgets(InBfr, BfrMax, FlPtr) == NULL)
  50.     {
  51.         /*  Check for end of file.  */
  52.         if ( feof( FlPtr ) )
  53.             return( EOF );
  54.         else if ( ferror( FlPtr ) )
  55.         {
  56.             fprintf(ErrFile,
  57.                     "%s %d : Error - reading source file.\n",
  58.                     __FILE__,
  59.                     __LINE__);
  60.             exit( 1 );
  61.         }
  62.     }
  63.  
  64.     /*  Remove trailing '\n' character.
  65.     *
  66.     *   Maybe THIS time I got it right. . .
  67.     */
  68.     LineNumber++;
  69.     for (i = strlen( InBfr );
  70.          i > 0 && (InBfr[i - 1] == '\n' || InBfr[i - 1] == '\r');
  71.          i--
  72.         )
  73.         ;
  74.     InBfr[i] = '\0';
  75.  
  76.     /*  Return OK.  */
  77.     return( OK );
  78. }
  79.  
  80. /*-----------------------------------------------------------------------------
  81. | Routine   :   ShowSynopsis() --- Show a summary of the command line
  82. |               syntax.
  83. -----------------------------------------------------------------------------*/
  84.  
  85. static  char    *Synopsis[] =
  86. {
  87. "Options:\n",
  88. "    -b[-]        Break incompletes into separate files.\n",
  89. "    -d[-]        Dump descriptions flag.\n",
  90. "    -e <file>    File for errors (default standard error).\n",
  91. "    -f[-]        Modify file names to be MS-DOS compatible.\n",
  92. "    -h           Interpret headers in source files.\n",
  93. "    -i <file>    File to write incomplete binaries to.\n",
  94. "    -r <e|g|n|r> Set news reader type (SEGMENT begin line RE).\n",
  95. "    -s           Assume segments in order in file.\n",
  96. "    -t <file>    File for text only segments.\n",
  97. "    -u           UU decoder, pure and simple.\n",
  98. "    -v           Print the version number and quit.\n",
  99. "    -?           Show this help summary.\n\n",
  100. "Example:\n",
  101. "    unpost -d -e errors -t text -i multiple.1 multiple.uue\n",
  102. "        Save errors, text segments, descriptions and incompletes.\n\n",
  103. NULL
  104. };
  105.  
  106. static
  107. void    ShowSynopsis(void)
  108. {
  109.     register    int     i;
  110.  
  111.     /*  Show header and version number. */
  112.     printf("%s --- Extract a uuencoded binary from a multi-part posting.\n\n",
  113.            Version);
  114.  
  115.     /*  Show synopsis.  */
  116.     for (i = 0; Synopsis[i]; i++)
  117.         printf( Synopsis[i] );
  118.  
  119.     /*  Show current state of binary flags. */
  120.     printf("File Name Modifying       (-f) : %-3.3s\n",
  121.             (MsDosFileNms) ? "On" : "Off");
  122.     printf("Create Description Files  (-d) : %-3.3s\n",
  123.             (DumpDesc) ? "On" : "Off");
  124.     printf("Separate Incomplete Files (-b) : %-3.3s\n",
  125.             (SepIncomps) ? "On" : "Off");
  126. }
  127.  
  128. /*-----------------------------------------------------------------------------
  129. | Routine   :   CmdLineParse() --- Parse the command line.
  130. |
  131. | Inputs    :   argc    - Number of command line arguments.
  132. |               argv    - List of command line argument strings.
  133. |               SwList  - Switch list.
  134. -----------------------------------------------------------------------------*/
  135.  
  136. static
  137. void    CmdLineParse(int        argc,
  138.                      char       **argv,
  139.                      char       *SwList)
  140. {
  141.     register    int     i;
  142.     auto        char    *ArgPtr;
  143.     auto        char    *SwPtr;
  144.     auto        char    SwChar;
  145.     auto        char    ModeFlag;
  146.  
  147.     /*  Check for no arguments. */
  148.     if (argc < 2)
  149.     {
  150.         /*  Give synopsis and quit. */
  151.         ShowSynopsis();
  152.         exit( 1 );
  153.     }
  154.  
  155.     /*  Scan entire command line.   */
  156.     ErrFile = stderr;
  157.     ModeFlag = 'h';
  158.     for (i = 1; i < argc; i++)
  159.     {
  160.         /*  Get a pointer to the argument.  */
  161.         ArgPtr = argv[i];
  162.  
  163.         /*  Is this a switch?   */
  164.         if (*ArgPtr == '-')
  165.         {
  166.             /*  Get switch character.   */
  167.             if ((SwChar = *++ArgPtr) == '\0')
  168.             {
  169.                 /*  There is no character after the switch marker,
  170.                 *   so declare an error.
  171.                 */
  172.                 ShowSynopsis();
  173.                 exit( 1 );
  174.             }
  175.             else if ((SwPtr = strchr(SwList, SwChar)) == NULL)
  176.             {
  177.                 /*  Error, this is evidently an illegal switch
  178.                 *   character.
  179.                 */
  180.                 ShowSynopsis();
  181.                 exit( 1 );
  182.             }
  183.             else if (SwPtr[1] == '>')
  184.             {
  185.                 /*  Get parameter string.  Parameter string can
  186.                 *   follow immediately after the switch character,
  187.                 *   or it can be the next command line string.
  188.                 */
  189.                 if (*++ArgPtr == '\0')
  190.                 {
  191.                     /*  Next command line parameter is switch
  192.                     *   parameter string.
  193.                     */
  194.                     if (i + 1 < argc)
  195.                         ArgPtr = argv[++i];
  196.                     else
  197.                     {
  198.                         ShowSynopsis();
  199.                         exit( 1 );
  200.                     }
  201.                 }
  202.             }
  203.             else
  204.                 ArgPtr++;
  205.         }
  206.         else
  207.             SwChar = ' ';
  208.  
  209.         /*  Have argument processed.    */
  210.         switch ( SwChar )
  211.         {
  212.         case 'b':
  213.             /*  Set or reset flag that tells UNPOST to separate incompletes
  214.             *   into their own files.
  215.             */
  216.             if (*ArgPtr == '-')
  217.                 SepIncomps = 0;
  218.             else
  219.                 SepIncomps = 1;
  220.             break;
  221.         case 'c':
  222.             /*  Initialize the parser, using the default configuration OR
  223.             *   the configuration file.
  224.             */
  225.             LoadCfg( ArgPtr );
  226.             break;
  227.         case 'd':
  228.             if (*ArgPtr == '-')
  229.                 DumpDesc = 0;
  230.             else
  231.                 DumpDesc = 1;
  232.             break;
  233.         case 'e':
  234.             /*  Close a file that is already open.  */
  235.             if ( ErrFile )
  236.                 fclose( ErrFile );
  237.  
  238.             /*  Open a new error file.  */
  239.             if ((ErrFile = fopen(ArgPtr, TXT_WRITE)) == NULL)
  240.             {
  241.                 fprintf(stderr,
  242.                         "%s %d : Error - Could not open file '%s' ",
  243.                         __FILE__,
  244.                         __LINE__,
  245.                         ArgPtr);
  246.                 fprintf(stderr, "for output.\n");
  247.                 exit( 1 );
  248.             }
  249.             break;
  250.         case 'f':
  251.             if (*ArgPtr == '-')
  252.                 MsDosFileNms = 0;
  253.             else
  254.                 MsDosFileNms = 1;
  255.             break;
  256.         case 'i':
  257.             /*  Close a file that is already open.  */
  258.             if ( IncompFile )
  259.                 fclose( IncompFile );
  260.  
  261.             /*  Open an incompletes file.   */
  262.             if ((IncompFile = fopen(ArgPtr, TXT_APPEND)) == NULL)
  263.             {
  264.                 fprintf(stderr,
  265.                         "%s %d : Error - Could not open file '%s' ",
  266.                         __FILE__,
  267.                         __LINE__,
  268.                         ArgPtr);
  269.                 fprintf(stderr, "for output.\n");
  270.                 exit( 1 );
  271.             }
  272.             break;
  273.         case 'r':
  274.             SetSegBegin( ArgPtr );
  275.             break;
  276.         case 't':
  277.             /*  Close a file that is already open.  */
  278.             if ( TextFile )
  279.                 fclose( TextFile );
  280.  
  281.             /*  Open file for saving text only segments.    */
  282.             if ((TextFile = fopen(ArgPtr, TXT_WRITE)) == NULL)
  283.             {
  284.                 fprintf(stderr,
  285.                         "%s %d : Error - Could not open file '%s' ",
  286.                         __FILE__,
  287.                         __LINE__,
  288.                         ArgPtr);
  289.                 fprintf(stderr, "for output.\n");
  290.                 exit( 1 );
  291.             }
  292.             break;
  293.         case 'h':
  294.         case 'u':
  295.         case 's':
  296.             ModeFlag = SwChar;
  297.             break;
  298.         case 'v':
  299.             printf("%s\n", Version);
  300.             exit( 0 );
  301.         case ' ':
  302.             /*  Select mode.    */
  303.             switch ( ModeFlag )
  304.             {
  305.             case 'h':
  306.                 Multiple( ArgPtr );
  307.                 break;
  308.             case 's':
  309.                 Single( ArgPtr );
  310.                 break;
  311.             case 'u':
  312.                 UUDecode( ArgPtr );
  313.                 break;
  314.             }
  315.             break;
  316.         default:
  317.             ShowSynopsis();
  318.             exit( 1 );
  319.         }
  320.     }
  321. }
  322.  
  323. #if defined(MUNGE_FILE_NAMES_PER_FS) && defined(SYSTEM_OS_2)
  324.  
  325. /*-----------------------------------------------------------------------------
  326. | Routine   :   IsHpfs() --- Is this an HPFS?
  327. |
  328. | Returns   :   Returns 0 for not a HPFS, or non zero for is.
  329. -----------------------------------------------------------------------------*/
  330.  
  331. #if defined(EMX_GCC_COMPILER)
  332.  
  333. int IsHpfs(void)
  334. {
  335.     auto    unsigned long   ulDrive;
  336.     auto    unsigned long   ulLogical;
  337.     auto    char            drive[3];
  338.     auto    char            name[16];
  339.  
  340.     /*  Check operating system mode.    */
  341.     if (_osmode == DOS_MODE)
  342.         return( 0 );
  343.  
  344.     /*  Get current disk drive. */
  345.     DosQueryCurrentDisk(&ulDrive, &ulLogical);
  346.  
  347.     /*  Set up drive name string.   */
  348.     drive[0] = (char) (ulDrive + '@');
  349.     drive[1] = ':';
  350.     drive[2] = '\0';
  351.  
  352.     /*  Get file system name string.    */
  353.     if (_filesys(drive, name, 16) == -1)
  354.         return( 0 );
  355.  
  356.     /*  Is this an HPFS?    */
  357.     if (strcmp(name, "HPFS") == 0)
  358.         return( 1 );
  359.     return( 0 );
  360. }
  361.  
  362. #elif   defined(OS_2_MSC_COMPILER)
  363.  
  364. int IsHpfs(void)
  365. {
  366.     auto    USHORT  nDrive;
  367.     auto    ULONG   lMap;
  368.     auto    BYTE    bData[64];
  369.     auto    BYTE    bName[3];
  370.     auto    USHORT  cbData;
  371.  
  372.     /*  MS-DOS does not have HPFS.  */
  373.     if (_osmode == DOS_MODE)
  374.         return( 0 );
  375.  
  376.     /*  Get the default drive.  */
  377.     DosQCurDisk(&nDrive, &lMap);
  378.  
  379.     /*  Set up the drive name.  */
  380.     bName[0] = (char) (nDrive + '@');
  381.     bName[1] = ':';
  382.     bName[2] = 0;
  383.     cbData = sizeof( bData );
  384.  
  385.     /*  Read the info, if we fail - assume non-HPFS.    */
  386.     if ( DosQFSAttach(bName, 0, FSAIL_QUERYNAME, bData, &cbData, 0L) )
  387.         return( 0 );
  388.     else if (strcmp(bData + (*((USHORT *) (bData + 2)) + 7), "HPFS") == 0)
  389.         return( 1 );
  390.     return( 0 );
  391. }
  392.  
  393. #endif
  394.  
  395. #endif
  396.  
  397. int     main(int    argc,
  398.              char   **argv)
  399. {
  400.     /*  If the user wants different file name munging on different
  401.     *   systems, set -f flag accordingly, otherwise, leave alone.
  402.     */
  403. #if defined(MUNGE_FILE_NAMES_PER_FS) && defined(SYSTEM_OS_2)
  404.     MsDosFileNms = ! IsHpfs();
  405. #endif
  406.  
  407.     /*  Parse command line parameters.  */
  408.     ParseInit();
  409.     CmdLineParse(argc, argv, "bc>de>fhi>r>st>uv");
  410.     return( 0 );
  411. }
  412.