Česky
Kamil Dudka

Tiny programs (C, C++, C#, ...)

File detail

Name:Downloadtail.c [Download]
Location: tiny > IJC > du2
Size:2.8 KB
Last modification:2007-08-29 17:44

Source code

/*
 * Soubor: tail.c - implementace utility tail v ISO C99
 * Kamil Dudka, FIT, DU2, priklad 1a, 17.4.2005
 */
 
 
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <stdarg.h>
 
const unsigned long MaxLineLength = 1024 + 1;	// 1024 znaku + znak zlomeni radku
const unsigned long DefaulLinesCount = 10;
 
/*
 * Vlastni funkce, provadejici filtrovani streamu
 */
void tail (FILE *, unsigned long);
 
/*
 * Funkce Error vytiskne chybove hlaseni na stderr a ukonci
 * program s chybovym kodem 1. Pred chybovym hlasenim tiskne
 * test "tail: ". Ma stejne parametry jako funkce printf.
 */
void Error(const char *fmt, ...);
 
/*
 * Zavre soubor, pokud soubor neni stdin
 */
inline void closeInput (FILE *);
 
/*
 * Funkce main nacte parametry a zavola funkci tail
 */
int main (int argc, char *argv[]) {
	bool minusDetected = false;
	unsigned long linesCount = DefaulLinesCount;
	FILE *input = stdin;
 
	// Cyklus postupne nacita parametry
	for (int i=1; i<argc; i++) {
		if (argv [i][0] == '-') {
			// Pokud je prvni znak '-', pokusi se nacist cislo			
			if (argv [i][1] == '-')
				Error ("Pocet radku musi byt kladny!");
 
			if (minusDetected)
				Error ("Duplicitni parametr!");
			minusDetected = true;
 
			if (1!= sscanf (argv[i]+1, "%lu", &linesCount))
				Error ("Neplatny parametr!");
 
			// Pokud neni prvni znak '-', pokusi se otevrit soubor
		} else if (NULL==(input= fopen (argv[i],"r")))
			Error ("Nelze otevrit vstupni soubor!");
	}
 
	// Zavola vlastni filtr
	tail (input, linesCount);
 
	// Po skonceni zavre vstupni soubor
	closeInput (input);
 
	return 0;
}
 
void Error(const char *fmt, ...) {
	// Inicializace funkce s promennym poctem parametru
	va_list pArgs;
	va_start (pArgs, fmt);
 
	// Vypis chybove hlasky na stderr
	fprintf (stderr, "tail: ");
	vfprintf (stderr, fmt, pArgs);
	fprintf (stderr, "\n");
 
	// Ukoncovaci makro funkce s promennym poctem parametru
	va_end (pArgs);
 
	// Shodi program s chybovym kodem 1
	exit (1);
}
 
inline void closeInput (FILE *input) {
	if (input != stdin)
		fclose (input);
}
 
void tail (FILE *input, unsigned long linesCount) {
 
	// Alokace bufferu potrebne velikosti na zasobniku
	// Pozor - muze dojit preteceni zasobniku !!!
	char fifo [linesCount][MaxLineLength+1];
 
	unsigned long readed = 0;
	unsigned long pos = 0;
 
	// Cyklus nacita radky ze souboru a uklada je do bufferu fifo 
	for (; NULL!=fgets (fifo[pos], MaxLineLength+1, input); readed++, pos= readed%linesCount)
		if (NULL== strstr (fifo [pos], "\n")) {
			closeInput (input);
			Error ("Prekrocena maximalni delka radku!");
		}
 
	if (readed < linesCount)
		// Vypisou se vsechny radky, ketere byly nacteny
		for (pos = 0; pos < readed; pos++)
			fputs (fifo [pos], stdout);
	else
		// Vypise se poslednich linesCount radku
		for (pos = 0; pos < linesCount; pos++)
			fputs (fifo [(readed + pos) % linesCount], stdout);
}