IMS (mail system) Part 2/2

Brandon S. Allbery allbery at ncoast.UUCP
Tue Jul 22 12:16:41 AEST 1986


#! /bin/sh
if test -r "ndir.c"; then
	echo "File ndir.c exists.  Enter new name or RETURN to skip.  (. to replace.)"
	read newname
	case "$newname" in
	".")	newname="ndir.c"
	esac
else
	newname="ndir.c"
fi
if test -z "$newname"; then
	echo "shx - $newname (skipped)"
else
	case "$newname" in
	"$sfile")
		echo "shx - $sfile (as $newname)"
		;;
	*)	echo "shx - $newname"
	esac
	sed 's/^X//' << '--EOF:ndir.c--' > "$newname"
X#include <sys/types.h>
X#include "ndir.h"
X
X#ifndef BSD
X
X/*
X * close a directory.
X */
Xclosedir(dirp)
X        register DIR *dirp;
X{
X        close(dirp->dd_fd);
X        dirp->dd_fd = -1;
X        dirp->dd_loc = 0;
X        free(dirp);
X}
X
X
X
X/*
X * open a directory.
X */
XDIR *
Xopendir(name)
X        char *name;
X{
X        register DIR *dirp;
X        register int fd;
X
X        if ((fd = eopen(name, 0)) == -1)
X                return NULL;
X        if ((dirp = (DIR *)malloc(sizeof(DIR))) == NULL) {
X                close (fd);
X                return NULL;
X        }
X        dirp->dd_fd = fd;
X        dirp->dd_loc = 0;
X        return dirp;
X}
X
X
X
X/*
X * read an old style directory entry and present it as a new one
X */
X#define ODIRSIZ 14
X
Xstruct  olddirect {
X        ino_t   od_ino;
X        char    od_name[ODIRSIZ];
X};
X
X/*
X * get next entry in a directory.
X */
Xstruct direct *
Xreaddir(dirp)
X        register DIR *dirp;
X{
X        register struct olddirect *dp;
X        static struct direct dir;
X
X        for (;;) {
X                if (dirp->dd_loc == 0) {
X                        dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, 
X                            DIRBLKSIZ);
X                        if (dirp->dd_size <= 0)
X                                return NULL;
X                }
X                if (dirp->dd_loc >= dirp->dd_size) {
X                        dirp->dd_loc = 0;
X                        continue;
X                }
X                dp = (struct olddirect *)(dirp->dd_buf + dirp->dd_loc);
X                dirp->dd_loc += sizeof(struct olddirect);
X                if (dp->od_ino == 0)
X                        continue;
X                dir.d_ino = dp->od_ino;
X                strncpy(dir.d_name, dp->od_name, ODIRSIZ);
X                dir.d_name[ODIRSIZ] = '\0'; /* insure null termination */
X                dir.d_namlen = strlen(dir.d_name);
X                dir.d_reclen = DIRBLKSIZ;
X                return (&dir);
X        }
X}
X
X#endif BSD
--EOF:ndir.c--
fi

if test -r "eopen.c"; then
	echo "File eopen.c exists.  Enter new name or RETURN to skip.  (. to replace.)"
	read newname
	case "$newname" in
	".")	newname="eopen.c"
	esac
else
	newname="eopen.c"
fi
if test -z "$newname"; then
	echo "shx - $newname (skipped)"
else
	case "$newname" in
	"$sfile")
		echo "shx - $sfile (as $newname)"
		;;
	*)	echo "shx - $newname"
	esac
	sed 's/^X//' << '--EOF:eopen.c--' > "$newname"
