#include "xbcomm.h"

#ifndef TMPDIR
#define TMPDIR "."
#endif

char *reasonForFail;
boolean DEBUG_PROC;
boolean UUencode;
boolean verboseOutput;
boolean scriptOut;
boolean noSplit;
boolean noZero;
boolean noConfirm;
boolean noDescribe;
boolean postIt;
boolean anonPost;
int *patchPart;
int patchPartUB;
int splitSize;
char *theDest, *extraDest, *theFile, *extraTitle, *labelInfo, *headFile;
char *anonUser, *anonSite, *anonHost, *anonPath, *anonSig, *anonAlias;
char *anonFile, *anonOther;
char *partRoot, *scriptRoot, *fileRoot, *fileName, *fileStats, *picRes, *tmpDir;
int fileType, topDECnt;
char *fullSum, *fullUUSum;
DirEntry *topDE;


static char *formatSubj( part )
int part;
{
    char subjLine[ 256 ];
    char *tmpStr;
 
	/* Format of the subject line: */
	/* `- filename (part/total) {label} ^REPOST^ [sh] "extraTitle"' */
	/* Of which {label}, ^REPOST^, [sh], and "extraTitle" are optional */
	/* depending upon specified input... */
	if ( topDECnt < 10 OR part > 9 ) 
	    sprintf( subjLine, "- %s (%d/%d)", fileName, part, topDECnt );
	else
	    sprintf( subjLine, "- %s (0%d/%d)", fileName, part, topDECnt );	
	if ( labelInfo ISNT NULL )
	{
	    tmpStr = copyString( subjLine );
	    sprintf( subjLine, "%s {%s}", tmpStr, labelInfo );
	    free( tmpStr );
	}
	if ( patchPart[ 0 ] )
	{
	    tmpStr = copyString( subjLine );
	    sprintf( subjLine, "%s ^REPOST^", tmpStr );
	    free( tmpStr );
	}
	if ( scriptOut )
	{
	    tmpStr = copyString( subjLine );
	    sprintf( subjLine, "%s [sh]", tmpStr );
	    free( tmpStr );
	}
	if ( extraTitle ISNT NULL )
	{
	    tmpStr = copyString( subjLine );
	    sprintf( subjLine, "%s \"%s\"", tmpStr, extraTitle );
	    free( tmpStr );
	}
	return( copyString( subjLine ) );
}

static boolean validPatchPart( num )
int num;
{
    int tmpPart;

	for ( tmpPart = 1; tmpPart <= patchPart[ 0 ]; tmpPart++ )
	    if ( patchPart[ tmpPart ] IS num )
		return( TRUE );
	return( FALSE );
}

static char *allPatchParts()
{
    int tmpPart, thisNum, lastNum;
    boolean doingRange;
    char *tmpStr, result[ 256 ];

	result[ 0 ] = NULLTERM;
	doingRange = FALSE;
	for ( tmpPart = 1; tmpPart <= patchPart[ 0 ]; tmpPart++ )
	{
	    if ( tmpPart IS 1 )
		sprintf( result, "%d", patchPart[ tmpPart ] );
	    else
	    {
		tmpStr = copyString( result );
		if ( ( thisNum = patchPart[ tmpPart ] ) IS ( lastNum + 1 ) )
		{
		    if ( NOT doingRange )
		        if ( tmpPart IS patchPart[ 0 ] )
			    sprintf( result, "%s-%d", tmpStr, thisNum );
			else
			    sprintf( result, "%s-", tmpStr );
		    else if ( tmpPart IS patchPart[ 0 ] )
			sprintf( result, "%s%d", tmpStr, thisNum );
		    doingRange = TRUE;
		}
		else if ( doingRange )
		{
		    sprintf( result, "%s%d,%d", tmpStr, lastNum, thisNum );
		    doingRange = FALSE;
		}
		else
		    sprintf( result, "%s,%d", tmpStr, thisNum );
		free( tmpStr );
	    }
	    lastNum = patchPart[ tmpPart ];
	}
	return( copyString( result ) );
}

static VOIDPARM addPatchPart( num )
int num;
{
    int *tmpAry;
    int tmpInt, lastSize;

	if ( ( patchPart[ 0 ] + 1 ) >= patchPartUB )
	{
	    /* extend the current array */
	    patchPartUB = patchPartUB + 5;
	    tmpAry = (int *)malloc( sizeof( int ) * patchPartUB );
	    lastSize = patchPart[ 0 ];
	    for ( tmpInt = 0; tmpInt <= lastSize; tmpInt++ )
		tmpAry[ tmpInt ] = patchPart[ tmpInt ];
	    free( patchPart );
	    patchPart = tmpAry;
	}
	patchPart[ 0 ]++;
	patchPart[ patchPart[ 0 ] ] = num;
	patchPart[ patchPart[ 0 ] + 1 ] = -1;
}

static VOIDPARM removePatchPart( num )
int num;
{
    int tmpInt, tmpInt1;

	for ( tmpInt = 1; tmpInt <= patchPart[ 0 ]; tmpInt++ )
	    if ( patchPart[ tmpInt ] IS num )
	    {
		for ( tmpInt1 = tmpInt; 
			tmpInt1 <= patchPart[ 0 ]; tmpInt1++ )
		    patchPart[ tmpInt1 ] = patchPart[ tmpInt1 + 1 ];
		patchPart[ patchPart[ 0 ] ] = -1;
		patchPart[ 0 ]--;
		break;
	    }	
}

static boolean readPatchParts( str )
char *str;
{
    int cPtr, iPtr, theLen, testInt, rangeIdx;
    char thisChar, tmpInt[ 16 ];
    boolean doingRange;

	theLen = strlen( str );
	iPtr = 0;
	doingRange = FALSE;
    	patchPart[ 0 ] = 0;
	for ( cPtr = 0; cPtr <= theLen; cPtr++ )
	{
	    if ( cPtr IS theLen )
	    {
	        tmpInt[ iPtr ] = NULLTERM;
		iPtr = 0;
	        if ( strlen( tmpInt ) )
	        {
		    testInt = atoi( tmpInt );
		    if ( doingRange )
			for ( rangeIdx = patchPart[ patchPart[ 0 ] ] + 1; 
				rangeIdx <= testInt; rangeIdx++ )
			    addPatchPart( rangeIdx );
		    else
			addPatchPart( testInt );
	        }
	        else
	        {
		    printf( "Invalid number specified as patch part!\n" );
		    return( FALSE );
	        }
	    }
	    else
	    {
	        thisChar = str[ cPtr ];
	    	if ( thisChar IS DASH )
		{
		    tmpInt[ iPtr ] = NULLTERM;
		    iPtr = 0;
		    if ( strlen( tmpInt ) )
		    {
			testInt = atoi( tmpInt );
		    	if ( doingRange )
			    printf( 
				"Ignoring intermediate range value of %d...\n",
				    testInt );
			else
			    addPatchPart( testInt );
		    }
		    else
		    {
			printf( "Invalid number specified as patch part!\n" );
			return( FALSE );
		    }
		    doingRange = TRUE;
		}
		else if ( thisChar IS COMMA )
		{
		    tmpInt[ iPtr ] = NULLTERM;
		    iPtr = 0;
		    if ( strlen( tmpInt ) )
		    {
			testInt = atoi( tmpInt );
		        if ( doingRange )
			    for ( rangeIdx = patchPart[ patchPart[ 0 ] ] + 1; 
				    rangeIdx <= testInt; rangeIdx++ )
			        addPatchPart( rangeIdx );
		        else
			    addPatchPart( testInt );
		    }
		    else
		    {
			printf( "Invalid number specified as patch part!\n" );
			return( FALSE );
		    }
		    doingRange = FALSE;
		}
		else
		{
		    tmpInt[ iPtr ] = thisChar;
	    	    iPtr++;
		}
	    }
	}
	return( TRUE );
}

static boolean lastPart( thisPart )
int thisPart;
{
    int arIdx;

	if ( patchPart[ 0 ] )
	{
	    for ( arIdx = 1; arIdx <= patchPart[ 0 ]; arIdx++ )
		if ( patchPart[ arIdx ] > thisPart )
		    return( FALSE );
	    return( TRUE );
	}
	else
	    return( thisPart IS topDECnt );
}

