Sophie

Sophie

distrib > Mandriva > 2010.2 > i586 > media > contrib-release-src > by-pkgid > 69dab5bccc449b8d7ef733ec806d568d > files > 9

maildrop-1.7.0-19mdv2010.1.src.rpm

/* subjadd.c     Adds a "label", such as [XYZ] to the subject line of an email
 *               on stdin and sends it to stdout.
 *
 *  Tab = 4
 *  cc subjadd.c -o subjadd
 */

#include	<stdio.h>
#include	<string.h>


/*--------------------------------------------------------------------------------*/

int main(int argc, char *argv[])
{

		    /* Flag to say we must add a Subject: line.
		     * and a temp for when we are looking for the
		     * end of the headers.
		     */

int  addsubjectline = 0;
char temph = 0; 


		    /* For storing the four chars after "Subject: "
		     * which may contain "Re: " and for counting them in case
		     * we reach the end of the file before then.
		     */
char t0 = 0; 
char t1 = 0; 
char t2 = 0; 
char t3 = 0; 
int  recount = 0;


		    /* Temp for the loop which passes the main body of the message.
		     */
char tempo = 0;

    if (argc == 1)
    {
	fprintf(stderr, "  subjadd was called with no arguments.  Usage:                   \n");
	fprintf(stderr, "                                                                  \n");
	fprintf(stderr, "  Adds a label such as [XYZ] to the subject line of an email on   \n");
	fprintf(stderr, "  stdin and sends it to stdout.  The label is the only argument.  \n");
	fprintf(stderr, "                                                                  \n");
	fprintf(stderr, "  subjadd [XYZ]     results in:                                   \n");
	fprintf(stderr, "                                                                  \n");
	fprintf(stderr, "    Subject: Foo                Subject: Re: Bar                  \n");
	fprintf(stderr, "    Subject: [XYZ] Foo          Subject: Re: [XYZ] Bar            \n");
	fprintf(stderr, "                                                                  \n");
	fprintf(stderr, "  Always passes the file, but only writes the label if it is the  \n");
	fprintf(stderr, "  sole argument.  If there was no subject line, then an empty one \n");
	fprintf(stderr, "  is added, preceded by an informative header line:               \n");
	fprintf(stderr, "                                                                  \n");
	fprintf(stderr, "    X-Subjadd: No subject line, so this one was added by subjadd. \n");
	fprintf(stderr, "                                                                  \n");
	fprintf(stderr, "  \"subjadd\" primarily means \"adding to the subject line\"      \n");
	fprintf(stderr, "  but if there was no subject line, then its function is to       \n");
	fprintf(stderr, "  \"add a subject line\" too.                                     \n");
	fprintf(stderr, "                                                                  \n");
	fprintf(stderr, "  Always returns 0.  Intended to be used with the xfilter         \n");
	fprintf(stderr, "  command of Sam Varshavchik's Maildrop mail filtering program.   \n");
	fprintf(stderr, "                                                                  \n");
	fprintf(stderr, "  Public domain.   Robin Whittle  www.firstpr.com.au  8 July 2001 \n");
	fprintf(stderr, "   Control C to exit!                                             \n");
    }


					/* Look for the following sequence:
					 *  "\nSubject: " 
					 * whilst passing all bytes to stdout.
					 *
					 * We can't assume there is a Subject 
					 * line.  Netscape will send an email 
					 * without a Subject: line if you 
					 * really have no characters in your 
					 * subject.
					 *
					 * We want to add a Subject: line if 
					 * we reach the end of the headers 
					 * without finding one.
					 * 
					 * So we want to simultaneously look 
					 * for "Subject: " and pass it, but 
					 * also look for two consecutive 
					 * newlines and instead of passing the
					 * second one, add the X-Subjadd: line 
					 * and then the blank new Subject: 
					 * line.  Then we need to add the
					 * label and remember to add an extra
					 * newlines after that to end that 
					 * line and then to end the headers.
					 *
					 * This approach is a bit gumpy . . . 
					 *
					 * Check we are not at the end of the
					 * file, and then call getchar() to 
					 * read bytes from stdin.  If we 
					 * reach the end of the file without
					 * first finding the two consecutive
					 * newlines, then it wasn't a valid 
					 * RFC822 email anyway.  At end of 
					 * file, getchar() returns an EOF 
					 * character.
					 *
					 * Then keep reading bytes and 
					 * starting the search again if
					 * we don't find a double newline
					 * or "Subject: ".
					 *
					 * But the first test is to break
					 * out of the while statement if
					 * previous iterations have
					 * found a double newline, indicating
					 * end of header, and so setting
					 * addsubjectline to 1.
					 *
					 * So the while statement exits on
					 * an OR of any one of three tests
					 * being false:
					 *
					 * 1 - (addsubjectline == 0) means
					 *     exit when it is = 1.
					 *
					 * 2 - (not end of file) means 
					 *     exit on end of file.
					 *
					 * 3 - (not found "Subject: ") means
					 *     exit on finding "Subject".
					 */   			
					 	    
    while (     (addsubjectline == 0)
            &&  (!feof(stdin)) 
	    && !(    (putchar(getchar()) == '\n')

					/* Arrive here because we found
					 * a newline, and we can assume
					 * that the char before it, if any, 
					 * was not a newline.
					 *
					 * Now, take special action if the
					 * next character is a newline.
					 *
					 * If it was a newline: 
					 *
					 * 1 - Set addsubjectline to 1.
					 *
					 * 2 - Do not pass it to the output.
					 *
					 * 3 - Return untrue.
					 *
					 * Otherwise, pass it and compare
					 * it with "S".
					 */
					 
		 && (  ((temph = getchar()) == '\n')
                     ? (0 * (addsubjectline = 1))
		     : (putchar(temph) == 'S')
    		    )

                 && (putchar(getchar()) == 'u')
                 && (putchar(getchar()) == 'b')
        	 && (putchar(getchar()) == 'j')
        	 && (putchar(getchar()) == 'e')
        	 && (putchar(getchar()) == 'c')
        	 && (putchar(getchar()) == 't')
        	 && (putchar(getchar()) == ':')
        	 && (putchar(getchar()) == ' ')
               )
	  )	            
					/* End of big while statement. 
					 * Do nothing and execute it again
					 * if it is true, which means we
					 * only leave the loop when:
					 * 
					 * 1 - End of file - it was not
					 *     a valid RFC822 email.
					 * 
					 * 2 - We found a double newline.
					 *
					 * 3 - We found "Subject".
					 */
    {  }


					/*---------------------------------*/

					/* Exit if we hit the end of file.
					 * This should not happen with a
					 * proper RFC822 email.
					 */
    if (feof(stdin))
    {
	fprintf(stderr, "subjadd abnormal termination!  No double newline found for end of header.\n");
	exit(0);    
    }


    if (addsubjectline == 1)
    {
					/* Add the subject line, preceded by
					 * an informative X- header.
					 *
					 * puts() always adds a newline.
					 */
					 
	puts("X-Subjadd: No subject line, so this one was added by subjadd.");
        fprintf(stdout, "Subject: ");
    }
    else
    {
					/* Arrive here because we have found
					 * the "Subject: " line in the 
					 * header.
					 *
					 * Look for "Re: " and pass it if it 
					 * is there.
					 *
					 * If not, then don't pass it yet.
					 *
					 * This would be easy if we knew there
					 * were 4 more chars in the email, but
					 * maybe there are not.  Maybe the
					 * "Subject: " line has no text on it
					 * and this is the last line of the 
					 * header, and there is no body - just
					 * the two newlines which terminate 
					 * the header.  We still have to pass 
					 * each character and add the label.
					 *
					 * Proceed one char at a time and
					 * record how many characters we
					 * found before reaching the end
					 * of file.
					 */
        if (!feof(stdin)) 
        {
            t0 = (char)getchar();
		recount = 1;

    	    if (!feof(stdin)) 
            {
		t1 = (char)getchar();
	        recount = 2;
    
		if (!feof(stdin))
		{
	    	    t2 = (char)getchar();
		    recount = 3;
	
	    	    if (!feof(stdin))
		    {
	        	t3 = (char)getchar();
			recount = 4;

		    }
		}
	    }    
	}

					/* We have between 0 and 4 characters 
    				         * stored.  recount tells us how many. 
				         */

        if (    ((t0 == 'R') || (t0 == 'r'))
	     && ((t1 == 'E') || (t1 == 'e'))
             &&  (t2 == ':') 
	     &&  (t3 == ' ') 
    	   )
        {
					/* There was a "Re: ".  So pass it now.
					 *
					 * Set recount to 0 to show we have no
					 * characters stored which we need to
					 * pass after the label.
					 */
	    putchar(t0);
	    putchar(t1);
	    putchar(t2);
	    putchar(t3);
					
	    recount = 0;
	}
    }
					/*---------------------------------*/


					/* Whether we found a Subject line or 
					 * made our own, and if there was a
					 * Subject line, whether we found a 
					 * "Re: " and passed it, or not . . . 
					 *    
					 * Write the label - the first 
					 * argument - with a space after it. 
					 * If there is no first argument, or 
					 * if there is more than one then do 
					 * not write anything.
					 *
					 * puts() would be good to write to 
					 * stdio, except that it always 
					 * writes a \n too.
					 */
    if (argc == 2)
    {
        fprintf(stdout, "%s", argv[1]);
        putchar(' ');
    }

					/* Now, pass as many chars as we have 
					 * stored. These will be 0 to 4 chars 
					 * which were not "Re: ", which followed 
					 * "Subject: " and which now will follow 
					 * the label which we have just written.
					 *
					 * There are only chars stored if there 
					 * was a subject line, not followed by a 
					 * "Re: ".
					 */
    if (recount >= 1) putchar(t0);
    if (recount >= 2) putchar(t1);
    if (recount >= 3) putchar(t2);
    if (recount >= 4) putchar(t3);
    

					/* If we added a Subject line, then 
					 * we are now at the end of the 
					 * headers - so we add a newline
					 * to end the subject line and then
					 * another one to end the headers.
					 *
					 * When searching for the end of the
					 * headers, we found and passed the
					 * newline at the end of the last
					 * header and we found but did not
					 * pass the header-ending newline
					 * which followed.
					 */
    if (addsubjectline == 1)
    {
	putchar('\n');
	putchar('\n');
    }					 

					 
					/* We have done all the searching and
					 * changing  so now simply pass the 
					 * rest of the bytes.
					 *
					 * Copy stdin to stdout and exit when 
					 * there are no more chars to read.
					 *
					 * feof(stdin) is only valid after the
					 * getchar() which reads to the end of
					 * file.  So read, and then test if 
					 * the byte read is valid.
					 */
    while (1)
    {
	tempo = getchar();
    				 
	if (!feof(stdin))
	{
    	    putchar(tempo);
	}
	else
	{
    	    exit(0);
        }	
    }
}