X#include <stdio.h>
X#include <errno.h>
X
Xextern int errno;
Xstatic int __pop_pid = -1;
X
XFILE *efopen(file, mode)
Xchar *file, *mode; {
X	int alevel, chmg;
X	FILE *fp;
X	
X	switch (mode[0]) {
X		case 'r':
X			alevel = 4;
X			break;
X		case 'w':
X		case 'a':
X			alevel = 2;
X			break;
X	}
X	if (mode[1] == '+')
X		alevel = 6;
X	chmg = 0;
X	if (access(file, alevel) < 0)
X		if (errno != ENOENT)
X			return (FILE *) 0;
X		else
X			chmg = 1;
X	if ((fp = fopen(file, mode)) == (FILE *) 0)
X		return (FILE *) 0;
X	if (chmg)
X		chown(file, getuid(), getgid());
X	return fp;
X}
X
Xeopen(file, mode)
Xchar *file; {
X	int alevel, fd, chmg;
X	
X	switch (mode & 3) {
X		case 0:
X			alevel = 4;
X			break;
X		case 1:
X			alevel = 2;
X			break;
X		case 2:
X			alevel = 6;
X			break;
X	}
X	chmg = 0;
X	if (access(file, alevel) < 0)
X		if (errno != ENOENT)
X			return -1;
X		else
X			chmg = 1;
X	if ((fd = open(file, mode)) == -1)
X		return -1;
X	if (chmg)
X		chown(file, getuid(), getgid());
X	return fd;
X}
X		
XFILE *epopen(cmd, mode)
Xchar *mode; {
X	FILE *pfp;
X	int pfd[2];
X	int pmode;
X	
X	pmode = (*mode == 'r'? 1: 0);
X	pipe(pfd);
X	switch (__pop_pid = fork()) {
X		case -1:
X			return (FILE *) 0;
X		case 0:
X			setgid(getgid());
X			setuid(getuid());
X			close(pmode);
X			dup(pfd[pmode]);
X			close(pfd[!pmode]);
X			close(pfd[pmode]);
X			execl("/bin/sh", "sh", "-c", cmd, (char *) 0);
X			_exit(100);
X		default:
X			close(pfd[pmode]);
X			return fdopen(pfd[!pmode], mode);
X	}
X}
X
Xpclose(fp)
XFILE *fp; {
X	int status;
X
X	fclose(fp);
X	if (__pop_pid == -1)
X		return -1;
X	while (wait(&status) != __pop_pid)
X		;
X	return status;
X}
--EOF:eopen.c--
fi

if test -r "ims.h"; then
	echo "File ims.h exists.  Enter new name or RETURN to skip.  (. to replace.)"
	read newname
	case "$newname" in
	".")	newname="ims.h"
	esac
else
	newname="ims.h"
fi
if test -z "$newname"; then
	echo "shx - $newname (skipped)"
else
	case "$newname" in
	"$sfile")
		echo "shx - $sfile (as $newname)"
		;;
	*)	echo "shx - $newname"
	esac
	sed 's/^X//' << '--EOF:ims.h--' > "$newname"
X#include <stdio.h>
X#include <signal.h>
X#include <setjmp.h>
X#include <pwd.h>
X#include <time.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sys/ioctl.h>
X#include "ndir.h"
X
X#define IMSINIT		"/usr/lib/imsinit"
X#define IMSALIAS	"/usr/lib/imsaliases"
X
X#ifndef USG
X#define strchr		index
X#define strrchr		rindex
X#endif  USG
X
Xextern int readmsg(), printmsg(), reply(), gomsg(), mailto(), listmsg(),
X	forward(), byebye(), help(), setfolder(), readmbox(), savemsg(),
X	delmsg(), undelmsg(), nxbyebye(), expunge(), nextmsg(), prevmsg(),
X	varops(), foldlist(), aliasops(), unalias();
X
Xextern char *location();
Xextern char *strchr();
Xextern char *strrchr();
Xextern char *getenv();
Xextern FILE *efopen();
Xextern char *mlocation();
Xextern char *mflocation();
Xextern char *calloc();
Xextern char *realloc();
Xextern FILE *epopen();
Xextern char *basename();
Xextern char *getlogin();
Xextern struct passwd *getpwnam();
Xextern struct tm *localtime();
X
Xextern char folder[];
Xextern char cabinet[];
Xextern char pager[];
Xextern char sysmbox[];
Xextern char prompt[];
Xextern char sender[];
Xextern char mailbox[];
Xextern char editor[];
Xextern char printcmd[];
Xextern char savefolder[];
Xextern char autonext[];
Xextern char autoread[];
Xextern char askappend[];
Xextern char lines[];
Xextern char edforward[];
Xextern char alicount[];
Xextern int msg;
X
X#ifdef USG
X#define SYSMAILBOX	"/usr/mail/%s"
X#else
X#define SYSMAILBOX	"/usr/spool/mail/%s"
X#define strchr		index
X#define strrchr		rindex
X#endif USG
X
X#ifndef USG
X#include <sgtty.h>
X#define TERMIO		sgttyb
X#define TIO_GET		TIOCGETP
X#define TIO_SET		TIOCSETN
X#define TIO_ERASE	sg_erase
X#else   USG
X#include <termio.h>
X#define TERMIO		termio
X#define TIO_GET		TCGETA
X#define TIO_SET		TCSETAW
X#define TIO_ERASE	c_cc[VERASE]
X#endif  USG
--EOF:ims.h--
fi