static VOIDPARM generateP0Script( fPtr )
FILE *fPtr;
{
    	fprintf( fPtr, 
"\n    Instructions for extraction:\n" );
    	fprintf( fPtr, 
"    ----------------------------\n" );
	if ( postIt )
	{
    	    fprintf( fPtr, 
"    A) Using rn/nn news reader facilities (easiest - let the news reader do\n" );
    	    fprintf( fPtr, 
"          the work! - includes automatic extraction and filesum checking):\n" );
    	    fprintf( fPtr, 
"       1) Ignore the script below - just use the 'extract' feature of your\n" );
	    if ( topDECnt IS 1 )
	    {
    	        fprintf( fPtr, 
"          news reader to decode part 1 (NICE feature - unfortunately not\n" );
    	        fprintf( fPtr, 
"          available in all versions).\n" );
	    }
	    else
	    {
    	    fprintf( fPtr, 
"          news reader to decode the other %d pieces (NICE feature -\n",
		     topDECnt );
    	    fprintf( fPtr, 
"          unfortunately not available in all versions).\n" );
	    }
    	    fprintf( fPtr, 
"       2) Enjoy the resulting %s file!\n", 
		 fileName );
    	    fprintf( fPtr, 
"    B) UNIX script method (next easiest - recommended for beginners and\n" );
    	    fprintf( fPtr, 
"          those interested in automatic extraction and filesum checking):\n" );
	}
	else
	{
    	    fprintf( fPtr, 
"    A) UNIX script method (easiest - recommended for beginners and those\n" );
    	    fprintf( fPtr, 
"          interested in automatic extraction and filesum checking):\n" );
	}
	if ( topDECnt IS 1 )
	{
    	    fprintf( fPtr, 
"       1) Extract the shell script in part 1, removing everything before and\n" );
    	    fprintf( fPtr, 
"          including the \"shell begin here\" line, and everything after and\n" );
    	    fprintf( fPtr, 
"          including the \"shell end here\" line (save as %s1).\n", 
	             scriptRoot );
	    fprintf( fPtr, 
"       2) Execute 'sh %s1'.  This script will do all of the\n",
		     scriptRoot );
	    fprintf( fPtr, 
"          extraction, filesum checking, and decoding steps for you, detecting\n" );
	    fprintf( fPtr, 
"          any errors along the way.\n" );
	    fprintf( fPtr, 
"       3) Enjoy the resulting %s file!\n", 
		     fileName );
	}
	else
	{
    	    fprintf( fPtr, 
"       1) Extract the following shell script, removing everything before and\n" );
    	    fprintf( fPtr, 
"          including the \"shell begin here\" line, and everything after and\n" );
    	    fprintf( fPtr, 
"          including the \"shell end here\" line (save as %s.sh).\n", 
	             scriptRoot );
	    fprintf( fPtr, 
"       2) Save the remaining %d file parts into the files specified in\n", 
		     topDECnt );
	    fprintf( fPtr, 
"          their respective headers (these files should be in the same\n" );
	    fprintf( fPtr,
"          directory as %s.sh).\n", 
		     scriptRoot );
	    fprintf( fPtr, 
"       3) Execute 'sh %s.sh'.  This script will do all of the\n",
		     scriptRoot );
	    fprintf( fPtr, 
"          extraction, concatenation, filesum checking, and decoding steps for\n" );
	    fprintf( fPtr, 
"          you, detecting any errors along the way.\n" );
	    fprintf( fPtr, 
"       4) Enjoy the resulting %s file!\n", 
		     fileName );
	}
	if ( postIt )
    	    fprintf( fPtr, 
"    C) To manually edit/patch (for those familiar with these type of files\n" );
	else
    	    fprintf( fPtr, 
"    B) To manually edit/patch (for those familiar with these type of files\n" );
	fprintf( fPtr,
"          - and/or those without UNIX!):\n" );
    	fprintf( fPtr, 
"       1) Save everything between line pairs of the text\n" );
    	fprintf( fPtr, 
"          \"BEGIN --- CUT HERE --- Cut Here --- cut here ---\"\n" );
    	fprintf( fPtr, 
"                          ...and...\n" );
    	fprintf( fPtr, 
"          \"END --- CUT HERE --- Cut Here --- cut here ---\".\n" );
    	fprintf( fPtr, 
"       2) Concatenate the resulting file part(s) together (in order!)" );
	if ( UUencode )
	    fprintf( fPtr, " and\n          pipe the result into uudecode.\n" );
	else
	    fprintf( fPtr, ".\n" );
    	fprintf( fPtr, 
"       3) Enjoy the resulting %s file!\n", 
		 fileName );
	fprintf( fPtr, 
"\n\tIf you have any trouble with the above, I'm sure I'll get e-mail from\n" );
	fprintf( fPtr, 
"    you... (but if you DON'T have trouble, I wouldn't mind hearing that,\n" );
	fprintf( fPtr, 
"    either!!)\n\n" );
	if ( topDECnt ISNT 1 )
	{
	    fprintf( fPtr, 
"#--------shell begin here------- save as %s.sh\n",
		     scriptRoot );
	    fprintf( fPtr, 
"#! /bin/sh\n" );
	    if ( UUencode )
	        fprintf( fPtr, 
"# TOP-LEVEL script for translating %s from uuencoded form\n",
		         fileName );
	    else
	        fprintf( fPtr, 
"# TOP-LEVEL script for translating %s from transmitted form\n",
		         fileName );
	    fprintf( fPtr, 
"filePart=1\n" );
	    fprintf( fPtr, 
"missingFiles=\"\"\n" );
	    fprintf( fPtr, 
"until [ ${filePart} -eq %d ]\n",
		     topDECnt + 1 );
	    fprintf( fPtr, 
"do\n" );
	    if ( topDECnt > 9 )
	    {
	        fprintf( fPtr, 
"  if [ ${filePart} -lt 10 ]\n" );
	        fprintf( fPtr, 
"  then\n" );
	        fprintf( fPtr, 
"    partStr=\"0${filePart}\"\n" );
	        fprintf( fPtr, 
"  else\n" );
	        fprintf( fPtr, 
"    partStr=\"${filePart}\"\n" );
	        fprintf( fPtr, 
"  fi\n" );
	    }
	    else
	        fprintf( fPtr, 
"  partStr=\"${filePart}\"\n" );
	    fprintf( fPtr, 
"  test -f %s${partStr}\n",
		     scriptRoot );
	    fprintf( fPtr, 
"  fileErr=$?\n" );
	    fprintf( fPtr, 
"  if [ $fileErr -eq 0 ]\n" );
	    fprintf( fPtr, 
"  then\n" );
	    fprintf( fPtr, 
"    awk \" \\\n" );
	    fprintf( fPtr, 
"        /shell begin here/ { print_next = 1; } \\\n" );
	    fprintf( fPtr, 
"        /shell end here/ { print_mode = 0; } \\\n" );
	    fprintf( fPtr, 
"        { \\\n" );
	    fprintf( fPtr, 
"          if ( print_mode ) { \\\n" );
	    fprintf( fPtr, 
"            print; \\\n" );
	    fprintf( fPtr, 
"          } \\\n" );
	    fprintf( fPtr, 
"          if ( print_next ) { \\\n" );
	    fprintf( fPtr, 
"            print_mode = 1; \\\n" );
	    fprintf( fPtr, 
"            print_next = 0; \\\n" );
	    fprintf( fPtr, 
"          } \\\n" );
	    fprintf( fPtr, 
"        } \\\n" );
	    fprintf( fPtr, 
"        \" %s${partStr} > %s${partStr}.sh\n",
		     scriptRoot, scriptRoot );
	    fprintf( fPtr, 
"    test -f %s${partStr}.sh\n",
		     scriptRoot );
	    fprintf( fPtr, 
"    exErr=0\n" );
	    fprintf( fPtr, 
"    fileErr=$?\n" );
	    fprintf( fPtr, 
"    if [ $fileErr -eq 0 ]\n" );
	    fprintf( fPtr, 
"    then\n" );
	    fprintf( fPtr, 
"      chmod +x %s${partStr}.sh\n",
		     scriptRoot );
	    fprintf( fPtr, 
"      ./%s${partStr}.sh\n",
		     scriptRoot );
	    fprintf( fPtr, 
"      result=$?\n" );
	    fprintf( fPtr, 
"      if [ $result -eq 0 ]\n" );
	    fprintf( fPtr, 
"      then\n" );
	    fprintf( fPtr, 
"        rm -f %s${partStr}.sh %s${partStr}\n",
		     scriptRoot, scriptRoot );
	    fprintf( fPtr, 
"      else\n" );
	    fprintf( fPtr, 
"        if [ $result -eq 7 ]\n" );
	    fprintf( fPtr, 
"        then\n" );
	    fprintf( fPtr, 
"          rm -f %s${partStr}.sh %s${partStr}\n",
		     scriptRoot, scriptRoot );
	    fprintf( fPtr, 
"          missingFiles=\"\"\n" );
	    fprintf( fPtr, 
"          break\n" );
	    fprintf( fPtr, 
"        else\n" );
	    fprintf( fPtr, 
"          if [ $result -eq 6 ]\n" );
	    fprintf( fPtr, 
"          then\n" );
	    fprintf( fPtr, 
"            exit 1\n" );
	    fprintf( fPtr, 
"          else\n" );
	    fprintf( fPtr, 
"            echo \"Error in execution of %s${partStr}.sh - continuing...\"\n",
		     scriptRoot );
	    fprintf( fPtr, 
"            exErr=$result\n" );
	    fprintf( fPtr, 
"          fi\n" );
	    fprintf( fPtr, 
"        fi\n" );
	    fprintf( fPtr, 
"      fi\n" );
	    fprintf( fPtr, 
"    else\n" );
	    fprintf( fPtr, 
"      echo \"WARNING: File %s${partStr}.sh doesn't exist!! - continuing...\"\n",
		     scriptRoot );
	    fprintf( fPtr, 
"      test -f %s${partStr}.xb\n",
		     partRoot );
	    fprintf( fPtr, 
"      exErr=$?\n" );
	    fprintf( fPtr, 
"    fi\n" );
	    fprintf( fPtr, 
"  else\n" );
	    fprintf( fPtr, 
"    echo \"WARNING: File %s${partStr} doesn't exist!! - continuing...\"\n",
		     scriptRoot );
	    fprintf( fPtr, 
"    test -f %s${partStr}.xb\n",
		     partRoot );
	    fprintf( fPtr, 
"    exErr=$?\n" );
	    fprintf( fPtr, 
"  fi\n" );
	    fprintf( fPtr, 
"  if [ $exErr -ne 0 ]\n" );
	    fprintf( fPtr, 
"  then\n" );
	    fprintf( fPtr, 
"    if [ \"$missingFiles\" = \"\" ]\n" );
	    fprintf( fPtr, 
"    then\n" );
	    fprintf( fPtr, 
"      missingFiles=\"%s${partStr}.xb\"\n",
		     partRoot );
	    fprintf( fPtr, 
"    else\n" );
	    fprintf( fPtr, 
"      missingFiles=\"$missingFiles %s${partStr}.xb\"\n",
		     partRoot );
	    fprintf( fPtr, 
"    fi\n" );
	    fprintf( fPtr, 
"  fi\n" );
	    fprintf( fPtr, 
"  filePart=`expr $filePart + 1`\n" );
	    fprintf( fPtr, 
"done\n" );
	    fprintf( fPtr, 
"if [ \"$missingFiles\" = \"\" ]\n" );
	    fprintf( fPtr, 
"then\n" );
	    fprintf( fPtr, 
"  exit 0\n" );
	    fprintf( fPtr, 
"else\n" );
	    fprintf( fPtr, 
"  echo \"Cannot continue without file(s) ${missingFiles}...\"\n" );
	    fprintf( fPtr, 
"  exit 1\n" );
	    fprintf( fPtr, 
"fi\n" );
	    fprintf( fPtr, 
"#--------shell end here------- save as %s.sh\n",
		     scriptRoot );
	}
}

static VOIDPARM includeHeaderInfo( theFile )
FILE *theFile;
{
    char tempStr[ 256 ];
    FILE *tmpFile;

	if ( NOT ( tmpFile = fopen( headFile, "r" ) ) )
	{
	    printf( 
	    "ERROR:  Couldn't open header info file %s for read access\n",
		    headFile );
	    printf( 
	    "        No extra header info will therefore be included...\n" );
	}
	else
	{
	    while ( lineRead( tmpFile, tempStr ) ISNT EOF )
	    {
		if ( tempStr[ 0 ] IS NULLTERM )
		    printf( 
		    "WARNING:  Blank line in header info file ignored\n" );
		else
		    fprintf( theFile, "%s\n", tempStr );
	    }
	}
}

