home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume18
/
mush
/
part13
< prev
next >
Wrap
Internet Message Format
|
1991-04-22
|
51KB
From: argv@zipcode.com (Dan Heller)
Newsgroups: comp.sources.misc
Subject: v18i070: mush - Mail User's Shell, Part13/22
Message-ID: <1991Apr22.000428.18915@sparky.IMD.Sterling.COM>
Date: 22 Apr 91 00:04:28 GMT
Approved: kent@sparky.imd.sterling.com
X-Checksum-Snefru: 07578e65 281d7a92 a45fac4b f4b5fd2d
Submitted-by: Dan Heller <argv@zipcode.com>
Posting-number: Volume 18, Issue 70
Archive-name: mush/part13
Supersedes: mush: Volume 12, Issue 28-47
#!/bin/sh
# do not concatenate these parts, unpack them in order with /bin/sh
# file makefile.sun continued
#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck
if test "$Scheck" != 13; then
echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping makefile.sun'
else
echo 'x - continuing file makefile.sun'
sed 's/^X//' << 'SHAR_EOF' >> 'makefile.sun' &&
#
# Note that the default SunOS version for mush is 4.1. If you have an
# older version of SunOS, you must explicitly define SUN_3_5 or SUN_4_0.
#
HDRS= mush.h config.h-dist strings.h bindings.h options.h version.h glob.h
X
SRCS= addrs.c bind.c commands.c curs_io.c curses.c dates.c doproc.c \
X execute.c expr.c file.c fkeys.c folders.c glob.c hdrs.c init.c lock.c \
X loop.c macros.c mail.c main.c malloc.c misc.c misc_frame.c msgs.c \
X options.c panels.c pick.c print.c hdr_sw.c setopts.c signals.c sort.c \
X strings.c tool.c tooledit.c viewopts.c command2.c
X
OBJS= addrs.o bind.o commands.o curs_io.o curses.o dates.o doproc.o \
X execute.o expr.o file.o fkeys.o folders.o glob.o hdrs.o init.o lock.o \
X loop.o macros.o mail.o main.o malloc.o misc.o misc_frame.o msgs.o \
X options.o panels.o pick.o print.o hdr_sw.o setopts.o signals.o sort.o \
X strings.o tool.o tooledit.o viewopts.o command2.o
X
IMAGES= mail.icon.1 mail.icon.2
X
HELP_FILES= README README-7.0 README-7.1 README-7.2.0 README-7.2.2 \
X mush.1 cmd_help tool_help Mushrc Mailrc Gnurc \
X advanced.mushrc sample.mushrc digestify
X
MAKES= makefile.sun makefile.bsd makefile.sys.v makefile.xenix makefile.hpux
X
# If your SunOS version is 3.5, add -DSUN_3_5 to CFLAGS.
# If your SunOS version is 4.0, add -DSUN_4_0 to CFLAGS.
# If you are not using SUNTOOL, use makefile.bsd and add one of
# -DSUN_3_5, -DSUN_4_0, or -DSUN_4_1 to CFLAGS there.
CFLAGS= -O -DSUNTOOL -DCURSES -DBSD
LDFLAGS=
LIBES= -lcurses -ltermlib -lsuntool -lsunwindow -lpixrect
OTHERLIBS=
# Use some variant of this one if you #define MMDF in config.h
#OTHERLIBS=/usr/src/mmdf/lib/libmmdf.a
LINTFLAGS= -bxah -Dlint
X
mush: $(OBJS)
X @echo loading...
X @cc $(LDFLAGS) $(OBJS) $(LIBES) $(OTHERLIBS) -o mush
X
$(OBJS): config.h mush.h
loop.o: version.h
X
lint:
X lint $(LINTFLAGS) $(SRCS) -DSUNTOOL -DCURSES -DBSD
X
clean:
X rm -f *.o core mush
X
BINDIR= /usr/local/bin
LIBDIR= /usr/local/lib
MRCDIR= /usr/lib
MANDIR= /usr/local/man/man1
MANEXT= 1
X
install: mush
X mv mush $(BINDIR)
X strip $(BINDIR)/mush
X chmod 0755 $(BINDIR)/mush
X rm -f $(BINDIR)/mushtool
X ln -s $(BINDIR)/mush $(BINDIR)/mushtool
X cp mush.1 $(MANDIR)/mush.$(MANEXT)
X chmod 0644 $(MANDIR)/mush.$(MANEXT)
X cp tool_help $(LIBDIR)
X chmod 0644 $(LIBDIR)/tool_help
X cp cmd_help $(LIBDIR)
X chmod 0644 $(LIBDIR)/cmd_help
X cp Mushrc $(MRCDIR)/Mushrc
X chmod 0644 $(MRCDIR)/Mushrc
SHAR_EOF
echo 'File makefile.sun is complete' &&
chmod 0644 makefile.sun ||
echo 'restore of makefile.sun failed'
Wc_c="`wc -c < 'makefile.sun'`"
test 2454 -eq "$Wc_c" ||
echo 'makefile.sun: original size 2454, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= makefile.sys.v ==============
if test -f 'makefile.sys.v' -a X"$1" != X"-c"; then
echo 'x - skipping makefile.sys.v (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting makefile.sys.v (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'makefile.sys.v' &&
# Mush makefile for system V. Note: SIGRET should return void for normal
# sys-v, but Att PC users should *not* have it defined. See the README!!
#
HDRS1= mush.h config.h
HDRS2= strings.h options.h
HDRS3= bindings.h glob.h
HDRS4= version.h
SRCS1= commands.c dates.c execute.c expr.c folders.c \
X hdrs.c init.c loop.c mail.c main.c misc.c msgs.c pick.c \
X print.c setopts.c signals.c sort.c viewopts.c options.c lock.c
SRCS2= bind.c curs_io.c curses.c file.c strings.c macros.c \
X addrs.c malloc.c glob.c command2.c
X
OBJS1= commands.o dates.o execute.o expr.o folders.o \
X hdrs.o init.o loop.o mail.o main.o misc.o msgs.o pick.o \
X print.o setopts.o signals.o sort.o viewopts.o options.o lock.o
OBJS2= bind.o curs_io.o curses.o file.o strings.o macros.o \
X addrs.o malloc.o glob.o command2.o
X
HELP= README README-7.0 README-7.1 README-7.2.0 README-7.2.2 mush.1 \
X cmd_help Mushrc Mailrc Gnurc sample.mushrc advanced.mushrc digestify
X
# Sun OS systems who wish to compile with sys-v options:
# CC= /usr/5bin/cc
# CFLAGS= -O -DSYSV -DCURSES -DUSG -DDIRECTORY
# LIBS= -L/usr/5lib -lcurses
X
# IRIX 3.2 systems (SGI Iris workstations) should add -DDIRECTORY to CFLAGS
# SCO UNIX 3.2 should add -DDIRECTORY -DSELECT and should avoid library -lx
X
CFLAGS= -O -DSYSV -DUSG -DCURSES -DREGCMP -DSIGRET=void
LDFLAGS=
LIBS= -lcurses -lPW
OTHERLIBS=
# Use some variant of this one if you #define MMDF in config.h
#OTHERLIBS=/usr/src/mmdf/lib/libmmdf.a
PROG= mush
X
$(PROG): $(OBJS1) $(OBJS2)
X @echo loading...
X @$(CC) $(LDFLAGS) $(OBJS1) $(OBJS2) -o $(PROG) $(LIBS) $(OTHERLIBS)
X
$(OBJS1): $(HDRS1) $(HDRS2)
$(OBJS2): $(HDRS1) $(HDRS2) $(HDRS3)
loop.o: version.h
X
BINDIR= /usr/local/bin
LIBDIR= /usr/local/lib
MRCDIR= /usr/lib
MANDIR= /usr/local/man/man1
MANEXT= 1
X
install: mush
X cp mush $(BINDIR)
X strip $(BINDIR)/mush
X chmod 0755 $(BINDIR)/mush
X cp mush.1 $(MANDIR)/mush.$(MANEXT)
X chmod 0644 $(MANDIR)/mush.$(MANEXT)
X cp cmd_help $(LIBDIR)
X chmod 0644 $(LIBDIR)/cmd_help
X cp Mushrc $(MRCDIR)/Mushrc
X chmod 0644 $(MRCDIR)/Mushrc
SHAR_EOF
chmod 0644 makefile.sys.v ||
echo 'restore of makefile.sys.v failed'
Wc_c="`wc -c < 'makefile.sys.v'`"
test 2023 -eq "$Wc_c" ||
echo 'makefile.sys.v: original size 2023, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= makefile.xenix ==============
if test -f 'makefile.xenix' -a X"$1" != X"-c"; then
echo 'x - skipping makefile.xenix (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting makefile.xenix (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'makefile.xenix' &&
#
# makefile for Xenix machines. See "MODEL" below for your xenix type.
# some .c files may require the -LARGE compiler flag. Examples below.
# This makefile assumes an 80386 machine. If you have an 80286, see
# notes below. This makefile was built for SCO/microsoft xenix --if you
# are running some other kind of xenix, you might need to change the
# CFLAGS and LDFLAGS options.
#
HDRS= mush.h config.h-dist strings.h bindings.h options.h version.h glob.h
SRCS1= main.c init.c misc.c execute.c
SRCS2= signals.c msgs.c pick.c viewopts.c
SRCS3= sort.c expr.c folders.c dates.c
SRCS4= loop.c bind.c options.c
SRCS5= commands.c commands2.c setopts.c hdrs.c
SRCS6= mail.c print.c
SRCS7= curses.c curs_io.c
SRCS8= file.c strings.c malloc.c
SRCS9= lock.c macros.c addrs.c glob.c
OBJS= main.o init.o misc.o mail.o hdrs.o execute.o commands.o print.o file.o \
X signals.o setopts.o msgs.o pick.o sort.o expr.o strings.o \
X folders.o dates.o loop.o viewopts.o bind.o curses.o curs_io.o \
X lock.o macros.o options.o addrs.o malloc.o glob.o command2.o
HELP_FILES= README README-7.0 README-7.1 README-7.2.0 README-7.2.2 mush.1 \
X cmd_help Mushrc Mailrc Gnurc sample.mushrc advanced.mushrc digestify
X
# Memory model. Use -M3e for 80386 machines.
# Use -M2le -Mt32 -LARGE for 80286 machines.
MODEL= -M3e
X
#
# 80286 xenix may use this LDFLAGS define:
#LDFLAGS= -X -lx -M2le -Mt32 -F 8000 -SEG 256 -LARGE
LDFLAGS= -X -lx -M3
X
CFLAGS= $(MODEL) -O -DSYSV -DCURSES -DREGCMP -DUSG
LIBES= -lcurses -ltermlib
OTHERLIBS=
# Use some variant of this one if you #define MMDF in config.h
#OTHERLIBS=/usr/src/mmdf/lib/libmmdf.a
X
mush: $(OBJS)
X @echo loading...
X @cc $(LDFLAGS) $(OBJS) $(LIBES) $(OTHERLIBS) -o mush
X
$(OBJS): config.h mush.h
loop.o: version.h
X
# For 80286 machines, use these two lines...
# misc.o: misc.c
# cc $(CFLAGS) -LARGE -c misc.c
X
bind.o: bind.c
X cc $(CFLAGS) -LARGE -c bind.c
X
clean:
X rm -f *.o core mush
X
BINDIR= /usr/local/bin
LIBDIR= /usr/local/lib
MRCDIR= /usr/lib
MANDIR= /usr/local/man/man1
MANEXT= 1
X
install: mush
X cp mush $(BINDIR)
X strip $(BINDIR)/mush
X chmod 0755 $(BINDIR)/mush
X cp mush.1 $(MANDIR)/mush.$(MANEXT)
X chmod 0644 $(MANDIR)/mush.$(MANEXT)
X cp cmd_help $(LIBDIR)
X chmod 0644 $(LIBDIR)/cmd_help
X cp Mushrc $(MRCDIR)/Mushrc
X chmod 0644 $(MRCDIR)/Mushrc
SHAR_EOF
chmod 0644 makefile.xenix ||
echo 'restore of makefile.xenix failed'
Wc_c="`wc -c < 'makefile.xenix'`"
test 2293 -eq "$Wc_c" ||
echo 'makefile.xenix: original size 2293, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= malloc.c ==============
if test -f 'malloc.c' -a X"$1" != X"-c"; then
echo 'x - skipping malloc.c (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting malloc.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'malloc.c' &&
/*
X * This is a slightly modified version of the malloc.c distributed with
X * Larry Wall's perl 2.0 sources. RCS and sccs information has been
X * retained, but modified so that it will not actually affect checkin
X * or checkout of this file if revision control is used for Mush.
X *
X * Other changes include:
X * Removal of the ASSERT macro and other code related to the
X * preprocessor definition "debug"
X *
X * Replaced #include "perl.h" with #include "mush.h" (guess why)
X *
X * Warning messages are now printed with the mush Debug macro,
X * that is, they are normally suppressed
X *
X * Added a calloc() function, using mush's bzero()
X *
X * Also, the mush xfree() and free_vec() functions have been moved here.
X */
X
#include "mush.h"
X
/*
X * Compile this portion only if configured for INTERNAL_MALLOC
X */
#ifdef INTERNAL_MALLOC
#ifdef SYSV
#include <memory.h>
#define bcopy(src,dst,len) memcpy(dst,src,len)
#endif /* SYSV */
#define free xfree /* rename free for mush purposes */
X
/* Begin modified perl malloc.c */
X
/* Header: malloc.c,v 2.0 88/06/05 00:09:16 root Exp
X *
X * Log: malloc.c,v
X * Revision 2.0 88/06/05 00:09:16 root
X * Baseline version 2.0.
X *
X */
X
#ifndef lint
static char sccsid[] = "malloc.c 4.3 (Berkeley) 9/16/83";
#endif /* !lint */
X
#define RCHECK
/*
X * malloc.c (Caltech) 2/21/82
X * Chris Kingsley, kingsley@cit-20.
X *
X * This is a very fast storage allocator. It allocates blocks of a small
X * number of different sizes, and keeps free lists of each size. Blocks that
X * don't exactly fit are passed up to the next larger size. In this
X * implementation, the available sizes are 2^n-4 (or 2^n-12) bytes long.
X * This is designed for use in a program that uses vast quantities of memory,
X * but bombs when it runs out.
X */
X
/* I don't much care whether these are defined in sys/types.h--LAW */
X
#undef u_char
#define u_char unsigned char
#undef u_int
#define u_int unsigned int
#undef u_short
#define u_short unsigned short
X
/*
X * The overhead on a block is at least 4 bytes. When free, this space
X * contains a pointer to the next free block, and the bottom two bits must
X * be zero. When in use, the first byte is set to MAGIC, and the second
X * byte is the size index. The remaining bytes are for alignment.
X * If range checking is enabled and the size of the block fits
X * in two bytes, then the top two bytes hold the size of the requested block
X * plus the range checking words, and the header word MINUS ONE.
X */
union overhead {
X union overhead *ov_next; /* when free */
X struct {
X u_char ovu_magic; /* magic number */
X u_char ovu_index; /* bucket # */
#ifdef RCHECK
X u_short ovu_size; /* actual block size */
X u_int ovu_rmagic; /* range magic number */
#endif /* RCHECK */
X } ovu;
#define ov_magic ovu.ovu_magic
#define ov_index ovu.ovu_index
#define ov_size ovu.ovu_size
#define ov_rmagic ovu.ovu_rmagic
};
X
#define MAGIC 0xff /* magic # on accounting info */
#define OLDMAGIC 0x7f /* same after a free() */
#define RMAGIC 0x55555555 /* magic # on range info */
#ifdef RCHECK
#define RSLOP sizeof (u_int)
#else /* !RCHECK */
#define RSLOP 0
#endif /* RCHECK */
X
/*
X * nextf[i] is the pointer to the next free block of size 2^(i+3). The
X * smallest allocatable block is 8 bytes. The overhead information
X * precedes the data area returned to the user.
X */
#define NBUCKETS 30
static union overhead *nextf[NBUCKETS];
extern char *sbrk();
X
#ifdef MSTATS
/*
X * nmalloc[i] is the difference between the number of mallocs and frees
X * for a given block size.
X */
static u_int nmalloc[NBUCKETS];
#endif /* MSTATS */
X
char *
malloc(nbytes)
X register unsigned nbytes;
{
X register union overhead *p;
X register int bucket = 0;
X register unsigned shiftr;
X
X if (nbytes == 0)
X return NULL;
X /*
X * Convert amount of memory requested into
X * closest block size stored in hash buckets
X * which satisfies request. Account for
X * space used per block for accounting.
X */
X nbytes += sizeof (union overhead) + RSLOP;
X nbytes = (nbytes + 3) &~ 3;
X shiftr = (nbytes - 1) >> 2;
X /* apart from this loop, this is O(1) */
X while (shiftr >>= 1)
X bucket++;
X /*
X * If nothing in hash bucket right now,
X * request more memory from the system.
X */
X if (nextf[bucket] == (union overhead *)0)
X morecore(bucket);
X if ((p = (union overhead *)nextf[bucket]) == (union overhead *)0)
X return (NULL);
X /* remove from linked list */
X if (*((int*)p) > 0x10000000)
X Debug("Corrupt malloc ptr 0x%x at 0x%x\n",*((int*)p),p);
X nextf[bucket] = nextf[bucket]->ov_next;
X p->ov_magic = MAGIC;
X p->ov_index= bucket;
#ifdef MSTATS
X nmalloc[bucket]++;
#endif /* MSTATS */
#ifdef RCHECK
X /*
X * Record allocated size of block and
X * bound space with magic numbers.
X */
X if (nbytes <= 0x10000)
X p->ov_size = nbytes - 1;
X p->ov_rmagic = RMAGIC;
X *((u_int *)((caddr_t)p + nbytes - RSLOP)) = RMAGIC;
#endif /* RCHECK */
X return ((char *)(p + 1));
}
X
/*
X * Allocate more memory to the indicated bucket.
X */
static
morecore(bucket)
X register bucket;
{
X register union overhead *op;
X register int rnu; /* 2^rnu bytes will be requested */
X register int nblks; /* become nblks blocks of the desired size */
X register int siz;
X
X if (nextf[bucket])
X return;
X /*
X * Insure memory is allocated
X * on a page boundary. Should
X * make getpageize call?
X */
X op = (union overhead *)sbrk(0);
X if ((long)op & 0x3ff)
X sbrk(1024 - ((long)op & 0x3ff));
X /* take 2k unless the block is bigger than that */
X rnu = (bucket <= 8) ? 11 : bucket + 3;
X nblks = 1 << (rnu - (bucket + 3)); /* how many blocks to get */
X if (rnu < bucket)
X rnu = bucket;
X op = (union overhead *)sbrk(1 << rnu);
X /* no more room! */
X if ((long)op == -1)
X return;
X /*
X * Round up to minimum allocation size boundary
X * and deduct from block count to reflect.
X */
X if ((long)op & 7) {
X op = (union overhead *)(((long)op + 8) &~ 7);
X nblks--;
X }
X /*
X * Add new memory allocated to that on
X * free list for this hash bucket.
X */
X nextf[bucket] = op;
X siz = 1 << (bucket + 3);
X while (--nblks > 0) {
X op->ov_next = (union overhead *)((caddr_t)op + siz);
X op = (union overhead *)((caddr_t)op + siz);
X }
}
X
void
free(cp)
X char *cp;
{
X register int size;
X register union overhead *op;
X
X if (cp == NULL || debug > 4)
X return;
X op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
X if (op->ov_magic != MAGIC) {
X Debug("%s free() ignored\n",
X op->ov_magic == OLDMAGIC ? "Duplicate" : "Bad");
X return; /* sanity */
X }
X op->ov_magic = OLDMAGIC;
#ifdef RCHECK
X if (op->ov_rmagic != RMAGIC) {
X Debug("Range check failed, free() ignored\n");
X return;
X }
X if (op->ov_index <= 13 &&
X *(u_int *)((caddr_t)op + op->ov_size + 1 - RSLOP) != RMAGIC) {
X Debug("Range check failed, free() ignored\n");
X return;
X }
#endif /* RCHECK */
X if (op->ov_index >= NBUCKETS)
X return;
X size = op->ov_index;
X op->ov_next = nextf[size];
X nextf[size] = op;
#ifdef MSTATS
X nmalloc[size]--;
#endif /* MSTATS */
}
X
/*
X * When a program attempts "storage compaction" as mentioned in the
X * old malloc man page, it realloc's an already freed block. Usually
X * this is the last block it freed; occasionally it might be farther
X * back. We have to search all the free lists for the block in order
X * to determine its bucket: 1st we make one pass thru the lists
X * checking only the first block in each; if that fails we search
X * ``reall_srchlen'' blocks in each list for a match (the variable
X * is extern so the caller can modify it). If that fails we just copy
X * however many bytes was given to realloc() and hope it's not huge.
X */
int reall_srchlen = 4; /* 4 should be plenty, -1 =>'s whole list */
X
char *
realloc(cp, nbytes)
X char *cp;
X unsigned nbytes;
{
X register u_int onb;
X union overhead *op;
X char *res;
X register int i;
X int was_alloced = 0;
X
X if (cp == NULL)
X return (malloc(nbytes));
X op = (union overhead *)((caddr_t)cp - sizeof (union overhead));
X if (op->ov_magic == MAGIC) {
X was_alloced++;
X i = op->ov_index;
X } else {
X /*
X * Already free, doing "compaction".
X *
X * Search for the old block of memory on the
X * free list. First, check the most common
X * case (last element free'd), then (this failing)
X * the last ``reall_srchlen'' items free'd.
X * If all lookups fail, then assume the size of
X * the memory block being realloc'd is the
X * smallest possible.
X */
X if ((i = findbucket(op, 1)) < 0 &&
X (i = findbucket(op, reall_srchlen)) < 0)
X i = 0;
X }
X onb = (1 << (i + 3)) - sizeof (*op) - RSLOP;
#ifdef RCHECK
X /* There's something wrong with the "onb" size computation, above,
X * when RCHECK is defined. If you see this comment and can figure
X * out exactly how "onb" is being used here, let me know. Bart.
X */
X if (was_alloced) {
X free(cp); /* Hack so there's some chance res == cp */
X was_alloced = 0;
X }
#else /* RCHECK */
X /* avoid the copy if same size block */
X if (was_alloced &&
X nbytes <= onb && nbytes > (onb >> 1) - sizeof(*op) - RSLOP)
X return(cp);
#endif /* RCHECK */
X if ((res = malloc(nbytes)) == NULL)
X return (NULL);
X if (cp != res) /* common optimization */
X bcopy(cp, res, (nbytes < onb) ? nbytes : onb);
X if (was_alloced)
X free(cp);
X return (res);
}
X
/*
X * Search ``srchlen'' elements of each free list for a block whose
X * header starts at ``freep''. If srchlen is -1 search the whole list.
X * Return bucket number, or -1 if not found.
X */
static
findbucket(freep, srchlen)
X union overhead *freep;
X int srchlen;
{
X register union overhead *p;
X register int i, j;
X
X for (i = 0; i < NBUCKETS; i++) {
X j = 0;
X for (p = nextf[i]; p && j != srchlen; p = p->ov_next) {
X if (p == freep)
X return (i);
X j++;
X }
X }
X return (-1);
}
X
#ifdef MSTATS
/*
X * mstats - print out statistics about malloc
X *
X * Prints two lines of numbers, one showing the length of the free list
X * for each size category, the second showing the number of mallocs -
X * frees for each size category.
X */
mstats(s)
X char *s;
{
X register int i, j;
X register union overhead *p;
X int totfree = 0,
X totused = 0;
X
X Debug("Memory allocation statistics %s\nfree:\t", s);
X for (i = 0; i < NBUCKETS; i++) {
X for (j = 0, p = nextf[i]; p; p = p->ov_next, j++)
X ;
X Debug(" %d", j);
X totfree += j * (1 << (i + 3));
X }
X Debug("\nused:\t");
X for (i = 0; i < NBUCKETS; i++) {
X Debug( " %d", nmalloc[i]);
X totused += nmalloc[i] * (1 << (i + 3));
X }
X Debug("\n\tTotal in use: %d, total free: %d\n",
X totused, totfree);
}
#endif /* MSTATS */
X
/* End of modified perl malloc.c */
X
char *
calloc(nitems, itemsz)
u_int nitems, itemsz;
{
X char *cp;
X
X cp = malloc(nitems * itemsz);
X bzero(cp, nitems * itemsz);
X return cp;
}
X
/* These are needed for curses and other external linkage */
X
#undef free
X
char *
cfree(p, n, s)
char *p;
u_int n, s;
{
X xfree(p);
X return NULL;
}
X
char *
free(p)
char *p;
{
X xfree(p);
X return NULL;
}
X
#else /* INTERNAL_MALLOC */
X
char *stackbottom; /* set first thing in main() */
X
void
xfree(cp)
char *cp;
{
X extern char end[];
X
X if (cp && cp >= end && cp < stackbottom && cp < (char *) &cp && debug < 5)
X free(cp);
}
X
#endif /* INTERNAL_MALLOC */
X
void
free_elems(argv)
char **argv;
{
X register int n;
X
X if (!argv)
X return;
X for (n = 0; argv[n]; n++)
X xfree(argv[n]);
}
X
void
free_vec(argv)
char **argv;
{
X free_elems(argv);
X xfree((char *)argv);
}
SHAR_EOF
chmod 0600 malloc.c ||
echo 'restore of malloc.c failed'
Wc_c="`wc -c < 'malloc.c'`"
test 11289 -eq "$Wc_c" ||
echo 'malloc.c: original size 11289, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= misc.c ==============
if test -f 'misc.c' -a X"$1" != X"-c"; then
echo 'x - skipping misc.c (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting misc.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'misc.c' &&
/* @(#)misc.c (c) copyright 10/18/86 (Dan Heller) */
X
#include "mush.h"
X
/* check to see if a string describes a message that is within the range of
X * all messages; if invalid, return 0 and print error. else return msg number
X */
chk_msg(s)
register char *s;
{
X register int n;
X
X if ((n = atoi(s)) > 0 && n <= msg_cnt)
X return n;
X else if (*s == '^' && msg_cnt)
X return 1;
X else if (*s == '$' && msg_cnt)
X return msg_cnt;
X else if (*s == '.' && msg_cnt)
X return current_msg+1;
X print("Invalid message number: %s\n", s);
X return 0;
}
X
/*
X * loop thru all msgs starting with current_msg and find next undeleted and
X * unsaved message. If the variable "wrap" is set, wrap to the beginning of
X * the message list if we hit the end. otherwise, stop at the end of the list.
X */
next_msg()
{
X register int n = current_msg;
X register int wrap = !!do_set(set_options, "wrap") ||
X istool && !do_set(set_options, "show_deleted");
X
X if (!msg_cnt)
X return current_msg = 0;
X for (n++; n != current_msg; n++)
X if (n == msg_cnt) /* hit the end, start back at the beginning */
X if (!wrap)
X return current_msg;
X else
X n = -1; /* increments to 0 in loop */
X else if (isoff(msg[n].m_flags, DELETE) &&
X isoff(msg[n].m_flags, SAVED))
X return current_msg = n;
X return current_msg = 0;
}
X
/* since print_help just prints help, always return help() */
print_help(argc, argv)
register char **argv;
{
X int about = (argv && *argv && **argv == 'a');
X
X if (!argc || !*++argv)
X return help(0, about? "about": "general", cmd_help);
X if (argv[0][0] == '-')
X return help(0, about? "about": "help", cmd_help);
X return help(0, *argv, cmd_help);
}
X
/* since this function does not affect messages, return -1 */
/*ARGSUSED*/
help(unused, str, file)
char *str, *file;
{
X register char *p, **text = (char **)str;
X char buf[BUFSIZ], help_str[32];
X FILE *fp;
X
X /* If no file given, take "str" arg as message to print */
X if (!file || !*file) {
#ifdef SUNTOOL
#ifdef SUN_4_0 /* SunOS 4.0+ */
X /* SunOS 3.5 doesn't have enough file descriptors */
X turnon(glob_flags, NEW_FRAME);
#endif /* SUN_4_0 */
X strdup(more_prompt, "help");
#endif /* SUNTOOL */
X /* use the pager on the args to the function */
X (void) do_pager(NULL, TRUE);
X while (*text) {
X (void) do_pager(*text++, FALSE);
X if (do_pager("\n", FALSE) == EOF)
X break;
X }
X (void) do_pager(NULL, FALSE);
X return 0;
X } else {
X int d = 0;
X if ((p = getpath(file, &d)) && d == 0) {
X if (!(fp = fopen(p, "r"))) {
X print("Cannot open help file \"%s\".\n", p);
X return -1;
X }
X } else {
X if (d < 0)
X print("Cannot open help file \"%s\": %s\n", file, p);
X else
X print("Help file \"%s\" is a directory?!?\n", p);
X return -1;
X }
X }
X
X /* look for %str% in helpfile */
X (void) sprintf(help_str, "%%%s%%\n", str);
X
X while (p = fgets(buf, sizeof buf, fp))
X if (*p == '%' && !strcmp(p, help_str))
X break;
X if (!p)
X print("There is no help found for \"%s\".\n", (char *)str);
X else {
#ifdef SUNTOOL
#ifdef SUN_4_0 /* SunOS 4.0+ */
X /* SunOS 3.5 doesn't have enough file descriptors */
X turnon(glob_flags, NEW_FRAME);
#endif /* SUN_4_0 */
X strdup(more_prompt, sprintf(buf, "%s help", (char *)str));
#endif /* SUNTOOL */
X (void) do_pager(NULL, TRUE);
X while ((p = fgets(buf, sizeof buf, fp)) && strcmp(p, "%%\n"))
X if (do_pager(buf, FALSE) == EOF)
X break;
X (void) do_pager(NULL, FALSE);
X }
X (void) fclose(fp);
X
X return 0;
}
X
/* return -1 on error or number of arguments in argv that were parsed */
get_msg_list(argv, list)
register char **argv;
char list[];
{
X register char *p2, *p, *end, ch;
X char buf[BUFSIZ];
X register int n;
X
X if (!msg_cnt) {
X print("No messages.\n");
X return -1;
X }
X if (!argv || !*argv) {
X if (isoff(glob_flags, IS_PIPE))
X set_msg_bit(list, current_msg);
X return 0;
X }
X /* first, stuff argv's args into a single char array buffer */
X (void) argv_to_string(buf, argv);
X p = buf;
X
X Debug("get_msg_list: parsing: (%s): ", p);
X /* find the end of the message list */
X skipmsglist(0);
X end = p;
X while (*end && end != buf && !isspace(*end))
X --end;
X ch = *end, *end = '\0'; /* temporarily plug with nul */
X p = buf; /* reset to the beginning */
X /*
X * if do_range returns NULL, an invalid message was specified
X */
X if (!(p2 = do_range(p, list))) {
X *end = ch; /* just in case */
X return -1;
X }
X /*
X * if p2 == p (and p isn't $ or ^ or .), then no message list was
X * specified. set the current message in such cases if we're not piping
X */
X if (p2 == p) {
X if (*p == '$')
X set_msg_bit(list, msg_cnt-1);
X else if (*p == '^')
X set_msg_bit(list, 0);
X else if (*p == '.' || isoff(glob_flags, IS_PIPE))
X set_msg_bit(list, current_msg);
X }
X for (n = 0; p2 > p && *argv; n++)
X p2 -= (strlen(*argv++)+1);
X Debug("parsed %d args\n", n);
X *end = ch;
X return n;
}
X
/*
X * execute a command from a string. f'rinstance: "pick -f foobar"
X * The string is made into an argv and then run. Errors are printed
X * if the command failed to make.
X * NOTES:
X * NEVER pass straight text: e.g. "pick -f foobar", ALWAYS strcpy(buf, "...")
X * no history is expanded (ignore_bang).
X */
cmd_line(buf, list)
char buf[], list[];
{
X register char **argv;
X int argc, ret_val = -1;
X u_long save_do_pipe = ison(glob_flags, DO_PIPE);
X u_long save_is_pipe = ison(glob_flags, IS_PIPE);
X char dummy_list[MAXMSGS_BITS];
X
X turnoff(glob_flags, DO_PIPE);
X turnoff(glob_flags, IS_PIPE);
X if (argv = make_command(buf, TRPL_NULL, &argc))
X ret_val = do_command(argc, argv, list? list : dummy_list);
X if (save_do_pipe)
X turnon(glob_flags, DO_PIPE);
X else
X turnoff(glob_flags, DO_PIPE);
X if (save_is_pipe)
X turnon(glob_flags, IS_PIPE);
X else
X turnoff(glob_flags, IS_PIPE);
X return ret_val;
}
X
glob_test(s)
char *s;
{
X print("%s: glob_flags =", s);
X if (ison(glob_flags, DO_UPDATE))
X print_more(" DO_UPDATE");
X if (ison(glob_flags, REV_VIDEO))
X print_more(" REV_VIDEO");
X if (ison(glob_flags, CONT_PRNT))
X print_more(" CONT_PRNT");
X if (ison(glob_flags, DO_SHELL))
X print_more(" DO_SHELL");
X if (ison(glob_flags, DO_PIPE))
X print_more(" DO_PIPE");
X if (ison(glob_flags, IS_PIPE))
X print_more(" IS_PIPE");
X if (ison(glob_flags, IGN_SIGS))
X print_more(" IGN_SIGS");
X if (ison(glob_flags, IGN_BANG))
X print_more(" IGN_BANG");
X if (ison(glob_flags, ECHO_FLAG))
X print_more(" ECHO_FLAG");
X if (ison(glob_flags, IS_GETTING))
X print_more(" IS_GETTING");
X if (ison(glob_flags, PRE_CURSES))
X print_more(" PRE_CURSES");
X if (ison(glob_flags, READ_ONLY))
X print_more(" READ_ONLY");
X if (ison(glob_flags, REDIRECT))
X print_more(" REDIRECT");
X if (ison(glob_flags, WAS_INTR))
X print_more(" WAS_INTR");
X if (ison(glob_flags, WARNING))
X print_more(" WARNING");
X if (ison(glob_flags, NEW_MAIL))
X print_more(" NEW_MAIL");
X if (ison(glob_flags, CNTD_CMD))
X print_more(" CNTD_CMD");
X if (ison(glob_flags, IS_SENDING))
X print_more(" IS_SENDING");
X if (ison(glob_flags, MIL_TIME))
X print_more(" MIL_TIME");
X if (ison(glob_flags, DATE_RECV))
X print_more(" DATE_RECV");
X if (ison(glob_flags, IN_MACRO))
X print_more(" IN_MACRO");
X if (ison(glob_flags, LINE_MACRO))
X print_more(" LINE_MACRO");
X if (ison(glob_flags, QUOTE_MACRO))
X print_more(" QUOTE_MACRO");
X print_more("\n");
}
X
/*
X * Change the status flags for messages.
X * flags +r add the replied-to flag to the current message.
X * flags -S 4-7 remove the "saved" status on msgs 4-7
X * flags P * preserves all messages.
X * The + implies: add this flag to the current message's flag bits
X * The - implies: delete this flag to the current message's flag bits
X * No + or - implies that the msg's flag bits are set explicitly.
X * Marks and priorities are preserved in the m_flags field despite
X * what we're doing here. Thus, other actions taken by this function
X * do not affect marks and priorities.
X */
msg_flags(c, v, list)
register char **v, *list;
{
X register int i = 0, modify = 0, had_list = 0;
X register u_long newflag = 0;
X char sent[32], recv[32];
X
X while (v && *v && *++v)
X for (c = 0; v && v[0] && v[0][c]; c++)
X switch (lower(v[0][c])) {
X case '?' : return help(0, "msg_flags", cmd_help);
X case 'n' : turnon(newflag, UNREAD), turnoff(newflag, OLD);
X when 'd' : turnon(newflag, DELETE);
X when 'p' :
X if (v[0][c] == 'P')
X turnon(newflag, PRESERVE);
X else
X turnon(newflag, PRINTED);
X when 's' : turnon(newflag, SAVED);
X when 'u' : turnon(newflag, UNREAD); /* fall thru! */
X case 'o' : turnon(newflag, OLD);
X when 'r' :
X if (v[0][c] == 'R')
X turnoff(newflag, UNREAD), turnon(newflag, OLD);
X else
X turnon(newflag, REPLIED);
X when 'f' : turnon(newflag, FORWARD);
X when '+' : modify = 1;
X when '-' : modify = 2;
X when '\\' : ; /* skip to the next flag */
X otherwise:
X if ((i = get_msg_list(v, list)) <= 0) {
X print("Unknown flag: %c. Use flags -? for help\n",
X v[0][c]);
X return -1;
X } else {
X /* advance argv passed the msg-list */
X v += i;
X /* c will get ++'ed, so it should be 0 */
X c = -1;
X /* record that we have seen a message list */
X had_list = 1;
X }
X }
X
X /* If we haven't got a msglist, use current_msg */
X if (had_list == 0 && isoff(glob_flags, IS_PIPE))
X set_msg_bit(list, current_msg);
X
X for (i = 0; i < msg_cnt; i++) {
X if (!msg_bit(list, i))
X continue;
X else if (!newflag) {
X wprint("msg %d: offset: %d, lines: %d, bytes: %d, flags:", i+1,
X msg[i].m_offset, msg[i].m_lines, msg[i].m_size);
X if (ison(msg[i].m_flags, UNREAD))
X wprint(" UNREAD");
X if (ison(msg[i].m_flags, OLD))
X wprint(" OLD");
X if (ison(msg[i].m_flags, DELETE))
X wprint(" DELETE");
X if (ison(msg[i].m_flags, PRESERVE))
X wprint(" PRESERVE");
X if (ison(msg[i].m_flags, REPLIED))
X wprint(" REPLIED");
X if (ison(msg[i].m_flags, SAVED))
X wprint(" SAVED");
X if (ison(msg[i].m_flags, PRINTED))
X wprint(" PRINTED");
X if (ison(msg[i].m_flags, FORWARD))
X wprint(" FORWARD");
X if (ison(msg[i].m_flags, UPDATE_STATUS))
X wprint(" UPDATE_STATUS");
X for (modify = MAX_PRIORITY; modify > 0; modify--)
X if (ison(msg[i].m_flags, M_PRIORITY(modify)))
X wprint(" %c", 'A' + modify - 1);
X (void) strcpy(sent, date_to_ctime(msg[i].m_date_sent));
X (void) strcpy(recv, date_to_ctime(msg[i].m_date_recv));
X wprint("\n\tsent: %s\trecv: %s", sent, recv);
X } else {
X u_long save_priority = 0L;
X if (modify == 0) {
X int j;
X for (j = 0; j < MAX_PRIORITY; j++)
X if (ison(msg[i].m_flags, M_PRIORITY(j)))
X turnon(save_priority, M_PRIORITY(j));
X }
X switch (modify) {
X case 0: msg[i].m_flags = newflag;
X when 1: msg[i].m_flags |= newflag;
X when 2: msg[i].m_flags &= ~newflag;
X }
X if (save_priority)
X msg[i].m_flags |= save_priority;
X if (isoff(glob_flags, READ_ONLY)) {
X turnon(glob_flags, DO_UPDATE);
X turnon(msg[i].m_flags, DO_UPDATE);
X }
X }
X }
X return 0;
}
X
/*
X * Internal pager. Start the internal pager by passing the name of
X * the pager in buf and passing TRUE as start_pager. If the internal
X * pager is desired, pass NULL as buf. Continue paging by passing
X * FALSE as start_pager and the buf is the stuff to pass thru to the
X * pager. End paging by passing NULL as buf and FALSE as start_pager.
X * start_pager actually has a ternary value -- for use by pipe_msg.
X * If the pager can't be used, or is null, we're paging ourselves.
X * Windows does nothing but echo buf to the msg window (this will change).
X * The "buf" passed to the pager should be a line at a time so as to
X * count \n's. If there is more than one newline, the first one is nulled
X * and the next line done by calling do_pager recursively. WARNING: because
X * "buf" is changed, it is *illegal* for anyone calling this routine to pass
X * _constant_ strings --they should be strcpy'ed or sprintf'ed into a temp
X * buff before passing to this routine! Otherwise, ANSI-C compilers will
X * core dump. This is because constant strings are read-only.
X * Return EOF if pager died, user exited pager, or if user types 'q'
X * at the --more-- prompt for the internal pager.
X *
X * For windows, copy all the info into a tmpfile and set the pager_textsw
X * to that file. When the pager ends, delete the file -- textsw will
X * continue to read it since it does its own buffering.
X */
do_pager(buf, start_pager)
char *buf;
{
X static FILE *pp;
X static int cnt, len;
X static u_long save_echo_flag;
#ifdef SUNTOOL
X static char file[MAXPATHLEN];
X static Textsw sw;
X
X /* pipe_msg will pass -1 for start_pager to avoid this block */
X if (start_pager > -1 && istool) {
X if (buf && !start_pager) {
X if (istool < 2) /* can't use windows yet -- send to stdout */
X (void) fputs(buf, stdout);
X else {
X if (pp)
X fputs(buf, pp);
X else
X textsw_insert(isoff(glob_flags, NEW_FRAME)?
X pager_textsw : sw, buf, strlen(buf));
X }
X } else if (istool >= 2 && start_pager) {
X Frame text_frame;
X extern char *more_prompt;
X char *p;
X
X timeout_cursors(TRUE);
X if (ison(glob_flags, NEW_FRAME)) {
X char *crt_win = do_set(set_options, "crt_win");
X text_frame = window_create(tool, FRAME,
X FRAME_SHOW_LABEL, TRUE,
X FRAME_LABEL, more_prompt,
X WIN_HEIGHT, l_height()*(crt_win? atoi(crt_win):12),
X NULL);
X sw = window_create(text_frame, TEXTSW,
X TEXTSW_LINE_BREAK_ACTION, TEXTSW_WRAP_AT_CHAR,
X TEXTSW_CLIENT_DATA, text_frame,
X NULL);
X notify_interpose_event_func(sw, scroll_textwin, NOTIFY_SAFE);
X } else
X textsw_reset(pager_textsw, 0, 0);
X
X /* find a free tmpfile */
X if (!(p = getdir(do_set(set_options, "tmpdir"))))
alted:
X p = ALTERNATE_HOME;
X {
X int pid = getpid();
X do
X sprintf(file, "%s/..X%d", p, pid++);
X while (!Access(file, F_OK));
X }
X if (!(pp = mask_fopen(file, "w"))) {
X if (strcmp(p, ALTERNATE_HOME))
X goto alted;
X error("Can't create '%s'", tempfile);
X }
X return 0;
X } else if (!buf && !start_pager) { /* pager is done */
X if (pp)
X (void) fclose(pp);
X window_set(isoff(glob_flags, NEW_FRAME)? pager_textsw : sw,
X TEXTSW_FILE, file,
X TEXTSW_READ_ONLY, TRUE,
X TEXTSW_UPDATE_SCROLLBAR,
X NULL);
X if (ison(glob_flags, NEW_FRAME)) {
X turnoff(glob_flags, NEW_FRAME);
X window_set(window_get(sw, TEXTSW_CLIENT_DATA),
X WIN_SHOW, TRUE,
X FRAME_NO_CONFIRM, TRUE,
X FRAME_DONE_PROC, window_destroy,
X NULL);
X }
X if (unlink(file) == -1)
X error("Cannot unlink %s", file);
X timeout_cursors(FALSE);
X }
X return 0;
X }
#endif /* SUNTOOL */
X
X if (start_pager) {
X turnon(glob_flags, IGN_SIGS);
X if (!buf) {
X /* internal pager */
X save_echo_flag = ison(glob_flags, ECHO_FLAG);
X pp = stdout;
X if (save_echo_flag) {
X turnoff(glob_flags, ECHO_FLAG);
X echo_off();
X }
X } else {
X echo_on();
X if (!(pp = popen(buf, "w")))
X error(buf);
X }
X cnt = len = 0;
X } else if (!buf) {
X if (pp && pp != stdout)
X (void) pclose(pp);
X pp = NULL_FILE;
X if (save_echo_flag) {
X echo_on();
X turnon(glob_flags, ECHO_FLAG);
X } else
X echo_off();
X turnoff(glob_flags, IGN_SIGS);
X } else if (pp != stdout)
X return fputs(buf, pp); /* returns EOF if user exited pager */
X else {
X register char c = 0, *cr = index(buf, '\n');
X len += strlen(buf);
X if (cr) {
X int maxlen =
#ifdef CURSES
X iscurses ? COLS :
#endif /* CURSES */
X 80;
X if (len > maxlen)
X cnt += len / maxlen;
X len = 0;
X }
X if (cr && (c = *++cr) != '\0')
X *cr = 0; /* send one line to stdout and prompt for more */
X (void) fputs(buf, pp);
X if (cr && (++cnt / (crt-1))) {
X int n = c_more(NULL);
X if (n == '\n' || n == '\r')
X cnt--; /* go line by line */
X else if (n == CTRL('D') || lower(n) == 'd' || n < 0) {
X clearerr(stdin);
X cnt = ((crt-1)/2);
X } else if (lower(n) == 'q')
X /* could check if "c" is set, but... see warning above */
X return EOF;
X else
X cnt = 1;
X }
X if (c) {
X *cr = c;
X return do_pager(cr, FALSE);
X }
X }
X return 0;
}
X
/* curses based "more" like option */
c_more(p)
register char *p;
{
X register int c;
X
X if (!p)
X p = "--more--";
X print_more(p);
X
X while ((c = getchar()) >= 0 && c != CTRL('D') && !isspace(c) &&
X c != '\n' && c != '\r' && lower(c) != 'q' && lower(c) != 'd')
X bell();
X if (ison(glob_flags, ECHO_FLAG) && c != '\n' && c != '\r')
X while (getchar() != '\n');
X (void) printf("\r%*c\r", strlen(p), ' '); /* remove the prompt */
X (void) fflush(stdout);
X return c;
}
X
/*
X * Your "signature" is of the type:
X * file_or_path
X * $variable
X * \ literal string preceded by a backslash.
X * The variable will be expanded into its string value.
X * To sign the letter, the list of addresses is passed to this routine
X * (separated by whitespace and/or commas). No comment fields!
X *
X * If "autosign2" is set, then it must be of the form:
X * autosign2 = "*user user !host !some!path @dom.ain: ~/.sign2"
X *
X * The colon terminates the user/host lists from the "signature" to the right.
X *
X * Whitespace or commas separate tokens. If everyone on the list exists in
X * the autosign2 list, the alternate signature is used. In case of syntax
X * error, the alternate signature is used without checks (e.g. if the colon
X * is missing). The alternate signature == null is the same as not signing
X * the letter. An empty list forces signature2.
X *
X * If autosign2 is not set at all, then autosign is checked and used.
X * autosign = <signature>
X */
void
sign_letter(list, flags, fp)
register char *list; /* list of addresses -- no comment fields */
u_long flags;
FILE *fp;
{
X char buf[MAXPATHLEN], *signature;
X register char *p = NULL;
X FILE *pp2;
X int lines = 0, noisy;
X
X if (!list)
X return;
X while (isspace(*list))
X list++;
X if (!*list)
X return;
X if (ison(flags, SIGN)) {
X noisy = !chk_option("quiet", "autosign");
X if (!(p = do_set(set_options, "autosign2")))
X buf[0] = 0;
X else {
X if (!(signature = index(p, ':')))
X (void) strcpy(buf, p); /* No colon; use entire string as sig */
X else {
X int ret_val = 0;
X *signature = 0;
X /* p now points to a list of addresses and p2 points to the
X * signature format to use. Check that each address in the list
X * provided (parameter) matches the "addrs" in autosign2.
X */
X skipspaces(0);
X if (!*p)
X /* autosign2 = " : <signature>" send to all recipients */
X ret_val = 1;
X else if (p = alias_to_address(p)) {
X rm_cmts_in_addr(p);
X ret_val = compare_addrs(list, p, NULL);
X }
X *signature++ = ':'; /* must reset first! */
X buf[0] = 0;
X if (ret_val) {
X while (isspace(*signature))
X signature++;
X /* Null signatures don't sign anything. */
X if (!*strcpy(buf, signature))
X return;
X }
X }
X }
X if (!buf[0]) {
X if (!(p = do_set(set_options, "autosign")) || !*p) {
X char *home;
X if (!(home = do_set(set_options, "home")) || !*home)
X home = ALTERNATE_HOME;
X (void) sprintf(buf, "%s/%s", home, SIGNATURE);
X } else
X (void) strcpy(buf, p);
X if (noisy)
X wprint("Signing letter... ");
X } else if (noisy)
X wprint("Using alternate signature... ");
X (void) fseek(fp, 0L, 2); /* guarantee position at end of file */
X (void) fputc('\n', fp);
X (void) fflush(fp);
X if (*buf == '$')
X if (!(p = do_set(set_options, buf)))
X wprint("(%s isn't set -- letter not signed)\n", buf);
X else {
X putstring(p+1, fp);
X if (noisy)
X wprint("\n");
X }
X else if (*buf == '\\') {
X putstring(buf, fp);
X if (noisy)
X wprint("\n");
X } else if (*buf == '[') {
X char *rbr = index(buf, ']');
X if (rbr)
X *rbr = 0;
X putstring(buf + 1, fp);
X if (noisy)
X wprint("\n");
X } else if (*buf == '|' || *buf == '!') {
X (void) strcat(buf, " ");
X (void) strcat(buf, list);
X if (!(pp2 = popen(buf+1, "r")))
X error(buf+1);
X else {
X turnon(glob_flags, IGN_SIGS);
X while (fgets(buf, sizeof(buf), pp2)) {
X int len = strlen(buf);
X (void) fputs(buf, fp), lines++;
X if (len < sizeof buf - 1 && buf[len - 1] != '\n')
X (void) fputc('\n', fp);
X }
X (void) pclose(pp2);
X (void) fflush(fp);
X turnoff(glob_flags, IGN_SIGS);
X if (noisy)
X wprint("added %d line%s\n", lines, lines == 1? "" : "s");
X }
X } else {
X /* precede _file_ signatures ONLY with "-- \n" */
X (void) fputs("-- \n", fp);
X (void) fflush(fp);
X (void) file_to_fp(buf, fp, "r");
X }
X }
X
X (void) fflush(stdout); /* for sys-v and older xenix */
X
X /* if fortune is set, check to see if fortunates is set. If so,
X * check to see if all the recipient are on the fortunates list.
X */
X if (ison(flags, DO_FORTUNE)) {
X noisy = !chk_option("quiet", "fortune");
X if (p = do_set(set_options, "fortunates")) {
X if (!(p = alias_to_address(p)))
X return; /* no reason to hang around */
X rm_cmts_in_addr(p);
X if (!compare_addrs(list, p, buf)) {
X if (noisy) {
X wprint("\"fortunates\" does not contain \"%s\".\n", buf);
X wprint("No fortune added.\n");
X }
X return;
X }
X }
X if (noisy)
X wprint("You may be fortunate... ");
X if ((p = do_set(set_options, "fortune")) && *p == '/')
X (void) strcpy(buf, p);
X else
X (void) sprintf(buf, "%s %s", FORTUNE, (p && *p == '-')? p: "-s");
X if (!(pp2 = popen(buf, "r")))
X error(buf);
X else {
X turnon(glob_flags, IGN_SIGS);
X (void) fseek(fp, 0L, 2); /* go to end of file */
X while (fgets(buf, sizeof(buf), pp2))
X (void) fputs(buf, fp), lines++;
X (void) pclose(pp2);
X turnoff(glob_flags, IGN_SIGS);
X (void) fflush(fp);
X if (noisy)
X wprint("added %d line%s\n", lines, lines == 1? "" : "s");
X }
X }
X (void) fflush(stdout); /* for sys-v and older xenix */
}
X
X
/* return -1 since function doesn't affect messages */
check_flags(flags)
u_long flags;
{
X print_more(" ");
X if (ison(flags, VERBOSE))
X print_more("VERBOSE ");
X if (ison(flags, INCLUDE))
X print_more("INCLUDE ");
X if (ison(flags, INCLUDE_H))
X print_more("INCLUDE_H ");
X if (ison(flags, EDIT))
X print_more("EDIT ");
X if (ison(flags, SIGN))
X print_more("SIGN ");
X if (ison(flags, DO_FORTUNE))
X print_more("DO_FORTUNE ");
X if (ison(flags, NO_HEADER))
X print_more("NO_HEADER ");
X if (ison(flags, DELETE))
X print_more("DELETE ");
X if (ison(flags, OLD))
X print_more("OLD ");
X if (ison(flags, UNREAD))
X print_more("UNREAD ");
X if (ison(flags, UPDATE_STATUS))
X print_more("UPDATE_STATUS ");
X if (ison(flags, NO_PAGE))
X print_more("NO_PAGE ");
X if (ison(flags, INDENT))
X print_more("INDENT ");
X if (ison(flags, NO_IGNORE))
X print_more("NO_IGNORE ");
X if (ison(flags, PRESERVE))
X print_more("PRESERVE ");
X print_more("\n");
X return -1;
}
SHAR_EOF
chmod 0644 misc.c ||
echo 'restore of misc.c failed'
Wc_c="`wc -c < 'misc.c'`"
test 22738 -eq "$Wc_c" ||
echo 'misc.c: original size 22738, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= misc_frame.c ==============
if test -f 'misc_frame.c' -a X"$1" != X"-c"; then
echo 'x - skipping misc_frame.c (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting misc_frame.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'misc_frame.c' &&
/* @(#) misc_frame.c (c) copyright 9/29/89 (Dan Heller) */
X
/*
X * This file contains several functions which create dialog box frames
X * for (currently) mail aliases and ignored headers. Each dialog box
X * has a list of some kind and a way to add or delete items from the
X * list. The list is a textsw which is updated (currently) by do_set().
X * Public routines:
X * update_list_textsw(struct options **) updates the textsw list.
X * do_alias() creates the alias dialog frame box
X * do_ignore() creates the ignored headers dialog frame box
X */
X
#include "mush.h"
X
extern Notify_value fkey_interposer();
X
/****************** Mail Aliases ********************/
X
Frame alias_frame;
Panel_item alias_msg, alias_name, alias_value, alias_list_textsw;
static void set_alias();
X
Frame ignore_frame;
Panel_item ignore_msg, ignore_name, ignore_list_textsw;
static Panel_setting set_ignore();
X
#define MY_FRAME_WIDTH 600
X
static void
frame_help(item)
Panel_item item;
{
X (void) help(0, panel_get(item, PANEL_CLIENT_DATA), tool_help);
}
X
void
update_list_textsw(list)
struct options **list;
{
X Textsw save = pager_textsw;
X
X if (list == &aliases)
X pager_textsw = alias_list_textsw;
X else if (list == &ignore_hdr)
X pager_textsw = ignore_list_textsw;
X else
X /* no textsw for this guy yet */
X return;
X
X if (pager_textsw && !!window_get(pager_textsw, WIN_SHOW))
X (void) do_set(*list, NULL);
X pager_textsw = save;
}
X
static void
alias_done()
{
X window_destroy(alias_frame);
X alias_frame = (Frame) 0;
}
X
void
do_aliases()
{
X Panel panel;
X
X if (alias_frame) {
X window_set(alias_frame, WIN_SHOW, TRUE, NULL);
X return;
X }
#ifdef SUN_3_5
X if (nopenfiles(0) < 5) {
X print("Too many frames; close one first!\n");
X return;
X }
#endif /* SUN_3_5 */
X
X alias_frame = window_create(tool, FRAME,
X FRAME_SHOW_LABEL, TRUE,
X FRAME_LABEL, "Mail Aliases",
X FRAME_NO_CONFIRM, TRUE,
X FRAME_DONE_PROC, alias_done,
X WIN_SHOW, TRUE,
X WIN_WIDTH, MY_FRAME_WIDTH,
X NULL);
X
X panel = window_create(alias_frame, PANEL,
X PANEL_WIDTH, MY_FRAME_WIDTH,
X NULL);
X notify_interpose_event_func(panel, fkey_interposer, NOTIFY_SAFE);
X
X panel_create_item(panel, PANEL_BUTTON,
X PANEL_LABEL_IMAGE,
X panel_button_image(panel, "Help", 4, mush_font),
X PANEL_CLIENT_DATA, "aliases",
X PANEL_NOTIFY_PROC, frame_help,
X NULL);
X panel_create_item(panel, PANEL_BUTTON,
X PANEL_LABEL_IMAGE,
X panel_button_image(panel, "Set", 3, mush_font),
X PANEL_NOTIFY_PROC, set_alias,
X PANEL_CLIENT_DATA, TRUE,
X NULL);
X panel_create_item(panel, PANEL_BUTTON,
X PANEL_LABEL_IMAGE,
X panel_button_image(panel, "Unset", 5, mush_font),
X PANEL_NOTIFY_PROC, set_alias,
X PANEL_CLIENT_DATA, FALSE,
X NULL);
X
X alias_msg = panel_create_item(panel, PANEL_MESSAGE,
X PANEL_LABEL_STRING,
X "Type name of alias and address list and select <set> or <unset>",
X NULL);
X
X alias_name = panel_create_item(panel, PANEL_TEXT,
X PANEL_LABEL_STRING, "Alias Name:",
X PANEL_VALUE_DISPLAY_LENGTH, 60,
X NULL);
X alias_value = panel_create_item(panel, PANEL_TEXT,
X PANEL_LABEL_STRING, "Alias Address(es):",
X PANEL_VALUE_DISPLAY_LENGTH, 60,
X NULL);
X window_fit_height(panel);
X
X alias_list_textsw = window_create(alias_frame, TEXTSW,
X WIN_BELOW, panel,
X WIN_WIDTH, MY_FRAME_WIDTH,
X WIN_HEIGHT, 15 * l_height(),
#ifdef SUN_4_0 /* SunOS 4.0+ */
X TEXTSW_LINE_BREAK_ACTION, TEXTSW_WRAP_AT_WORD,
#else /* SUN_4_0 */
X TEXTSW_LINE_BREAK_ACTION, TEXTSW_WRAP_AT_CHAR,
#endif /* SUN_4_0 */
X NULL);
X (void) notify_interpose_event_func(alias_list_textsw,
X fkey_interposer, NOTIFY_SAFE);
X
X window_fit_height(alias_frame);
X update_list_textsw(&aliases);
}
X
static void
set_alias(item)
Panel_item item;
{
X int argc, set_it = (int)panel_get(item, PANEL_CLIENT_DATA);
X char buf[BUFSIZ], **argv, *name, *value;
X
X name = panel_get_value(alias_name);
X if (!*name) {
X panel_set(alias_msg, PANEL_LABEL_STRING, "Need an alias name.", NULL);
X return;
X }
X if (any(name, " \t")) {
X panel_set(alias_msg,
X PANEL_LABEL_STRING, "Alias name may not contain spaces.",
X NULL);
X return;
X }
X if (set_it) {
X value = panel_get_value(alias_value);
X if (!*value) {
X panel_set(alias_msg,
X PANEL_LABEL_STRING, "Specify alias address(es).",
X NULL);
X return;
X }
X sprintf(buf, "alias %s %s", name, value);
X } else
X sprintf(buf, "unalias %s", name);
X if (!(argv = mk_argv(buf, &argc, TRUE)) || do_alias(argc, argv) == -1)
X panel_set(alias_msg,
X PANEL_LABEL_STRING, "Couldn't set alias.",
X NULL);
X else
X panel_set(alias_msg,
X PANEL_LABEL_STRING, "",
X NULL);
X panel_set_value(alias_name, "");
X panel_set_value(alias_value, "");
X free_vec(argv);
}
X
/* int cuz it's also the callback for the text item */
static Panel_setting
set_ignore(item)
Panel_item item;
{
X int argc, set_it = (int)panel_get(item, PANEL_CLIENT_DATA);
X char buf[BUFSIZ], *name, **argv;
X
X name = panel_get_value(ignore_name);
X if (!*name) {
X panel_set(ignore_msg, PANEL_LABEL_STRING, "Missing header name.", NULL);
X return PANEL_NONE;
X }
X if (set_it)
X sprintf(buf, "ignore %s", name);
X else
X sprintf(buf, "unignore %s", name);
X /* set() will call update_list_textsw() */
X if (!(argv = mk_argv(buf, &argc, TRUE)) || set(argc, argv, NULL) == -1)
X panel_set(ignore_msg,
X PANEL_LABEL_STRING, "Internal Error!?",
X NULL);
X else
X panel_set(ignore_msg,
SHAR_EOF
true || echo 'restore of misc_frame.c failed'
fi
echo 'End of part 13'
echo 'File misc_frame.c is continued in part 14'
echo 14 > _shar_seq_.tmp
exit 0
exit 0 # Just in case...
--
Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD UUCP: uunet!sparky!kent
Phone: (402) 291-8300 FAX: (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.