home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / OPENSTEP / Networking / msend-3.3-I / msave.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-10-26  |  6.3 KB  |  354 lines

  1. /*
  2.  * msave.c
  3.  *
  4.  * Copyright (c) 1993 Zik Saleeba <zik@zikzak.apana.org.au>
  5.  *
  6.  * This is an implementation of saved message viewing.
  7.  * This implementation may be freely copied, modified, and 
  8.  * redistributed, provided that this comment is retained.
  9.  */
  10.  
  11. /* $Id: msave.c,v 1.1 1997/10/26 07:31:25 lukeh Exp $ */
  12.  
  13. #include "common.h"
  14. #include "msend.h"
  15.  
  16.  
  17. #define STARTBUFSIZE 16384
  18.  
  19.  
  20. static FILE *msgfile;
  21. static char *text;
  22. static int textsize;
  23. static int bufsize;
  24. static char *(*textindex)[];
  25. static int nummsgs;
  26. static char savepath[PATH_MAX+1];
  27.  
  28.  
  29. /*
  30.  * open, lock and read the file. Don't unlock here
  31.  */
  32.  
  33. void read_file(homedir)
  34.     char *homedir;
  35. {
  36.     int bytes;
  37.  
  38.     /* initialise the text buffer */
  39.     text = malloc(STARTBUFSIZE);
  40.     if (text == NULL) {
  41.         fprintf(stderr, "Out of memory\n");
  42.         exit(1);
  43.     }
  44.     bufsize = STARTBUFSIZE;
  45.     textsize = 0;
  46.     *text = '\0';
  47.  
  48.     savepath[PATH_MAX] = '\0';
  49. #ifdef SAVE_PATH
  50.     {
  51.         struct passwd *pwd;
  52.         pwd = getpwuid(getuid());
  53.         if (pwd == NULL) {
  54.             fprintf(stderr, "You don't exist - go away.");
  55.             exit(1);
  56.         }
  57.         strncpy(savepath, SAVE_PATH, PATH_MAX);
  58.         strncat(savepath, "/", PATH_MAX);
  59.         strncat(savepath, pwd->pw_name, PATH_MAX);
  60.     }
  61. #else
  62.     /* find the home directory */
  63.     if (homedir == NULL) {
  64.         homedir = (char *)getenv("HOME");
  65.         if (homedir == NULL) {
  66.             /* try the password file */
  67.             struct passwd *pwd;
  68.             pwd = getpwuid(getuid());
  69.             if (pwd == NULL) {
  70.                 fprintf(stderr, "You don't exist - go away.");
  71.                 exit(1);
  72.             }
  73.             homedir = pwd->pw_dir;
  74.         }
  75.     }
  76.     strncpy(savepath, homedir, PATH_MAX);
  77.     strncat(savepath, "/.message", PATH_MAX);
  78. #endif
  79.  
  80.     /* open the message file */
  81.     msgfile = fopen(savepath, "r+");
  82.     if (msgfile == NULL)
  83.         return; /* nothing in it */
  84.  
  85.     /* lock the file */
  86. #ifdef USE_LOCKFILES
  87.     if (lock_file(savepath)) {
  88.         fprintf(stderr, "Can't lock message file.\n");
  89.         exit(1);
  90.     }
  91. #else
  92. # ifdef USE_LOCKF
  93.     lockf(fileno(msgfile), F_LOCK, 0);
  94. # else
  95.     flock(fileno(msgfile), LOCK_EX);
  96. # endif
  97. #endif
  98.  
  99.     /* read in the entire text */
  100.     do {
  101.         bytes = fread(text+textsize, 1, bufsize-textsize, msgfile);
  102.         if (bytes >= bufsize-textsize) {
  103.             /* enlarge buffer and get more */
  104.             textsize += bytes;
  105.             bufsize *= 2;
  106.             text = realloc(text, bufsize);
  107.             if (text == NULL) {
  108.                 fprintf(stderr, "Out of memory\n");
  109. #ifdef USE_LOCKFILES
  110.                 unlock_file(savepath);
  111. #endif
  112.                 exit(1);
  113.             }
  114.         } 
  115.         else if (bytes > 0) {
  116.             /* just store what we've got */
  117.             textsize += bytes;
  118.         }
  119.     } while (bytes >= bufsize-textsize);
  120.     *(text+textsize) = '\0'; /* null terminate */
  121. }
  122.  
  123.  
  124. /*
  125.  * split the text into message-sized chunks
  126.  */
  127.  
  128. void index_text()
  129. {
  130.     char *pos;
  131.     int msgcount;
  132.  
  133.     /* count the messages */
  134.     nummsgs = 0;
  135.  
  136.     if (!text) return;
  137.  
  138.     pos = text;
  139.     while ( (pos = (char *)STRSTR(pos, MESSAGE_SEP)) != NULL) {
  140.         nummsgs++;
  141.         pos++;
  142.     }
  143.  
  144.     /* allocate the index array */
  145.     textindex = (char *(*)[])malloc(sizeof(char *) * nummsgs);
  146.  
  147.     /* fill in the index array and null terminate each message */
  148.     pos = text;
  149.     msgcount = 0;
  150.     while ( (pos = (char *)STRSTR(pos, MESSAGE_SEP)) != NULL) {
  151.         (*textindex)[msgcount++] = pos+strlen(MESSAGE_SEP);
  152.         *pos++ = '\0';
  153.     }
  154. }
  155.  
  156.  
  157. char *message_was_unread(msgno)
  158.     int msgno;
  159. {
  160.     char *pos;
  161.  
  162.     /* find "Unread" string */
  163.     pos = (*textindex)[msgno] + 10;
  164.     while (*pos == '*')    /* skip '*'s */
  165.         pos++;
  166.     while (*pos == ' ')    /* skip ' 's */
  167.         pos++;
  168.  
  169.     if (strncmp(pos, "Unread message from", 19) == 0)
  170.         return pos-2;
  171.     else
  172.         return NULL;
  173. }
  174.  
  175.  
  176. /*
  177.  * display messages and mark them as read
  178.  */
  179.  
  180. void display_message(msgno)
  181.     int msgno;
  182. {
  183.     char *pos;
  184.  
  185.     /* display it */
  186.     printf("%s\n", (*textindex)[msgno]);
  187.  
  188.     /* mark as read */
  189.     if ( (pos = message_was_unread(msgno)) != NULL) {
  190.         strncpy(pos, " A message arrived at", 21);
  191.         fseek(msgfile, (long)pos - (long)text, SEEK_SET);
  192.         fprintf(msgfile, " A message arrived at");
  193.     }
  194. }
  195.  
  196.  
  197. void write_shorter(savemsgs)
  198.     int savemsgs;
  199. {
  200.     int msgcount;
  201.  
  202.     if (msgfile == NULL)
  203.         return;
  204.  
  205.     if (nummsgs > savemsgs) {
  206.         /* must shorten */
  207.         rewind(msgfile);
  208.         for (msgcount = nummsgs - savemsgs; msgcount < nummsgs; msgcount++)
  209.             fprintf(msgfile, "%s%s", MESSAGE_SEP, (*textindex)[msgcount]);
  210.         fflush(msgfile);
  211.         ftruncate(fileno(msgfile), ftell(msgfile));
  212.     }
  213. }
  214.  
  215.  
  216. void closeup()
  217. {
  218.     if (msgfile) {
  219.         fclose(msgfile);
  220. #ifdef USE_LOCKFILES
  221.         unlock_file(savepath);
  222. #endif
  223.         if (text) {
  224.             free(text);
  225.             free(textindex);
  226.         }
  227.     }
  228. }
  229.  
  230.  
  231. void last_message(showmsgs, savemsgs)
  232.     int showmsgs;
  233.     int savemsgs;
  234. {
  235.     int msgcount;
  236.     int first;
  237.  
  238.     read_file(NULL);
  239.     index_text();
  240.  
  241.     /* choose 'all' by default */
  242.     if (showmsgs == 0)
  243.         first = nummsgs - 5;
  244.     else {
  245.         first = nummsgs - showmsgs;
  246.     }
  247.     if (first < 0)
  248.         first = 0;
  249.  
  250.     /* display */
  251.     for (msgcount = first; msgcount < nummsgs; msgcount++)
  252.         display_message(msgcount);
  253.  
  254.     write_shorter(savemsgs);
  255.     closeup();
  256. }
  257.  
  258.  
  259. void unread_message(savemsgs)
  260.     int savemsgs;
  261. {
  262.     int msgcount;
  263.  
  264.     read_file(NULL);
  265.     index_text();
  266.  
  267.     for (msgcount = 0; msgcount < nummsgs; msgcount++) {
  268.         if (message_was_unread(msgcount) != NULL)
  269.             display_message(msgcount);
  270.     }
  271.  
  272.     write_shorter(savemsgs);
  273.     closeup();
  274. }
  275.  
  276.  
  277. int check_unread()
  278. {
  279.     int msgcount;
  280.     int numunread;
  281.  
  282.     read_file(NULL);
  283.     index_text();
  284.  
  285.     /* how many unread messages are there? */
  286.     numunread = 0;
  287.     for (msgcount = 0; msgcount < nummsgs; msgcount++) {
  288.         if (message_was_unread(msgcount) != NULL)
  289.             numunread++;
  290.     }
  291.  
  292.     /* display what we've found */
  293.     if (numunread > 0) {
  294.         printf("You have %d unread message%s from:", 
  295.                 numunread, (numunread > 1) ? "s" : "");
  296.         for (msgcount = 0; msgcount < nummsgs; msgcount++) {
  297.             if (message_was_unread(msgcount) != NULL) {
  298.                 char *frompos = (char *)STRSTR((*textindex)[msgcount],
  299.                             "From: ");
  300.                 if (frompos != NULL) {
  301.                     putchar(' ');
  302.                     frompos += 6;
  303.                     while ( *frompos != ' ' &&
  304.                         *frompos != '\n' &&
  305.                         *frompos != '\0' )
  306.                         putchar(*frompos++);
  307.                 }
  308.             }
  309.         }
  310.         printf(" (\"%s -u\" to read)\n", prog);
  311.     }
  312.  
  313.     closeup();
  314.     return (numunread == 0) ? 1 : 0;
  315. }
  316.  
  317.  
  318. void makeshort(savemsgs)
  319.     int savemsgs;
  320. {
  321.     read_file(NULL);
  322.     index_text();
  323.     write_shorter(savemsgs);
  324.     closeup();
  325. }
  326.  
  327.  
  328. void expire(savemsgs)
  329.     int savemsgs;
  330. {
  331.     struct passwd *user;
  332.  
  333.     /* give a nasty message if we're not root */
  334.     if (geteuid() != 0) {
  335.         fprintf(stderr, "Only root can expire other people's messages.\n");
  336.         exit(1);
  337.     }
  338.  
  339.     /* set default messages */
  340.     if (savemsgs == 0)
  341.         savemsgs = 20;
  342.  
  343.     /* expire */
  344.     while ( (user = getpwent()) != NULL) {
  345.         read_file(user->pw_dir);
  346.         index_text();
  347.         if (nummsgs > 0) {
  348.             /* bother to expire */
  349.             write_shorter(savemsgs);
  350.         }
  351.         closeup();
  352.     }
  353. }
  354.