fls.c source

Home
/******************************************************************************
*
*	fls 0.4 (14-Feb-2011) -  Copyright (C) 2011 Dario Niedermann
*
* 	From Line Separator:
*	"Fixes" mbox files by adding a blank line before each "From " line
*	(except the 1st) that is not preceded by a blank line.
*
* 	Compile with: 'cc -O2 -o fls fls.c'
*
* 	Released with NO WARRANTY under the GPLv3 license
*
*******************************************************************************/

#include <stdio.h>
#include <string.h>
#include <sysexits.h>
#include <unistd.h>
#include <assert.h>

// lines longer than LINESIZE are still supported,
// they'll just be read LINESIZE characters at a time
#define LINESIZE 2048

unsigned char	verbose = 0;

void prUsage(char * progName, char * msg)
{
 if (strlen(msg)) fprintf(stderr, "%s: %s\n", progName, msg);
 fprintf(stderr, "Usage: %s [-hv] FILE\n", progName);
}

int parseCmdLine(int argc, char * argv[])
// returns index of 1st non-option argument if all is OK,
// or a negative number that's the opposite of the intended
// exit code for main()
{
 int opt, rc = 0;

 while ((opt = getopt(argc, argv, "vh")) != -1) {
	switch (opt) {
		case 'v': verbose++; break;
		case 'h': prUsage(argv[0], ""); rc = -EX_TEMPFAIL; break;
		/* '?' */
		default: prUsage(argv[0], ""); rc = -EX_USAGE;
	}
 }
 assert(optind > 0);
 return (rc < 0) ? rc : optind;
}

int main (int argc, char * argv[])
{
 char	fName[1024], line[LINESIZE], thisLineEmpty = 0, prevLineEmpty = 0;
 int	i = 0, blankLinesAdded = 0, fileArgIndex;
 FILE *	filePtr;

 if (argc == 1) { prUsage(argv[0], "missing file operand"); return EX_USAGE; }
 
 if ((fileArgIndex = parseCmdLine(argc, argv)) < 0)	// cmdline parsing returned err?
	 return -fileArgIndex;

 // else...
 strcpy(fName, argv[fileArgIndex]);

 if ((filePtr = fopen(fName, "r")) == NULL) {	// can't open file?
	fprintf(stderr, "%s: `%s' not found or unreadable\n", argv[0], fName);
 	return EX_NOINPUT; }			// exit

 // else...
 while (!feof(filePtr)) {
	prevLineEmpty = thisLineEmpty;	// what was 'this line' state in prev.
					// cycle, is 'previous line' now
	thisLineEmpty = 0;		// still don't know if the line we're
					// going to fetch will be empty
 	fgets(line, LINESIZE, filePtr);
 	if (strcmp(line,"\n") == 0)	// found an empty line?
 		thisLineEmpty = 1;	// take note.
 	else {				// Not an empty line?
 		thisLineEmpty = 0;
 		if ((strncmp("From ", line, 5) == 0)	// if it's a 'From ' line
 		&& (!prevLineEmpty)			// & previous line wasn't empty
 		&& (i > 0)) {				// & it's not the 1st line...
 			putchar('\n');			// ...emit an empty line
			blankLinesAdded++; }
 	}
	fputs(line, stdout);	// in any case, emit the line
 	i++;			// inc line counter
 }
 fclose(filePtr);
 if (verbose) fprintf(stderr,"%s: added %d blank lines\n", argv[0], blankLinesAdded);
 return EX_OK;
}
“fls” is Copyright © Dario Niedermann
released with NO WARRANTY under the terms of the GPLv3 license.

Home Valid HTML 4.01 Strict  Valid CSS!