static VOIDPARM createPart0( VOIDPARM )
{
    FILE *tmpFile, *sigFile;
    char tempStr[ 256 ];
    char *homePath, *tempSum, *tempFname, *p0Subj, *replyto;
    int commandResult, partNum;
    DirEntry *tmpDE;
  
	if ( verboseOutput )
	{
	    printf( "...creating part 0" );
	    fflush( stdout );
	}
	p0Subj = formatSubj( 0 );
	sprintf( tempStr, "%s/%s.p0h", tmpDir, fileRoot );
	tmpFile = fopen( tempStr, "w" );
	if ( postIt )
	{
	    if ( anonPost )
		addAnonHeader( tmpFile, 0 );
	    fprintf( tmpFile, "Subject: %s\n", p0Subj );
	    fprintf( tmpFile, "Newsgroups: %s\n", theDest );
	    if ( extraDest ISNT NULL )
	        fprintf( tmpFile, "Followup-to: %s\n", extraDest );
            replyto = (char *)getenv( "REPLYTO" );
            if ( replyto ISNT NULL )
               fprintf( tmpFile, "Reply-To: %s\n", replyto );
	    fprintf( tmpFile, "Distribution: world\n" );
	    fprintf( tmpFile, "X-Posting-Software: " );
	}
	else
	{
#ifdef SysVMail
	    fprintf( tmpFile, "To: %s\n", theDest );
	    fprintf( tmpFile, "Subject: %s\n", p0Subj );
#else
	    fprintf( tmpFile, "~s %s\n", p0Subj );
#endif
	    if ( extraDest ISNT NULL )
#ifdef SysVMail
	        fprintf( tmpFile, "Cc: %s\n", extraDest );
#else
	        fprintf( tmpFile, "~c %s\n", extraDest );
#endif
	    fprintf( tmpFile, "X-Mailing-Software: " );
	}
	fprintf( tmpFile, "xmitBin v%s by D. Jim Howard (deej@cadence.com)\n",
		 xmitBinRev );
	if ( headFile ISNT NULL )
	    includeHeaderInfo( tmpFile );

	/* OK - that's all the header information - now on to the real */
	/* stuff! */
	fprintf( tmpFile, "\n" );
	fclose( tmpFile );
	sprintf( tempStr, "%s.dsc", descPath() );
	if ( noDescribe )
	    sprintf( tempStr, "mv %s/%s.p0h %s/%s.p0", tmpDir, fileRoot, 
		     tmpDir, fileRoot );
	else if ( fileExists( tempStr ) )
	{
	    sprintf( tempStr, "%s.pat", descPath() );
	    if ( patchPart[ 0 ] AND fileExists( tempStr ) )
		sprintf( tempStr, 
			 "cat %s/%s.p0h %s.pat %s.dsc > %s/%s.p0;rm %s/%s.p0h", 
		         tmpDir, fileRoot, descPath(), descPath(), 
			 tmpDir, fileRoot, tmpDir, fileRoot );
	    else
	        sprintf( tempStr, 
			 "cat %s/%s.p0h %s.dsc > %s/%s.p0;rm %s/%s.p0h", 
		         tmpDir, fileRoot, descPath(), tmpDir, fileRoot, 
			 tmpDir, fileRoot );
	}
	else
	{
	    sprintf( tempStr, "%s.pat", descPath() );
	    if ( patchPart[ 0 ] AND fileExists( tempStr ) )
	        sprintf( tempStr, 
			 "cat %s/%s.p0h %s.pat > %s/%s.p0;rm %s/%s.p0h", 
		         tmpDir, fileRoot, descPath(), tmpDir, fileRoot, 
			 tmpDir, fileRoot );
	    else
	        sprintf( tempStr, "cat %s/%s.p0h > %s/%s.p0;rm %s/%s.p0h", 
		         tmpDir, fileRoot, tmpDir, fileRoot, tmpDir, fileRoot );
	}
	system( tempStr );
	/* Write known statistics to file */
	sprintf( tempStr, "%s/%s.p0", tmpDir, fileRoot );
	tmpFile = fopen( tempStr, "a" );
	fprintf( tmpFile, "\n\tThis description and the associated " );
	if ( topDECnt > 1 )
	    if ( UUencode )
	        fprintf( tmpFile, 
		         "%d parts contain the uuencoded\n    form of %s",
		         topDECnt, fileName );
	    else
	        fprintf( tmpFile, 
		         "%d parts contain the transmitted\n    form of %s",
		         topDECnt, fileName );
	else if ( UUencode )
	    fprintf( tmpFile, 
		     "part contains the uuencoded form\n    of %s",
		     fileName );
	else
	    fprintf( tmpFile, 
		     "part contains the transmitted form\n    of %s",
		     fileName );
	if ( fileType IS UNKNOWN )
	    fprintf( tmpFile, ".\n" );
	else
	    fprintf( tmpFile, ", which is a %s %s picture.\n", 
		     fileStats, picRes );
	if ( scriptOut )
	    generateP0Script( tmpFile );
	else
	{
	    fprintf( tmpFile, "\n    UNIX 'wc -lc' of %s: %s\n", 
		     fileName, fullSum );
	    if ( UUencode )
	    	fprintf( tmpFile, "    UNIX 'wc -lc' of uuencoded %s: %s\n", 
		         fileName, fullUUSum );
	    if ( topDECnt > 1 )
	    {
	    	tmpDE = topDE;
	    	partNum = 1;
	    	while ( tmpDE ISNT NULL )
	    	{
		    tempFname = gDEName( tmpDE );
		    sprintf( tempStr, 
			     "wc -lc %s | awk '{ printf \"%%s %%s\", $1, $2 }'",
		 	     tempFname ); 
		    tempSum = shellResult( tempStr, &commandResult );
	            fprintf( tmpFile, "    UNIX 'wc -lc' of " );
		    if ( UUencode )
			fprintf( tmpFile, "uuencoded " );
		    fprintf( tmpFile, "%s part %d: %s\n", 
		             fileName, partNum, tempSum );
		    tmpDE = nDE( tmpDE );
		    partNum++;
		}
	    }
	}

	tempStr[ 0 ] = NULLTERM;
	homePath = (char *)getenv( "HOME" );
	if ( ( homePath ISNT NULL ) AND ( strlen ( homePath ) ISNT 0 ) )
	    sprintf( tempStr, "%s/.signature", homePath );
	if ( anonPost AND ( anonSig ISNT NULL ) )
	    sprintf( tempStr, "%s", anonSig );
	if ( ( tempStr[ 0 ] ISNT NULLTERM ) AND fileExists( tempStr ) )
	{
	    /* Read in/write out the .signature file - news */
	    /* posters often munge > 4 line .sigs... */
	    fprintf( tmpFile, "-- \n" );
	    sigFile = fopen( tempStr, "r" );
	    while ( lineRead( sigFile, tempStr ) ISNT EOF )
	        fprintf( tmpFile, "%s\n", tempStr );
	    fclose( sigFile );
	}
	fclose( tmpFile );
	if ( verboseOutput )
	    if ( lastPart( 0 ) )
	        printf( " - done.\n" );
	    else
	    {
		printf( "," );
		fflush( stdout );
	    }
}

static VOIDPARM generateUUScriptHeader( fPtr, partNum )
FILE *fPtr;
int partNum;
{
    char partStr[ 3 ], tempStr[ 256 ];

	if ( topDECnt < 10 OR partNum > 9 )
	    sprintf( partStr, "%d", partNum );
	else
	    sprintf( partStr, "0%d", partNum );
	if ( noSplit OR noZero OR topDECnt IS 1 )
	    fprintf( fPtr,
"#--------shell begin here-------\n" );
	else
	    fprintf( fPtr,
"#--------shell begin here------- save as %s%s\n",
		     scriptRoot, partStr );
	fprintf( fPtr,
"#! /bin/sh\n" );
	fprintf( fPtr,
"# NOTE: THIS IS *NOT* A \"shar\" FILE!!\n" );
	fprintf( fPtr,
"#       ALL INFORMATION BETWEEN \"cut here\" PAIRS MAY BE EXTRACTED BY ANY\n" );
	if ( noSplit OR noZero )
	    fprintf( fPtr,
"#       MEANS YOU DESIRE, INCLUDING BY EXECUTING THIS SCRIPT.\n" );
	else
	{
	    fprintf( fPtr,
"#       MEANS YOU DESIRE, INCLUDING BY EXECUTING THIS SCRIPT (see part 0 for\n" );
	    fprintf( fPtr,
"#       instructions).\n" );
	}
	fprintf( fPtr,
"# %s, part %d/%d\n",
		 fileName, partNum, topDECnt );
	fprintf( fPtr,
"# Concatenate %s*.xb files, pipe to uudecode to create '%s'.\n",
		 partRoot, fileName );
	fprintf( fPtr,
"echo \"Extracting %s%s.xb\"\n",
		 partRoot, partStr );
	/* Use "\?\?" below to avoid trigraph problems... */
	fprintf( fPtr,
"if [ `echo $0 | sed -e 's?.*/\?\?'` = \"sh\" ]\n" );
	fprintf( fPtr,
"then\n" );
	fprintf( fPtr,
"  echo \"Using this script as shell standard input disables automatic\"\n" );
	fprintf( fPtr,
"  echo \"  truncation detection.  Truncation is likely if the next message\"\n" );
	fprintf( fPtr,
"  echo \"  isn't '%s%s.xb extracted successfully!'...\"\n",
		 partRoot, partStr );
	fprintf( fPtr,
"else\n" );
	fprintf( fPtr,
"  fend=`grep \"End of\" $0 | sed -e '/^\\ \\ fend/d'`\n" );
	fprintf( fPtr,
"  if [ \"$fend\" = \"\" ]\n" );
	fprintf( fPtr,
"  then\n" );
	fprintf( fPtr,
"    echo \"ERROR:  %s part %d is truncated!\"\n",
		 fileName, partNum );
	fprintf( fPtr,
"    exit 1\n" );
	fprintf( fPtr,
"  fi\n" );
	fprintf( fPtr,
"fi\n" );
	fprintf( fPtr,
"sed -e '/^BEGIN/d' -e '/^END/d' << \\EndOfXBSection > %s%s.xb\n",
		 partRoot, partStr );
	fprintf( fPtr,
"BEGIN --- CUT HERE --- Cut Here --- cut here ---\n" );
}

static VOIDPARM generateUUScriptTrailer( fPtr, partNum, partFname )
FILE *fPtr;
int partNum;
char *partFname;
{
    char partStr[ 3 ], tempStr[ 256 ];
    char *tempSum;
    int commandResult;

	if ( topDECnt < 10 OR partNum > 9 )
	    sprintf( partStr, "%d", partNum );
	else
	    sprintf( partStr, "0%d", partNum );
	sprintf( tempStr, 
		 "wc -lc %s | awk '{ printf \"%%s %%s\", $1, $2 }'",
	         partFname ); 
    	tempSum = shellResult( tempStr, &commandResult );
	fprintf( fPtr,
"END --- CUT HERE --- Cut Here --- cut here ---\n" );
	fprintf( fPtr,
"EndOfXBSection\n" );
	fprintf( fPtr,
"wcSize=`wc -lc %s%s.xb | awk '{ printf \"%%s %%s\", $1, $2 }'`\n",
		 partRoot, partStr );
	fprintf( fPtr,
"if [ \"$wcSize\" = \"%s\" ]\n",
		 tempSum );
	fprintf( fPtr,
"then\n" );
	fprintf( fPtr,
"  echo \"%s%s.xb extracted successfully!\"\n",
		 partRoot, partStr );
	fprintf( fPtr,
"else\n" );
	fprintf( fPtr,
"  echo \"ERROR IN %s%s.xb EXTRACTION!\"\n",
		 partRoot, partStr );
	fprintf( fPtr,
"  echo \"Expecting sum of '%s', got ${wcSize}...\"\n",
		 tempSum );
	fprintf( fPtr,
"  exit 1\n" );
	fprintf( fPtr,
"fi\n" );
	fprintf( fPtr,
"if [ `echo %s*.xb | wc -w` -eq %d ]\n",
		 partRoot, topDECnt );
	fprintf( fPtr,
"then\n" );
	fprintf( fPtr,
"  echo \"All uuencoded parts of %s extracted, uudecoding...\"\n",
		 fileName );
	fprintf( fPtr,
"  cat %s*.xb > %s.UU\n",
		 partRoot, scriptRoot );
	fprintf( fPtr, 
"  test -f %s.UU\n",
		 scriptRoot );
	fprintf( fPtr, 
"  fileErr=$?\n" );
	fprintf( fPtr, 
"  if [ $fileErr -eq 0 ]\n" );
	fprintf( fPtr, 
"  then\n" );
	fprintf( fPtr, 
"    wcSize=`wc -lc %s.UU | awk '{ printf \"%%s %%s\", $1, $2 }'`\n",
		 scriptRoot );
	fprintf( fPtr, 
"    if [ \"$wcSize\" = \"%s\" ]\n",
		 fullUUSum );
	fprintf( fPtr, 
"    then\n" );
	fprintf( fPtr, 
"      cat %s.UU | uudecode\n",
		 scriptRoot );
	fprintf( fPtr, 
"      extrErr=$?\n" );
	fprintf( fPtr, 
"      if [ $extrErr -eq 0 ]\n" );
	fprintf( fPtr, 
"      then\n" );
	fprintf( fPtr, 
"        test -f %s\n",
		 fileName );
	fprintf( fPtr, 
"        fileErr=$?\n" );
	fprintf( fPtr, 
"        if [ $fileErr -eq 0 ]\n" );
	fprintf( fPtr, 
"        then\n" );
	fprintf( fPtr, 
"          wcSize=`wc -lc %s | awk '{ printf \"%%s %%s\", $1, $2 }'`\n",
		 fileName );
	fprintf( fPtr, 
"          if [ \"$wcSize\" = \"%s\" ]\n",
		 fullSum );
	fprintf( fPtr, 
"          then\n" );
	fprintf( fPtr, 
"            echo \"%s extracted successfully!\"\n",
		 fileName );
	fprintf( fPtr, 
"            rm %s*.xb %s.UU\n",
		 partRoot, scriptRoot );
	fprintf( fPtr, 
"            exit 7\n" );
	fprintf( fPtr, 
"          else\n" );
	fprintf( fPtr, 
"            echo \"ERROR IN %s filesum!\"\n",
		 fileName );
	fprintf( fPtr, 
"            echo \"Expecting sum of '%s', got ${wcSize}...\"\n",
		 fullSum );
	fprintf( fPtr, 
"            exit 1\n" );
	fprintf( fPtr, 
"          fi\n" );
	fprintf( fPtr, 
"        else\n" );
	fprintf( fPtr, 
"          echo \"ERROR: File %s doesn't exist!!\"\n",
		 fileName );
	fprintf( fPtr, 
"          exit 1\n" );
	fprintf( fPtr, 
"        fi\n" );
	fprintf( fPtr, 
"      else\n" );
	fprintf( fPtr, 
"        echo \"ERROR:  In extraction of %s - examine %s.UU...\"\n",
		 fileName, scriptRoot );
	fprintf( fPtr, 
"        exit 1\n" );
	fprintf( fPtr, 
"      fi\n" );
	fprintf( fPtr, 
"    else\n" );
	fprintf( fPtr, 
"      echo \"ERROR IN %s.UU filesum!\"\n",
		 scriptRoot );
	fprintf( fPtr, 
"      echo \"Expecting sum of '%s', got ${wcSize}...\"\n",
		 fullUUSum );
	fprintf( fPtr, 
"      exit 1\n" );
	fprintf( fPtr, 
"    fi\n" );
	fprintf( fPtr, 
"  else\n" );
	fprintf( fPtr, 
"    echo \"ERROR: File %s.UU doesn't exist!!\"\n",
		 scriptRoot );
	fprintf( fPtr, 
"    exit 1\n" );
	fprintf( fPtr, 
"  fi\n" );
	fprintf( fPtr, 
"fi\n" );
	fprintf( fPtr, 
"exit 0\n" );
	fprintf( fPtr,
"#\n" );
	fprintf( fPtr,
"# End of '%s%s.xb'\n",
		 partRoot, partStr );
	fprintf( fPtr,
"#\n" );
	if ( noSplit OR noZero OR topDECnt IS 1 )
	    fprintf( fPtr,
"#--------shell end here-------\n" );
	else
	    fprintf( fPtr,
"#--------shell end here------- save as %s%s\n",
		     scriptRoot, partStr );
	fprintf( fPtr,
"('wc -lc %s%s' should be '%s' -\n",
		     scriptRoot, partStr, tempSum );
	fprintf( fPtr,
"  between/not including \"BEGIN\"/\"END\" pairs...)\n" );
	fprintf( fPtr,
"('wc -lc %s' should be '%s'...)\n",
		 fileName, fullSum );
}

