v07i081: xmail -- Mail front end for X11, Patch1, Part01/06

news news at sun.Eng.Sun.COM
Fri Jun 1 13:39:47 AEST 1990


Submitted-by: parns.nsc.com!michael (Michael C. Wagnitz)
Posting-number: Volume 7, Issue 81
Archive-name: xmail/patch1.01
Patch-To: xmail: Volume 6, Issue 41-46

The following files constitute the first (and only) official patch to the
Mail X11 front-end xmail.  Due to a most fortunate delay in shipment of these
patches, I have been able to re-combine the full set of enhancements originally
announced as two sets of patches into this one complete set.  This should help
to reduce the net bandwidth.

After unsharing these files, you will have a MANIFEST of this patch
distribution, a file of CHANGES, and a set of five files named Patch.01[a-e]
that must be concatenated into one patch file (PATCH.01) which is then to be
applied to an original set of xmail sources.

My thanks go to the many contributors of patches and suggestions for xmail.

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 5)."
# Contents:  CHANGES MANIFEST Patch.01b
# Wrapped by michael at harley on Tue May 29 10:33:49 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'CHANGES' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'CHANGES'\"
else
echo shar: Extracting \"'CHANGES'\" \(6361 characters\)
sed "s/^X//" >'CHANGES' <<'END_OF_FILE'
X
X                                                                   May, 1990
X
X   The following changes have been effected for Patchlevel 1 of xmail.
X
X
XImakefile:	Made improvements in dependencies and SunOS defines.
X		Removed requirement for linkage to system math library.
X
XHelpText.c:	Text revised and reformatted to better fit the help window
X
XMailwatch.c:	Corrected illegal pointer combinations and added resources
X		to allow the user to specify the number of times to ring the
X		bell when new mail has arrived.  Fixed new mail bell to ring
X		only if flag is not already up.
X
XMailwatch.h:	Eliminated warning for duplicate XtNfile definition
X
Xactions.c:	Corrected illegal pointer combinations, added support for
X		improved index handler and Blind carbon copies.  Also added
X		support for .mailrc "printmail" definition, and improved error
X		messages when attempting to select non-existant or undefined
X		mail folders.  Used integer math instead of sqrt() function to
X		calculate box dimensions for aliases list.
X
XcallMail.c:	Corrected attempts to write to read-only strings, and fixed
X		case where fork child dies for improper command arguments or
X		illegal or unfound image execution which tried to write error
X		messages to the xmail pipe instead of the terminal screen.
X		A dying child process now also terminates the xmail process.
X
Xcallbacks.c:	Added support for external sendmail function, improved index
X		handler, and mail variable 'alwaysignore' which is now used
X		to determine header levels for reply, forward, and printed
X		messages.  If recipient selection fails to find a value for
X		the <Return_Path:> to a message, the <From:> designate is now
X		used, to eliminate failures to provide a <To:> addressee.
X		Also fixed bug in replyalls which failed to pick up names from
X		the original To: field when preparing addresses for the reply.
X
Xdefs.h:		Changed TITLE definition to accomodate use of PATCHLEVEL.
X
Xenvirons.c:	Alias support has been extended to include the word 'group'
X		when manually extracting mail aliases from the user's .mailrc
X		file.  Support has also been included for continuation lines.
X		Mechanisms to expand the MAILRC environment variable definition
X		have been eliminated, so that xmail behaves more like mail.
X		Corrected a bug in getMailEnv to return 'True' for variables
X		which have no additional value, such as 'hold' or 'autoprint'.
X		Changed strchr() calls to index().
X
Xhandler.c:	Function icon_handler() has been added to switch xmail to a
X		dummy mail folder whenever the application is iconified, and
X		to switch back to the previous folder on de-iconification.
X		Improved index_handler() to eliminate repaints of the index
X		window for every deletion or undeletion.  Also added code to
X		display as many new message headers as possible, to elminate
X		unnecessary scrolling of the index window.
X
Xmail.c:		Changed the fputs() to a write() to help eliminate i/o hanging,
X		added Blind Carbon Copy support to the sendMail function, and
X		added XMail class resources to the xterm messsage entry window.
X		Changed strrchr() call declarations to rindex().
X
Xparser.c:	Eliminated multiple redraws of the index window during message
X		deletions, and corrected index message markers for 'N'ew,
X		'D'eleted, and undeleted mail messages.  Corrected a bug in the
X		delete processing to not reread entire message and corrected a
X		bug to erase index and text window datas if no current folder.
X
Xutils.c:	Added use of PATCHLEVEL in determining TITLE version revision
X		and changed calls for strchr() to index().
X
Xwindows.c:	Changed name of "hold" button to "preserve", to better match
X		error message text when used incorrectly, eliminated making
X		the preserve button insensitive, to allow use of "set" menu
X		in any folder, added a "set" menu to the "preserve" command
X		button, to toggle mail variables, "alwaysignore", "autoprint",
X		and "hold", and corrected character processing in the file
X		window, to allow deletion and insertion within the line,
X		instead of always at the end.  Added use of PATCHLEVEL in
X		determining TITLE version revision
X
Xxmail.c:	added support for the -iconic command line option, corrected
X		resource handling for iconGeometry, and improved default font
X		handling for minimum dimensions of the xmail application window.
X		Also fixed processing of geometry specifications for the top
X		level window.  Update the 'what' database string to reflect
X		current version.
X
X
X
XI would like to thank the many contributors of suggestions and actual patches.
XI would also like to thank those persons who sent in complaints, as they were
Xoften the predictors of the many other corrections and enhancements to xmail. 
X
X*) Message size tests in parser.c were extended to include support for DEC
X   mail return on size requests, to prevent core dumps under Ultrix UWS 2.2
X   thanks to patches from Dirk Grunwald <grunwald at foobar.Colorado.EDU>
X
X*) Corrections to Imakefile to eliminate the need to set SunOS dependency
X   flags manually were driven by suggestions from Casey Leedom
X   <casey at gauss.llnl.gov> and David Elliott <dce at smsc.sony.com>.
X
X*) The regular expressions definitions in xmailregex.h were corrected as a
X   result of suggestions from Casey Leedom.
X
X*) Suggestions from Casey Leedom, Mark Williams <msw at cpsc.UCalgary.CA>,
X   and Mark Scholl <scholl at inf.ethz.ch> helped identify a problem in the
X   communications links with mail.  writeMail() now uses a write instead
X   of fputs, and the connection parameters are set for APPEND instead of
X   non-blocking i/o, to eliminate run-away cpu cycles.
X
X*) Many, many illegal pointer combination errors were identified and corrected
X   by Christos Zoulas <christos at guillemin.EE.cornell.edu>
X
X*) Thanks go to Robert Viduya <robert at shangri-la.gatech.ude> for suggestions
X   and assistance in adding an icon handler to switch to a dummy mail folder
X   during iconification, to prevent collisions in mail if run from another
X   process while xmail is running.
X
X*) Support for an alternate sendmail function was provided after receiving
X   suggestions from Jim Blythe <jsblythe%uk.co.gec-mrc at nsfnet-relay.ac.uk>
X
X*) Blind carbon copy support and correction of several bugs were suggested
X   by Jeff Dauber <dauber at parns.nsc.com>
X
X*) Support for mail variables autoprint and hold were corrected thanks to
X   requests from Dwayne Lee <dwayne at asic.nsc.com>
END_OF_FILE
if test 6361 -ne `wc -c <'CHANGES'`; then
    echo shar: \"'CHANGES'\" unpacked with wrong size!
fi
# end of 'CHANGES'
fi
if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MANIFEST'\"
else
echo shar: Extracting \"'MANIFEST'\" \(460 characters\)
sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
X   File Name		Archive #	Description
X-----------------------------------------------------------
X CHANGES                    1	List of enhancements to xmail
X MANIFEST                   1	This shipping list
X Patch.01a                  2	Patch file for xmail
X Patch.01b                  1	Patch file for xmail
X Patch.01c                  3	Patch file for xmail
X Patch.01d                  4	Patch file for xmail
X Patch.01e                  5	Patch file for xmail
END_OF_FILE
if test 460 -ne `wc -c <'MANIFEST'`; then
    echo shar: \"'MANIFEST'\" unpacked with wrong size!