if test -r "ndir.h"; then
	echo "File ndir.h exists.  Enter new name or RETURN to skip.  (. to replace.)"
	read newname
	case "$newname" in
	".")	newname="ndir.h"
	esac
else
	newname="ndir.h"
fi
if test -z "$newname"; then
	echo "shx - $newname (skipped)"
else
	case "$newname" in
	"$sfile")
		echo "shx - $sfile (as $newname)"
		;;
	*)	echo "shx - $newname"
	esac
	sed 's/^X//' << '--EOF:ndir.h--' > "$newname"
X/*	dir.h	4.4	82/07/25	*/
X
X#ifdef BSD
X#include <sys/dir.h>
X#else
X
X/*
X * A directory consists of some number of blocks of DIRBLKSIZ
X * bytes, where DIRBLKSIZ is chosen such that it can be transferred
X * to disk in a single atomic operation (e.g. 512 bytes on most machines).
X *
X * Each DIRBLKSIZ byte block contains some number of directory entry
X * structures, which are of variable length.  Each directory entry has
X * a struct direct at the front of it, containing its inode number,
X * the length of the entry, and the length of the name contained in
X * the entry.  These are followed by the name padded to a 4 byte boundary
X * with null bytes.  All names are guaranteed null terminated.
X * The maximum length of a name in a directory is MAXNAMLEN.
X *
X * The macro DIRSIZ(dp) gives the amount of space required to represent
X * a directory entry.  Free space in a directory is represented by
X * entries which have dp->d_reclen >= DIRSIZ(dp).  All DIRBLKSIZ bytes
X * in a directory block are claimed by the directory entries.  This
X * usually results in the last entry in a directory having a large
X * dp->d_reclen.  When entries are deleted from a directory, the
X * space is returned to the previous entry in the same directory
X * block by increasing its dp->d_reclen.  If the first entry of
X * a directory block is free, then its dp->d_ino is set to 0.
X * Entries other than the first in a directory do not normally have
X * dp->d_ino set to 0.
X */
X#define DIRBLKSIZ	512
X#define	MAXNAMLEN	255
X
Xstruct	direct {
X	long	d_ino;			/* inode number of entry */
X	short	d_reclen;		/* length of this record */
X	short	d_namlen;		/* length of string in d_name */
X	char	d_name[MAXNAMLEN + 1];	/* name must be no longer than this */
X};
X
X/*
X * The DIRSIZ macro gives the minimum record length which will hold
X * the directory entry.  This requires the amount of space in struct direct
X * without the d_name field, plus enough space for the name with a terminating
X * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
X */
X#ifdef DIRSIZ
X#undef DIRSIZ
X#endif
X#define DIRSIZ(dp) \
X    ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
X
X#ifndef KERNEL
X/*
X * Definitions for library routines operating on directories.
X */
Xtypedef struct _dirdesc {
X	int	dd_fd;
X	long	dd_loc;
X	long	dd_size;
X	char	dd_buf[DIRBLKSIZ];
X} DIR;
X#ifndef NULL
X#define NULL 0
X#endif
Xextern	DIR *opendir();
Xextern	struct direct *readdir();
Xextern	closedir();
X#endif KERNEL
X
X#endif BSD
--EOF:ndir.h--
fi

if test -r "ims.1"; then
	echo "File ims.1 exists.  Enter new name or RETURN to skip.  (. to replace.)"
	read newname
	case "$newname" in
	".")	newname="ims.1"
	esac