static VOIDPARM generateScriptHeader( fPtr, partNum )
FILE *fPtr;
int partNum;
{
    char partStr[ 3 ], tempStr[ 256 ];

	if ( topDECnt < 10 OR partNum > 9 )
	    sprintf( partStr, "%d", partNum );
	else
	    sprintf( partStr, "0%d", partNum );
	if ( noSplit OR noZero OR topDECnt IS 1 )
	    fprintf( fPtr,
"#--------shell begin here-------\n" );
	else
	    fprintf( fPtr,
"#--------shell begin here------- save as %s%s\n",
		     scriptRoot, partStr );
	fprintf( fPtr,
"#! /bin/sh\n" );
	fprintf( fPtr,
"# NOTE: THIS IS *NOT* A \"shar\" FILE!!\n" );
	fprintf( fPtr,
"#       ALL INFORMATION BETWEEN \"cut here\" PAIRS MAY BE EXTRACTED BY ANY\n" );
	if ( noSplit OR noZero )
	    fprintf( fPtr,
"#       MEANS YOU DESIRE, INCLUDING BY EXECUTING THIS SCRIPT.\n" );
	else
	{
	    fprintf( fPtr,
"#       MEANS YOU DESIRE, INCLUDING BY EXECUTING THIS SCRIPT (see part 0 for\n" );
	    fprintf( fPtr,
"#       instructions).\n" );
	}
	fprintf( fPtr,
"# %s, part %d/%d\n",
		 fileName, partNum, topDECnt );
	fprintf( fPtr,
"# Concatenate %s*.xb files to create '%s'.\n",
		 partRoot, fileName );
	fprintf( fPtr,
"echo \"Extracting %s%s.xb\"\n",
		 partRoot, partStr );
	/* Use "\?\?" below to avoid trigraph problems... */
	fprintf( fPtr,
"if [ `echo $0 | sed -e 's?.*/\?\?'` = \"sh\" ]\n" );
	fprintf( fPtr,
"then\n" );
	fprintf( fPtr,
"  echo \"Using this script as shell standard input disables automatic\"\n" );
	fprintf( fPtr,
"  echo \"  truncation detection.  Truncation is likely if the next message\"\n" );
	fprintf( fPtr,
"  echo \"  isn't '%s%s.xb extracted successfully!'...\"\n",
		 partRoot, partStr );
	fprintf( fPtr,
"else\n" );
	fprintf( fPtr,
"  fend=`grep \"End of\" $0 | sed -e '/^\\ \\ fend/d'`\n" );
	fprintf( fPtr,
"  if [ \"$fend\" = \"\" ]\n" );
	fprintf( fPtr,
"  then\n" );
	fprintf( fPtr,
"    echo \"ERROR:  %s part %d is truncated!\"\n",
		 fileName, partNum );
	fprintf( fPtr,
"    exit 1\n" );
	fprintf( fPtr,
"  fi\n" );
	fprintf( fPtr,
"fi\n" );
	fprintf( fPtr,
"sed -e '/^BEGIN/d' -e '/^END/d' << \\EndOfXBSection > %s%s.xb\n",
		 partRoot, partStr );
	fprintf( fPtr,
"BEGIN --- CUT HERE --- Cut Here --- cut here ---\n" );
}

static VOIDPARM generateScriptTrailer( fPtr, partNum, partFname )
FILE *fPtr;
int partNum;
char *partFname;
{
    char partStr[ 3 ], tempStr[ 256 ];
    char *tempSum;
    int commandResult;

	if ( topDECnt < 10 OR partNum > 9 )
	    sprintf( partStr, "%d", partNum );
	else
	    sprintf( partStr, "0%d", partNum );
	sprintf( tempStr, 
		 "wc -lc %s | awk '{ printf \"%%s %%s\", $1, $2 }'",
	         partFname ); 
    	tempSum = shellResult( tempStr, &commandResult );
	fprintf( fPtr,
"END --- CUT HERE --- Cut Here --- cut here ---\n" );
	fprintf( fPtr,
"EndOfXBSection\n" );
	fprintf( fPtr,
"wcSize=`wc -lc %s%s.xb | awk '{ printf \"%%s %%s\", $1, $2 }'`\n",
		 partRoot, partStr );
	fprintf( fPtr,
"if [ \"$wcSize\" = \"%s\" ]\n",
		 tempSum );
	fprintf( fPtr,
"then\n" );
	fprintf( fPtr,
"  echo \"%s%s.xb extracted successfully!\"\n",
		 partRoot, partStr );
	fprintf( fPtr,
"else\n" );
	fprintf( fPtr,
"  echo \"ERROR IN %s%s.xb EXTRACTION!\"\n",
		 partRoot, partStr );
	fprintf( fPtr,
"  echo \"Expecting sum of '%s', got ${wcSize}...\"\n",
		 tempSum );
	fprintf( fPtr,
"  exit 1\n" );
	fprintf( fPtr,
"fi\n" );
	fprintf( fPtr,
"if [ `echo %s*.xb | wc -w` -eq %d ]\n",
		 partRoot, topDECnt );
	fprintf( fPtr,
"then\n" );
	fprintf( fPtr,
"  echo \"All parts of %s extracted, concatenating...\"\n",
		 fileName );
	fprintf( fPtr,
"  cat %s*.xb > %s\n",
		 partRoot, fileName );
	fprintf( fPtr, 
"  test -f %s\n",
		 fileName );
	fprintf( fPtr, 
"  fileErr=$?\n" );
	fprintf( fPtr, 
"  if [ $fileErr -eq 0 ]\n" );
	fprintf( fPtr, 
"  then\n" );
	fprintf( fPtr, 
"    wcSize=`wc -lc %s | awk '{ printf \"%%s %%s\", $1, $2 }'`\n",
		 fileName );
	fprintf( fPtr, 
"    if [ \"$wcSize\" = \"%s\" ]\n",
		 fullSum );
	fprintf( fPtr, 
"    then\n" );
	fprintf( fPtr, 
"      echo \"%s processed successfully!\"\n",
		 fileName );
	fprintf( fPtr, 
"      rm %s*.xb\n",
		 partRoot );
	fprintf( fPtr, 
"      exit 7\n" );
	fprintf( fPtr, 
"    else\n" );
	fprintf( fPtr, 
"      echo \"ERROR IN %s filesum!\"\n",
		 fileName );
	fprintf( fPtr, 
"      echo \"Expecting sum of '%s', got ${wcSize}...\"\n",
		 fullSum );
	fprintf( fPtr, 
"      exit 1\n" );
	fprintf( fPtr, 
"    fi\n" );
	fprintf( fPtr, 
"  else\n" );
	fprintf( fPtr, 
"    echo \"ERROR: File %s doesn't exist!!\"\n",
		 fileName );
	fprintf( fPtr, 
"    exit 1\n" );
	fprintf( fPtr, 
"  fi\n" );
	fprintf( fPtr, 
"fi\n" );
	fprintf( fPtr, 
"exit 0\n" );
	fprintf( fPtr,
"#\n" );
	fprintf( fPtr,
"# End of '%s%s.xb'\n",
		 partRoot, partStr );
	fprintf( fPtr,
"#\n" );
	if ( noSplit OR noZero OR topDECnt IS 1 )
	    fprintf( fPtr,
"#--------shell end here-------\n" );
	else
	    fprintf( fPtr,
"#--------shell end here------- save as %s%s\n",
		     scriptRoot, partStr );
	fprintf( fPtr,
"('wc -lc %s%s' should be '%s'...)\n",
		 scriptRoot, partStr, tempSum );
	fprintf( fPtr,
"('wc -lc %s' should be '%s'...)\n",
		 fileName, fullSum );
}

