ftp.nice.ch/Attic/openStep/unix/connectivity/communication/msend.3.3.m.I.bs.tgz#/msend-3.3/msave.c

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.