Fixes vim mode line.
[banana.git] / mbox-helper / mbox-helper.c
index c539c78..6edb007 100644 (file)
@@ -1,5 +1,10 @@
-/** 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
@@ -36,13 +37,15 @@ typedef struct
 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;
     }
@@ -54,13 +57,13 @@ MBox *openMBox(char *filename)
     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;
@@ -73,14 +76,19 @@ void closeMBox(MBox *mbox)
 }
 
 /** 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);
     }
@@ -106,33 +114,22 @@ char *readLine(MBox *mbox)
     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;
@@ -152,13 +149,19 @@ void readMessage(MBox *mbox, bool display)
 }
 
 /** 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;
     }
@@ -182,11 +185,11 @@ void readHeaders(MBox *mbox, char **headers, int hdrsize)
                 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) {
@@ -213,7 +216,7 @@ void readHeaders(MBox *mbox, char **headers, int 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;
@@ -221,12 +224,13 @@ void rewindMBox(MBox *mbox)
     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;
@@ -236,51 +240,58 @@ bool rewindMessage(MBox *mbox)
 }
 
 /** 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"
@@ -304,8 +315,9 @@ void help(void)
 
 /** 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();
@@ -325,11 +337,8 @@ int main(int argc, char *argv[])
     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':
@@ -340,7 +349,7 @@ int main(int argc, char *argv[])
             if (endptr == optarg) {
                 error("invalid message id");
             }
-            if (*endptr != ':') {
+            if (*endptr != ':' || !*(endptr+1)) {
                 lmid = fmid;
             } else {
                 lmid = atoi(endptr + 1);
@@ -349,7 +358,7 @@ int main(int argc, char *argv[])
           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);
@@ -371,13 +380,14 @@ int main(int argc, char *argv[])
             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++) {
@@ -386,22 +396,25 @@ int main(int argc, char *argv[])
 
     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)) {
@@ -411,7 +424,7 @@ int main(int argc, char *argv[])
         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++) {