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.