else
	newname="ims.1"
fi
if test -z "$newname"; then
	echo "shx - $newname (skipped)"
else
	case "$newname" in
	"$sfile")
		echo "shx - $sfile (as $newname)"
		;;
	*)	echo "shx - $newname"
	esac
	sed 's/^X//' << '--EOF:ims.1--' > "$newname"
X.TH IMS LOCAL
X.ds i \fBims\fR
X.SH NAME
X\*i \- Intelligent Message System
X.SH SYNOPSIS
X.B \*i
X[ -i ]
X.br
X.B \*i
X.I \*i-command-string
X.SH DESCRIPTION
X\*i is a mail system intended to replace 
X.BR mail (1)
Xfor regular use.  It uses
X.B mail
Xto send messages, in order to retain compatibility with other mailers.
X.PP
X\*i implements a true ``folder'' mechanism for handling mail.  A mail
Xcabinet (by default 
X.IR $HOME/.mail )
Xis established the first time the program is run, as is a standard
Xfolder (by default
X.IR incoming-mail ).
XOn entry, mail is read into files in the standard folder, unless the
X.I -i
Xoption is given or an
X.I \*i-command-string
Xis specified.  The message pointer is then set to the first new message
Xand a command prompt is issued.
X.PP
XThere are two ways to use \*i:
X.IR "interactive mode" ,
Xwhich issues a prompt until a
X.I quit
Xor
X.I xit
Xcommand is issued or a
X.I control-D
Xis typed, and
X.IR "command mode" ,
Xwhich executes the command line and then exits as if the
X.I xit
Xcommand had been issued.  The two modes are described in detail below.
X.SH SETUP
X\*i understands a number of environment variables, supports variables of
Xits own, and provides reasonable defaults for anything not specified.
XThe environment variables, \*i variables, and their meanings are described
Xin Table 1 at the end of this document.
X.PP
XEnvironment variables are specified in the usual way (see
X.IR sh (1)
Xor
X.IR csh (1)
Xfor examples).  \*i variables are set in the file specified by the
X.I IMSINIT
Xvariable, or $HOME/.imsinit if no
X.I IMSINIT
Xenvironment variable exists.  They may also be set by the
X.I set
Xcommand from within \*i.
XThere is also a system IMSINIT file,
X.IR /usr/lib/imsinit .
X.PP
XThe
X.I IMSINIT
Xfile contains assignment statements of the form:
X.sp
X.nf
X.ce
X\fIvariable\fR = \fIvalue\fR
X.fi
X.sp
XA 
X.I value
Xmay be a single word or quoted text; if quoted, the value may comprise
Xseveral lines of the
X.I IMSINIT
Xfile, but this is discouraged because few, if any, \*i commands make use
Xof multiple-line values.  The
X.I print-command
Xvariable is a possible exception.
X.SH COMMANDS
X\*i supports a large number of commands for manipulating messages and
Xfolders.  They are detailed below.
X.nr i) 5
X.de LS
X.PP
X.ns
X.in +5n+\\n(i)n
X.ll -5n
X..
X.de LI
X.sp
X.ti -\\n(i)n
X\fB\\$1\fR \-
X..
X.de L+
X.sp
X.ti -\\n(i)n
X\fB\\$1\fR
X.br
X.ns
X..
X.de LE
X.ll
X.in
X.PP
X.ns
X..
X.LS
X.LI delete
XDelete the named message, or the current message.  If
X.I type-next-automatically
Xis affirmative, a
X.I type
Xcommand is executed with no arguments afterward.
X.LI undelete
XRestore a message deleted with the
X.I delete
Xcommand.  Note that if
X.I xit
Xis used to exit \*i, deleted messages will remain deleted but will also
Xremain recoverable; an
X.I expunge
Xcommand, either explicit or via the
X.I quit
Xcommand, is required to physically delete messages.
X.LI expunge
XPhysically delete messages marked for deletion with the
X.I delete
Xcommand.  An implicit 
X.I expunge
Xis done by the
X.I quit
Xcommand.  Unless an
X.I expunge
Xis performed, deleted messages still exist and are recoverable with
X.IR undelete .
X



More information about the Comp.sources.unix mailing list