static VOIDPARM createFileParts( VOIDPARM )
{
    FILE *tmpFile, *sigFile;
    char tempStr[ 256 ];
    char *homePath, *tempFname, *tempSubj, *replyto;
    int commandResult, partNum;
    DirEntry *tmpDE;
    boolean partCreated;
  
	if ( verboseOutput AND ( noSplit OR noZero OR
		( patchPart[ 0 ] AND NOT validPatchPart( 0 ) ) ) )
	    printf( "...creating part " );
	partCreated = FALSE;
	tmpDE = topDE;
	partNum = 1;
	while ( tmpDE ISNT NULL )
	{
	    tempFname = gDEName( tmpDE );
	    if ( ( NOT patchPart[ 0 ] ) OR validPatchPart( partNum ) )
	    {
	        if ( verboseOutput )
		{
	            printf( "%d", partNum );
	    	    fflush( stdout );
		}
	        tempSubj = formatSubj( partNum );
	    	sprintf( tempStr, "%s/%s.p%dh", tmpDir, fileRoot, partNum );
	    	tmpFile = fopen( tempStr, "w" );
	    	if ( postIt )
	    	{
	    	    if ( anonPost )
			addAnonHeader( tmpFile, partNum );
	            fprintf( tmpFile, "Subject: %s\n", tempSubj );
	            fprintf( tmpFile, "Newsgroups: %s\n", theDest );
	            if ( extraDest ISNT NULL )
	        	fprintf( tmpFile, "Followup-to: %s\n", extraDest );
            	    replyto = (char *)getenv( "REPLYTO" );
            	    if ( replyto ISNT NULL )
               		fprintf( tmpFile, "Reply-To: %s\n", replyto );
	    	    fprintf( tmpFile, "Distribution: world\n" );
	    	    fprintf( tmpFile, "X-Posting-Software: " );
		}
		else
		{
#ifdef SysVMail
	    	    fprintf( tmpFile, "To: %s\n", theDest );
	    	    fprintf( tmpFile, "Subject: %s\n", tempSubj );
#else
	    	    fprintf( tmpFile, "~s %s\n", tempSubj );
#endif
	    	    if ( extraDest ISNT NULL )
#ifdef SysVMail
	        	fprintf( tmpFile, "Cc: %s\n", extraDest );
#else
	        	fprintf( tmpFile, "~c %s\n", extraDest );
#endif
	    	    fprintf( tmpFile, "X-Mailing-Software: " );
		}
		fprintf( tmpFile, 
			 "xmitBin v%s by D. Jim Howard (deej@cadence.com)\n",
		 	 xmitBinRev );
		if ( headFile ISNT NULL )
		    includeHeaderInfo( tmpFile );

		fprintf( tmpFile, "\n" );
		if ( ( partNum IS 1 ) AND ( noSplit OR noZero ) )
		{
		    sprintf( tempStr, "%s.dsc", descPath() );
		    if ( fileExists( tempStr ) )
		    {
		    	fclose( tmpFile );
		    	sprintf( tempStr, "cat %s/%s.p%dh %s.dsc > %s/%s.p%dp", 
		 	         tmpDir, fileRoot, partNum, descPath(), 
				 tmpDir, fileRoot, partNum );
		    	system( tempStr );
		    	sprintf( tempStr, "mv %s/%s.p%dp %s/%s.p%dh", 
		 	         tmpDir, fileRoot, partNum, 
				 tmpDir, fileRoot, partNum );
		    	system( tempStr );
	    	    	sprintf( tempStr, "%s/%s.p%dh", tmpDir, fileRoot, 
				 partNum );
	    	    	tmpFile = fopen( tempStr, "a" );
			/* Write known statistics to file */
			fprintf( tmpFile, 
				 "\n\tThis description and the associated " );
			if ( topDECnt > 1 )
			{
	    		    fprintf( tmpFile, "%d parts contain the ", 
				     topDECnt );
			    if ( UUencode )
				fprintf( tmpFile, "uuencoded\n    form " );
			    else
				fprintf( tmpFile, "transmitted\n    form " );
			}
			else
			{
	    		    fprintf( tmpFile, "part contains the " );
			    if ( UUencode )
				fprintf( tmpFile, "uuencoded form\n    " );
			    else
				fprintf( tmpFile, "transmitted form\n    " );
			}
			fprintf( tmpFile, "of %s", fileName );
			if ( fileType IS UNKNOWN )
	    		    fprintf( tmpFile, ".\n" );
			else
	    		    fprintf( tmpFile, ", which is a %s %s picture.\n", 
		     		     fileStats, picRes );
		    	fprintf( tmpFile, "\n" );
		    }
		}
		else
		{
		    sprintf( tempStr, "%s.pat", descPath() );
		    if ( patchPart[ 0 ] AND fileExists( tempStr ) )
		    {
		    	fclose( tmpFile );
		    	sprintf( tempStr, "cat %s/%s.p%dh %s.pat > %s/%s.p%dp", 
		 	         tmpDir, fileRoot, partNum, descPath(), 
				 tmpDir, fileRoot, partNum );
		    	system( tempStr );
		    	sprintf( tempStr, "mv %s/%s.p%dp %s/%s.p%dh", 
		 	         tmpDir, fileRoot, partNum, 
				 tmpDir, fileRoot, partNum );
		    	system( tempStr );
	    	    	sprintf( tempStr, "%s/%s.p%dh", tmpDir, fileRoot, 
				 partNum );
	    	    	tmpFile = fopen( tempStr, "a" );
		    	fprintf( tmpFile, "\n" );
		    }
		}
		if ( scriptOut )
		    if ( UUencode )
		        generateUUScriptHeader( tmpFile, partNum );
		    else
		        generateScriptHeader( tmpFile, partNum );
		else
		    fprintf( tmpFile, 
		    "BEGIN --- CUT HERE --- Cut Here --- cut here --- %s %d/%d\n",
			     fileName, partNum, topDECnt );
		fclose( tmpFile );
		sprintf( tempStr, 
			 "cat %s/%s.p%dh %s > %s/%s.p%d;rm %s/%s.p%dh", 
		 	 tmpDir, fileRoot, partNum, tempFname, 
			 tmpDir, fileRoot, partNum, tmpDir, fileRoot, partNum );
		system( tempStr );
		sprintf( tempStr, "%s/%s.p%d", tmpDir, fileRoot, partNum );
		tmpFile = fopen( tempStr, "a" );
		if ( scriptOut )
		{
		    if ( UUencode )
		        generateUUScriptTrailer( tmpFile, partNum, tempFname );
		    else
		        generateScriptTrailer( tmpFile, partNum, tempFname );
		}
		else
		    fprintf( tmpFile, 
		    "END --- CUT HERE --- Cut Here --- cut here --- %s %d/%d\n",
			     fileName, partNum, topDECnt );
		fprintf( tmpFile, "\n" );
		tempStr[ 0 ] = NULLTERM;
		homePath = (char *)getenv( "HOME" );
		if ( ( homePath ISNT NULL ) AND ( strlen ( homePath ) ISNT 0 ) )
	    	    sprintf( tempStr, "%s/.signature", homePath );
		if ( anonPost AND ( anonSig ISNT NULL ) )
	    	    sprintf( tempStr, "%s", anonSig );
		if ( ( tempStr[ 0 ] ISNT NULLTERM ) AND fileExists( tempStr ) )
		{
		    /* Read in/write out the .signature file - news */
		    /* posters often munge > 4 line .sigs... */
		    fprintf( tmpFile, "-- \n" );
		    sigFile = fopen( tempStr, "r" );
		    while ( lineRead( sigFile, tempStr ) ISNT EOF )
		        fprintf( tmpFile, "%s\n", tempStr );
		    fclose( sigFile );
		}
		fclose( tmpFile );
		if ( verboseOutput AND ( NOT lastPart( partNum ) ) )
		{
	    	    printf( "," );
	    	    fflush( stdout );
		}
		partCreated = TRUE;
	    }
	    tmpDE = nDE( tmpDE );
	    sprintf( tempStr, "rm %s", tempFname );
	    system( tempStr );
	    partNum++;
	}
	if ( verboseOutput AND partCreated )
	    printf( " - done.\n" );
}

