-/** Read an mbox
- */
+/********************************************************************************
+* mbox-helper/mbox-helper.c : read and parse an mbox file
+* ------------------------
+*
+* This file is part of the banana distribution
+* Copyright: See COPYING files that comes with this distribution
+********************************************************************************/
#define _GNU_SOURCE
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <locale.h>
+#include <stdbool.h>
+#include <getopt.h>
/** Macros
*/
-#define LTRIM(pos) while (isspace(*pos)) { pos++; }
-#define STRTOLOWER(str, ptr) for (ptr = str ; *ptr ; ptr++) { *ptr = tolower(*ptr); }
-
-/** Boolean
- */
-typedef char bool;
-#define TRUE ((bool)(-1))
-#define FALSE ((bool)(0))
+#define LTRIM(pos) while (isspace(*pos)) { ++pos; }
+#define STRTOLOWER(str, ptr) for (ptr = str ; *ptr ; ++ptr) { *ptr = tolower(*ptr); }
/** MBox pointer
*/
typedef struct
{
- FILE *fp; // File pointer
+ FILE *fp; // File pointer
long int lastLine; // Offset of the precedent line (-1 if invalid)
long int currentLine; // Offset of the current line
long int messageId; // Current message Id
MBox;
/** Open a mbox
+ * @param filename char* Path to the file to open
+ * @return NULL on error, a well initialized MBox structure pointer on success
*/
-MBox *openMBox(char *filename)
+static MBox *openMBox(char *filename)
{
FILE *fp;
MBox *mbox;
- fp = fopen(filename, "r");
+ fp = fopen(filename, "r");
if (!fp) {
return NULL;
}
mbox->messageId = 0;
mbox->messageBeginning = 0;
mbox->line = NULL;
- mbox->isFrom_ = FALSE;
+ mbox->isFrom_ = false;
return mbox;
}
/** Close a mbox
*/
-void closeMBox(MBox *mbox)
+static void closeMBox(MBox *mbox)
{
if (!mbox) {
return;
}
/** Read a line in a file
+ * @param mbox MBox the source mbox
+ * @return the read line
+ *
+ * This function do not only read the line, it does minimum parsing stuff and
+ * set the corresponding mbox structure flags
*/
-char *readLine(MBox *mbox)
+static char *readLine(MBox *mbox)
{
int length;
mbox->lastLine = mbox->currentLine;
mbox->currentLine = ftell(mbox->fp);
- mbox->isFrom_ = FALSE;
-
+ mbox->isFrom_ = false;
+
if (!mbox->line) {
mbox->line = (char*)malloc(1001);
}
return mbox->line;
}
-/** Return to the last line
+/** Read a From_ line from the mbox
+ * the From_ line MUST be the current or the next one
*/
-bool lastLine(MBox *mbox)
-{
- if (mbox->lastLine != -1) {
- fseek(mbox->fp, mbox->lastLine, SEEK_SET);
- mbox->lastLine = -1;
- readLine(mbox);
- return TRUE;
- }
- return FALSE;
-}
-
-bool readFrom_(MBox *mbox)
+static bool readFrom_(MBox *mbox)
{
if (!mbox->isFrom_) {
readLine(mbox);
}
- if (!mbox->isFrom_) {
- return FALSE;
- }
- return TRUE;
+ return !!mbox->isFrom_;
}
/** Read a message
+ * The message is not stored or returned, just skipped.
+ * If display is true, the message is printed on stdio
*/
-void readMessage(MBox *mbox, bool display)
+static void readMessage(MBox *mbox, bool display)
{
if (!readFrom_(mbox)) {
return;
}
/** Read the headers of a message
+ * Read the given headers of the current message of the given mbox
+ * @param mbox MBox source
+ * @param headers char** list of requested headers
+ * @param hdrsize int size of @ref headers
+ *
+ * THe headers are printed on stdio
*/
-void readHeaders(MBox *mbox, char **headers, int hdrsize)
+static void readHeaders(MBox *mbox, char **headers, int hdrsize)
{
char *current = NULL;
char *pos, *ptr;
int size, i;
-
+
if (!readFrom_(mbox)) {
return;
}
continue;
}
size = pos - mbox->line;
- for (i = 0 ; i < hdrsize ; i++) {
- if (strlen(headers[i]) == size && strcasestr(mbox->line, headers[i]) == mbox->line) {
+ for (i = 0 ; i < hdrsize ; ++i) {
+ if ((int)strlen(headers[i]) == size && strcasestr(mbox->line, headers[i]) == mbox->line) {
current = (char*)malloc(size + 1);
strcpy(current, headers[i]);
- current[size] = '\0';
+ current[size] = '\0';
}
}
if (!current && !hdrsize) {
/** Go back to the beginning of the file
*/
-void rewindMBox(MBox *mbox)
+static void rewindMBox(MBox *mbox)
{
fseek(mbox->fp, 0, SEEK_SET);
mbox->messageId = 0;
readLine(mbox);
}
-/** Go back to the beginning of the message
+/** Go back to the beginning of the current message
+ * @return true if the beginning of a message has been reached
*/
-bool rewindMessage(MBox *mbox)
+static bool rewindMessage(MBox *mbox)
{
if (mbox->isFrom_) {
- return TRUE;
+ return true;
}
fseek(mbox->fp, mbox->messageBeginning, SEEK_SET);
mbox->currentLine = -1;
}
/** Move to the given offset
+ * @param mbox MBox the source mbox
+ * @param offset int offset where to go
+ * @param idx int index of the message corresponding with the offset
+ * @return true if the given offset is the beginning of a message
*/
-bool goToOffset(MBox *mbox, int offset, int index)
+static bool goToOffset(MBox *mbox, int offset, int idx)
{
fseek(mbox->fp, offset, SEEK_SET);
mbox->currentLine = -1;
mbox->lastLine = -1;
mbox->messageBeginning = offset;
- mbox->messageId = index;
+ mbox->messageId = idx;
readLine(mbox);
if (!mbox->isFrom_) {
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
/** Move to the given message number
+ * @param mbox MBox the source mbox
+ * @param idx int the index of the message where to go
+ * @return true if the given message has been reached
*/
-bool goToMessage(MBox *mbox, int index)
+static bool goToMessage(MBox *mbox, int idx)
{
- if (mbox->messageId > index) {
- rewindMBox(mbox);
- } else if(mbox->messageId == index) {
+ if (mbox->messageId > idx) {
+ rewindMBox(mbox);
+ } else if(mbox->messageId == idx) {
rewindMessage(mbox);
- return TRUE;
+ return true;
} else if (!mbox->isFrom_) {
while (!feof(mbox->fp) && !mbox->isFrom_) {
readLine(mbox);
}
if (feof(mbox->fp)) {
- return FALSE;
+ return false;
}
}
- while (mbox->messageId < index && !feof(mbox->fp)) {
- readMessage(mbox, FALSE);
+ while (mbox->messageId < idx && !feof(mbox->fp)) {
+ readMessage(mbox, false);
}
- if (mbox->messageId == index) {
- return TRUE;
+ if (mbox->messageId == idx) {
+ return true;
}
- return FALSE;
+ return false;
}
-/** Display the program help
+/** Display the program usage help
*/
-void help(void)
+static void help(void)
{
printf("Usage: mbox-helper [action] [options] -f filename [header1 [header2 ...]]\n"
"Actions: only the last action given is applied\n"
/** Display an error message
* This function display the giver error, then show the program help and exit the program
+ * The memory must be cleared before calling this function
*/
-void error(char *message)
+static void error(const char *message)
{
fprintf(stderr, "Invalid parameters: %s\n", message);
help();
int headerNb = 0;
char *endptr;
MBox *mbox;
-
- /* getopt variables */
- extern char *optarg;
- extern int optind, optopt;
+ // Parse command line
while ((c = getopt(argc, argv, ":bcdp:hm:f:")) != -1) {
switch (c) {
case 'f':
if (endptr == optarg) {
error("invalid message id");
}
- if (*endptr != ':') {
+ if (*endptr != ':' || !*(endptr+1)) {
lmid = fmid;
} else {
lmid = atoi(endptr + 1);
case 'p':
if ((endptr = strchr(optarg, ':')) != NULL) {
pmid = strtol(optarg, &endptr, 10);
- if (*endptr != ':') {
+ if (*endptr != ':' || !*(endptr+1)) {
error("invalid position couple given");
}
pos = atoi(endptr + 1);
break;
}
}
-
+
+ // Check command line arguments consistence
if (!filename) {
error("no file defined");
}
setlocale(LC_ALL, "C");
-
+
headerNb = argc - optind;
headers = (argv + optind);
for (i = 0 ; i < headerNb ; i++) {
mbox = openMBox(filename);
if (!mbox) {
- fprintf(stderr, "can't open file '%s'", filename);
+ fprintf(stderr, "can't open file '%s'\n", filename);
+ return 1;
}
if ((fmid >= pmid || fmid == -1) && pos) {
if (!goToOffset(mbox, pos, pmid)) {
fprintf(stderr, "Offset %d do not match with a message beginning\n", pos);
rewindMBox(mbox);
- }
+ }
}
+
+ // Do requested stuff
switch (action) {
case 'b':
if (fmid == -1) {
- fprintf(stderr, "you have to define a message number");
+ fprintf(stderr, "you have to define a message number\n");
break;
}
goToMessage(mbox, fmid);
- readMessage(mbox, TRUE);
+ readMessage(mbox, true);
break;
case 'c':
while (!feof(mbox->fp)) {
break;
case 'd':
if (fmid == -1) {
- fprintf(stderr, "you have to define a message number");
+ fprintf(stderr, "you have to define a message number\n");
break;
}
for (i = fmid ; i <= lmid ; i++) {