This is msave.c in view mode; [Download] [Up]
/* * msave.c * * Copyright (c) 1993 Zik Saleeba <zik@zikzak.apana.org.au> * * This is an implementation of saved message viewing. * This implementation may be freely copied, modified, and * redistributed, provided that this comment is retained. */ /* $Id: msave.c,v 1.1 1997/10/26 07:31:25 lukeh Exp $ */ #include "common.h" #include "msend.h" #define STARTBUFSIZE 16384 static FILE *msgfile; static char *text; static int textsize; static int bufsize; static char *(*textindex)[]; static int nummsgs; static char savepath[PATH_MAX+1]; /* * open, lock and read the file. Don't unlock here */ void read_file(homedir) char *homedir; { int bytes; /* initialise the text buffer */ text = malloc(STARTBUFSIZE); if (text == NULL) { fprintf(stderr, "Out of memory\n"); exit(1); } bufsize = STARTBUFSIZE; textsize = 0; *text = '\0'; savepath[PATH_MAX] = '\0'; #ifdef SAVE_PATH { struct passwd *pwd; pwd = getpwuid(getuid()); if (pwd == NULL) { fprintf(stderr, "You don't exist - go away."); exit(1); } strncpy(savepath, SAVE_PATH, PATH_MAX); strncat(savepath, "/", PATH_MAX); strncat(savepath, pwd->pw_name, PATH_MAX); } #else /* find the home directory */ if (homedir == NULL) { homedir = (char *)getenv("HOME"); if (homedir == NULL) { /* try the password file */ struct passwd *pwd; pwd = getpwuid(getuid()); if (pwd == NULL) { fprintf(stderr, "You don't exist - go away."); exit(1); } homedir = pwd->pw_dir; } } strncpy(savepath, homedir, PATH_MAX); strncat(savepath, "/.message", PATH_MAX); #endif /* open the message file */ msgfile = fopen(savepath, "r+"); if (msgfile == NULL) return; /* nothing in it */ /* lock the file */ #ifdef USE_LOCKFILES if (lock_file(savepath)) { fprintf(stderr, "Can't lock message file.\n"); exit(1); } #else # ifdef USE_LOCKF lockf(fileno(msgfile), F_LOCK, 0); # else flock(fileno(msgfile), LOCK_EX); # endif #endif /* read in the entire text */ do { bytes = fread(text+textsize, 1, bufsize-textsize, msgfile); if (bytes >= bufsize-textsize) { /* enlarge buffer and get more */ textsize += bytes; bufsize *= 2; text = realloc(text, bufsize); if (text == NULL) { fprintf(stderr, "Out of memory\n"); #ifdef USE_LOCKFILES unlock_file(savepath); #endif exit(1); } } else if (bytes > 0) { /* just store what we've got */ textsize += bytes; } } while (bytes >= bufsize-textsize); *(text+textsize) = '\0'; /* null terminate */ } /* * split the text into message-sized chunks */ void index_text() { char *pos; int msgcount; /* count the messages */ nummsgs = 0; if (!text) return; pos = text; while ( (pos = (char *)STRSTR(pos, MESSAGE_SEP)) != NULL) { nummsgs++; pos++; } /* allocate the index array */ textindex = (char *(*)[])malloc(sizeof(char *) * nummsgs); /* fill in the index array and null terminate each message */ pos = text; msgcount = 0; while ( (pos = (char *)STRSTR(pos, MESSAGE_SEP)) != NULL) { (*textindex)[msgcount++] = pos+strlen(MESSAGE_SEP); *pos++ = '\0'; } } char *message_was_unread(msgno) int msgno; { char *pos; /* find "Unread" string */ pos = (*textindex)[msgno] + 10; while (*pos == '*') /* skip '*'s */ pos++; while (*pos == ' ') /* skip ' 's */ pos++; if (strncmp(pos, "Unread message from", 19) == 0) return pos-2; else return NULL; } /* * display messages and mark them as read */ void display_message(msgno) int msgno; { char *pos; /* display it */ printf("%s\n", (*textindex)[msgno]); /* mark as read */ if ( (pos = message_was_unread(msgno)) != NULL) { strncpy(pos, " A message arrived at", 21); fseek(msgfile, (long)pos - (long)text, SEEK_SET); fprintf(msgfile, " A message arrived at"); } } void write_shorter(savemsgs) int savemsgs; { int msgcount; if (msgfile == NULL) return; if (nummsgs > savemsgs) { /* must shorten */ rewind(msgfile); for (msgcount = nummsgs - savemsgs; msgcount < nummsgs; msgcount++) fprintf(msgfile, "%s%s", MESSAGE_SEP, (*textindex)[msgcount]); fflush(msgfile); ftruncate(fileno(msgfile), ftell(msgfile)); } } void closeup() { if (msgfile) { fclose(msgfile); #ifdef USE_LOCKFILES unlock_file(savepath); #endif if (text) { free(text); free(textindex); } } } void last_message(showmsgs, savemsgs) int showmsgs; int savemsgs; { int msgcount; int first; read_file(NULL); index_text(); /* choose 'all' by default */ if (showmsgs == 0) first = nummsgs - 5; else { first = nummsgs - showmsgs; } if (first < 0) first = 0; /* display */ for (msgcount = first; msgcount < nummsgs; msgcount++) display_message(msgcount); write_shorter(savemsgs); closeup(); } void unread_message(savemsgs) int savemsgs; { int msgcount; read_file(NULL); index_text(); for (msgcount = 0; msgcount < nummsgs; msgcount++) { if (message_was_unread(msgcount) != NULL) display_message(msgcount); } write_shorter(savemsgs); closeup(); } int check_unread() { int msgcount; int numunread; read_file(NULL); index_text(); /* how many unread messages are there? */ numunread = 0; for (msgcount = 0; msgcount < nummsgs; msgcount++) { if (message_was_unread(msgcount) != NULL) numunread++; } /* display what we've found */ if (numunread > 0) { printf("You have %d unread message%s from:", numunread, (numunread > 1) ? "s" : ""); for (msgcount = 0; msgcount < nummsgs; msgcount++) { if (message_was_unread(msgcount) != NULL) { char *frompos = (char *)STRSTR((*textindex)[msgcount], "From: "); if (frompos != NULL) { putchar(' '); frompos += 6; while ( *frompos != ' ' && *frompos != '\n' && *frompos != '\0' ) putchar(*frompos++); } } } printf(" (\"%s -u\" to read)\n", prog); } closeup(); return (numunread == 0) ? 1 : 0; } void makeshort(savemsgs) int savemsgs; { read_file(NULL); index_text(); write_shorter(savemsgs); closeup(); } void expire(savemsgs) int savemsgs; { struct passwd *user; /* give a nasty message if we're not root */ if (geteuid() != 0) { fprintf(stderr, "Only root can expire other people's messages.\n"); exit(1); } /* set default messages */ if (savemsgs == 0) savemsgs = 20; /* expire */ while ( (user = getpwent()) != NULL) { read_file(user->pw_dir); index_text(); if (nummsgs > 0) { /* bother to expire */ write_shorter(savemsgs); } closeup(); } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.