static VOIDPARM changeOrAddInfo( VOIDPARM )
{
    char *answer, *filePath, *problem, tempStr[ 256 ];
    boolean doEdits;
    FILE *tmpFile;

	/* Post vs. mail */
	printf( "This article is currently scheduled to be " );
	if ( postIt )
	    printf( "posted - mail instead? (y or [n]) ->" );
	else
	    printf( "mailed - post instead? (y or [n]) ->" );
	answer = getAnswer();
	if ( strlen( answer ) AND
		NOT ( strcmp( answer, "y" ) AND strcmp( answer, "Y" ) ) )
	{
	    if ( postIt )
		postIt = FALSE;
	    else
		postIt = TRUE;
	}

	/* Destination */
	printf( "The destination " );
	if ( postIt )
	    printf( "news group " );
	else
	    printf( "mail address " );
	printf( 
	    "is currently set at '%s'\n   - change it? ([n] or new_value) ->",
		theDest );
	answer = getAnswer();
	if ( strlen( answer ) AND
	    	( strcmp( answer, "n" ) OR strcmp( answer, "N" ) ) )
	    theDest = answer;

	/* Mail CC/post follow-up */
	if ( postIt )
	    printf( "The posting follow-up group is currently " );
	else
	    printf( "The mailing CC list is currently " );
	if ( extraDest IS NULL )
	    printf( "not set" );
	else
	    printf( "set as '%s'", extraDest );
	printf( "\n    - change it? ([n] or new_value" );
	if ( extraDest IS NULL )
	    printf( ") ->" );
	else
	    printf( " {'.' to set to NULL}) ->" );
	answer = getAnswer();
	if ( strlen( answer ) AND
	    	( strcmp( answer, "n" ) OR strcmp( answer, "N" ) ) )
	    if ( NOT strcmp( answer, "." ) )
		extraDest = NULL;
	    else
	    	extraDest = answer;

	if ( postIt )
	{
	    /* Anonymous posting stuff... */
	    if ( anonPost )
	    {
	        printf( "Posting anonymously as '%s' - change?\n", anonFile );
		printf( "    ([n], anonymous_user, or '.' for no anonymity) ->" );
	    }
	    else
		printf( "Post anonymously? ([n] or anonymous_user) ->" );
	    answer = getAnswer();
    	    if ( strlen( answer ) AND
    		    ( strcmp( answer, "n" ) OR strcmp( answer, "N" ) ) )
	    	if ( NOT strcmp( answer, "." ) )
		{
		    anonFile = NULL;
		    anonPost = FALSE;
		}
	    	else
		{
	    	    anonFile = answer;
		    anonPost = TRUE;
		}
	    if ( anonPost )
	    {
	    	/* Anonymous data description file */
		filePath = anonDataFilePath();
	    	if ( fileExists( filePath ) )
	    	{
	            printf( "The anonymous data is currently specified as:\n" );
	            sprintf( tempStr, "cat %s", filePath );
	            system( tempStr );
	            printf( "...change this data? (y or [n]) ->" );
	            answer = getAnswer();
	            if ( strlen( answer ) AND NOT 
			    ( strcmp( answer, "y" ) AND strcmp( answer, "Y" ) ) )
		        doEdits = TRUE;
	            else
		        doEdits = FALSE;
	        }
	        else
	        {
	            printf( 
	        "Anonymous data does not exist - create/edit it? ([y] or n) ->" );
	            answer = getAnswer();
	            if ( strlen( answer ) AND NOT 
		    	    ( strcmp( answer, "n" ) AND strcmp( answer, "N" ) ) )
		    {
		        doEdits = FALSE;
			printf( 
		"This data is required!  Anonymous posting disabled...\n" );
			anonPost = FALSE;
		    }
	            else
		        doEdits = TRUE;
	        }
	        if ( doEdits )
	        {
		    if ( verifyEnvPath( "EDITOR" ) )
		    {
	                sprintf( tempStr, "${EDITOR} %s", filePath );
	                system( tempStr );
		    }
		    else
		    {
		        printf( 
	"WARNING:  env var 'EDITOR' not set - data cannot be editted\n" );
		        suggest( "vi", NULL );
			if ( NOT fileExists( filePath ) )
			{
			    printf( 
		"This data is required!  Anonymous posting disabled...\n" );
			    anonPost = FALSE;
			}
		    }
	        }
		if ( anonPost AND ( problem = anonFileParse() ) )
		{
		    printf( "ERROR:  In parsing anonymous file '%s'\n    %s\n",
			    anonFile, problem );
		    printf( "  Anonymous posting disabled...\n" );
		    anonPost = FALSE;
		}
	    }
	}

	/* Label info */
	printf( "The label is currently " );
	if ( labelInfo IS NULL )
	    printf( "not set" );
	else
	    printf( "set as '{%s}'", labelInfo );
	printf( "\n    - change it? ([n] or new_value" );
	if ( labelInfo IS NULL )
	    printf( ") ->" );
	else
	    printf( " {'.' to set to NULL}) ->" );
	answer = getAnswer();
	if ( strlen( answer ) AND
	    	( strcmp( answer, "n" ) OR strcmp( answer, "N" ) ) )
	    if ( NOT strcmp( answer, "." ) )
		labelInfo = NULL;
	    else
	    	labelInfo = answer;

	/* Additional title info */
	printf( "The extra title info is currently " );
	if ( extraTitle IS NULL )
	    printf( "not set" );
	else
	    printf( "set as '%s'", extraTitle );
	printf( "\n    - change it? ([n] or new_value" );
	if ( extraTitle IS NULL )
	    printf( ") ->" );
	else
	    printf( " {'.' to set to NULL}) ->" );
	answer = getAnswer();
	if ( strlen( answer ) AND
	    	( strcmp( answer, "n" ) OR strcmp( answer, "N" ) ) )
	    if ( NOT strcmp( answer, "." ) )
		extraTitle = NULL;
	    else
	    	extraTitle = answer;

	/* Use description? */
	printf( "Currently, the description information (if any) will " );
	if ( noDescribe )
	    printf( "NOT " );
	printf( "be included\n    - change this? (y or [n]) ->" );
	answer = getAnswer();
	if ( strlen( answer ) AND
		NOT ( strcmp( answer, "y" ) AND strcmp( answer, "Y" ) ) )
	{
	    if ( noDescribe )
		noDescribe = FALSE;
	    else
		noDescribe = TRUE;
	}

	if ( NOT noDescribe )
	{
	    /* Description */
	    sprintf( tempStr, "%s.dsc", descPath() );
	    if ( fileExists( tempStr ) )
	    {
	        printf( "The description currently reads:\n" );
	        sprintf( tempStr, "cat %s.dsc", descPath() );
	        system( tempStr );
	        printf( "...change this description? (y or [n]) ->" );
	        answer = getAnswer();
	        if ( strlen( answer ) AND NOT 
			( strcmp( answer, "y" ) AND strcmp( answer, "Y" ) ) )
		    doEdits = TRUE;
	        else
		    doEdits = FALSE;
	    }
	    else
	    {
	        printf( 
	        "Description does not exist - create/edit it? ([y] or n) ->" );
	        answer = getAnswer();
	        if ( strlen( answer ) AND NOT 
			( strcmp( answer, "n" ) AND strcmp( answer, "N" ) ) )
		    doEdits = FALSE;
	        else
	        {
		    doEdits = TRUE;
	            tmpFile = fopen( tempStr, "w" );
	    	    fprintf( tmpFile, "\t%s is a ", fileName );
		    if ( UUencode )
	    	        fprintf( tmpFile, "uuencoded " );
	    	    if ( fileType ISNT UNKNOWN )
	    	    {
	                fprintf( tmpFile, "picture of " );
		        /* Look at picture first to better */
		        /* write a description... */
			if ( verifyEnvPath( "VIEWER" ) )
			{
	                    sprintf( tempStr, "${VIEWER} %s", theFile );
	                    system( tempStr );
			}
			else
			{
			    printf( 
	"WARNING:  env var 'VIEWER' not set - picture cannot be viewed\n" );
			    suggest( "xv", "-perfect" );
			}
	    	    }
	    	    fprintf( tmpFile, "\n" );
	    	    fclose( tmpFile );
	        }
	    }
	    if ( doEdits )
	    {
		if ( verifyEnvPath( "EDITOR" ) )
		{
	            sprintf( tempStr, "${EDITOR} %s.dsc", descPath() );
	            system( tempStr );
		}
		else
		{
		    printf( 
	"WARNING:  env var 'EDITOR' not set - description cannot be editted\n" );
		    suggest( "vi", NULL );
		}
	    }
	}

	/* Use extra header file? */
	printf( "Currently, extra header information (if any) will " );
	if ( headFile IS NULL )
	    printf( "NOT " );
	printf( "be used\n    - change this? (y or [n]) ->" );
	answer = getAnswer();
	if ( strlen( answer ) AND
		NOT ( strcmp( answer, "y" ) AND strcmp( answer, "Y" ) ) )
	{
	    if ( headFile IS NULL )
	    {
		printf( "Enter name of header information file ->" );
		headFile = getAnswer();
	    }
	    else
		headFile = NULL;
	}
	if ( headFile ISNT NULL )
	{
	    if ( fileExists( headFile ) )
	    {
	        printf( "The header information currently reads:\n" );
	        sprintf( tempStr, "cat %s", headFile );
	        system( tempStr );
	        printf( "...change this information? (y or [n]) ->" );
	        answer = getAnswer();
	        if ( strlen( answer ) AND NOT 
		  	( strcmp( answer, "y" ) AND strcmp( answer, "Y" ) ) )
		    doEdits = TRUE;
	        else
		    doEdits = FALSE;
	    }
	    else
	    {
	        printf( 
		"Header info does not exist - create/edit it? ([y] or n) ->" );
	        answer = getAnswer();
	        if ( strlen( answer ) AND NOT 
		    	( strcmp( answer, "n" ) AND strcmp( answer, "N" ) ) )
		    doEdits = FALSE;
	        else
		    doEdits = TRUE;
	    }
	    if ( doEdits )
	    {
	    	if ( verifyEnvPath( "EDITOR" ) )
	    	{
	            sprintf( tempStr, "${EDITOR} %s", headFile );
	            system( tempStr );
		}
		else
		{
		    printf( 
	"WARNING:  env var 'EDITOR' not set - header info cannot be editted\n" );
		    suggest( "vi", NULL );
		}
	    }
	}

	/* Post/mail patch part? */
	printf( "Currently, " );
	if ( patchPart[ 0 ] )
	    printf( "only selected parts will " );
	else
	    printf( "the whole file is to " );
	printf( "be sent - change this? (y or [n]) ->" );
	answer = getAnswer();
	if ( strlen( answer ) AND
		NOT ( strcmp( answer, "y" ) AND strcmp( answer, "Y" ) ) )
	{
	    if ( patchPart[ 0 ] )
		patchPart[ 0 ] = 0;
	    else
	    {
		patchPart[ 0 ] = 1;
		patchPart[ 1 ] = 0;
		patchPart[ 2 ] = -1;
		if ( noSplit )
		{
		    printf( 
"(The specification of a patch part implies that the file must be split.\n" );
		    printf( 
" Automatically enabling file splitting...)\n" );
		    noSplit = FALSE;
		}
	    }
	}

	/* Patch part */
	if ( patchPart[ 0 ] )
	{
	    printf( 
"The part(s) to send is currently set at %s - change it? ([n] or new_value) ->",
		    allPatchParts() );
	    answer = getAnswer();
	    if ( strlen( answer ) AND
	    	    ( strcmp( answer, "n" ) OR strcmp( answer, "N" ) ) )
	        readPatchParts( answer );
	    if ( noZero AND validPatchPart( 0 ) )
	    {
		printf( 
"(The specification of part 0 as a patch part implies that part 0\n" );
		printf( 
" should be created.  Automatically enabling part 0 creation...)\n" );
		noZero = FALSE;
	    }

	    if ( NOT noDescribe )
	    {
	        /* Patch note */
	        sprintf( tempStr, "%s.pat", descPath() );
	        if ( fileExists( tempStr ) )
	        {
	            printf( "The patch note currently reads:\n" );
	            sprintf( tempStr, "cat %s.pat", descPath() );
	            system( tempStr );
	            printf( "...change this patch note? (y or [n]) ->" );
	            answer = getAnswer();
	            if ( strlen( answer ) AND
		            NOT ( strcmp( answer, "y" ) AND 
			          strcmp( answer, "Y" ) ) )
		        doEdits = TRUE;
	            else
		        doEdits = FALSE;
	        }
	        else
	        {
	            printf( 
	        "Patch note does not exist - create/edit it? ([y] or n) ->" );
	            answer = getAnswer();
	            if ( strlen( answer ) AND
		            NOT ( strcmp( answer, "n" ) AND 
			          strcmp( answer, "N" ) ) )
		        doEdits = FALSE;
	            else
		    {
		        doEdits = TRUE;
	    	        tmpFile = fopen( tempStr, "w" );
	    	        fprintf( tmpFile, 
				 "\t(This patch was produced because \n" );
	    	        fclose( tmpFile );
		    }
	        }
	        if ( doEdits )
	        {
		    if ( verifyEnvPath( "EDITOR" ) )
		    {
	                sprintf( tempStr, "${EDITOR} %s.pat", descPath() );
	                system( tempStr );
		    }
		    else
		    {
		
		        printf( 
"WARNING:  env var 'EDITOR' not set - patch description cannot be editted\n" );
			suggest( "vi", NULL );
		    }
	        }
	    }
	}


	/* Script output */
	printf( "Script output is currently " );
	if ( scriptOut )
	    printf( "set - unset it? (y or [n]) ->" );
	else
	    printf( "not set - set it? (y or [n]) ->" );
	answer = getAnswer();
	if ( strlen( answer ) AND
		NOT ( strcmp( answer, "y" ) AND strcmp( answer, "Y" ) ) )
	{
	    if ( scriptOut )
		scriptOut = FALSE;
	    else
		scriptOut = TRUE;
	}

	/* To split, or not to split? */
	printf( "File splitting is currently " );
	if ( noSplit )
	    printf( "disabled - enable it? (y or [n]) ->" );
	else
	    printf( "enabled - disabled it? (y or [n]) ->" );
	answer = getAnswer();
	if ( strlen( answer ) AND
		NOT ( strcmp( answer, "y" ) AND strcmp( answer, "Y" ) ) )
	{
	    if ( noSplit )
		noSplit = FALSE;
	    else
	    {
		noSplit = TRUE;
		if ( patchPart[ 0 ] )
		{
		    printf( 
"(Disabling file splitting implies that no patch parts will be produced.\n" );
		    printf( 
" Automatically disabling patch part creation...)\n" );
		    patchPart[ 0 ] = 0;
		}
	    }
	}
	/* OK - HOW to split? */
	if ( NOT noSplit )
	{
	    /* Split size */
	    printf( 
    "The split size is currently set at %d - change it? ([n] or new_value) ->",
		    splitSize );
	    answer = getAnswer();
	    if ( strlen( answer ) AND
	    	    ( strcmp( answer, "n" ) OR strcmp( answer, "N" ) ) )
	        splitSize = atoi( answer );

	    /* Create a part 0 with instructions and extraction script? */
	    /* (Only makes sense to ask if we're splitting the file!) */
	    printf( "Part 0 creation is currently " );
	    if ( noZero )
	        printf( "disabled - enable it? (y or [n]) ->" );
	    else
	        printf( "enabled - disabled it? (y or [n]) ->" );
	    answer = getAnswer();
	    if ( strlen( answer ) AND
		    NOT ( strcmp( answer, "y" ) AND strcmp( answer, "Y" ) ) )
	    {
	        if ( noZero )
		    noZero = FALSE;
	        else
		{
		    noZero = TRUE;
		    if ( patchPart[ 0 ] AND validPatchPart( 0 ) )
		    {
		        printf( 
"(Disabling part 0 creation implies that part 0 should not be sent as a.\n" );
		        printf( 
" patch part.  Automatically removing part 0 as a patch part...)\n" );
			removePatchPart( 0 );
		    }
		}
	    }

	}

	/* Verbose output */
	printf( "Verbose output is currently " );
	if ( verboseOutput )
	    printf( "set - unset it? (y or [n]) ->" );
	else
	    printf( "not set - set it? (y or [n]) ->" );
	answer = getAnswer();
	if ( strlen( answer ) AND
		NOT ( strcmp( answer, "y" ) AND strcmp( answer, "Y" ) ) )
	{
	    if ( verboseOutput )
		verboseOutput = FALSE;
	    else
		verboseOutput = TRUE;
	}
}