fi
# end of 'MANIFEST'
fi
if test -f 'Patch.01b' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Patch.01b'\"
else
echo shar: Extracting \"'Patch.01b'\" \(46474 characters\)
sed "s/^X//" >'Patch.01b' <<'END_OF_FILE'
X!        tmp[x] = '\0';
X!        foldir[foldlen] = '\0';
X!        strcat(foldir, &tmp[1]);
X!        if ((dirp = opendir(foldir)) != NULL) {
X!           tmp[x++] = '/';
X            tmp[x] = '\0';
X!          }
X!        n = 4;
X!        XtSetArg(args[n], XtNlabel, tmp);				n++;
X!        XtSetArg(args[n], XtNfromHoriz, to_left);			n++;
X!        if (! to_left) XtSetArg(args[n], XtNfromVert, above);		n++;
X  
X!        this_one = XtCreateManagedWidget("listbutton", commandWidgetClass,
X                                                  lw, args, n);
X!        if (dirp != NULL) {
X!           closedir(dirp);
X!           sprintf(trans, dir_Trans, &tmp[1], foldir, "0");
X!           XtOverrideTranslations(this_one, XtParseTranslationTable(trans));
X           }
X        }
X-    }
X     }	/* end - if some trans strlen */
X  /*
X  ** If folders menu exists, pop it up, after setting x,y coordinates
X  */
X   if (popup->core.being_destroyed) {
X!     Bell("No mail folders exist\n");
X     } else {
X      if (! XtIsRealized(popup))		/* see if folder list is small */
X         XtRealizeWidget(popup);		/* enough to fit if anchored at */
X--- 791,836 ----
X               } else {
X                 if (x == 0) tmp[x++] = '+';	/* start folder names with a 'plus' */
X                 tmp[x++] = *p;
X+              }
X            }
X  
X!        if (x) {
X            tmp[x] = '\0';
X!           foldir[foldlen] = '\0';
X!           strcat(foldir, &tmp[1]);
X!           if ((dirp = opendir(foldir)) != NULL) {
X!              tmp[x++] = '/';
X!              tmp[x] = '\0';
X!             }
X!           XtSetArg(args[4], XtNlabel, tmp);
X!           XtSetArg(args[5], XtNfromHoriz, to_left);			n = 6;
X!           if (! to_left) XtSetArg(args[n], XtNfromVert, above);		n++;
X  
X!           this_one = XtCreateManagedWidget("listbutton", commandWidgetClass,
X                                                  lw, args, n);
X!           if (dirp != NULL) {
X!              closedir(dirp);
X!              sprintf(trans, dir_Trans, &tmp[1], foldir, "0");
X!              XtOverrideTranslations(this_one, XtParseTranslationTable(trans));
X!             }
X           }
X        }
X     }	/* end - if some trans strlen */
X  /*
X  ** If folders menu exists, pop it up, after setting x,y coordinates
X  */
X   if (popup->core.being_destroyed) {
X!     if (! *foldir)
X!        Bell("No value set for \"folder\"\n");
X!     else {
X!        if (dirp && !mailpid) {
X!           Bell("No mail folders exist\n");
X!          } else {
X!           foldir[foldlen - 1] = '\0';
X!           sprintf(tmp, "%s not found\n", foldir);
X!           Bell(tmp);
X!          }
X!       }
X     } else {
X      if (! XtIsRealized(popup))		/* see if folder list is small */
X         XtRealizeWidget(popup);		/* enough to fit if anchored at */
X***************
X*** 790,810 ****
X         ad = XtDisplay(w);
X         n = XMail.buttonHeight / 2;
X        } else {
X!        aw = XtWindow(WidgetOf(WidgetOf(toplevel, "vpane"), "commandPanel"));
X!        ad = XtDisplay(WidgetOf(WidgetOf(toplevel, "vpane"), "commandPanel"));
X!  n = XMail.commandMinHeight / 2;
X        }
X      root = RootWindow(ad, DefaultScreen(ad));
X  
X!  XTranslateCoordinates(ad, aw, root, XMail.menuX, n, &x, &y, &dumy);
X  
X!  n = 0;
X!  XtSetArg(args[n], XtNx, x);			n++;
X!  XtSetArg(args[n], XtNy, y);			n++;
X!     XtSetValues(popup, (ArgList) args, n);
X     }
X  
X!  XtFree(List);
X  
X  } /* SetFolders */
X  
X--- 841,860 ----
X         ad = XtDisplay(w);
X         n = XMail.buttonHeight / 2;
X        } else {
X!        aw = XtWindow(WidgetOf(WidgetOf(toplevel, "topBox"), "commandPanel"));
X!        ad = XtDisplay(WidgetOf(WidgetOf(toplevel, "topBox"), "commandPanel"));
X!        n = XMail.commandMinHeight / 2;
X        }
X      root = RootWindow(ad, DefaultScreen(ad));
X  
X!     XTranslateCoordinates(ad, aw, root, XMail.menuX, n, &x, &y, &dumy);
X  
X!     XtSetArg(args[0], XtNx, x);
X!     XtSetArg(args[1], XtNy, y);
X!     XtSetValues(popup, (ArgList) args, 2);
X     }
X  
X!  XtFree((char *)List);
X  
X  } /* SetFolders */
X  
X***************
X*** 820,827 ****
X  String *params;
X  Cardinal *num_params;
X  {
X!  Arg		args[3];
X!  Widget		tw;
X   Window		aw, dumy;
X   Display	*ad;
X   int		indx, status, x, y, scn;
X--- 870,877 ----
X  String *params;
X  Cardinal *num_params;
X  {
X!  Arg		args[2];
X!  Widget		tb, tw;
X   Window		aw, dumy;
X   Display	*ad;
X   int		indx, status, x, y, scn;
X***************
X*** 834,844 ****
X       if (strcmp(params[0], HelpNames[indx]) == 0) break;
X  
X   if (HelpNames[indx]) {
X!     XtTextSetSource(WidgetOf(WidgetOf(WidgetOf(toplevel, "vpane"), "help"), "helpWindow"), HelpStrings[indx], (XtTextPosition) 0);
X  /*
X  ** Position help relative to textWindow
X  */
X!     tw  = WidgetOf(WidgetOf(toplevel, "vpane"), "textWindow");
X      aw  = XtWindow(tw);
X      ad  = XtDisplay(tw);
X      scn = DefaultScreen(ad);
X--- 884,895 ----
X       if (strcmp(params[0], HelpNames[indx]) == 0) break;
X  
X   if (HelpNames[indx]) {
X!     tb = WidgetOf(toplevel, "topBox");
X!     XtTextSetSource(WidgetOf(WidgetOf(tb, "help"), "helpWindow"), HelpStrings[indx], (XtTextPosition) 0);
X  /*
X  ** Position help relative to textWindow
X  */
X!     tw  = WidgetOf(tb, "textWindow");
X      aw  = XtWindow(tw);
X      ad  = XtDisplay(tw);
X      scn = DefaultScreen(ad);
X***************
X*** 848,861 ****
X  
X      XtSetArg(args[0], XtNx, x);
X      XtSetArg(args[1], XtNy, y);
X!     XtSetValues(WidgetOf(WidgetOf(toplevel, "vpane"), "help"), args, 2);
X  
X!     XtPopup(WidgetOf(WidgetOf(toplevel, "vpane"), "help"), XtGrabNone);
X     }
X  } /* SetHelp */
X  
X  
X  /*
X  ** @(#)SetPopup() - place named popup at menuX, menuY relative to Widget w.
X  */
X  /* ARGSUSED */
X--- 899,988 ----
X  
X      XtSetArg(args[0], XtNx, x);
X      XtSetArg(args[1], XtNy, y);
X!     XtSetValues(WidgetOf(tb, "help"), args, 2);
X  
X!     XtPopup(WidgetOf(tb, "help"), XtGrabNone);
X     }
X  } /* SetHelp */
X  
X  
X+ /* 
X+ ** @(#)SetMenu() - create a menu for toggling selected mail options
X+ */
X+ XtActionProc
X+ SetMenu(parent, event, params, num_params)
X+ Widget		parent;
X+ XEvent		*event; /* unused */
X+ String		*params;
X+ Cardinal	*num_params;
X+ {
X+  Arg	 	args[6];
X+  Display        *ad;
X+  Widget		menu, layout, previous, next;
X+  Window         aw, dumy, root;
X+  char		*c, label[BUFSIZ], name[BUFSIZ];		
X+  int		indx, x, y;
X+ 
X+  static String b_Trans =
X+ 	"<EnterWindow>:	set() \n\
X+ 	 <LeaveWindow>: reset() \n\
X+ 	 <Btn3Up>:	SetCursor(True) notify() SetCursor() unset()";
X+ 
X+  static String m_Trans =
X+ 	"<Btn3Up>:	MenuPopdown(set_menu)";
X+ 
X+  static String list[] = { "alwaysignore", "autoprint", "hold", NULL };
X+ 
X+ 
X+  menu = XtNameToWidget(parent, "set_menu");
X+ 
X+  if (! menu || menu->core.being_destroyed) {
X+     XtSetArg(args[0], XtNtranslations, XtParseTranslationTable(m_Trans));
X+     menu = XtCreatePopupShell("set_menu",overrideShellWidgetClass,parent,args,1);
X+ 
X+     XtSetArg(args[0], XtNdefaultDistance, (XtArgVal) 1);
X+     layout = XtCreateManagedWidget("menu", formWidgetClass, menu, args, ONE);
X  /*
X+ ** create the menu buttons
X+ */
X+     indx = XTextWidth(TextFontStr, " ", 1) * 18 + 12;
X+     previous = NULL;
X+     XtSetArg(args[0], XtNwidth, indx);
X+     XtSetArg(args[1], XtNfont, TextFontStr);
X+     XtSetArg(args[2], XtNjustify, XtJustifyLeft);
X+     XtSetArg(args[3], XtNtranslations, XtParseTranslationTable(b_Trans));
X+     for (indx = 0; list[indx] != NULL; indx++) {
X+         strcpy(label, "set ");
X+         if ((c = GetMailEnv(list[indx])) != NULL) {
X+            strcat(label, "no");
X+            XtFree(c);
X+           }
X+         strcat(label, list[indx]);		/* set window name by label */
X+         strcpy(name, &label[4]);
X+         XtSetArg(args[4], XtNlabel, label);
X+         XtSetArg(args[5], XtNfromVert, previous);
X+         next = XtCreateManagedWidget(name, commandWidgetClass, layout, args, 6);
X+         XtAddCallback(next, XtNcallback, (XtCallbackProc) DoSet, NULL);
X+         previous = next;
X+        }
X+ 
X+     XtRealizeWidget(menu);
X+    }
X+ 
X+  aw = XtWindow(parent);
X+  ad = XtDisplay(parent);
X+  indx = XMail.buttonHeight / 2;
X+  root = RootWindow(ad, DefaultScreen(ad));
X+ 
X+  XTranslateCoordinates(ad, aw, root, XMail.menuX, indx, &x, &y, &dumy);
X+ 
X+  XtSetArg(args[0], XtNx, x);
X+  XtSetArg(args[1], XtNy, y);
X+  XtSetValues(menu, (ArgList) args, 2);
X+ } /* SetMenu */
X+ 
X+ 
X+ /*
X  ** @(#)SetPopup() - place named popup at menuX, menuY relative to Widget w.
X  */
X  /* ARGSUSED */
X***************
X*** 939,945 ****
X   cm.format = 32;
X   cm.data.l[0] = XA_PRIMARY;
X  
X!  XSendEvent(XtDisplay(w), cm.window, TRUE, NoEventMask, &cm);
X  
X   for (; *s && !isdigit(*s); s++);
X   left = s - IndexBuf;
X--- 1066,1072 ----
X   cm.format = 32;
X   cm.data.l[0] = XA_PRIMARY;
X  
X!  XSendEvent(XtDisplay(w), cm.window, TRUE, NoEventMask, (XEvent *) &cm);
X  
X   for (; *s && !isdigit(*s); s++);
X   left = s - IndexBuf;
X***************
X*** 963,971 ****
X  String		*params;
X  Cardinal	*num_params;
X  {
X!  caddr_t	client_data;
X!  caddr_t	call_data;
X! 
X!  client_data = params[0];
X!  DoQuit(w, client_data, call_data);
X  } /* Quit */
X--- 1090,1094 ----
X  String		*params;
X  Cardinal	*num_params;
X  {
X!  DoQuit(w, *params, NULL);
X  } /* Quit */
X*** ../v1.0/callMail.c	Sun May 27 21:05:43 1990
X--- callMail.c	Sun May 27 21:09:56 1990
X***************
X*** 43,56 ****
X  #include	<sgtty.h>
X  #include	"global.h"
X  
X! FILE   	    	*mailfp = NULL;		/* file pointer to mail */
X  int    	    	mail_fd;		/* mail process master tty id */
X  int    	    	mailpid;		/* mail process id */
X  int    	    	mailInputId;		/* mail input id */
X  
X- static char 	*pty = "/dev/pty??";	/* master side of pseudo-terminal */
X- static char 	*tty = "/dev/tty??";	/* slave side of pseudo-terminal */
X- 
X  /*
X   *  Xmail talks to mail through a pseudo terminal which is a pair of master
X   *  and slave devices: /dev/pty?? and /dev/tty??, where ?? goes from p0 to
X--- 43,57 ----
X  #include	<sgtty.h>
X  #include	"global.h"
X  
X! #define PTYTEMPL "/dev/pty??"
X! #define TTYTEMPL "/dev/tty??"
X! 
X  int    	    	mail_fd;		/* mail process master tty id */
X  int    	    	mailpid;		/* mail process id */
X  int    	    	mailInputId;		/* mail input id */
X+ char		pty[10];		/* master side of pseudo-terminal */
X+ char		tty[10];		/* slave side of pseudo-terminal */
X  
X  /*
X   *  Xmail talks to mail through a pseudo terminal which is a pair of master
X   *  and slave devices: /dev/pty?? and /dev/tty??, where ?? goes from p0 to
X***************
X*** 65,70 ****
X--- 66,72 ----
X   int  i, master; 
X   char c;
X  
X+  (void) strcpy(pty, PTYTEMPL);
X   for (c='p'; c<='s'; c++) {
X       pty[8] = c;
X       for (i=0; i<16; i++) {
X***************
X*** 86,91 ****
X--- 88,94 ----
X  {
X   int slave;
X  
X+  (void) strcpy(tty, TTYTEMPL);
X   tty[8] = pty[8];
X   tty[9] = pty[9];
X   if ((slave = open(tty, O_RDWR)) != -1) {
X***************
X*** 106,122 ****
X  int argc;
X  char *argv[];
X  {
X!  struct sgttyb Sgtty;
X!  int           master;			/* file descriptor of master pty */
X!  int           slave;			/* file descriptor to slave pty */
X!  char          *Mailpgm,		/* name of executable Mailpgm */
X!                errmsg[BUFSIZ];
X  
X!  Mailpgm = (char *) getenv("XMAILER");	/* first looks up env var */
X!  if (Mailpgm == NULL)
X!     Mailpgm = XtNewString(XMAILER);
X    
X!  master = openMaster();
X   slave = openSlave();
X  
X   ioctl(slave, TIOCGETP, &Sgtty);
X--- 109,124 ----
X  int argc;
X  char *argv[];
X  {
X!  struct sgttyb	Sgtty;
X!  int		slave;			/* file descriptor to slave pty */
X!  char		*Mailpgm;		/* name of executable Mailpgm */
X!  char		buf[BUFSIZ];
X  
X! 
X!  if (! (Mailpgm = (char *)getenv("XMAILER")))	/* first looks up env var */
X!     Mailpgm = "Mail";
X    
X!  mail_fd = openMaster();
X   slave = openSlave();
X  
X   ioctl(slave, TIOCGETP, &Sgtty);
X***************
X*** 125,158 ****
X  
X   mailpid = fork();
X   if (mailpid == -1) {
X!     perror("Cannot fork mail process");
X      exit(1);
X     } else if (mailpid) { 
X               /* 
X                * Parent : close the slave side of pty
X                *          close stdin and stdout
X!               *          set the mail file descriptor to nonblocking mode
X!               *          open file pointer with read/write access to mail
X!               *          set unbuffered mode
X                *          register mail input with X
X                */
X               close(slave);
X!              if (master != 0)		/* if we're restarting, master IS 0 */
X                  close(0);
X               close(1);
X!              fcntl(master, F_SETFL, FNDELAY);
X!              mail_fd = master;			/* use descriptor for reads */
X!              mailfp = fdopen(master, "r+");	/* need mailfp for fputs */
X!              setbuf(mailfp, NULL);
X!              mailInputId = XtAddInput(master, XtInputReadMask, readMail, NULL);
X              } else { 
X               /* 
X!               * Child : close master side of pty
X                *         redirect stdin, stdout, stderr of mail to pty
X                *         unbuffer output data from mail
X                *         exec mail with arguments
X                */
X!              close(master);
X               dup2(slave, 0);
X               dup2(slave, 1);
X               dup2(slave, 2);
X--- 127,155 ----
X  
X   mailpid = fork();
X   if (mailpid == -1) {
X!     perror("callMail: Cannot fork Mail process");
X      exit(1);
X     } else if (mailpid) { 
X               /* 
X                * Parent : close the slave side of pty
X                *          close stdin and stdout
X!               *          set the mail file descriptor to append mode
X                *          register mail input with X
X                */
X               close(slave);
X!              if (mail_fd != 0)		/* if we're restarting, mail_fd IS 0 */
X                  close(0);
X               close(1);
X!              fcntl(mail_fd, F_SETFL, FAPPEND);
X!              mailInputId = XtAddInput(mail_fd, XtInputReadMask, readMail, NULL);
X              } else { 
X               /* 
X!               * Child : close mail_fd side of pty
X                *         redirect stdin, stdout, stderr of mail to pty
X                *         unbuffer output data from mail
X                *         exec mail with arguments
X                */
X!              close(mail_fd);
X               dup2(slave, 0);
X               dup2(slave, 1);
X               dup2(slave, 2);
X***************
X*** 162,169 ****
X               setbuf(stdout, NULL);
X               argv[0] = Mailpgm;
X               execvp(Mailpgm, argv);
X!              sprintf(errmsg, "callMail: Cannot call %s", Mailpgm);
X!              perror(errmsg);
X               exit(1);
X              }
X  } /* callMail */
X--- 159,177 ----
X               setbuf(stdout, NULL);
X               argv[0] = Mailpgm;
X               execvp(Mailpgm, argv);
X!              /*
X!               * If we fail to make contact, we must re-establish
X!               * access to the terminal screen that started us for
X!               * our error message, because we don't want to send
X!               * it up the xmail pipe.  Also, terminate our parent.
X!               */
X!              if ((slave = open("/dev/tty", O_RDWR)) != -1) {
X!                 dup2(slave, 1);
X!                 dup2(slave, 2);
X!                 perror(Mailpgm);
X!                }
X!              sprintf(buf, "kill -INT %s\n", &tmpName[10]);
X!              system(buf);
X               exit(1);
X              }
X  } /* callMail */
X*** ../v1.0/callbacks.c	Sun May 27 21:05:44 1990
X--- callbacks.c	Sun May 27 21:09:57 1990
X***************
X*** 30,35 ****
X--- 30,36 ----
X  #include "global.h"
X  #include <sys/wait.h>
X  #include <sys/stat.h>
X+ #include <pwd.h>
X  
X  
X  /*
X***************
X*** 91,96 ****
X--- 92,98 ----
X   FILE		*fp;
X   char		*p, *record, *folder, *getenv();
X   char		From[BUFSIZ], Copy[BUFSIZ], s[BUFSIZ];
X+  int		n;
X   struct stat	st_buf;
X  
X  
X***************
X*** 115,120 ****
X--- 117,125 ----
X      if (*CcBuf)
X         fprintf(fp, "Cc: %s\n", alias(CcBuf));
X  
X+     if (*BccBuf)
X+        fprintf(fp, "Bcc: %s\n", alias(BccBuf));
X+ 
X      fprintf(fp, "\n");			/* separate header from text */
X      fclose(fp);
X     }
X***************
X*** 126,133 ****
X      */
X      if (*Recipient && (*SubjBuf ||
X         (stat(tmpName, &st_buf) == 0 && st_buf.st_size))) {
X!        sprintf(s, "cat %s_ %s | /usr/lib/sendmail -toi -om 2> /dev/null", tmpName, tmpName);
X         system(s);
X  /*
X  ** If user has set 'record' in their .mailrc, add a message copy to that file
X  */
X--- 131,141 ----
X      */
X      if (*Recipient && (*SubjBuf ||
X         (stat(tmpName, &st_buf) == 0 && st_buf.st_size))) {
X!        if ((p = GetMailEnv("sendmail")) == NULL)
X!             p = XtNewString("/usr/lib/sendmail");
X!        sprintf(s, "cat %s_ %s | %s -toi -om 2> /dev/null", tmpName, tmpName, p);
X         system(s);
X+        XtFree(p);
X  /*
X  ** If user has set 'record' in their .mailrc, add a message copy to that file
X  */
X***************
X*** 177,187 ****
X                    sprintf(Copy, "%s/%s", getenv("HOME"), &record[1]);
X            XtFree(record);
X           }
X!        if (*Recipient && (*SubjBuf ||
X!           (stat(tmpName, &st_buf) == 0 && st_buf.st_size))) {
X            sprintf(s, "cat %s_ %s >> %s 2> /dev/null", tmpName, tmpName, Copy);
X            system(s);
X!           sprintf(s, "Canceled letter appended to %s\n", Copy);
X            Bell(s);
X           } else Bell("Nothing to save in your dead letter box\n");
X        }
X--- 185,202 ----
X                    sprintf(Copy, "%s/%s", getenv("HOME"), &record[1]);
X            XtFree(record);
X           }
X!        st_buf.st_size = 0;		/* (in case msg file does not exist) */
X!        if (*Recipient || *SubjBuf ||
X!           (stat(tmpName, &st_buf) == 0 && st_buf.st_size)) {
X!           n = st_buf.st_size;			/* remember num bytes in msg */
X!           if (stat((char *)sprintf(s, "%s_", tmpName), &st_buf) == 0)
X!              n += st_buf.st_size;		/* include bytes in header */
X!           st_buf.st_size = -1;			/* see if our target exists */
X!           stat(Copy, &st_buf);
X            sprintf(s, "cat %s_ %s >> %s 2> /dev/null", tmpName, tmpName, Copy);
X            system(s);
X!           sprintf(s, "\"%s\" [%s] (%d bytes)\n", Copy,
X!                  (st_buf.st_size >= 0) ? "Appended" : "New file", n);
X            Bell(s);
X           } else Bell("Nothing to save in your dead letter box\n");
X        }
X***************
X*** 213,228 ****
X   else if (strcmp(Command, "file %\n") != 0 && strcmp(Command, "inc\n") != 0)
X           Bell("No mail\n");		/* But if no new mail, complain */
X        else {
X!          for (n = 0; n < mailargc; n++) {
X!              if (strcmp(mailargv[n], "-f") == 0) {
X!                 for (i = n + 2; i <= mailargc;) mailargv[n++] = mailargv[i++];
X!                 mailargc -= 2;		/* throw away any folder argument */
X!                 n -= 2;			/* re-examine new mailargv value */
X!                }
X!             }
X           callMail(mailargc, mailargv);	/* restart the mail connections */
X           strcpy(Command, "Start");	/* Let em know we've re-started */
X!          UnsetNewmail(w, closure, call_data);
X     }
X  } /* DoIt */
X  
X--- 228,240 ----
X   else if (strcmp(Command, "file %\n") != 0 && strcmp(Command, "inc\n") != 0)
X           Bell("No mail\n");		/* But if no new mail, complain */
X        else {
X!          if (strcmp(mailargv[mailargc - 2], "-f") == 0) {
X!             mailargc -= 2;		/* throw away any folder argument */
X!             mailargv[mailargc] = NULL;	/* and NULL end of argument list */
X!            }
X           callMail(mailargc, mailargv);	/* restart the mail connections */
X           strcpy(Command, "Start");	/* Let em know we've re-started */
X!          UnsetNewmail(w, NULL, NULL);
X     }
X  } /* DoIt */
X  
X***************
X*** 265,271 ****
X--- 277,308 ----
X  } /* DoQuit */
X  
X  
X+ /*
X+ ** @(#)DoSet() - send specified set request to mail and destroy current menu.
X+ */
X  /* ARGSUSED */
X+ XtCallbackProc
X+ DoSet(w, closure, call_data)
X+ Widget	w;
X+ caddr_t	closure;
X+ caddr_t	call_data;
X+ {
X+  char	*c, buf[32];
X+ 
X+ 
X+  if (! mailpid)				/* If connections are okay,... */
X+     Bell("No mail\n");			/* if no new mail, complain */
X+  else {
X+     sprintf(buf, "set %s", w->core.name);
X+     c = QueryMail(buf);
X+     XtFree(c);
X+ 
X+     XtDestroyWidget(XtParent(XtParent(w)));
X+    }
X+ } /* DoSet */
X+ 
X+ 
X+ /* ARGSUSED */
X  /*
X  ** @(#)DoWith() - send client_data command to mail with selected msg number
X  */
X***************
X*** 281,288 ****
X   if (! mailpid)
X      Bell("No mail\n");
X   else {
X!     pos = XtTextGetInsertionPoint(WidgetOf(WidgetOf(toplevel, "vpane"), "indexWindow"));
X      num = PositionToMsgNumber(pos);	/* no current message returns zero */
X      if (num) sprintf(Command, "%s %d\n", client_data, num);
X      else sprintf(Command, "%s \n", client_data);
X      writeMail(Command);
X--- 318,326 ----
X   if (! mailpid)
X      Bell("No mail\n");
X   else {
X!     pos = XtTextGetInsertionPoint(WidgetOf(WidgetOf(toplevel, "topBox"), "indexWindow"));
X      num = PositionToMsgNumber(pos);	/* no current message returns zero */
X+     if (*client_data == 'u' && IndexBuf[pos + 1] != 'D') num = 0;
X      if (num) sprintf(Command, "%s %d\n", client_data, num);
X      else sprintf(Command, "%s \n", client_data);
X      writeMail(Command);
X***************
X*** 353,359 ****
X         }
X      sprintf(buf, "File: +%s%s", tmp, folder_name);
X     }
X!  writeText(WidgetOf(WidgetOf(WidgetOf(toplevel, "vpane"), "commandPanel"), "fileWindow"), buf, 0);
X  } /* GetFolderName */
X  
X  
X--- 391,397 ----
X         }
X      sprintf(buf, "File: +%s%s", tmp, folder_name);
X     }
X!  writeText(WidgetOf(WidgetOf(WidgetOf(toplevel, "topBox"), "commandPanel"), "fileWindow"), buf, 0);
X  } /* GetFolderName */
X  
X  
X***************
X*** 371,388 ****
X   Cardinal	*num_params;
X   FILE		*fp;
X   Position	pos;
X!  String		*params, p, q, r, txt, author, subject, others, date, reference;
X!  XEvent		*event;
X   int		erasable = 0;
X   
X  
X!  txt = author = subject = others = date = reference = "";
X   if (*client_data != 's') {
X      if ((fp = fopen(tmpName, "w")) == NULL)
X         Bell("xmail: Cannot open temp file for writing\n");
X  
X!     pos = XtTextGetInsertionPoint(WidgetOf(WidgetOf(toplevel, "vpane"), "indexWindow"));
X!     sprintf(Command, "P %d", PositionToMsgNumber(pos));
X      txt = QueryMail(Command);
X      if (fp) {
X         switch (*client_data) {
X--- 409,438 ----
X   Cardinal	*num_params;
X   FILE		*fp;
X   Position	pos;
X!  String		*params, p, q, r;
X!  String		txt, ccList, author, subject, others, date, reference, empty;
X!  char		*us, *getlogin();
X   int		erasable = 0;
X+  int		alwaysIgnore;
X   
X  
X!  txt = ccList = author = subject = others = date = reference = empty = "";
X   if (*client_data != 's') {
X      if ((fp = fopen(tmpName, "w")) == NULL)
X         Bell("xmail: Cannot open temp file for writing\n");
X  
X!     pos = XtTextGetInsertionPoint(WidgetOf(WidgetOf(toplevel, "topBox"), "indexWindow"));
X! 
X!     if (p = GetMailEnv("alwaysignore")) {
X!        XtFree(p);
X!        alwaysIgnore = 1;
X!       } else alwaysIgnore = 0;
X! 
X!     if (alwaysIgnore)		/* use 'alwaysignore' to decide how we print */
X!        sprintf(Command, "p %d", PositionToMsgNumber(pos));
X!     else
X!        sprintf(Command, "P %d", PositionToMsgNumber(pos));
X! 
X      txt = QueryMail(Command);
X      if (fp) {
X         switch (*client_data) {
X***************
X*** 419,429 ****
X  /*
X  ** strip author, subject, and Carbon copy information from the selected message
X  */
X      for (p = txt; *p; p++) {
X!         if (strcmp(p, "") == 0 || strncmp(p, "Status:", 7) == 0) break;
X  
X          if (strncmp(p, "Return-Path:", 12) == 0) {
X!            author = p + 14;
X             for (p = author; *p && *p != '>'; p++);
X             if (*p) *p++ = '\0';
X             for (; *p && *p != '\n'; p++);
X--- 469,484 ----
X  /*
X  ** strip author, subject, and Carbon copy information from the selected message
X  */
X+     if (alwaysIgnore) {		/* we must now get full headers, for data */
X+        XtFree(txt);
X+        sprintf(Command, "P %d", PositionToMsgNumber(pos));
X+        txt = QueryMail(Command);
X+       }
X      for (p = txt; *p; p++) {
X!         if (strcmp(p, empty) == 0 || strncmp(p, "Status:", 7) == 0) break;
X  
X          if (strncmp(p, "Return-Path:", 12) == 0) {
X!            author = p + 14;		/* step over the opening '<' chevron */
X             for (p = author; *p && *p != '>'; p++);
X             if (*p) *p++ = '\0';
X             for (; *p && *p != '\n'; p++);
X***************
X*** 441,446 ****
X--- 496,507 ----
X             if (*p) *p = '\0';
X            }
X  
X+         else if (strncmp(p, "To:", 3) == 0) {
X+            others = p + 4;
X+            for (p = others; *p && *p != '\n'; p++);
X+            if (*p) *p = '\0';
X+           }
X+ 
X          else if (strncmp(p, "Subject:", 8) == 0) {
X             subject = p + 9;
X             for (p = subject; *p && *p != '\n'; p++);
X***************
X*** 448,485 ****
X            }
X  
X          else if (strncmp(p, "Cc:", 3) == 0) {
X!            others = p + 4;
X!            for (p = others; *p && *p != '\n'; p++);
X             if (*p) *p = '\0';
X            }
X          else for (; *p && *p != '\n'; p++);
X         } /* end - for all of message body */
X  
X!     if (*client_data != 'a' && *client_data != 'A')
X!        others = "";	/* If not [rR]eplyall, make sender enter any Cc: */
X  
X      if (fp) fclose(fp);
X  
X      XtFree(txt);
X     } /* end - if client_data does not equal 's' */
X  
X!  if (*client_data != 'S' && *client_data != 's')
X      strcpy(Recipient, author);
X  
X!  strcpy(InReply, "");
X   if (*client_data != 's' && *reference && *date) {
X      r = (*client_data == 'S') ? "Forwarding" : "In-Reply-To";
X      sprintf(InReply, "%s: Mail from '%s' dated %s", r, reference, date);
X     }
X  
X   if (*subject) {
X!     strcpy(SubjBuf, "");
X!     if (strncmp(subject, "Re: ", 4) != 0)
X         strcat(SubjBuf, "Re: ");
X      strcat(SubjBuf, subject);
X     }
X  
X!  strcpy(CcBuf, others);
X  
X   sendMail(w);
X  } /* Reply */
X--- 509,592 ----
X            }
X  
X          else if (strncmp(p, "Cc:", 3) == 0) {
X!            ccList = p + 4;
X!            for (p = ccList; *p && *p != '\n'; p++);
X             if (*p) *p = '\0';
X            }
X          else for (; *p && *p != '\n'; p++);
X         } /* end - for all of message body */
X  
X!     if (*client_data != 'a' && *client_data != 'A') {
X!        ccList = empty;	/* If not [rR]eplyall, make sender enter any Cc: */
X!        others = empty;
X!       } else {		/* otherwise, remove ourself from the others list */
X!        us = getlogin();
X!        if (! us) {
X!           struct passwd *pw = getpwuid(getuid());
X  
X+           if (pw)
X+              us = pw->pw_name;
X+          }
X+        for (p = others; *us && *p; p++) {
X+            if (strncmp(p, us, strlen(us)) == 0) {
X+               for (us = p + strlen(us); *us && *us != ',' && *us != ' ';) us++;
X+               for (; *us && (*us == ',' || *us == ' ');) us++;
X+               for (; *us;) *p++ = *us++;
X+               *p = '\0';
X+               break;
X+              }
X+            while (*p && *p != ',' && *p != ' ') p++;
X+            while (*p && (*p == ',' || *p == ' ')) p++;
X+            p--;
X+           }
X+       }
X+ 
X      if (fp) fclose(fp);
X  
X      XtFree(txt);
X     } /* end - if client_data does not equal 's' */
X  
X!  strcpy(Recipient, empty);
X! /*
X! ** If message did not have a 'Return-Path', use 'From' for reply recipient
X! */
X!  if (*client_data != 'S' && *client_data != 's') {
X      strcpy(Recipient, author);
X+     if (! *Recipient && *reference) {
X+        erasable = 0;
X+        author = reference;
X+        for (p = author; *p && *p != ' '; p++);
X+        if (*p) {
X+           erasable = 1;
X+           *p = '\0';
X+          }
X+        strcpy(Recipient, author);
X+        if (erasable) *p = ' ';
X+       }
X+     if (*others && (*client_data == 'a' || *client_data == 'A')) {
X+        if (LASTCH(Recipient) != ',')
X+           strcat(Recipient, ", ");
X+        strcat(Recipient, others);
X+        for (p = Recipient + strlen(Recipient) - 1; *p == ' ' || *p == ','; p--);
X+        *++p = '\0';			/* drop any trailing ", " garbage */
X+       }
X+    }
X  
X!  strcpy(InReply, empty);
X   if (*client_data != 's' && *reference && *date) {
X      r = (*client_data == 'S') ? "Forwarding" : "In-Reply-To";
X      sprintf(InReply, "%s: Mail from '%s' dated %s", r, reference, date);
X     }
X  
X+  strcpy(SubjBuf, empty);
X   if (*subject) {
X!     if ((strncmp(subject, "Re:", 3) != 0 && strncmp(subject, "Re;", 3) != 0))
X         strcat(SubjBuf, "Re: ");
X      strcat(SubjBuf, subject);
X     }
X  
X!  strcpy(CcBuf, ccList);
X!  strcpy(BccBuf, empty);
X  
X   sendMail(w);
X  } /* Reply */
X***************
X*** 503,509 ****
X   if (! mailpid)
X      Bell("No mail\n");
X   else {
X!  pos = XtTextGetInsertionPoint(WidgetOf(WidgetOf(toplevel, "vpane"), "indexWindow"));
X   num = PositionToMsgNumber(pos);	/* no current message returns zero */
X  
X   if (*cmd == 'C' || *cmd == 'S' || *cmd == 'W' || num == 0) {
X--- 610,616 ----
X   if (! mailpid)
X      Bell("No mail\n");
X   else {
X!  pos = XtTextGetInsertionPoint(WidgetOf(WidgetOf(toplevel, "topBox"), "indexWindow"));
X   num = PositionToMsgNumber(pos);	/* no current message returns zero */
X  
X   if (*cmd == 'C' || *cmd == 'S' || *cmd == 'W' || num == 0) {
X***************
X*** 513,519 ****
X         sprintf(Command, "%s \n", cmd);
X        }
X     } else {
X!     if ((n = TextGetLastPos(WidgetOf(WidgetOf(WidgetOf(toplevel, "vpane"), "commandPanel"), "fileWindow")) - StartPos) > 0) {
X         FileBuf[StartPos + n] = '\0';
X         p = FileBuf + StartPos;
X         sprintf(Command, "%s %d %s\n", cmd, num, p);
X--- 620,626 ----
X         sprintf(Command, "%s \n", cmd);
X        }
X     } else {
X!     if ((n = TextGetLastPos(WidgetOf(WidgetOf(WidgetOf(toplevel, "topBox"), "commandPanel"), "fileWindow")) - StartPos) > 0) {
X         FileBuf[StartPos + n] = '\0';
X         p = FileBuf + StartPos;
X         sprintf(Command, "%s %d %s\n", cmd, num, p);
X***************
X*** 554,560 ****
X   Widget	cw;
X  
X   if (! Highlighted) {
X!     cw = WidgetOf(WidgetOf(WidgetOf(toplevel, "vpane"), "commandPanel"), "Newmail");
X      XSetWindowBackgroundPixmap(XtDisplay(toplevel), XtWindow(cw), hatch);
X      XtUnmapWidget(cw);
X      XtMapWidget(cw);
X--- 661,667 ----
X   Widget	cw;
X  
X   if (! Highlighted) {
X!     cw = WidgetOf(WidgetOf(WidgetOf(toplevel, "topBox"), "commandPanel"), "Newmail");
X      XSetWindowBackgroundPixmap(XtDisplay(toplevel), XtWindow(cw), hatch);
X      XtUnmapWidget(cw);
X      XtMapWidget(cw);
X***************
X*** 573,585 ****
X  caddr_t	client_data;		/* unused */
X  caddr_t	call_data;		/* unused */
X  {
X!  Widget	cw;
X  
X   if (Highlighted) {
X-     cw = WidgetOf(WidgetOf(WidgetOf(toplevel, "vpane"), "commandPanel"), "Newmail");
X      XSetWindowBackground(XtDisplay(toplevel), XtWindow(cw), cw->core.background_pixel);
X      XtUnmapWidget(cw);
X      XtMapWidget(cw);
X      Highlighted = 0;
X     }
X  } /* UnsetNewmail */
X--- 680,692 ----
X  caddr_t	client_data;		/* unused */
X  caddr_t	call_data;		/* unused */
X  {
X!  Widget	cw = WidgetOf(WidgetOf(WidgetOf(toplevel, "topBox"), "commandPanel"), "Newmail");
X  
X   if (Highlighted) {
X      XSetWindowBackground(XtDisplay(toplevel), XtWindow(cw), cw->core.background_pixel);
X      XtUnmapWidget(cw);
X      XtMapWidget(cw);
X      Highlighted = 0;
X+     reset_mailbox(WidgetOf(WidgetOf(toplevel, "icon"), "mailbox"));
X     }
X  } /* UnsetNewmail */
X*** ../v1.0/defs.h	Sun May 27 21:05:48 1990
X--- defs.h	Sun May 27 21:11:35 1990
X***************
X*** 48,65 ****
X  #include <X11/StringDefs.h>
X  #include <X11/Shell.h>
X  #include <X11/Xatom.h>
X! #ifdef X11R3
X! #include <X11/Cardinals.h>
X! #include <X11/VPaned.h>
X! #include <X11/Form.h>
X! #include <X11/AsciiText.h>
X! #include <X11/TextP.h>
X! #include <X11/Box.h>
X! #include <X11/List.h>
X! #include <X11/Command.h>
X! #include <X11/Dialog.h>
X! #include <X11/Label.h>
X! #else
X  #include <X11/Xaw/Cardinals.h>
X  #include <X11/Xaw/VPaned.h>
X  #include <X11/Xaw/Form.h>
X--- 48,56 ----
X  #include <X11/StringDefs.h>
X  #include <X11/Shell.h>
X  #include <X11/Xatom.h>
X! 
X! #if XtSpecificationRelease >= 4
X! /* R4 */
X  #include <X11/Xaw/Cardinals.h>
X  #include <X11/Xaw/VPaned.h>
X  #include <X11/Xaw/Form.h>
X***************
X*** 70,81 ****
X  #include <X11/Xaw/Command.h>
X  #include <X11/Xaw/Dialog.h>
X  #include <X11/Xaw/Label.h>
X  #endif
X  
X! #define	TITLE		"xmail 1.0"	/* program title and version string */
X! #define	MAXARGS		20		/* max number of args */
X  #define	StartPos	 6		/* size of 'File: ' (del stop point) */
X- #define	XMAILER		"Mail"		/* name of mail program executable */
X  #define	LASTCH(s)	(s[strlen(s)-1])
X  #define	TEXTWIDTH	(TextFontStr->max_bounds.width)
X  #define	TEXTHEIGHT	(TextFontStr->max_bounds.descent + TextFontStr->max_bounds.ascent)
X--- 61,82 ----
X  #include <X11/Xaw/Command.h>
X  #include <X11/Xaw/Dialog.h>
X  #include <X11/Xaw/Label.h>
X+ #else
X+ /* R3 */
X+ #include <X11/Cardinals.h>
X+ #include <X11/VPaned.h>
X+ #include <X11/Form.h>
X+ #include <X11/AsciiText.h>
X+ #include <X11/TextP.h>
X+ #include <X11/Box.h>
X+ #include <X11/List.h>
X+ #include <X11/Command.h>
X+ #include <X11/Dialog.h>
X+ #include <X11/Label.h>
X  #endif
X  
X! #define	TITLE		"xmail 1."	/* program title and version string */
X  #define	StartPos	 6		/* size of 'File: ' (del stop point) */
X  #define	LASTCH(s)	(s[strlen(s)-1])
X  #define	TEXTWIDTH	(TextFontStr->max_bounds.width)
X  #define	TEXTHEIGHT	(TextFontStr->max_bounds.descent + TextFontStr->max_bounds.ascent)
X***************
X*** 89,94 ****
X--- 90,97 ----
X  typedef struct {
X      String	textFont;		/* xmail text font */
X      String	helpFont;		/* xmail help font */
X+     String	iconGeometry;		/* xmail icon geometry */
X+     String	MFileName;		/* mail option -f filename */
X      Dimension	shellWidth;		/* xmail window width */
X      Dimension	fileBoxWidth;		/* file window box width */
X      Dimension	indexHeight;		/* index window height */
X***************
X*** 105,117 ****
X      Dimension	helpY;			/* help y offset from textWindow */
X      Dimension	menuX;			/* menu x offset from parent */
X      Dimension	menuY;			/* menu y offset from parent */
X! 
X      Boolean	bellRing;		/* xmail audible bell option */
X-     Boolean	mailopt_i;		/* mail option -i */
X      Boolean	mailopt_n;		/* mail option -n */
X      Boolean	mailopt_U;		/* mail option -U */
X-     String	MFileName;		/* mail option -f filename */
X-     String	SubjectStr;		/* mail option -s subject */
X      Boolean	Show_Last;		/* xmail show latest option -ls */
X  } XmailResources;
X  
X--- 108,117 ----
X      Dimension	helpY;			/* help y offset from textWindow */
X      Dimension	menuX;			/* menu x offset from parent */
X      Dimension	menuY;			/* menu y offset from parent */
X!     Boolean	iconic;			/* xmail starts in withdrawn state */
X      Boolean	bellRing;		/* xmail audible bell option */
X      Boolean	mailopt_n;		/* mail option -n */
X      Boolean	mailopt_U;		/* mail option -U */
X      Boolean	Show_Last;		/* xmail show latest option -ls */
X  } XmailResources;
X  
X*** ../v1.0/directory.c	Sun May 27 21:05:49 1990
X--- directory.c	Sun May 27 21:09:58 1990
X***************
X*** 46,52 ****
X  String		*params;
X  Cardinal	*num_params;
X  {
X!  Arg		args[MAXARGS];
X   Cardinal	label_width, path_length, n, depth, x, y;
X   DIR		*new_dir, *dirp;
X   String		name, path;
X--- 46,52 ----
X  String		*params;
X  Cardinal	*num_params;
X  {
X!  Arg		args[6];
X   Cardinal	label_width, path_length, n, depth, x, y;
X   DIR		*new_dir, *dirp;
X   String		name, path;
X***************
X*** 106,121 ****
X      if (label_width) {
X      (void) sprintf(trans, b_Trans, depth, name);
X  
X!     n = 0;
X!     XtSetArg(args[n], XtNwidth, label_width);				n++;
X!     XtSetArg(args[n], XtNfont, TextFontStr);				n++;
X!     XtSetArg(args[n], XtNcallback, callbacks);				n++;
X!     XtSetArg(args[n], XtNtranslations, XtParseTranslationTable(trans));	n++;
X  /*
X  ** create the menu buttons
X  */
X      bw = NULL;
X!     for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp), n = 4) {
X          if (strcmp(dp->d_name, ".") && strcmp(dp->d_name, "..")) {
X  /*
X  ** If this 'folder file' is also a directory, mark it with a trailing slash '/'
X--- 106,120 ----
X      if (label_width) {
X      (void) sprintf(trans, b_Trans, depth, name);
X  
X!     XtSetArg(args[0], XtNwidth, label_width);
X!     XtSetArg(args[1], XtNfont, TextFontStr);
X!     XtSetArg(args[2], XtNcallback, callbacks);
X!     XtSetArg(args[3], XtNtranslations, XtParseTranslationTable(trans));
X  /*
X  ** create the menu buttons
X  */
X      bw = NULL;
X!     for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
X          if (strcmp(dp->d_name, ".") && strcmp(dp->d_name, "..")) {
X  /*
X  ** If this 'folder file' is also a directory, mark it with a trailing slash '/'
X***************
X*** 124,135 ****
X             sprintf(s, "%s/%s", path, dp->d_name);
X             if ((new_dir = opendir(s)) != NULL) {
X                sprintf(tmp, "%s/", dp->d_name);
X!               XtSetArg(args[n], XtNlabel, tmp);
X               } else
X!               XtSetArg(args[n], XtNlabel, dp->d_name);
X! 	   n++;
X!            XtSetArg(args[n], XtNfromVert, bw);				n++;
X!            bw = XtCreateManagedWidget("menubutton",commandWidgetClass,layout,args,n);
X  /*
X  ** If this 'folder' is a directory, add a button popup menu of its files.
X  */
X--- 123,133 ----
X             sprintf(s, "%s/%s", path, dp->d_name);
X             if ((new_dir = opendir(s)) != NULL) {
X                sprintf(tmp, "%s/", dp->d_name);
X!               XtSetArg(args[4], XtNlabel, tmp);
X               } else
X!               XtSetArg(args[4], XtNlabel, dp->d_name);
X!            XtSetArg(args[5], XtNfromVert, bw);
X!            bw = XtCreateManagedWidget("menubutton",commandWidgetClass,layout,args,6);
X  /*
X  ** If this 'folder' is a directory, add a button popup menu of its files.
X  */
X*** ../v1.0/environs.c	Sun May 27 21:05:50 1990
X--- environs.c	Sun May 27 21:11:35 1990
X***************
X*** 40,46 ****
X  {
X   static	char	tmp[BUFSIZ];
X   static	char	buf[BUFSIZ];
X!  char		*s, *p, *list, *value;
X   int		i, n;
X   FILE		*fp;
X  
X--- 40,46 ----
X  {
X   static	char	tmp[BUFSIZ];
X   static	char	buf[BUFSIZ];
X!  char		*s, *p, *list, *value, *index();
X   int		i, n;
X   FILE		*fp;
X  
X***************
X*** 50,55 ****
X--- 50,61 ----
X      strcpy(tmp, name);
X  /*
X  ** If not already done, extract the mail alias list and build the alias table.
X+ **
X+ ** We also provide support for the alias alias group, and the possibility that
X+ ** the user has entered multiple names for an alias without comma separation,
X+ ** or that mail has handed us a list with wierd comma combinations due to the
X+ ** user's attempts to include commas in the list.  Support is also provided
X+ ** for processing continuation lines, if we had to read the .mailrc ourselves.
X  */
X   if (! aliases) {
X      if (mailpid)
X***************
X*** 59,66 ****
X         list = XtMalloc(i);
X         strcpy(list, "");
X         if ((fp = fopen(mailrcFile(), "r")) != NULL) {
X!           while (s = fgets(buf, BUFSIZ, fp)) {
X!              if (strncmp(buf, "alias", 5) == 0) {
X                  for (s = &buf[5]; *s == ' ' || *s == '\t'; s++);
X                  if (strlen(list) + strlen(s) > i) {
X                     i += BUFSIZ;
X--- 65,73 ----
X         list = XtMalloc(i);
X         strcpy(list, "");
X         if ((fp = fopen(mailrcFile(), "r")) != NULL) {
X!           s = fgets(buf, BUFSIZ, fp);
X!           while (s) {
X!              if (strncmp(buf,"alias",5) == 0 || strncmp(buf,"group",5) == 0) {
X                  for (s = &buf[5]; *s == ' ' || *s == '\t'; s++);
X                  if (strlen(list) + strlen(s) > i) {
X                     i += BUFSIZ;
X***************
X*** 68,85 ****
X                    }
X                  strcat(list, s);
X                 }
X              }
X            fclose(fp);
X           }
X        }
X      for (i = 1, p = list; *p; p++) if (*p == '\n') i++;
X      aliases = (AliasRec **) XtMalloc((i + 1) * sizeof(AliasRec *));
X! 
X      for (n = 0, p = list; n < i && *p; n++, p++) {
X          aliases[n] = (AliasRec *) XtMalloc(sizeof(AliasRec));
X          for (aliases[n]->name = p; *p && *p != ' ' && *p != '\t'; p++);
X          for (*p++ = '\0'; *p && (*p == ' ' || *p == '\t'); p++);
X!         for (aliases[n]->alias = p; *p && *p != '\n'; p++);
X          if (*p) *p = '\0';
X         }
X      aliases[n] = (AliasRec *) XtMalloc(sizeof(AliasRec));
X--- 75,128 ----
X                    }
X                  strcat(list, s);
X                 }
X+              if (s[strlen(s) - 2] != '\\')	/* if not a continuation line */
X+                 s = fgets(buf, BUFSIZ, fp);	/* just read the next line */
X+              else {				/* resolve continuation lines */
X+                 while ((s = fgets(buf,BUFSIZ,fp)) && s[strlen(s)-2] == '\\') {
X+                       strcpy(&list[strlen(list) - 2], " ");
X+                       for (; *s == ' ' || *s == '\t'; s++);
X+                       if (strlen(list) + strlen(s) + 1 > i) {
X+                          i += BUFSIZ;
X+                          list = XtRealloc(list, i);
X+                         }
X+                       strcat(list, s);
X+                      }
X+                 if (s) {
X+                    strcpy(&list[strlen(list) - 2], " ");
X+                    for (; *s == ' ' || *s == '\t'; s++);
X+                    if (strlen(list) + strlen(s) + 1 > i) {
X+                       i += BUFSIZ;
X+                       list = XtRealloc(list, i);
X+                      }
X+                    strcat(list, s);
X+                    s = fgets(buf, BUFSIZ, fp);
X+                   }
X+                }
X              }
X            fclose(fp);
X           }
X        }
X+ /*
X+ ** count up the number of aliases in the list and allocate the list size
X+ */
X      for (i = 1, p = list; *p; p++) if (*p == '\n') i++;
X      aliases = (AliasRec **) XtMalloc((i + 1) * sizeof(AliasRec *));
X! /*
X! ** Copy the pointers for the alias names and values into an array, marking
X! ** the ends of each with a null and separating any multiple values with a
X! ** comma.  Ensure there is no trailing comma in the value list.
X! */
X      for (n = 0, p = list; n < i && *p; n++, p++) {
X          aliases[n] = (AliasRec *) XtMalloc(sizeof(AliasRec));
X+         for (; *p && (*p == ' ' || *p == '\t'); p++);
X          for (aliases[n]->name = p; *p && *p != ' ' && *p != '\t'; p++);
X          for (*p++ = '\0'; *p && (*p == ' ' || *p == '\t'); p++);
X!         for (aliases[n]->alias = p; *p && *p != '\n'; p++) {
X!             if ((*p == ' ' || *p == '\t') && *(p+1) && *(p+1) != '\n' &&
X!                *(p-1) != *p && *(p-1) != ',') *p = ',';
X!            }
X!         for (s = p - 1; *s == ',' || *s == ' ' || *s == '\t'; s--);
X!         if (*++s == ',' || *s == ' ' || *s == '\t') *s = '\0';
X          if (*p) *p = '\0';
X         }
X      aliases[n] = (AliasRec *) XtMalloc(sizeof(AliasRec));
X***************
X*** 86,95 ****
X      aliases[n] = NULL;
X     }
X  /*
X! ** If name is made up of more than one word, check each word for aliasing.
X  */
X   if (value = tmp) {
X!     if (strchr(tmp, ',') || strchr(tmp, ' ') || strchr(tmp, '\t')) {
X         buf[0] = '\0';
X         for (p = value; *p;) {
X             for (; *p && *p != ',' && *p != ' ' && *p != '\t'; p++);
X--- 129,138 ----
X      aliases[n] = NULL;
X     }
X  /*
X! ** If input is made up of more than one word, check each word for aliasing.
X  */
X   if (value = tmp) {
X!     if (index(tmp, ',') || index(tmp, ' ') || index(tmp, '\t')) {
X         buf[0] = '\0';
X         for (p = value; *p;) {
X             for (; *p && *p != ',' && *p != ' ' && *p != '\t'; p++);
X***************
X*** 127,158 ****
X  
X  /*
X  ** @(#)GetMailEnv() - Get environment value from mail or shell
X  */
X  char *
X  GetMailEnv(item)
X  char	*item;
X  {
X!  static char	*mailenv;
X!  char		*s, *c, *value, *getenv();
X   char		buf[BUFSIZ];
X   register int	length;
X  
X  
X   value = NULL;
X   if (! mailpid) {
X!     if (! (value = GetMailrc(item))) {
X!        if ((s = getenv(item)) != NULL)
X            value = XtNewString(s);
X        }
X     } else {
X!     if (! mailenv)
X!        mailenv = QueryMail("set");
X  
X!     for (s = mailenv; *s && strncmp(s, item, strlen(item)); s++)
X          for (; *s && *s != '\n'; s++);
X  
X      if (! *s) {
X!        if (s = getenv(item))
X            value = XtNewString(s);
X        } else {
X         for (; *s && *s != '"' && *s != '\n'; s++);
X--- 170,204 ----
X  
X  /*
X  ** @(#)GetMailEnv() - Get environment value from mail or shell
X+ **                    Accomodate the case of trailing blanks on the item.
X  */
X  char *
X  GetMailEnv(item)
X  char	*item;
X  {
X!  char		*mailenv, *s, *c, *value, *getenv();
X   char		buf[BUFSIZ];
X   register int	length;
X  
X  
X   value = NULL;
X+  strcpy(buf, item);
X+  for (length = 0; buf[length] && buf[length] != ' '; length++);
X+  buf[length] = '\0';
X+ 
X   if (! mailpid) {
X!     if (! (value = GetMailrc(buf))) {
X!        if ((s = getenv(buf)) != NULL)
X            value = XtNewString(s);
X        }
X     } else {
X!     mailenv = QueryMail("set");
X  
X!     for (s = mailenv; *s && strncmp(s, buf, length); s++)
X          for (; *s && *s != '\n'; s++);
X  
X      if (! *s) {
X!        if (s = getenv(buf))
X            value = XtNewString(s);
X        } else {
X         for (; *s && *s != '"' && *s != '\n'; s++);
X***************
X*** 166,171 ****
X--- 212,218 ----
X            value[length] = '\0';
X           }
X        }
X+     XtFree(mailenv);
X     }
X   return(value);
X  } /* GetMailEnv */
X***************
X*** 172,202 ****
X  
X  
X  /*
X! ** @(#)mailrcFile() - Return a pointer to fully qualified mailrc file name
X  */
X  char *
X  mailrcFile()
X  {
X!  char		*s, *h, *p, *getenv();
X   static char	buf[BUFSIZ];
X  
X!  if ((s = getenv("MAILRC")) == NULL) {
X      if ((s = getenv("HOME")) == NULL) s = "";
X      sprintf(buf, "%s/.mailrc", s);
X-    } else {
X-     if (*s == '/' || (*s != '~' && *s != '$')) sprintf(buf, "%s", s);
X-     else {
X-        if (*s == '~') {
X-           if ((h = getenv("HOME")) == NULL) h = "";
X-              sprintf(buf, "%s%s", h, &s[1]);
X-          } else {
X-           for (p = s; *p && (*p == '$' || *p == '{' || *p == '('); p++);
X-           for (s = p; *s && *s != '}' && *s != ')'; s++);
X-           *s++ = '\0';
X-           if ((h = getenv(p)) == NULL) h = "";
X-           sprintf(buf, "%s/%s", h, s);
X-          }
X-       }
X     }
X   return((char *)buf);
X  } /* mailrcFile */
X--- 219,237 ----
X  
X  
X  /*
X! ** @(#)mailrcFile() - Return a path to environment or default .mailrc file
X  */
X  char *
X  mailrcFile()
X  {
X!  char		*s, *getenv();
X   static char	buf[BUFSIZ];
X  
X!  if (s = getenv("MAILRC"))
X!     (void) strcpy(buf, s);
END_OF_FILE
if test 46474 -ne `wc -c <'Patch.01b'`; then
    echo shar: \"'Patch.01b'\" unpacked with wrong size!
fi
# end of 'Patch.01b'
fi
echo shar: End of archive 1 \(of 5\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 3 4 5 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 5 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0

dan
----------------------------------------------------
O'Reilly && Associates   argv at sun.com / argv at ora.com
Opinions expressed reflect those of the author only.



More information about the Comp.sources.x mailing list