/* (maybe) uuencode and (maybe) split the file, process appropriate file(s) */
/* to be ready to be mailed/posted */
static VOIDPARM prepareOutput( VOIDPARM )
{
    FILE *tmpFile;
    char tempStr[ 1024 ];
    char *answer;
    int commandResult, thisPID;
    boolean notConfirmed;
    boolean needSleep = TRUE;

	getFileStats();
	/* Write the description of the file (if necessary) */
	if ( ( ( NOT patchPart[ 0 ] ) OR validPatchPart( 0 ) ) AND
		( NOT noDescribe ) )
	{
	    sprintf( tempStr, "%s.dsc", descPath() );
	    if ( NOT fileExists( tempStr ) )
	    {
	        if ( noConfirm )
	        {
	    	    printf( 
"ERROR:  File description %s must exist if using -nc option - aborting...\n",
			    tempStr );
		    exit( 1 );
	        }
	        tmpFile = fopen( tempStr, "w" );
	        fprintf( tmpFile, "\t%s is a ", fileName );
		if ( UUencode )
	            fprintf( tmpFile, "uuencoded " );
	        if ( fileType ISNT UNKNOWN )
	        {
	            fprintf( tmpFile, "picture of " );
		    /* Look at picture first to better write a description... */
		    if ( verifyEnvPath( "VIEWER" ) )
		    {
	                sprintf( tempStr, "${VIEWER} %s", theFile );
	                system( tempStr );
		    }
		    else
		    {
			printf( 
	"WARNING:  env var 'VIEWER' not set - picture cannot be viewed\n" );
			suggest( "xv", "-perfect" );
		    }
	        }
	        fprintf( tmpFile, "\n" );
	        fclose( tmpFile );
		if ( verifyEnvPath( "EDITOR" ) )
		{
		    if ( verboseOutput AND needSleep )
		    {
		    	printf( 
"(Sleeping for 15 seconds to allow reading of all previous info)...\n" );
		    	sleep( 15 );
			needSleep = FALSE;
		    }
	            sprintf( tempStr, "${EDITOR} %s.dsc", descPath() );
	            system( tempStr );
		}
		else
		{
		    printf( 
	"WARNING:  env var 'EDITOR' not set - description cannot be editted\n" );
		    suggest( "vi", NULL );
		}
	    }
	}
	sprintf( tempStr, "%s.pat", descPath() );
	if ( patchPart[ 0 ] AND NOT fileExists( tempStr ) )
	{
	    if ( noConfirm )
		printf( "WARNING:  Patch note %s does not exist...\n",
			tempStr );
	    else
	    {
	        /* edit a "patch note" */
	        tmpFile = fopen( tempStr, "w" );
	        fprintf( tmpFile, "\t(This patch was produced because \n" );
	        fclose( tmpFile );
		if ( verifyEnvPath( "EDITOR" ) )
		{
		    if ( verboseOutput AND needSleep )
		    {
			printf( 
"(Sleeping for 15 seconds to allow reading of all previous info)..." );
			sleep( 15 );
			needSleep = FALSE;
		    }
	            sprintf( tempStr, "${EDITOR} %s.pat", descPath() );
	            system( tempStr );
		}
		else
		{
		    printf( 
"WARNING:  env var 'EDITOR' not set - patch description cannot be editted\n" );
		    suggest( "vi", NULL );
		}
	    }
	}
	if ( NOT noConfirm )
	{
	    notConfirmed = TRUE;
	    while ( notConfirmed )
	    {
	        /* Confirm current options */
	        if ( ( NOT patchPart[ 0 ] ) OR validPatchPart( 0 ) )
	        {
		    if ( noDescribe )
		        printf( "\n>>>No file description will be used<<<\n" );
		    else
		    {
		        sprintf( tempStr, "%s.dsc", descPath() );
		        if ( fileExists( tempStr ) )
			{
		            printf( "\n>>>File description:<<<\n" );
	                    sprintf( tempStr, "cat %s.dsc", descPath() );
	                    system( tempStr );
			}
			else
		            printf( "\n>>>NO FILE DESCRIPTION EXISTS!<<<\n" );
		    }
	        }
	        if ( patchPart[ 0 ] )
	        {
		    if ( noDescribe )
		        printf( "\n>>>No patch description will be used<<<\n" );
		    else
		    {
	                sprintf( tempStr, "%s.pat", descPath() );
	                if ( fileExists( tempStr ) )
		        {
		            printf( "\n>>>Patch description:<<<\n" );
	                    sprintf( tempStr, "cat %s.pat", descPath() );
	                    system( tempStr );
		        }
		        else
		            printf( "\n>>>NO PATCH DESCRIPTION EXISTS!<<<\n" );
		    }
	        }
	        if ( postIt )
		{
	            printf( "\nPost " );
		    if ( anonPost )
			printf( "(anonymously as '%s') ", anonFile );
		}
	        else
	            printf( "\nMail " );
	        if ( patchPart[ 0 ] )
	            printf( "'%s' part(s) %s to '%s'", theFile, 
			    allPatchParts(), theDest );
	        else
	            printf( "'%s' to '%s'", theFile, theDest );
		if ( noSplit )
		    printf( " (as a single file)" );
		else if ( noZero )
		    printf( " (without a part 0)" );
	        if ( extraDest ISNT NULL )
	            if ( postIt )
	    	        printf( ",\n - with follow-ups to '%s'", extraDest );
	            else
	    	        printf( ",\n - copying '%s'", extraDest );
	        if ( labelInfo )
		{
	            printf( ",\n - with label '{%s}'", labelInfo );
		    if ( extraTitle )
			printf( ", and additional title '%s'", extraTitle );
		}
	        else if ( extraTitle )
	            printf( ",\n - with additional title '%s'", extraTitle );
	        if ( headFile ISNT NULL )
	            printf( ",\n - using extra header info from '%s'", 
			    headFile );
	        printf( ",\n\t\t\tor change info? ([y], n, or c) ->" );
	        /* continue/change? */
	        answer = getAnswer();
	        if ( strlen( answer ) )
	        {
	            if ( NOT ( strcmp( answer, "n" ) AND strcmp( answer, "N" ) ) )
	            {
	    	        printf( 
	"OK!  Aborting subsequent operation... (description file retained)\n" );
	    	        exit( 1 );
	            }
	            else if ( NOT 
			( strcmp( answer, "c" ) AND strcmp( answer, "C" ) ) )
		        /* Allow the user to change any info except the file */
		        /* name.  In addition, s/he may also add information */
		        changeOrAddInfo();
	            else if ( NOT 
			( strcmp( answer, "y" ) AND strcmp( answer, "Y" ) ) )
		        notConfirmed = FALSE;
	        }
	        else
	            notConfirmed = FALSE;
	    }
	}

	if ( postIt )
	{
	    if ( NOT verifyEnvPath( "POSTER" ) )
	    {
		printf( 
		"ERROR:  env var 'POSTER' not set - file cannot be posted\n" );
		suggest( "inews", "-h" );
		exit( 1 );
	    }
	}
	else
	{
	    if ( NOT verifyEnvPath( "MAILER" ) )
	    {
		printf( 
		"ERROR:  env var 'MAILER' not set - file cannot be mailed\n" );
		if ( headFile IS NULL )
		    suggest( "mail", NULL );
		else
		    suggest( "sendmail", NULL );
		exit( 1 );
	    }
	}

	/* process the file */
	if ( verboseOutput )
	{
	    if ( UUencode )
	    {
	        if ( noSplit )
	    	    printf( "...uuencoding %s...", theFile );
	        else
	    	    printf( "...uuencoding/splitting %s...", theFile );
	    }
	    else if ( NOT noSplit )
	    	printf( "...splitting %s...", theFile );
	    fflush( stdout );
	}
	if ( UUencode )
	{
#ifdef __linux__
	    sprintf( tempStr, "encode %s -f%s > %s/%s.UU", theFile, 
		     fileName, tmpDir, fileRoot );
#else
	    sprintf( tempStr, "uuencode %s %s > %s/%s.UU", theFile, 
		     fileName, tmpDir, fileRoot );
#endif
	    if ( DEBUG_PROC )
	        printf( "About to execute:\n  '%s'\n", tempStr );
	    system( tempStr );
	}
	if ( noSplit )
	{
	    if ( UUencode )
	        sprintf( tempStr, "%s.UU", fileRoot );
	    else
	        sprintf( tempStr, "%s", theFile );
	    dirList( tempStr );
	    if ( verboseOutput )
	        printf( "done.\n" );
	}
	else
	{
	    thisPID = getpid();
	    if ( UUencode )
	        sprintf( tempStr, "split -%d %s/%s.UU %s/%d=", 
			 splitSize, tmpDir, fileRoot, tmpDir, thisPID );
	    else
	        sprintf( tempStr, "split -%d %s %s/%d=", 
			 splitSize, theFile, tmpDir, thisPID );
	    if ( DEBUG_PROC )
	        printf( "About to execute:\n  '%s'\n", tempStr );
	    system( tempStr );
	    sprintf( tempStr, "%d=", thisPID );
	    dirList( tempStr );
	    if ( verboseOutput )
	        printf( "done [%d part(s)].\n", topDECnt );
	}
	/* Get "wc" statistics on the file and the uuencoded version */
	sprintf( tempStr, 
		 "wc -lc %s | awk '{ printf \"%%s %%s\", $1, $2 }'",
		 theFile );
	fullSum = shellResult( tempStr, &commandResult );
	if ( DEBUG_PROC )
	    printf( "fullSum is %s (%d)\n", fullSum, commandResult );
	if ( UUencode )
	{
	    sprintf( tempStr,
		 "wc -lc %s/%s.UU | awk '{ printf \"%%s %%s\", $1, $2 }'",
		     tmpDir, fileRoot ); 
	    fullUUSum = shellResult( tempStr, &commandResult );
	    if ( DEBUG_PROC )
	        printf( "fullUUSum is %s (%d)\n", fullUUSum, commandResult );
	}
	/* Create all necessary parts */
	if ( NOT ( noSplit OR noZero ) AND 
		( ( NOT patchPart[ 0 ] ) OR validPatchPart( 0 ) ) )
	    createPart0();
	createFileParts();
	if ( UUencode )
	{
	    /* Remove the temporary .UU file */
	    sprintf( tempStr, "rm -f %s/%s.UU", tmpDir, fileRoot );
	    system( tempStr );
	}
}


static VOIDPARM executeActions( VOIDPARM )
{
    char tempStr[ 256 ], tmpFileName[ 256 ];
    int partNum, startPart, commandResult;
    boolean sigMoved=FALSE;
    char *homePath, *commandError, *commStr;

	if ( verboseOutput )
	    printf( "...transmitting part " );
	if ( postIt )
	{
	    homePath = (char *)getenv( "HOME" );
	    if ( ( homePath ISNT NULL ) AND ( strlen ( homePath ) ISNT 0 ) )
	    {
   	        sprintf( tempStr, "%s/.signature", homePath );
    	        if ( fileExists( tempStr ) )
    	        {
		    /* Temporarily rename the .sig file so it doesn't get */
		    /* "double included" ! */
		    sigMoved = TRUE;
		    sprintf( tempStr, "mv %s/.signature %s/..signature", 
			     homePath, homePath );
		    system( tempStr ); 
    	        }
	    }
	}
	if ( noSplit OR noZero )
	    startPart = 1;
	else
	    startPart = 0;
	for ( partNum = startPart; partNum <= topDECnt; partNum++ )
	    if ( ( NOT patchPart[ 0 ] ) OR validPatchPart( partNum ) )
	    {
		if ( verboseOutput )
		{
	    	    printf( "%d", partNum );
	    	    fflush( stdout );
		}
		sprintf( tmpFileName, "%s/%s.p%d", tmpDir, fileRoot, partNum );
		/* You got the right one, baby! */
		if ( postIt )
		{
		    commStr = (char *)malloc( strlen( "${POSTER} < " ) +
					      strlen( tmpFileName ) + 1 );
		    sprintf( commStr, "${POSTER} < %s", tmpFileName );
		}
		else
		{
		    commStr = (char *)malloc( strlen( "${MAILER}  < " ) +
					      strlen( theDest ) +
					      strlen( tmpFileName ) + 1 );
		    sprintf( commStr, "${MAILER} %s < %s", theDest, tmpFileName );
		}
		if ( DEBUG_PROC )
		    printf( 
		    "At this point, I WOULD have executed the command:\n%s\n", 
			    commStr );
		else
		    commandError = shellResult( commStr, &commandResult );
		if ( commandResult )
		{
		    printf( "ERROR in transmission of %s - file not removed!\n",
			    tmpFileName );
		    printf( "ERROR was: %s\n", commandError );
		}
		else if ( NOT DEBUG_PROC )
		{
		    sprintf( tempStr, "sleep 7;rm -f %s", tmpFileName );
		    system( tempStr );
		    unlink( tmpFileName );
		}
		if ( verboseOutput AND ( NOT lastPart( partNum ) ) )
		{
	    	    printf( "," );
	    	    fflush( stdout );
		}
	    }
	if ( sigMoved )
        {
	    /* Move the .sig file back... */
	    sprintf( tempStr, "mv %s/..signature %s/.signature", 
		     homePath, homePath );
	    system( tempStr ); 
        }
	if ( verboseOutput )
	    printf( " - done.\n" );
}

static VOIDPARM cleanUp( VOIDPARM )
{
    char tempStr[ MAXPATHLEN ];
    char *envPath, *answer;

	if ( verifyEnvPath( "DSCDIR" ) AND NOT noConfirm )
	{
	    envPath = (char *)getenv( "DSCDIR" );	
	    sprintf( tempStr, "%s/%s.dsc", envPath, fileRoot );
	    if ( NOT fileExists( tempStr ) )
	    {
		sprintf( tempStr, "%s/%s.dsc", tmpDir, fileRoot );
	    	if ( fileExists( tempStr ) )
		{
		    /* Find out if it's OK to move the description file to */
		    /* the description directory... */
		    printf( 
		"\nMove description file for %s to $DSCDIR? ([y] or n) ->", 
			    theFile );
		    answer = getAnswer();
		    if ( NOT ( strlen( answer ) AND
			       strcmp( answer, "y" ) AND 
			       strcmp( answer, "Y" ) ) )
		    {
	    		sprintf( tempStr, "mv %s/%s.dsc %s", tmpDir, fileRoot,
				 envPath );
	    		system( tempStr ); 
		    }
		}
	    }
	    sprintf( tempStr, "%s/%s.pat", envPath, fileRoot );
	    if ( NOT fileExists( tempStr ) )
	    {
		sprintf( tempStr, "%s/%s.pat", tmpDir, fileRoot );
	    	if ( fileExists( tempStr ) )
		{
		    /* Find out if it's OK to move the description file to */
		    /* the description directory... */
		    printf( 
			"\nMove patch note for %s to $DSCDIR? ([y] or n) ->", 
			    theFile );
		    answer = getAnswer();
		    if ( NOT ( strlen( answer ) AND
			       strcmp( answer, "y" ) AND 
			       strcmp( answer, "Y" ) ) )
		    {
	    		sprintf( tempStr, "mv %s/%s.pat %s", tmpDir, fileRoot,
				 envPath );
	    		system( tempStr ); 
		    }
		}
	    }
	}
}

static VOIDPARM stateUsage( VOIDPARM )
{
    fprintf( stderr, "Usage: xmitBin %s\n\t%s\n\t%s\n\t%s\n",
	"-d destination -f fileToXmit [-post [-as user]] [-verbose] [-nc]",
	"[-nd] [-no0] [-nosplit | -patch whichPart [-split splitSize]]",
	"[-a followUps/cclist] [-noscript] [-noencode]",
	"[-l label] [extraTitleInfo]" );
}

static boolean verifyInitialRunConditions( VOIDPARM )
{
    char *problem;
    int ignored;

	/* Verify the presence of: */
	/*	awk */
	/*	cat */
	/*	split */
	/*	uuencode */
	/*	wc */
	/* ...in the current PATH... */
	if ( NOT utilInPath( "awk", TRUE ) )
	    return( FALSE );
	if ( NOT utilInPath( "cat", TRUE ) )
	    return( FALSE );
	if ( NOT utilInPath( "split", TRUE ) )
	    return( FALSE );
#ifdef __linux__
	if ( UUencode AND NOT utilInPath( "encode", TRUE ) )
#else
	if ( UUencode AND NOT utilInPath( "uuencode", TRUE ) )
#endif
	    return( FALSE );
	if ( NOT utilInPath( "wc", TRUE ) )
	    return( FALSE );
	if ( theDest IS NULL )
	{
	    if ( postIt )
	        printf( 
		"ERROR:  Destination newsgroup(s) not provided - aborting\n" ); 
	    else
	        printf( 
		"ERROR:  Destination mail address not provided - aborting\n" ); 
	    stateUsage();
	    return( FALSE );
	}
	if ( anonPost )
	{
	    if ( postIt )
	    {
		if ( problem = anonFileParse() )
		{
		    printf( "ERROR:  In parsing anonymous file '%s'\n    %s\n",
			    anonFile, problem );
		    return( FALSE );
		}
	    }
	    else
	    {
	        printf( 
		"ERROR:  Must use -post with -as option - aborting\n" ); 
	        stateUsage();
	        return( FALSE );
	    }
	}
	if ( theFile IS NULL )
	{
	    printf( "ERROR:  File to transmit not provided - aborting\n" );
	    stateUsage();
	    return( FALSE );
	}
	if ( NOT fileExists( theFile ) )
	{
	    printf( "ERROR:  File %s does not exist - aborting\n", theFile );
	    return( FALSE );
	}
	if ( ( headFile ISNT NULL ) AND NOT fileExists( headFile ) )
	{
	    printf( "ERROR:  Header info file %s does not exist - aborting\n", 
		    headFile );
	    return( FALSE );
	}
	if ( NOT getRootName() )
	    printf( "Errors in breaking up path of %s!!\n", theFile );
	if ( DEBUG_PROC )
	{
	    printf( 
		"File name of %s is '%s' (root '%s', script root '%s',\n", 
		    theFile, fileName, fileRoot, scriptRoot );
	    printf( "  part root '%s')...\n", partRoot );
	}
	return( openTopShell() );
}

static VOIDPARM stateRunConditions( VOIDPARM )
{
    boolean result=TRUE;

	printf( "\nxmitBin run conditions:\n" );
	if ( postIt )
	{
	    printf( "Posting " );
	    if ( anonPost )
		printf( "as '%s' ", anonFile );
	}
	else
	    printf( "Mailing " );
	if ( scriptOut )
	    printf( "[script-type output] " );
	printf( "%s ", theFile );
	if ( patchPart[ 0 ] )
	    printf( "{part(s) %s} ", allPatchParts() );
	printf( "to '%s'\n", theDest );
	if ( extraDest ISNT NULL )
	    if ( postIt )
	        printf( "  (Follow-ups directed to '%s')\n", extraDest );
	    else
	        printf( "  (Including '%s' on the \"cc\" list)\n", extraDest );
	if ( noDescribe )
	    printf( "(No (patch) description will be included)\n" );
	if ( noConfirm )
	    printf( "(No confirmation of options will be required)\n" );
	if ( extraTitle )
	    printf( "Title addition of '%s'\n", extraTitle );
	if ( headFile ISNT NULL )
	    printf( "Adding extra header information from %s\n", headFile );
	printf( "%s will be ", theFile );
	if ( UUencode )
	    printf( "uuencoded and " );
	if ( noSplit )
	    printf( "kept intact in one piece\n" );
	else	
	    printf( "split into files of max length %d\n", splitSize );
	if ( noSplit OR noZero )
	    printf( 
	"No part 0 with instructions and extraction script will be sent.\n" );
	printf( "Using %s as the temporary file directory\n", tmpDir );
	printf( "\n" );
}

int main( count, args )
int count;
char **args;
{
    int argCnt=1;
    char *cptr;
    boolean splitting=FALSE;
    boolean notDone=TRUE;

	/* initialization/defaults */
	DEBUG_PROC = FALSE;
	UUencode = TRUE;
	verboseOutput = FALSE;
	scriptOut = TRUE;
	noSplit = FALSE;
	noZero = FALSE;
	noConfirm = FALSE;
	noDescribe = FALSE;
	anonPost = FALSE;
	postIt = FALSE;
	patchPartUB = 5;
	patchPart = (int *)malloc( sizeof( int ) * patchPartUB );
	patchPart[ 0 ] = 0;
	patchPart[ 1 ] = -1;
	splitSize = 800;
	theDest = NULL;
	extraDest = NULL;
	theFile = NULL;
	extraTitle = NULL;
	labelInfo = NULL;
	anonFile = NULL;
	headFile = NULL;
	tmpDir = copyString( TMPDIR );
	if ( verifyEnvPath( "TMPDIR" ) )
	    tmpDir = (char *)getenv( "TMPDIR" );

	count--;
	if ( count IS 0 )
	{
	    stateUsage();
	    exit( 0 );
	}
	while ( notDone )
	{
	    if ( argCnt > count )
		notDone = FALSE;
	    else
	    {
		cptr = args[ argCnt ];
		if ( NOT strcmp( cptr, "-debug" ) )
		    DEBUG_PROC = TRUE;
		else if ( NOT strcmp( cptr, "-noencode" ) )
		    UUencode = FALSE;
		else if ( NOT strcmp( cptr, "-verbose" ) )
		    verboseOutput = TRUE;
		else if ( NOT strcmp( cptr, "-noscript" ) )
		    scriptOut = FALSE;
		else if ( NOT strcmp( cptr, "-nosplit" ) )
		{
	            if ( splitting )
		    {
			reasonForFail = copyString( 
				"-nosplit conflicts with -split option" );
		        notDone = TRUE;
		    }
		    else if ( patchPart[ 0 ] )
		    {
			reasonForFail = copyString( 
				"-nosplit conflicts with -patch option" );
		        notDone = TRUE;
		    }
		    else
		    {
			if ( noZero )
			{
			    printf( 
			"WARNING: -nosplit implies -no0 (-no0 ignored)\n" );
			    noZero = FALSE;
			}
		        noSplit = TRUE;
		    }
		}
		else if ( NOT strcmp( cptr, "-no0" ) )
		{
		    if ( noSplit )
			printf( 
			"WARNING: -nosplit implies -no0 (-no0 ignored)\n" );
		    else if ( patchPart[ 0 ] AND validPatchPart( 0 ) )
		    {
			reasonForFail = copyString( 
				"-no0 conflicts with -patch 0 option" );
		        notDone = TRUE;
		    }
		    else
		        noZero = TRUE;
		}
		else if ( NOT strcmp( cptr, "-nc" ) )
		    noConfirm = TRUE;
		else if ( NOT strcmp( cptr, "-nd" ) )
		    noDescribe = TRUE;
		else if ( NOT strcmp( cptr, "-post" ) )
		    postIt = TRUE;
		else if ( NOT strcmp( cptr, "-patch" ) )
		{
		    argCnt++;
	            if ( argCnt > count )
		    {
			reasonForFail = copyString( 
				"No patch size specified to -patch option" );
		        notDone = TRUE;
		    }
		    else if ( noSplit )
		    {
			reasonForFail = copyString( 
				"-nosplit conflicts with -patch option" );
		        notDone = TRUE;
		    }
	            else
		    {
			readPatchParts( args[ argCnt ] );
		        if ( noZero AND validPatchPart( 0 ) )
		        {
			    reasonForFail = copyString( 
				    "-no0 conflicts with -patch 0 option" );
		            notDone = TRUE;
		        }
		    }
		}
		else if ( NOT strcmp( cptr, "-split" ) )
		{
		    argCnt++;
	            if ( argCnt > count )
		    {
			reasonForFail = copyString( 
				"No split size specified to -split option" );
		        notDone = TRUE;
		    }
	            else if ( noSplit )
		    {
			reasonForFail = copyString( 
				"-split conflicts with -nosplit option" );
		        notDone = TRUE;
		    }
		    else
		    {
			splitSize = atoi( args[ argCnt ] );
			splitting = TRUE;
		    }
		}
		else if ( NOT strcmp( cptr, "-d" ) )
		{
		    argCnt++;
	            if ( argCnt > count )
		    {
			reasonForFail = copyString( 
				"No destination specified to -d option" );
		        notDone = TRUE;
		    }
		    else
			theDest = copyString( args[ argCnt ] );
		}
		else if ( NOT strcmp( cptr, "-f" ) )
		{
		    argCnt++;
	            if ( argCnt > count )
		    {
			reasonForFail = copyString( 
				"No filename specified to -f option" );
		        notDone = TRUE;
		    }
		    else
			theFile = copyString( args[ argCnt ] );
		}
		else if ( NOT strcmp( cptr, "-l" ) )
		{
		    argCnt++;
	            if ( argCnt > count )
		    {
			reasonForFail = copyString( 
				"No argument specified to -l option" );
		        notDone = TRUE;
		    }
		    else
			labelInfo = copyString( args[ argCnt ] );
		}
		else if ( NOT strcmp( cptr, "-a" ) )
		{
		    argCnt++;
	            if ( argCnt > count )
		    {
			reasonForFail = copyString( 
				"No argument specified to -a option" );
		        notDone = TRUE;
		    }
		    else
			extraDest = copyString( args[ argCnt ] );
		}
		else if ( NOT strcmp( cptr, "-as" ) )
		{
		    argCnt++;
	            if ( argCnt > count )
		    {
			reasonForFail = copyString( 
				"No anon user specified to -as option" );
		        notDone = TRUE;
		    }
		    else
		    {
			anonFile = copyString( args[ argCnt ] );
			anonPost = TRUE;
		    }
		}
		else if ( NOT strcmp( cptr, "-xh" ) )
		{
		    argCnt++;
	            if ( argCnt > count )
		    {
			reasonForFail = copyString( 
				"No file specified to -xh option" );
		        notDone = TRUE;
		    }
		    else
		    {
			headFile = copyString( args[ argCnt ] );
		    }
		}
		else
		{
		    extraTitle = addString( extraTitle, args[ argCnt ], " " );
		}
	    argCnt++;
	    }
	}
    	if ( reasonForFail ISNT NULL )
    	{
	    printf( "ERROR: %s\n", reasonForFail );
	    exit( -1 );
    	}
	if ( NOT verifyInitialRunConditions() )
	    exit( -1 );
	if ( verboseOutput )
	    stateRunConditions();
	prepareOutput();
	executeActions();
	cleanUp();

	exit( 0 );
}


syntax highlighted by Code2HTML, v. 0.9.1