Subject: jak.html From: R Ballard Date: Mon, 17 Apr 1995 19:27:08 -0400
How the Web Was Won
Subject: jak.html From: R Ballard Date: Mon, 17 Apr 1995 19:27:08 -0400


/*
 * xmail - X window system interface to the mail program
 *
 * Copyright 1990,1991,1992 by National Semiconductor Corporation
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of National Semiconductor Corporation not
 * be used in advertising or publicity pertaining to distribution of the
 * software without specific, written prior permission.
 *
 * NATIONAL SEMICONDUCTOR CORPORATION MAKES NO REPRESENTATIONS ABOUT THE
 * SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE.  IT IS PROVIDED "AS IS"
 * WITHOUT EXPRESS OR IMPLIED WARRANTY.  NATIONAL SEMICONDUCTOR CORPORATION
 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  IN NO
 * EVENT SHALL NATIONAL SEMICONDUCTOR CORPORATION BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 *
 * Author:  Michael C. Wagnitz - National Semiconductor Corporation
 *
 */


#include "global.h"
#include "MailwatchP.h"
#include "xmailregexp.h"
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#ifdef vms
extern int	noshare errno;
extern int	noshare sys_nerr;
extern char	noshare *sys_errlist[];
#else
extern int	errno;
extern int	sys_nerr;
extern char	*sys_errlist[];
#endif

extern	char	otherBuf[BUFSIZ];

#if ! defined(SIGCHLD) && defined(SIGCLD)
#define	SIGCHLD		SIGCLD
#endif

/*
** @(#)Autograph() - Add user's Sign or sign autograph to outgoing mail
**                   Then make button insensitive, to prevent multiple calls.
**                   If requested autograph signature does not exist, tell user.
**		     Because we can now be called by a translation table entry,
**		     check to see if already insensitive before proceeding.
*/
/* ARGSUSED */
void
Autograph(w, closure, call_data)
Widget	w;
XtPointer	closure;
XtPointer	call_data;		/* unused */
{
 int		n;
 String		cp, autograph;
 char		tmp[BUFSIZ], *C = (char *) closure;
 FILE		*fp;
 struct stat	st_buf;


 if (XtIsSensitive(w)) {	 /* if okay to proceed... */
    (void) strcpy(tmp, "Sign");  /* Default action is to use Sign autograph */
    if (*C == 'a') tmp[0] = 's';
    autograph = GetMailEnv(tmp); /* First, see if an autograph entry exists */

    if (! autograph) {
       /*
       ** If no Sign or sign, see if the user has created a .signature file
       */
       st_buf.st_size = 0;
       (void) sprintf(tmp, "%s/.Signature", HOME);
       if (*C == 'a')
          (void) sprintf(tmp, "%s/.signature", HOME);
       if (stat(tmp, &st_buf) != -1 &&
           st_buf.st_size < BUFSIZ &&
          (fp = fopen(tmp, "r")) != NULL) {
          autograph = (String) XtMalloc((unsigned) st_buf.st_size + 1);
          n = fread(autograph, sizeof(char), (int) st_buf.st_size, fp);
          autograph[n] = '\0';
          (void) fclose(fp);
         } else {
          (void) strcpy(tmp, "Cannot find a 'Sign'ature to append\n");
          if (*C == 'a') tmp[15] = 's';
          if (st_buf.st_size) {
             (void) sprintf(tmp,"Cannot append your .Signature (exceeds %d characters)\n",
                    BUFSIZ - 1);
             if (*C == 'a') tmp[20] = 's';
            }
          Bell(tmp);
          return;
         }
      } else {
       if ((int)strlen(autograph) >= BUFSIZ) {
          (void) sprintf(tmp,"Cannot append your Signature (exceeds %d characters)\n",
                    BUFSIZ - 1);
          if (*C == 'a') tmp[19] = 's';
          Bell(tmp);
          XtFree((String) autograph);
          return;
         }
      }

    XtSetSensitive(w, False);	/* Don't let us be pressed more than once */
    if (*C == 'A')		/* also make other sign button inoperative */
       XtSetSensitive(XtNameToWidget(XtParent(w), "autograph"), False);
    else			/* if this was a request for lowercase sign */
       XtSetSensitive(XtNameToWidget(XtParent(w), "Autograph"), False);

    for (cp = autograph, n = 0; n < BUFSIZ - 1 && *cp; cp++)
        if (*cp == '\\' && *(cp + 1) == 'n') {
           tmp[n++] = '\n';	/* Replace newline strings with a character */
           cp++;
          } else tmp[n++] = *cp;

    if (tmp[n - 1] != '\n')	/* make sure msg ends with a newline */
       tmp[n++] = '\n';
    tmp[n] = '\0';

    if ((fp = fopen(tmpName, "a")) != NULL) {
       if (*tmp != '-' || *(tmp + 1) != '-')	/* add a signature separator */
          (void) fwrite("-- \n", sizeof(char), 4, fp);
       (void) fwrite(tmp, sizeof(* tmp), strlen(tmp), fp);
       (void) fclose(fp);
      }
    XtFree((String) autograph);
   } /* end - if we were currently sensitive */
} /* Autograph */


/*
** @(#)endDelivery() - catch the signal when the delivery child finishes
*/
#if defined(sun) 
void
#else
int
#endif
endDelivery(signum)
int	signum;
{
 int	status;


 if (signum == SIGCHLD &&
     mailpid != wait(&status))		/* in case mail child was what died */
 (void) signal(SIGCHLD, SIG_DFL);	/* turn off the endDelivery hook */

#if !defined(sun) && !defined(SVR4)
 return 1;
#endif

} /* endDelivery */


/*
** @(#)DoCopy() - send a copy of the message to the indicated folder file
*/
DoCopy(file, to, subject, inreply, cc, bcc, outfolder, edits, add_face)
char	*file, *to, *subject, *inreply, *cc, *bcc;
int	outfolder, edits, add_face;
{
 int		len, n;
 time_t		clock;
 char		*m, tmp[BUFSIZ], From[BUFSIZ], Copy[BUFSIZ];
 MailwatchWidget mb = (MailwatchWidget) XtNameToWidget(toplevel,"icon.mailbox");
 FILE		*fp, *xf;
 struct stat	st_buf;


 if (file[0]) {
    st_buf.st_size = 0;			/* (in case msg file does not exist) */
    (void) stat(tmpName, &st_buf);

    (void) time(&clock);
    (void) sprintf(From, "From %s %24.24s\n", mb->mailbox.username, (char *) ctime(&clock));

    switch (file[0]) {
       case '|':			/* accomodate alias with Sun pipe cmd */
       (void) sprintf(Copy, "%s.pipe", tmpName);
                break;
       case '~':			/* file with a tilde expansion name */
          if (file[1] == '/')
             (void) sprintf(Copy, "%s%s", HOME, &file[1]);
          else {
             struct passwd *pw;

             for (len = 0, n = 1; file[n] && file[n] != '/';)
                 tmp[len++] = file[n++];
             tmp[len] = '\0';

             if (pw = getpwnam(tmp))
                (void) sprintf(Copy, "%s%s", pw->pw_dir, &file[n]);
             else (void) strcpy(Copy, file);
            }
                break;
       case '/':			/* file with an absolute path name */
                (void) strcpy(Copy, file);
                break;
       case '+':			/* file with a folder relative name */
                if (! foldir[0])
                   (void) strcpy(Copy, file);
                else
                   (void) sprintf(Copy, "%s%s", foldir, &file[1]);
                break;

        default:
                if (file[0] == '.' && file[1] == '/')
                   (void) strcpy(Copy, file);
                else if (outfolder == 0 || ! foldir[0]) {
                   if (strchr(file, '/') == NULL)	/* no dir reference */
                      (void) strcpy(Copy, file);
                   else		/* assume file with dir is relative to home */
                      (void) sprintf(Copy, "%s/%s", HOME, file);
                  } else {	/* if outfolder (and folder name is included) */
                      (void) sprintf(Copy, "%s%s", foldir, file);
                  }
                break;
      }

    if ((fp = fopen(Copy, "a")) == NULL) {
       /*
       ** Can't use the Bell routine internally, because we're a child.
       ** So, just pump the message to stderr and let user deal with it.
       */
       (void) sprintf(tmp, "Could not write file %s - %s\n", Copy,
              (errno < sys_nerr)? sys_errlist[errno]:"Unknown error");
       (void) fprintf(stderr, tmp);
      } else {
                     (void) fprintf(fp, From);
       if (*to)      (void) fprintf(fp, "To: %s\n", to);
       if (*subject) (void) fprintf(fp, "Subject: %s\n", subject);
       if (*inreply) (void) fprintf(fp, "%s\n", inreply);
       /*
       ** Add support for custom header information as a resource
       ** and for editheaders mail option.  If editheaders, find
       ** custom header information in message text.
       */
       if (edits) {
          int	skip;


          if (st_buf.st_size) {
             xf = fopen(tmpName, "r");
             while (fgets(tmp, BUFSIZ, xf) != NULL) {
                if (tmp[0] == '\n') break;
                if (tmp[0] != ' ' && tmp[0] != '\t') skip = 0;
                if (strncmp(tmp,"To: ", 4) == 0) { skip = 1; continue; }
                if (strncmp(tmp,"Subject: ", 9) == 0) { skip = 1; continue; }
                if (strncmp(tmp,"In-Reply-To: ",13)==0) { skip = 1; continue; }
                if (strncmp(tmp,"Forwarding: ",12)==0) { skip = 1; continue; }
                if (strncmp(tmp,"Cc: ", 4) == 0) { skip = 1; continue; }
                if (strncmp(tmp,"Bcc: ", 5) == 0) { skip = 1; continue; }
                if (! skip) (void) fprintf(fp, "%s", tmp);
               }
             (void) fclose(xf);
            } else
             if (m = XGetDefault(XtDisplay(toplevel), "XMail", "customHeader"))
               {
                if (m[0] == '"' || m[0] == "'"[0]) {
                   bcopy(m + 1, m, strlen(m) - 1);
                   while (LASTCH(m) == '"' || LASTCH(m) == "'"[0])
                         LASTCH(m) = '\0';
                  }
                if (LASTCH(m) != '\n')
                   (void) fprintf(fp, "%s\n", m);
                else
                   (void) fprintf(fp, "%s", m);
               }
         } else
       if (m = XGetDefault(XtDisplay(toplevel), "XMail", "customHeader")) {
           if (m[0] == '"' || m[0] == "'"[0]) {
              bcopy(m + 1, m, strlen(m) - 1);
              while (LASTCH(m) == '"' || LASTCH(m) == "'"[0])
                    LASTCH(m) = '\0';
             }
          if (LASTCH(m) != '\n')
                     (void) fprintf(fp, "%s\n", m);
          else
                     (void) fprintf(fp, "%s", m);
         }
       if (*cc)      (void) fprintf(fp, "Cc: %s\n", cc);
       if (*bcc)     (void) fprintf(fp, "Bcc: %s\n", bcc);
#ifdef X_FACE
       if (add_face) {
          (void) sprintf(tmp, "%s/.face", HOME);
          if (xf = fopen(tmp, "r")) {
             n = 1;
             while (fgets(tmp, BUFSIZ, xf) != NULL) {
                   if (n) {
                      n = 0;
                      if (strncmp(tmp, "X-Face:", 7) != 0)
                           (void) fprintf(fp, "X-Face:");
                     }
                   (void) fprintf(fp, "%s", tmp);
                  }
             (void) fclose(xf);
            }
         }
#endif /* X_FACE */
       (void) fprintf(fp, "\n");
       if (st_buf.st_size) {
          xf = fopen(tmpName, "r");
          while (fgets(tmp, BUFSIZ, xf) != NULL) {
                if (edits) {	/* if headers edited, drop them now */
                   if (tmp[0] == '\n') edits = 0;
                   continue;
                  }
                if (strncmp(tmp,"From ",5) == 0) (void)fprintf(fp,">");
                (void) fprintf(fp, "%s", tmp);
               }
          (void) fclose(xf);
          if (*tmp != '\n')
             (void) fprintf(fp, "\n");
         }
       (void) fclose(fp);
       if (file[0] == '|') {
          (void) sprintf(tmp, "/bin/cat %s %s", Copy, file);
          (void) system(tmp);
          (void) unlink(Copy);
         }
      } /* end - if we opened the target file successfully */
   } /* end - if passed file variable is not null */
} /* end - DoCopy */


/*
** @(#)Done() - Send composed message - if closure data says "Deliver"
*/
/* ARGSUSED */
void
Done(w, closure, call_data)
Widget w;
XtPointer closure;
XtPointer call_data;
{
 int		outfolder, n, len, edit_headers;
 int		add_face = 1;		/* Are we using faces.sendmail script */
 String		m, q, z ;
 char		record[BUFSIZ], Copy[BUFSIZ], tmp[BUFSIZ], addressees[BUFSIZ];
 char		To[BUFSIZ], Subject[BUFSIZ], Cc[BUFSIZ], Bcc[BUFSIZ];
 char		*c = (char *) closure;
 Widget		popup;
 Arg		args[1];
 FILE		*fp, *xf, *popen();
 struct stat	st_buf;
 struct passwd	*pw;


 Bell(Default_Status_Info);

 popup = XtNameToWidget(toplevel, "topBox.commandPanel.Send.popup");
 if (! popup) return;			/* SOMEthing would be VERY wrong here */

 XtPopdown(popup);			/* remove from view but don't destroy */
 XWarpPointer(XtDisplay(toplevel), None,
              XtWindow(XtNameToWidget(toplevel, "topBox.textWindow.text")),
              0,0,0,0, XMail.helpX * 2, XMail.helpY);

 st_buf.st_size = 0;			/* (in case msg file does not exist) */
 (void) stat(tmpName, &st_buf);
 record[0] = Copy[0] = tmp[0] = addressees[0] = '\0';
 To[0] = Subject[0] = Cc[0] = Bcc[0] = '\0';

 if (strcmp(c, "Deliver") != 0) {
    /*
    ** Restore sensitivity of the Autograph, Send, and reply for next time
    */
    XtSetSensitive(XtNameToWidget(XtParent(w), "Autograph"), True);
    XtSetSensitive(XtNameToWidget(XtParent(w), "autograph"), True);
    XtSetSensitive(XtParent(popup), True);
    XtSetSensitive(XtNameToWidget(toplevel, "topBox.commandPanel.reply"), True);
    n = st_buf.st_size;		/* the number of bytes in the message text */
    if (n == 0 && *c == 'c')
       Bell("No text to save in your dead letter file\n");
    else {
       if (n && (*c == 'c' || ! Confirm("REALLY discard this text"))) {
          if (! (m = GetMailEnv("DEAD")))
             (void) sprintf(Copy, "%s/dead.letter", HOME);
          else {
             (void) strcpy(record, m);
             XtFree((String) m);
             if (record[0] != '~')
                (void) strcpy(Copy, record);	/* take whatever is given */
             else {
                if (record[1] == '/')
                   (void) sprintf(Copy, "%s%s", HOME, &record[1]);
                else {
                   for (len = 0, n = 1; record[n] && record[n] != '/';)
                       tmp[len++] = record[n++];
                   tmp[len] = '\0';

                   if (pw = getpwnam(tmp))
                      (void) sprintf(Copy, "%s%s", pw->pw_dir, &record[n]);
                   else (void) strcpy(Copy, record);
                  }
               }
            }
          st_buf.st_size = -1;		/* see if our target exists */
          (void) stat(Copy, &st_buf);
          if (fp = fopen(Copy, "a")) {
             xf = fopen(tmpName, "r");
             while (fgets(tmp, BUFSIZ, xf) != NULL) {
                   if (strncmp(tmp, "From ", 5) == 0) (void) fprintf(fp, ">");
                   (void) fprintf(fp, "%s", tmp);
                  }
             (void) fclose(xf);
             if (*tmp != '\n')
                (void) fprintf(fp, "\n");
             (void) fclose(fp);

             (void) sprintf(tmp, "\"%s\" [%s] (%d bytes)\n", Copy,
                 (st_buf.st_size >= 0) ? "Appended" : "New file", n);
             Bell(tmp);
            } else {
             (void) sprintf(tmp, "Could not write file %s - %s\n", Copy,
                    (errno < sys_nerr)? sys_errlist[errno] : "Unknown error");
             Bell(tmp); 
            }
         }
      }					/* end - if some message text exists */
    (void) unlink(tmpName);		/* remove the message text file */
   } else {				/* Deliver this message text */
    /*
    ** Call the alias() routine recursively, to de-alias the user's To:, Cc:,
    ** and Bcc: fields.
    */
    To[0] = Subject[0] = Cc[0] = Bcc[0] = otherBuf[0] = '\0';
    /*
    ** Retrieve current values from the header buffers
    */
    m = NULL;
    XtSetArg(args[0], XtNstring, &m);
    XtGetValues(XtNameToWidget(popup, "*SubjCc*To"), args, 1);
    if (m && *m) {
       (void) strncpy(addressees, m, BUFSIZ);
       (void) strncpy(To, m, BUFSIZ);	/* in case there's no user recipient */
       /*
       ** alias() adds filenames to a list and returns just user addresses
       ** (it also automatically wraps long header lines)
       */
       for (m = alias(addressees); strcmp(m, addressees); m = alias(addressees))
           (void) strncpy(addressees, m, BUFSIZ);
       if (addressees[0])		/* if some real users are named... */
          (void) strncpy(To, addressees, BUFSIZ);
      }
    
    m = NULL;
    XtSetArg(args[0], XtNstring, &m);
    XtGetValues(XtNameToWidget(popup, "*SubjCc*Subject"), args, 1);

    if ((! addressees[0] && ! otherBuf[0]) || (! *m && st_buf.st_size == 0)) {
       if (! addressees[0])
          Bell("No recipient specified\n"); 
       else
          Bell("No subject and no message body\n"); 
       Waiting = TRUE;		/* so popup's EnterNotify won't overwrite msg */
       /*
       ** FORCE the user to either complete the message or abort delivery
       */
       XtPopup(popup, XtGrabNone);

       XSync(XtDisplay(toplevel), False);

       XtAddEventHandler(popup, StructureNotifyMask, False, warp_handler, (XtPointer)NULL);
      } else {			/* if there is a message to be delivered... */
       /*
       ** Restore the sensitivity of the Autograph, Send, and reply buttons
       */
       XtSetSensitive(XtNameToWidget(XtParent(w), "Autograph"), True);
       XtSetSensitive(XtNameToWidget(XtParent(w), "autograph"), True);
       XtSetSensitive(XtParent(popup), True);
       XtSetSensitive(XtNameToWidget(toplevel, "topBox.commandPanel.reply"), True);

       if (*m) {
          /*
          ** Format the subject line to wrap on ~70 characters.  In case the
          ** user didn't install the xmail default resources file, also look
          ** for imbedded newlines in the Subject text.
          */
          for (n = 0, len = 9; *m && n < BUFSIZ; n++, len++) {
              Subject[n] = *m++;
              if (Subject[n] == '\n') {
                 if (! *m) Subject[n] = '\0';
                 else if (len < 35) Subject[n] = ' ';
                      else { Subject[++n] = '\t'; len = 8; }
                } else if (len % 70 == 0)
                          if (Subject[n] == ' ') {
                             Subject[++n] = '\n';
                             Subject[++n] = '\t';
                             len = 8;
                            } else len--;	/* break at a word boundary */
             }
          Subject[n] = '\0';
         }
    
       m = NULL;
       XtSetArg(args[0], XtNstring, &m);
       XtGetValues(XtNameToWidget(popup, "*SubjCc*Cc"), args, 1);
       if (m && *m) {
          (void) strncpy(tmp, m, BUFSIZ);
          for (m = alias(tmp); strcmp(m, tmp); m = alias(tmp))
              (void) strncpy(tmp, m, BUFSIZ);

          if (*m) {
             if (addressees[0]) (void) strcat(addressees, ", ");
             (void) strcat(addressees, m);
             (void) strncpy(Cc, m, BUFSIZ);
            }
         }

       m = NULL;
       XtSetArg(args[0], XtNstring, &m);
       XtGetValues(XtNameToWidget(popup, "*SubjCc*Bcc"), args, 1);
       if (m && *m) {
          (void) strncpy(tmp, m, BUFSIZ);
          for (m = alias(tmp); strcmp(m, tmp); m = alias(tmp))
              (void) strncpy(tmp, m, BUFSIZ);

          if (*m) {
             if (addressees[0]) (void) strcat(addressees, ", ");
             (void) strcat(addressees, m);
             (void) strncpy(Bcc, m, BUFSIZ);
            }
         }
       /*
       ** To avoid a bug in Sun's sendmail (for occasionally not being able to
       ** find the name of the real author of the message), strip commas from
       ** the address list and pass the recipient names to sendmail on the
       ** command line, ala Mail.  Also, strip all but the actual address from
       ** any compound addresses present in the list.
       */
       for (q = addressees; *q; q++) {
           if (*q == ',') {		/* remove any commas */
              if (q[1] == ' ') {	/* if comma is followed by a space */
                 for (m = q, z = q + 1; *z;) *m++ = *z++;
                 *m = '\0';		/* then shift string left by one */
                }
              else *q = ' ';		/* else substitute space for comma */
              q++;
             }
           if (*q == '\n' && *(q+1) == '\t') {	/* drop any newline tabs */
              for (m = q, z = q + 2; *z;) *m++ = *z++;
              *m = '\0';
             }
           if (z = strchr(q, ',')) {	/* find the end of next alias in list */
              n = (int) (z - q);
              for (m = tmp, z = q; *z && n--;) *m++ = *z++;
              *m = '\0';		/* shorten our search to just this */
              if ((m = strchr(tmp, '<')) || (m = strchr(tmp, '('))) {
                 if (*m == '<') {	/* if its a chevroned address type */
                    (void) sscanf(m, "<%[^>]>", Copy);
                    len = strlen(Copy);	/* save the address part of this only */
                    for (m = Copy; *m && len--;) *q++ = *m++;
                    for (m = q; *z;) *m++ = *z++;
                    *m = '\0';		/* shift rest of addressees left */
                    for (; *q && *q != ','; q++);
                    if (*q) q--;
                   } else {		/* must be a parenthetical style */
                    for (n = 0; tmp[n] && strchr(" \n\t", tmp[n]); n++);
                    if (1 == sscanf(&tmp[n], "%*[^)]) %s", Copy)) {
                       bcopy(Copy, q, strlen(Copy));
                       m = q + strlen(Copy);
                       bcopy(z, m, strlen(z) + 1);
                       if (q = strchr(q, ',')) q--;
                      } else {
                       (void) sscanf(&tmp[n], "%s", Copy);	/* address preceeds */
                       m = q + strlen(Copy);
                       bcopy(z, m, strlen(z) + 1);
                       if (q = strchr(q, ',')) q--;
                      }
                   }
                } else q = z - 1;	/* skip to alias end if not compound */
             } else {			/* last (or only) alias in the list */
              if ((m = strchr(q, '<')) || (m = strchr(q, '('))) {
                 if (*m == '<') {
                    if (! sscanf(q, "%*[^<]<%[^>]>", Copy))
                         (void) sscanf(q, "<%[^>]>", Copy);
                    bcopy(Copy, q, strlen(Copy) + 1);
                   } else {
                    for (z = q; strchr(" \n\t", *z); z++);
                    if (1 == sscanf(z, "%*[^)]) %s", Copy)) {
                       bcopy(Copy, q, strlen(Copy) + 1);
                      } else {
                       (void) sscanf(z, "%s", Copy);
                       z[strlen(Copy) + 1] = '\0';
                      }
                   }
                }
              break;			/* no more commas to be replaced */
             }
          }

       if (! (m = GetMailEnv("sendmail")))
            m = XtNewString("/usr/lib/sendmail");
#ifdef X_FACE
       else {
          add_face = (strcmp(&m[strlen(m)-14], "faces.sendmail") != 0) ? 1 : 0;
         }
#endif /* X_FACE */
       /*
       ** The following arguments are passed to the sendmail command:
       **
       ** -oi	don't accept a dot on a line by itself as message termination
       **
       ** -om	send to "me" too, if I am a member of an alias expansion
       */
       (void) sprintf(tmp, "exec %s -oi -om %s\n", m, addressees);
       XtFree((String) m);

       initfoldir();

       if (m = GetMailEnv("outfolder")) {
          outfolder = 1;
          XtFree((String) m);
         } else outfolder = 0;

       if (m = GetMailEnv("record")) {
          (void) strncpy(record, m, BUFSIZ);
          XtFree((String) m);
         } else record[0] = '\0';

       if (m = GetMailEnv("editheaders")) {
          XtFree((String) m);
          edit_headers = 1;
         } else edit_headers = 0;

       /*
       ** Fork a child process to effect the message delivery functions.
       */
       if ((n = fork()) != 0) {			/* if we are not the child */
          if (n == -1) {			/* delivery fork failed ... */
             if (errno == ENOMEM)
                Bell("Not enough core for message delivery child\n");
             else
                Bell("No more processes - no message delivery!?!\n");
            } else				/* parent sets delivery hook */
             (void) signal(SIGCHLD, endDelivery);

          return;
         }
       /*
       ** Use this child process to effect our message delivery function.
       */
       (void) close(ConnectionNumber(XtDisplay(toplevel)));

       if (addressees[0]) {		/* if there are primary addresses... */
          /*
          ** First, mail the header information and message text (in temporary
          ** file) using sendmail.  If we fail, we can't use the Bell routine
          ** because we are a child process, so write any complaints to stderr.
          */
          if (! (fp = popen(tmp, "w")))
             (void) fprintf(stderr, "xmail: Couldn't connect to sendmail.\n"); 
          else {
             if (To[0])      (void) fprintf(fp, "To: %s\n", To);
             if (Subject[0]) (void) fprintf(fp, "Subject: %s\n", Subject);
             if (InReply[0]) (void) fprintf(fp, "%s\n", InReply);
             /*
             ** Add support for custom header information as a resource
             ** and for editheaders mail option.  If editheaders, find
             ** custom header information in message text.
             */
             if (edit_headers) {
                int	skip;

                if (st_buf.st_size) {
                   xf = fopen(tmpName, "r");
                   while (fgets(tmp, BUFSIZ, xf) != NULL) {
                      if (tmp[0] == '\n') break;
                      if (tmp[0] != ' ' && tmp[0] != '\t') skip = 0;
                      if (strncmp(tmp,"To: ", 4) == 0) {skip = 1; continue;}
                      if (strncmp(tmp,"Subject: ", 9) == 0) {skip=1;continue;}
                      if (strncmp(tmp,"In-Reply-To: ",13)==0) {skip=1;continue;}
                      if (strncmp(tmp,"Forwarding: ",12)==0) {skip=1;continue;}
                      if (strncmp(tmp,"Cc: ", 4) == 0) {skip = 1; continue;}
                      if (strncmp(tmp,"Bcc: ", 5) == 0) {skip = 1; continue;}
                      if (! skip) (void) fprintf(fp, "%s", tmp);
                     }
                   (void) fclose(xf);
                  } else
                   if (m = XGetDefault(XtDisplay(toplevel), "XMail", "customHeader"))
                     {
                      if (m[0] == '"' || m[0] == "'"[0]) {
                         bcopy(m + 1, m, strlen(m) - 1);
                         while (LASTCH(m) == '"' || LASTCH(m) == "'"[0])
                               LASTCH(m) = '\0';
                        }
                      if (LASTCH(m) != '\n')
                         (void) fprintf(fp, "%s\n", m);
                      else
                         (void) fprintf(fp, "%s", m);
                     }
               } else
             if (m = XGetDefault(XtDisplay(toplevel), "XMail", "customHeader"))
               {
                if (m[0] == '"' || m[0] == "'"[0]) {
                   bcopy(m + 1, m, strlen(m) - 1);
                   while (LASTCH(m) == '"' || LASTCH(m) == "'"[0])
                         LASTCH(m) = '\0';
                  }
                if (LASTCH(m) != '\n')
                   (void) fprintf(fp, "%s\n", m);
                else
                   (void) fprintf(fp, "%s", m);
               }

             if (Cc[0])      (void) fprintf(fp, "Cc: %s\n", Cc);
             if (Bcc[0])     (void) fprintf(fp, "Bcc: %s\n", Bcc);
#ifdef X_FACE
             /*
             ** Look for, and add contents of, user's ~/.face file unless
             ** user is already invoking the faces.sendmail script, which
             ** does the job itself.  In that case, don't add info here.
             ** To accomodate both cases, look for and add header if none. 
             */
             if (add_face) {
                (void) sprintf(tmp, "%s/.face", HOME);
                if (xf = fopen(tmp, "r")) {
                   n = 1;
                   while (fgets(tmp, BUFSIZ, xf) != NULL) {
                         if (n) {
                            n = 0;
                            if (strncmp(tmp, "X-Face:", 7) != 0)
                                 (void) fprintf(fp, "X-Face:");
                           }
                         (void) fprintf(fp, "%s", tmp);
                        }
                   (void) fclose(xf);
                  }
               }
#endif /* X_FACE */
             (void) fprintf(fp, "\n");	/* separate the header from any text */
             /*
             ** Now write message text (if any) to the sendmail process.  ANY
             ** line which begins with the keyword ``From '' gets prepended
             ** with a greater than (>) symbol.
             */
             if (st_buf.st_size) {
                xf = fopen(tmpName, "r");
                len = edit_headers;
                while (fgets(tmp, BUFSIZ, xf) != NULL) {
                      if (len) {	/* if headers edited, drop them now */
                         if (tmp[0] == '\n') len = 0;
                         continue;
                        }
                      if (strncmp(tmp,"From ",5) == 0) (void) fprintf(fp, ">");
                      (void) fprintf(fp, "%s", tmp);
                     }
                (void) fclose(xf);

                if (tmp[0] != '\n')
                   (void) fprintf(fp, "\n");	/* ensure a blank last line */
               }
             (void) pclose(fp);		/* this concludes sendmail delivery */
            }
          /*
          ** If user has set ``record'' in their .mailrc,
          ** add a message copy to that record file.
          */
          (void) DoCopy(record, To, Subject, InReply, Cc, Bcc,
                        outfolder, edit_headers, add_face);

         }			/* end - if there are any primary addresses */
       /*
       ** If other addresses exist, send copies to those files or folders.
       */
       if (*otherBuf) {
          for (m = otherBuf; *m;) {
              for (q = m; *q && *q != ','; q++);
              if (*q == ',') {
                 *q = '\0';
                 n = 1;
                } else n = 0;

              (void) DoCopy(m, To, Subject, InReply, Cc, Bcc,
                            outfolder, edit_headers, add_face);

              q += n;
              m = q;
             }			/* end - for each record in otherBuf */
         }			/* end - if there were records in otherBuf */
       (void) unlink(tmpName);	/* remove any message text */
       exit(1);			/* the delivery child sub-process */
       /* NOTREACHED */
      }				/* end - if there was something to deliver */
   }				/* end - if we wanted to deliver a message */
} /* Done */


/*
** @(#)DoIt() - send command - passed via client_data argument - to mail
*/
/* ARGSUSED */
void
DoIt(w, closure, call_data)
Widget		w;
XtPointer		closure;
XtPointer		call_data;
{
 int		n;
 Arg		args[1];
 String		c, buf;


 SetCursor(NORMAL);
 (void) sprintf(Command, "%s\n", closure);
 if (mailpid) {				/* If connections are okay,... */
    if ((n = match(command_pattern, Command)) != XM_C_FILE && n != XM_C_NEWMAIL) {
       SetCursor(WATCH);		/* will be reset by parser routine */
       writeMail(Command);
      } else {				/* check for commit of any changes */
       buf = NULL;
       XtSetArg(args[0], XtNlabel, &buf);
       XtGetValues(XtNameToWidget(toplevel, "topBox.titleBar.title"), args, 1);

       c = strrchr(buf, 'l');  if (c) c -= 2;
       if (! c || strncmp(c, "deleted", 7) != 0 ||
           strcmp(closure, "inc") == 0 ||
           Confirm("COMMIT all changes to this folder")) {
          writeMail(Command);
          SetCursor(WATCH);
          (void) strcpy(lastFolder, buf);	/* save for utimes update */
         }
      }
   } else if (XM_C_NEWMAIL != match(command_pattern, Command))
         Bell("No current mail connection\n");		/* if not 'Newmail' */
     else {
         SetCursor(WATCH);		/* will be reset by parser routine */
         if (mailargc > 2 && strcmp(mailargv[mailargc - 2], "-f") == 0) {
            mailargc -= 2;		/* throw away any folder argument */
            mailargv[mailargc] = NULL;	/* and NULL end of argument list */
           }
         callMail(mailargv);		/* restart the mail connections */
         (void) strcpy(Command, "Start"); /* Let em know we've re-started */
         UnsetNewmail(w, (XtPointer) NULL, (XtPointer) NULL);
         In_Bogus_Mail_File = False;	/* reset this so titleBar will chg */
        }
} /* DoIt */


/*
** @(#)DoPrint() - Call the PrintMsg action routine from a callback
*/
/* ARGSUSED */
void
DoPrint(w, closure, call_data)
Widget	w;
XtPointer closure;
XtPointer	call_data;
{
 PrintMsg(w, NULL, NULL, NULL);
} /* DoPrint */


/*
** @(#)DoQuit() - Terminate xmail after first closing mail connection
*/
/* ARGSUSED */
void
DoQuit(w, closure, call_data)
Widget w;
XtPointer closure;
XtPointer call_data;
{
 Arg		args[1];
 String		c, buf, C = (char *) closure;


 if (mailpid) {				/* check for commit of any changes */
    buf = NULL;
    XtSetArg(args[0], XtNlabel, &buf);
    XtGetValues(XtNameToWidget(toplevel, "topBox.titleBar.title"), args, 1);

    c = strrchr(buf, 'l');  if (c) c -= 2;
    if (*C != 'q' || ! c || strncmp(c, "deleted", 7) != 0 ||
        Confirm("Changes in folder.  REALLY quit")) {
       (void) sprintf(Command, "%s\n", C);
       writeMail(Command);
      } else return;
   }

 XCloseDisplay(XtDisplay(toplevel));

 _exit(0);
} /* DoQuit */


/*
** @(#)DoSet() - send specified set request to mail and destroy current menu.
**		 To accommodate those systems where mail cannot handle the
**		 'set no' commands, convert 'set no's to unsets.
*/
/* ARGSUSED */
void
DoSet(w, closure, call_data)
Widget	w;
XtPointer	closure;
XtPointer	call_data;
{
 char	*c, buf[32];


 if (! mailpid)
    Bell("No current mail connection\n");
 else {
    SetCursor(WATCH);
    c = w->core.name;
    if ((int)strlen(c) > 5 && strcmp(&c[strlen(c) - 6], "expert") == 0)
       if (*c == 'n')
            XMail.expert = (Boolean) 0;
       else XMail.expert = (Boolean) 1;
    else {
       if (*c == 'n')
          (void) sprintf(buf, "unset %s", &c[2]);
       else
          (void) sprintf(buf, "set %s", c);

       c = QueryMail(buf);
      }

    XtDestroyWidget(XtParent(XtParent(w)));
    SetCursor(NORMAL);
   }
} /* DoSet */


/* ARGSUSED */
/*
** @(#)DoWith() - send client_data command to mail with selected msg number
*/
void
DoWith(w, client_data, call_data)
Widget	w;
XtPointer	client_data;
XtPointer	call_data;
{
 int	num = 1;
 char 	*c = (char *) client_data;


 Waiting = TRUE;		/* so popup's EnterNotify won't overwrite msg */
 if (*c == 'n' || *c == '-')
    DoSelected(w, (XEvent *)NULL, &c, (Cardinal *)&num);
 else if (! mailpid) Bell("No current mail connection\n");
 else {
    SetCursor(WATCH);
    num = SelectionNumber(*c == 'u');

    if (num) (void) sprintf(Command, "%s %d\n", c, num);
    else (void) sprintf(Command, "%s \n", c);

    writeMail(Command);
   }
} /* DoWith */


/* ARGSUSED */
/*
** @(#)DropIt() - callback to destroy the current folder popup list(s)
*/
void
DropIt(w, client_data, call_data)
Widget w;
XtPointer client_data;
XtPointer call_data;
{
 Widget	popup = XtNameToWidget(toplevel,"topBox.commandPanel.Folder.popupList");
 if (popup)
    XtDestroyWidget(popup);
 SetCursor(NORMAL);
} /* DropIt */


/*
** @(#)GetAliasName() - retrieve alias name from button label
*/
/* ARGSUSED */
void
GetAliasName(w, shell, call_data)
Widget		w;
Widget		shell;
XtPointer		call_data;		/* unused */
{
 Arg		args[1];
 String		alias_name;


 XtSetArg(args[0], XtNlabel, &alias_name);
 XtGetValues(w, (ArgList) args, 1);	/* get this entry's label value */

 XtPopdown(XtParent(XtParent(w)));	/* aliasList<-table<-entry */

 if (TextGetLastPos(shell))		/* if some alias is already in there */
    writeTo(shell, ", ", APPEND);	/* add comma separator between names */

 writeTo(shell, alias_name, APPEND);
} /* GetAliasName */


/*
** @(#)GetFolderName() - retrieve full folder name from button labels
*/
/* ARGSUSED */
void
GetFolderName(w, client_data, call_data)
Widget	w;
XtPointer	client_data, call_data;
{
 Arg		args[1];
 int		k, n, x;
 String		folder_name;
 Widget		shell;
 char		tmp[BUFSIZ], buf[BUFSIZ];


 XtSetArg(args[0], XtNlabel, &folder_name);
 XtGetValues(w, (ArgList) args, 1);

 if (! call_data)				/* just a simple label name */
    (void) sprintf(buf, "File: %s", folder_name);
 else {						/* multiple stack of names */
    tmp[0] = '\0';
    shell = w;
    (void) sscanf(call_data, "%d", &n);		/* using the nesting depth */

    for (x = 1, k = (n * 2) + n - 1; k; k--) {
        shell = shell->core.parent;		/* travel up the widget tree */
        if (++x == 3) {				/* when we get to a label... */
           x = 0;
           (void) strcpy(buf, shell->core.name); /* stuff label name in */
           (void) strcat(buf, tmp);		/* front of previous labels */
           (void) strcpy(tmp, buf);		/* to build a complete path */
          }
       }
    (void) sprintf(buf, "File: +%s%s", tmp, folder_name);
   }
 writeTo(XtNameToWidget(toplevel, "topBox.commandPanel.fileWindow"),
         buf, REPLACE);
} /* GetFolderName */


/*
** @(#)ReEdit() - Call the editMail routine to re-edit a message
*/
/* ARGSUSED */
void
ReEdit(w, closure, call_data)
Widget	w;		/* unused */
XtPointer closure;	/* unused */
XtPointer	call_data;	/* unused */
{
 Widget	Popup = XtNameToWidget(toplevel, "topBox.commandPanel.Send.popup");


 if (! Popup) {
    XBell(XtDisplay(toplevel), 33);
    return;				/* SOMEthing must be VERY wrong here */
   }

 XtPopdown(Popup);			/* pop down the send popup */

 editMail();				/* re-edit the message file */
} /* ReEdit */


/*
** @(#)Reply() - send a reply to the author of the selected message
**               include its text and/or copy the other recipients, if asked.
*/
/* ARGSUSED */
void
Reply(w, client_data, call_data)
Widget w;
XtPointer client_data;
XtPointer call_data;
{
 int		n, fd, alwaysIgnore, edit_headers, erasable = 0;
 String		p, q, r, txt;
 char		*us, *getlogin(), *C = (char *) client_data;
 char		oldFrom[BUFSIZ], author[BUFSIZ], returnPath[BUFSIZ];
 char		toList[BUFSIZ], date[BUFSIZ], subject[BUFSIZ], ccList[BUFSIZ];
 char		Recipient[BUFSIZ];
 Widget		sb = XtNameToWidget(toplevel, "topBox.commandPanel.Send");
 
#if defined(SIGACTION) || defined(SVR4) || defined(linux)
 struct sigaction outvec; 
 
 (void) sigaction(SIGCHLD, NULL, &outvec);
 if (outvec.sa_handler != SIG_DFL)
#else
 struct	sigvec	ovec;

 (void) sigvec(SIGCHLD, NULL, &ovec);
 if (ovec.sv_handler != SIG_DFL)
#endif
   {
    Bell("Still delivering your previous message.  Please try again later.\n");
    return;
   }

 XtSetSensitive(sb, False);	/* Don't start more than one composition */
 XtSetSensitive(XtNameToWidget(toplevel, "topBox.commandPanel.reply"), False);

 oldFrom[0] = author[0] = returnPath[0] = date[0] = subject[0] = '\0';
 ccList[0] = toList[0] = '\0';

 if (p = GetMailEnv("editheaders")) {
    XtFree((String) p);
    edit_headers = 1;
   } else edit_headers = 0;

 if (*C != 's' || edit_headers) {
    if ((fd = open(tmpName, O_WRONLY | O_CREAT, 0600)) == -1) {
       Bell("xmail: Cannot open the temp file\n");
       return;
      }

    if (p = GetMailEnv("alwaysignore")) {
       XtFree((String) p);
       alwaysIgnore = (strchr("SRA", *C)) ? 1 : 0;
      } else alwaysIgnore = 0;

    if (alwaysIgnore)		/* do we need to include a limited copy? */
       (void) sprintf(Command, "p %d", SelectionNumber(False));
    else
       (void) sprintf(Command, "P %d", SelectionNumber(False));

    if ((p = GetMailEnv("indentprefix")) != NULL)
       erasable = 1;
    else
       p = "\t";

    txt = QueryMail(Command);

    switch (*C) {
       case 'S':
            (void) write(fd, "---------- Begin Forwarded Message ----------\n", 46);
            /*
            ** Any lines that begin with keyword 'From ' get a leading symbol
            */
            for (q = r = txt; *r;) {
                for (; *r && *r != '\n'; r++);
                    if (*r == '\n') {		/* For each line of text */
                       if (strncmp(q, "From ", 5) == 0)
                          (void) write(fd, ">", 1);
                       (void) write(fd, q, r - q + 1);
                       q = ++r;
                      }
               }
            if (*q) {				/* should never happen, but. */
               if (strncmp(q, "From ", 5) == 0)
                  (void) write(fd, ">", 1);
               (void) write(fd, q, strlen(q));	/* write last line of text */
               if (LASTCH(q) != '\n')
                  (void) write(fd, "\n", 1);
              }
            (void) write(fd, "----------- End Forwarded Message -----------\n", 46);
            break;
       case 'R':
       case 'A':
            n = strlen(p);
            for (q = r = txt; *r;) {
                for (; *r && *r != '\n'; r++);
                    if (*r == '\n') {		/* For each line of insert */
                       (void) write(fd, p, n);	/* write indent prefix, */
                       (void) write(fd, q, r - q + 1);	/* followed by text */
                       q = ++r;
                      }
               }
            if (*q) {				/* should never happen, but. */
               (void) write(fd, p, n);		/* write the indent prefix, */
               (void) write(fd, q, strlen(q));	/* this last line of text, */
               if (LASTCH(q) != '\n')
                  (void) write(fd, "\n", 1);	/* and an ending newline. */
              }
            if (erasable)
               XtFree((String) p);
            break;
      } /* end - switch on client_data */

    (void) close(fd);

    if (alwaysIgnore) {		/* get full headers for data (top 100 lines) */
       txt = QueryMail("unset alwaysignore");
       (void) sprintf(Command, "top %d", SelectionNumber(False));
       txt = QueryMail(Command);
      }
    /*
    ** strip header information from the original message
    */
    for (p = txt; *p; p++) {
        if (*p == '\n' || strncmp(p, "Status:", 7) == 0) break;

        if (strncmp(p, "From ", 5) == 0 ) {
           bzero(oldFrom, BUFSIZ);
           p += 5;
           for (q = p; *q && *q != ' ' && *q != '\n'; q++);
           (void) strncpy(oldFrom, p, q - p);	/* drop the date portion now */
           for (; *q && *q != '\n'; q++);	/* skip to end of this line */
           p = q;
          }

        else if (strncmp(p, "Return-Path:", 12) == 0) {
           bzero(returnPath, BUFSIZ);
           p += 13;
           for (q = p; *q && *q != '\n'; q++);
           (void) strncpy(returnPath, p, q - p); /* drop trailing newline */	
           p = q;
          }

        else if (strncmp(p, "Date:", 5) == 0) {
           bzero(date, BUFSIZ);
           p += 6;
           for (q = p; *q && *q != '\n'; q++);
           (void) strncpy(date, p, q - p);
           p = q;
          }

        else if (strncmp(p, "From:", 5) == 0) {
           bzero(author, BUFSIZ);
           p += 6;
           for (q = p; *q && *q != '\n'; q++);
           while (*(q+1) && strchr(" \t", *(q+1))) {
                 *q = ' ';		/* change this newline to a space */
                 *(q+1) = ' ';		/* change possible tab to a space */
                 for (q++; *q && *q != '\n'; q++);
                }
           (void) strncpy(author, p, q - p);
           p = q;
          }

        else if (strncmp(p, "To:", 3) == 0) {
           bzero(toList, BUFSIZ);
           p += 4;
           for (q = p; *q && *q != '\n'; q++);
           while (*(q+1) && strchr(" \t", *(q+1))) {
                 *q = ' ';		/* change this newline to a space */
                 *(q+1) = ' ';		/* change possible tab to a space */
                 for (q++; *q && *q != '\n'; q++);
                }
           if (*C == 'a' || *C == 'A')
              (void) strncpy(toList, p, q - p);
           p = q;
          }

        else if (strncmp(p, "Subject:", 8) == 0) {
           bzero(subject, BUFSIZ);
           p += 9;
           for (q = p; *q && *q != '\n'; q++);
           while (*(q+1) && strchr(" \t", *(q+1))) {
                 *q = ' ';		/* change this newline to a space */
                 *(q+1) = ' ';		/* change possible tab to a space */
                 for (q++; *q && *q != '\n'; q++);
                }
           (void) strncpy(subject, p, q - p);
           p = q;
          }

        else if (strncmp(p, "Cc:", 3) == 0) {
           bzero(ccList, BUFSIZ);
           p += 4;
           for (q = p; *q && *q != '\n'; q++);
           while (*(q+1) && strchr(" \t", *(q+1))) {
                 *q = ' ';		/* change this newline to a space */
                 *(q+1) = ' ';		/* change possible tab to a space */
                 for (q++; *q && *q != '\n'; q++);
                }
           if (*C == 'a' || *C == 'A')
              (void) strncpy(ccList, p, q - p);
           p = q;
          }
        else for (; *p && *p != '\n'; p++);
       } /* end - for all of message body */

    if (alwaysIgnore)			/* restore this if originally set */
       p = QueryMail("set alwaysignore");

    if (toList[0] != '\0') {		/* remove ourself from the list */
       if (! (us = getlogin())) {
          struct passwd *pw = getpwuid((uid_t) getuid());

          if (pw)
             us = pw->pw_name;
          else
             us = "no_name";
         }
       for (p = toList; *us && *p; p++) {
           if (strncmp(p, us, strlen(us)) == 0) {
              for (q = p + strlen(us); *q && *q != ',' && *q != ' '; q++);
              for (; *q && (*q == ',' || *q == ' '); q++);
              bcopy(q, p, strlen(q) + 1);
              continue;
             }
           while (*p && *p != ',' && *p != ' ') p++;
           while (*p && (*p == ',' || *p == ' ')) p++;
           p--;
          }
      }
   } /* end - if client_data does not equal 's' */

 InReply[0] = Recipient[0] = '\0';
/*
** If message did not have a 'From:', use 'Return-Path:' for reply recipient.
** If message also did not have a 'Return-Path', use the older style 'From '.
*/
 if (*C != 'S' && *C != 's') {
    p = author;
    if (! *p && returnPath[0]) 
       p = returnPath;
    if (! *p && oldFrom[0])
       p = oldFrom;

    (void) strcpy(Recipient, p);
/*
** If author's name consists of a compound address (i.e. name 
, ** (Name) address, or equivalents...) strip off the real address portion ** (i.e. that portion not in parens, but possibly between chevrons). */ if ((p = strchr(Recipient, '<')) || (p = strchr(Recipient, '('))) switch (*p) { case '<': q = strchr(p++, '>'); *q = '\0'; /* '
Name' or 'Name
' */ bcopy(p, Recipient, strlen(p) + 1); break; case '(': q = strchr(p, ')'); /* skipping past the parens */ if (p == Recipient) { /* '(Name) address' format */ for (q++; *q && (*q == ' ' || *q == '\t'); q++); bcopy(p, Recipient, strlen(p) + 1); } else { /* 'address (Name)' format */ for (; (p-1) > Recipient && (*(p-1) == ' ' || *(p-1) == '\t'); p--); *p = '\0'; } break; } /* ** If this sender wishes to include all recipients of the original message in ** this response, include all others except this sender in that address list. */ if (toList[0] && (*C == 'a' || *C == 'A')) { if (LASTCH(Recipient) && LASTCH(Recipient) != ',' && (int)strlen(Recipient) + 2 < BUFSIZ) (void) strcat(Recipient, ", "); if ((int)strlen(Recipient) + (int)strlen(toList) < BUFSIZ) (void) strcat(Recipient, toList); for (p = Recipient + strlen(Recipient) - 1; *p == ' ' || *p == ','; p--); *++p = '\0'; /* drop any trailing ", " garbage */ } } if (*C != 's' && author[0] && date[0]) { r = (*C == 'S') ? "Forwarding" : "In-Reply-To"; (void) sprintf(InReply, "%s: Mail from '%s'\n%*sdated: %s", r, author, strlen(r) - 5, " ", date); } sendMail(sb); fd = -1; if (edit_headers) { (void) sprintf(Command, "%s_", tmpName); if (rename(tmpName, Command)) Bell("xmail: Cannot rename edit file for editheaders\n"); else if ((fd = open(tmpName, O_WRONLY | O_CREAT, 0600)) < 0) { Bell("xmail: Cannot reopen the edit file for editheaders\n"); return; } } if (! Recipient[0]) { writeTo(XtNameToWidget(sb, "*To"), "", REPLACE); if (fd >= 0) (void) write(fd, "To: \n", 5); } else { writeTo(XtNameToWidget(sb, "*To"), Recipient, REPLACE); if (fd >= 0) { if (*C == 's' && edit_headers) (void) write(fd, "To: \n", 5); else { (void) write(fd, "To: ", 4); (void) write(fd, Recipient, strlen(Recipient)); (void) write(fd, "\n", 1); } } } if (! subject[0]) { writeTo(XtNameToWidget(sb, "*Subject"), "", REPLACE); if (fd >= 0) (void) write(fd, "Subject: \n", 10); } else { n = ((strchr("Rr", subject[0]) != NULL) && (strchr("Ee", subject[1]) != NULL) && (strchr(":;", subject[2]) != NULL)); if (n) writeTo(XtNameToWidget(sb, "*Subject"), subject, REPLACE); else { writeTo(XtNameToWidget(sb, "*Subject"), "Re: ", REPLACE); writeTo(XtNameToWidget(sb, "*Subject"), subject, APPEND); } if (fd >= 0) { if (*C == 's' && edit_headers) (void) write(fd, "Subject: \n", 10); else { (void) write(fd, "Subject: ", 9); if (! n) (void) write(fd, "Re: ", 4); (void) write(fd, subject, strlen(subject)); (void) write(fd, "\n", 1); if (InReply[0]) { (void) write(fd, InReply, strlen(InReply)); (void) write(fd, "\n", 1); } } if (p = XGetDefault(XtDisplay(toplevel), "XMail", "customHeader")) { if (p[0] == '"' || p[0] == "'"[0]) { bcopy(p + 1, p, strlen(p) - 1); while (LASTCH(p) == '"' || LASTCH(p) == "'"[0]) LASTCH(p) = '\0'; } (void) write(fd, p, strlen(p)); if (LASTCH(p) != '\n') (void) write(fd, "\n", 1); } } } if (! ccList[0]) { writeTo(XtNameToWidget(sb, "*Cc"), "", REPLACE); if (fd >= 0 && edit_headers) (void) write(fd, "Cc: \n", 5); } else { writeTo(XtNameToWidget(sb, "*Cc"), ccList, REPLACE); if (fd >= 0) { (void) write(fd, "Cc: ", 4); (void) write(fd, ccList, strlen(ccList)); (void) write(fd, "\n", 1); } } writeTo(XtNameToWidget(sb, "*Bcc"), "", REPLACE); if (fd >= 0 && edit_headers) (void) write(fd, "Bcc: \n", 6); if (fd >= 0) { (void) write(fd, "\n", 1); if ((erasable = open(Command, O_RDONLY)) < 0) { Bell("xmail: Cannot reread the edit file for editheaders\n"); return; } (void) unlink(Command); while (n = read(erasable, Command, BUFSIZ)) (void) write(fd, Command, n); (void) close(erasable); (void) close(fd); } editMail(); } /* Reply */ /* ** @(#)Save() - (or copy) a message to specified folder or mbox */ /* ARGSUSED */ void Save(w, client_data, call_data) Widget w; XtPointer client_data; XtPointer call_data; { int num; String p, r, FBuf; XawTextPosition pos; Arg args[1]; Widget fileWindow; char *cmd = (char *) client_data; if (! mailpid) Bell("No current mail connection\n"); else { SetCursor(WATCH); /* reset by parser routines */ num = SelectionNumber(False); /* no current message returns zero */ if (*cmd == 'C' || *cmd == 'S' || num == 0) { if (num) { (void) sprintf(Command, "%s %d\n", cmd, num); Bell(""); /* Reset bell worthyness flag */ } else { (void) sprintf(Command, "%s \n", cmd); } } else { fileWindow = XtNameToWidget(toplevel, "topBox.commandPanel.fileWindow"); pos = TextGetLastPos(fileWindow); if (pos - StartPos > 0) { XtSetArg(args[0], XtNstring, &FBuf); XtGetValues(fileWindow, args, 1); if (FBuf[pos] != '\0') FBuf[pos] = '\0'; p = XtNewString(&FBuf[StartPos]); (void) sprintf(Command, "%s %d %s\n", cmd, num, p); XtFree((String) p); } else { /* ** If no specified filename, use the mbox pointer. We MUST include ** it here, because specifying the message number for the action ** would be interpreted as a filename, if we didn't append one. */ if (! (p = GetMailEnv("MBOX"))) (void) sprintf(Command, "%s %d %s/mbox\n", cmd, num, HOME); else { initfoldir(); if (*p != '+' && (*p == '/' || (*p == '.' && *(p+1) == '/') || foldir[0] == '\0')) { (void) sprintf(Command, "%s %d %s\n", cmd, num, p); } else { (void) sprintf(Command, "%s %d %s%s\n", cmd, num, foldir, (*p == '+') ? &p[1] : p); } XtFree((String) p); } } } writeMail(Command); } } /* Save */ /* ** @(#)SetNewmail - Highlight Newmail button to attract user attention */ /* ARGSUSED */ void SetNewmail(w, client_data, call_data) Widget w; /* unused */ XtPointer client_data; /* unused */ XtPointer call_data; /* unused */ { Widget cw; if (! Highlighted) { cw = XtNameToWidget(toplevel, "topBox.commandPanel.Newmail"); XSetWindowBackgroundPixmap(XtDisplay(toplevel), XtWindow(cw), hatch); XtUnmapWidget(cw); XtMapWidget(cw); Highlighted = 1; reset_mailbox(XtNameToWidget(toplevel, "icon.mailbox"), 0); } } /* SetNewmail */ /* ** @(#)UnsetNewmail - Remove Newmail button highlighting */ /* ARGSUSED */ void UnsetNewmail(w, client_data, call_data) Widget w; /* unused */ XtPointer client_data; /* unused */ XtPointer call_data; /* unused */ { Widget cw = XtNameToWidget(toplevel, "topBox.commandPanel.Newmail"); if (Highlighted) { XSetWindowBackground(XtDisplay(toplevel), XtWindow(cw), cw->core.background_pixel); XtUnmapWidget(cw); XtMapWidget(cw); Highlighted = 0; reset_mailbox(XtNameToWidget(toplevel, "icon.mailbox"), 1); } } /* UnsetNewmail */ /* * xmail - X window system interface to the mail program * * Copyright 1990,1991,1992 by National Semiconductor Corporation * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of National Semiconductor Corporation not * be used in advertising or publicity pertaining to distribution of the * software without specific, written prior permission. * * NATIONAL SEMICONDUCTOR CORPORATION MAKES NO REPRESENTATIONS ABOUT THE * SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" * WITHOUT EXPRESS OR IMPLIED WARRANTY. NATIONAL SEMICONDUCTOR CORPORATION * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO * EVENT SHALL NATIONAL SEMICONDUCTOR CORPORATION BE LIABLE FOR ANY SPECIAL, * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Michael C. Wagnitz - National Semiconductor Corporation * */ #include "global.h" String Autograph_Info[] = { "Append your 'Sign'ature (if any) to the message text", "Append your 'sign'ature (if any) to the message text", NULL }; String Copy_Info[] = { "Copy the selected message to the specified folder", "Copy the message to a folder named for it's author", NULL }; String Default_Status_Info = "Press for help on any window"; String Delete_Info[] = { "Delete the currently selected message", "Undelete the selected or most recently deleted message", NULL }; String Deliver_Info[] = { "Deliver this message", "Re-edit this message", "Cancel the request but save the text in the dead letter file", "Abort this request and discard the text", NULL }; String Folder_Info[] = { "Access the specified folder, or select from the list", "Copy this folder name to the fileWindow", "Copy the folder path to the fileWindow or view the next level", NULL }; String Hold_Info[] = { "Preserve the selected message in the system folder", NULL }; String NewMail_Info[] = { "Re-read your system mail folder", "Incorporate new mail without committing any current changes", "Make xmail refresh the folder list next time it's displayed", NULL }; String Print_Info[] = { "Print the selected message on the system printer", NULL }; String Quit_Info[] = { "Quit xmail", "Leave xmail without committing any current changes", NULL }; String Read_Info[] = { "Read the next message", "Read the previous message", "Read the current message", "Read the current message, and include full mail headers", NULL }; String Reply_Info[] = { "Reply to the author of the message", "Reply to the author of, and include the message text", "Include all recipients of the original message in your reply", "Include all recipients, and the text, of this message", NULL }; String Save_Info[] = { "Save the selected message in the specified folder", "Save the message in a folder named for it's author", "Write the message to the folder, but don't include headers", NULL }; String Send_Info[] = { "Compose and send a new mail message", "Forward a copy of the selected mail message", NULL }; String SendMail_Info[] = { "Specify the name(s) of the recipient(s) ( for help)", "Enter the subject of this message ( for help)", "Specify the names of any carbon copy recipients ( for help)", "Enter the names of any blind carbon copy recipients ( for help)", NULL }; String Abort_Help = "\n\n\n\n\n\n\ Pressing the \"Abort\" button cancels delivery of the\n\ message, and deletes any text that may have been created."; String Bcc_Help = "\n\ Specify any blind carbon copy recipients for this message\n\ using the Bcc: window. Blind carbon recipient names are\n\ removed from the message prior to delivery.\n\n\ Pressing the right mouse button in this window displays\n\ a list of your aliases. Releasing the right mouse\n\ button while one of the alias names is highlighted\n\ copies that name into the window, preceding it with a\n\ comma if necessary.\n\n\ Standard editing functions associated with the text widget\n\ are supported, and can be altered using the application\n\ resources."; String Cancel_Help = "\n\n\n\n\n\ Pressing the \"Cancel\" button causes delivery of this\n\ message to be abandoned, but saves a copy of the message\n\ text in your dead letter file (default $HOME/dead.letter)\n\ without any header information."; String Cc_Help = "\n\n\ Specify carbon copy recipients for this message using the\n\ Cc: window. Multiple recipients should be comma separated.\n\n\ Pressing the right mouse button in this window displays a\n\ list of your aliases. Releasing the right mouse button\n\ while one of the alias names is highlighted copies that\n\ name into this window, preceded with a comma if needed.\n\n\ Standard editing functions associated with the text widget\n\ are supported, and can be altered using the application\n\ resources."; String Copy_Help = "\n\ Pressing this button copies the current message to the\n\ file or folder named in the File: window, without marking\n\ the original for removal. (If a folder name is not\n\ specified, it will be copied to your mbox folder.)\n\n\ The right mouse button pops up a menu for both the copy\n\ and Copy commands.\n\n\ The uppercase (Copy) command copies the message to a file\n\ whose name is derived from the author of the message,\n\ rather than from any name currently in the File: window.\n\n\ See also the save command help for additional information."; String Delete_Help = "\ Pressing this button removes the selected message from the\n\ current folder.\n\n\ The right mouse button displays a menu for both the delete\n\ and undelete commands.\n\n\ Undelete restores the selected message (if it has been\n\ marked 'D'eleted), otherwise the deleted message with the\n\ smallest message number is restored.\n\n\ Undelete may be used repeatedly to restore all deleted\n\ messages if changes have not yet been committed.\n\n\ See also preserve, save, folder, Newmail, and quit."; String Deliver_Help = "\n\n\n\n\n\ The Deliver button will send the composed message text\n\ to your sendmail daemon for delivery to the specified\n\ recipient(s)."; String File_Help = "\n\ The File: window provides a mechanism for specifying a\n\ file or folder name for use by other xmail commands.\n\n\ Text entered beyond the right margin of the window will\n\ cause a horizontal scrollbar to appear, for scrolling the\n\ displayed text to the left or right as needed for viewing.\n\n\ Pressing the backspace or delete key erases a previously\n\ entered character. Control_W (^W) erases a previous word\n\ and Control_U (^U) the entire line.\n\n\ See the folder and save commands for more information."; String Folder_Help = "\ The left button changes the active folder to the one\n\ specified in the File: window. Changing folders COMMITs\n\ any modifications to the current folder.\n\n\ The right button displays a menu of folders from which to\n\ choose. Clicking the left button on a directory (indicated\n\ by trailing slash) while still holding down the right,\n\ expands that directory if it contains files. Folders with\n\ unread messages will be highlighted by a hatch pattern.\n\ Releasing the right button copies the selected name to the\n\ File: window.\n\n\ The current menu can be erased (to include new folders\n\ created since the menu was last generated) by using the\n\ Drop option provided with the Newmail command button menu."; String Hold_Help = "\n\ The Preserve command marks the selected message for\n\ retention in the system mailbox. Normally when a message\n\ is 'saved' to some other folder file, it is automatically\n\ deleted from your system folder. 'Preserve' causes mail\n\ to not remove the original from your system mail folder.\n\n\ Pressing the right mouse button on the Preserve command\n\ presents a menu of four mail (and one xmail) variables\n\ that may be toggled while currently operating in xmail.\n\n\ Commands listed denote what state each variable will be\n\ changed to, if the appropriate label is highlighted when\n\ the right mouse button is released."; String Index_Help = "\n\ The index window displays a list of mail messages in the\n\ current folder, as well as the currently selected message.\n\n\ Pressing the left mouse button anywhere on a line marks\n\ the message as selected (for other commands) but does not\n\ automatically display the message in the text window.\n\n\ Pressing the right button selects and also automatically\n\ displays the message.\n\ See also the next command help for additional information.\n\n\ The index window header list may be scrolled using either\n\ the scrollbar and mouse or keyboard keys. See the Text\n\ window help for a description of the keys supported."; String NewMail_Help = "\ The Newmail button will be highlighted with a hatching\n\ pattern whenever new mail has arrived for your account.\n\n\ Pressing the NewMail button accesses your system folder\n\ (if mail exists) and includes any new mail delivered\n\ since the last time your system folder was accessed.\n\ This action also resets any button highlighting, and\n\ COMMITS any changes that may have been made to the\n\ current folder. (Confirmation provided if not expert.)\n\n\ The right mouse button provides a menu for committing\n\ changes, incorporating new messages without committing\n\ changes (only if currently in your system folder), or\n\ causing xmail to redetermine the list of mail folders."; String Print_Help = "\n\n\n\ Pressing this button causes the selected message to be\n\ printed on the system printer.\n\n\ A message will be displayed in the status window\n\ indicating which message was printed, along with its\n\ size in bytes.\n\n\ See also the Index window for help on selecting a message."; String Quit_Help = "\n\n\ quit - terminates xmail, committing changes made to the\n\ current folder.\n\n\ The right mouse button pops up a menu for the quit and\n\ exit commands.\n\n\ Use exit when you wish to leave xmail without committing\n\ the current folder's changes.\n\n\ See also the folder, Newmail, and delete commands."; String Read_Help = "\n\ Pressing this button causes the next message in the list\n\ to be displayed in the text (bottom) window.\n\n\ Current message selection is indicated by caret (>) in\n\ the index (top) window.\n\n\ The right mouse button displays a menu for reading the\n\ next message, reading the previous or current message,\n\ or reading the current message with full headers (this\n\ overrides any suppression of normally ignored fields).\n\n\ See also the Index window help for more information."; String ReEdit_Help = "\n\n\n\n\n\ Use the ReEdit selection to perform additional changes\n\ to the current message composition. When completed, you\n\ will again be presented with the send completion menu."; String Reply_Help = "\n\n\ reply - initiates the mechanism to create and send a mail\n\ message to the author of a current message.\n\n\ The right mouse button displays a menu for selecting\n\ 'reply', 'reply included', 'replyall' (which addresses all\n\ recipients of the original mail), or 'replyall included'.\n\ The include options automatically copy the original\n\ message into the new one.\n\nSee also the Send command."; String Save_Help = "\n\ save - copies a message to the file or folder named in\n\ the File: window, marking the original for deletion.\n\ If none is specified, the name in your environment MBOX\n\ is used ($HOME/mbox by default).\n\n\ The right button pops up a menu of related commands.\n\n\ A written (vs. copied) message does not include mail\n\ headers or trailing blank line.\n\n\ Uppercase commands create a file named from the author of\n\ the message, rather than any name in the File: window."; String Send_Help = "\n\ send - initiates the mechanism to create and send a\n\ message to the designated recipient(s). The right mouse\n\ button displays a menu which provides the choice of\n\ 'send'ing, or 'forwarding a message'. Forwarding includes\n\ the text of the current message in the new one.\n\n\ As with the 'reply' command, a dialog box is provided to\n\ specify the name of the recipient(s), subject, and to whom\n\ to send copies of this message. Pressing the 'Deliver'\n\ button completes the operation.\n\n\ See also the reply command help for additional information."; String Sign_Help = "\n\n\n\ Pressing this Autograph button will append your .mailrc\n\ defined 'Sign'ature (uppercase 'S') text to the current\n\ message composition, replacing any backslash-'n' character\n\ combinations (\\n) found in it with true newline characters.\n\ (See the Mail(1) man page for details on defining a Sign.)\n\n\ If your .mailrc does not contain a Sign definition, xmail\n\ will look for a .Signature file in your home directory,\n\ appending its contents, if any, to the current composition."; String sign_Help = "\n\n\n\ Pressing this autograph button will append your .mailrc\n\ defined 'sign'ature (lowercase 's') text to the current\n\ message composition, replacing any backslash-'n' character\n\ combinations (\\n) found in it with true newline characters.\n\ (See the Mail(1) man page for details on defining a sign.)\n\n\ If your .mailrc does not contain a sign definition, xmail\n\ will look for a .signature file in your home directory,\n\ appending its contents, if any, to the current composition."; String Status_Help = "\n\n\n\ The Status window displays xmail program info, status, and\n\ error messages.\n\n\ Error messages usually cause the terminal bell to ring, to\n\ attract the user's attention.\n\n\ The BELL can be disabled, by either including the command\n\ line option -nb, or by specifying the '*bellRing' resource\n\ as False."; String Subject_Help = "\n\n\ The Subject: window provides a method for specifying the\n\ subject for this mail message.\n\n\ Text entered beyond the right margin of the window will\n\ cause a horizontal scrollbar to appear, for scrolling the\n\ displayed text to the left or right as needed for viewing.\n\n\ Pressing the backspace or delete key erases a previously\n\ entered character, while Control_W (^W) erases a previous\n\ word and Control_U (^U) to the beginning of the line."; String Text_Help = "\n\ The text window displays the currently selected message.\n\ See the Index window help on how to select a message.\n\n\ Text and index windows may be scrolled using either the\n\ mouse and scrollbar, or the keyboard keys in the manner\n\ of text display programs such as \"more\" and \"less\".\n\n\ spacebar - scroll down a page b - scroll up a page\n\ return - scroll down a line k - scroll up a line\n\ G - go to end of text ' - go to top of text\n\n\ The both windows also support keyboard access to each of\n\ the command buttons. See the xmail man page for details\n\ or press the question mark key (?) within the text window."; String Text2_Help = "\n\ Keyboard key defaults that duplicate command button actions:\n\n\ a - REPLY to ALL recipients A - REPLY to ALL INCLUDED\n\ c - COPY a message C - COPY to AUTHOR file\n\ d - DELETE the message u - UNDELETE a message\n\ f - READ with FULL headers F - FORWARD a message\n\ m - MAIL a message M - REPLY to a message\n\ i - Incorporate NEW MAIL N - retrieve NEW MAIL\n\ p - read PREVIOUS message P - PRINT a message\n\ r - READ the current message R - REPLY included\n\ s - SAVE current message S - SAVE to AUTHOR\n\ n - read the NEXT message w - WRITE current message\n\ q - QUIT, committing changes x - EXIT, no commits\n\ ? - DISPLAY this help info - REMOVE this help info"; String Title_Help = "\n\n\n\n\ The Titlebar window displays the xmail program name and the\n\ current version number, along with the name of the current\n\ mail folder being accessed, and its message count(s).\n\n\ Pressing the left mouse button on the National Semiconductor\n\ Corporation logo in the top left corner of the title bar\n\ issues an XLib request to iconify this xmail application."; String To_Help = "\n\ Use the To: window to specify the recipients for this mail\n\ message. Text entered beyond the right margin of the\n\ window will cause a horizontal scrollbar to appear, for\n\ scrolling the displayed text left or right as desired for\n\ viewing. Pressing the backspace or delete key erases the\n\ previously entered character, while Control_W (^W) erases\n\ a previous word and Control_U (^U) to the start of a line.\n\n\ Pressing the right mouse button in this window displays a\n\ list of your alias names. Releasing the right mouse\n\ button while one of the names is highlighted will copy\n\ that name into the window, prepending it with a comma if\n\ needed."; /* HelpText */ /* * xmail - X window system interface to the mail program * * Copyright 1990,1991,1992 by National Semiconductor Corporation * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of National Semiconductor Corporation not * be used in advertising or publicity pertaining to distribution of the * software without specific, written prior permission. * * NATIONAL SEMICONDUCTOR CORPORATION MAKES NO REPRESENTATIONS ABOUT THE * SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" * WITHOUT EXPRESS OR IMPLIED WARRANTY. NATIONAL SEMICONDUCTOR CORPORATION * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO * EVENT SHALL NATIONAL SEMICONDUCTOR CORPORATION BE LIABLE FOR ANY SPECIAL, * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * The following software modules were created and are Copyrighted by National * Semiconductor Corporation: * * 1. warp_handler: * 2. extract_of: * 3. endEdits: * 4. editMail: * 5. makeHeading: * 6. makeButton: * 7. sendMail: * * Author: Michael C. Wagnitz - National Semiconductor Corporation * */ #include "global.h" #include #include #include #include #ifdef vms extern int noshare errno; #else extern int errno; #endif #if ! defined(SIGCHLD) && defined(SIGCLD) #define SIGCHLD SIGCLD #endif #ifndef DEFAULT_VISUAL #ifndef linux #define DEFAULT_VISUAL "/usr/ucb/vi" #else #define DEFAULT_VISUAL "/usr/bin/vi" #endif #endif static int editMail_pid; /* ARGSUSED */ void warp_handler(Widget w, XtPointer client_data, XEvent *event, Boolean *continueToDispatch) { Widget Popup = XtNameToWidget(toplevel,"topBox.commandPanel.Send.popup"); Widget To = XtNameToWidget(Popup, "SubjCc.To"); if (event->type == MapNotify) { XWarpPointer(XtDisplay(toplevel), None, XtWindow(To), 0,0,0,0, 15, 10); XtRemoveEventHandler(Popup, StructureNotifyMask, False, warp_handler, NULL); } } /* ** @(#)extract_of - strip off header information from a buffer and return ** the extracted information and the incremented pointer */ char * extract_of(char **p) { int n; static char tmp[BUFSIZ]; for (n = 0; *(*p); (*p)++) { if (*(*p) == '\n' && *((*p) + 1) != ' ' && *((*p) + 1) != '\t') break; if (*(*p) == '\n') { if (tmp[n - 1] != ' ' && tmp[n - 1] != '\t') tmp[n++] = ' '; for ((*p)++; *(*p) && (*(*p) == ' ' || *(*p) == '\t');) (*p)++; } if (*(*p) != '\n') tmp[n++] = *(*p); } tmp[n] = '\0'; return((char *)tmp); } /* ** @(#)endEdits() - catch the signal when the edit child finishes ** (The idea for this was ``borrowed'' from xrn.) ** If editheaders is set, extract selected header ** information from the message text file and ** install it in the appropriate header windows. ** Then, popup the completion window with header ** edit windows and completion control buttons. */ #if defined(sun) || defined(SVR4) void #else int #endif endEdits(int signum) { int fd, status; String p, q; char buf[BUFSIZ]; Widget sb, Popup; if (signum != SIGCHLD) #if defined(sun) || defined(SVR4) return ; #else return 1; #endif if (editMail_pid != wait(&status)) #if defined(sun) || defined(SVR4) return ; /* the mail child could die too */ #else return 1; #endif (void) signal(SIGCHLD, SIG_DFL); /* turn off the endEdits hook */ sb = XtNameToWidget(toplevel, "topBox.commandPanel.Send"); if (p = GetMailEnv("editheaders")) { XtFree((String) p); if ((fd = open(tmpName, O_RDONLY)) >= 0) { while (1) { bzero(Command, BUFSIZ); status = read(fd, Command, BUFSIZ); for (p = Command; *p; p++) { if (*p == '\n' && *(p - 1) == '\n') { status = 0; break; } if (strncmp(p, "To: ", 4) == 0) { p += 4; writeTo(XtNameToWidget(sb, "*To"), extract_of(&p), REPLACE); } else if (strncmp(p, "Subject: ", 9) == 0) { p += 9; writeTo(XtNameToWidget(sb,"*Subject"),extract_of(&p),REPLACE); } else if (strncmp(p, "In-Reply-To: ", 13) == 0) { p += 13; (void) strcpy(buf, extract_of(&p)); if (! (q = strchr(buf, ':'))) (void) sprintf(InReply, "In-Reply-To: %s", buf); else { q -= 5; if (strncmp(q, "dated: ", 7) != 0) (void) sprintf(InReply, "In-Reply-To: %s", buf); else { *(q - 1) = '\0'; (void) sprintf(InReply, "In-Reply-To: %s\n ", buf); (void) strcat(InReply, q); } } } else if (strncmp(p, "Forwarding: ", 12) == 0) { p += 12; (void) strcpy(buf, extract_of(&p)); if (! (q = strchr(buf, ':'))) (void) sprintf(InReply, "Forwarding: %s", buf); else { q -= 5; if (strncmp(q, "dated: ", 7) != 0) (void) sprintf(InReply, "Forwarding: %s", buf); else { *(q - 1) = '\0'; (void) sprintf(InReply, "Forwarding: %s\n ", buf); (void) strcat(InReply, q); } } } else if (strncmp(p, "Cc: ", 4) == 0) { p += 4; writeTo(XtNameToWidget(sb, "*Cc"), extract_of(&p), REPLACE); } else if (strncmp(p, "Bcc: ", 5) == 0) { p += 5; writeTo(XtNameToWidget(sb, "*Bcc"), extract_of(&p), REPLACE); } else { for (;*p && *p != '\n';) p++; } } if (status < BUFSIZ) break; } (void) close(fd); } } Popup = XtNameToWidget(sb, ".popup"); SetXY(Popup, XtNameToWidget(toplevel, "topBox.commandPanel"), 0, 0); XtPopup(Popup, XtGrabNone); XSync(XtDisplay(toplevel), False); XtAddEventHandler(Popup, StructureNotifyMask, False, warp_handler, NULL); #if defined(sun) || defined(SVR4) return ; #else return 1; #endif } /* ** @(#)editMail() - edit a mail message using the preferred editor ** ** Support is now provided for declaring the editor command as an xmail ** resource, ala xrn. If the resource ``xmail.editorCommand'' is defined, ** it must contain an `sprintf'-able format string that provides for the ** inclusion of both a display name and the name of the file to be edited. ** If the resource declaration is not included, or does not contain the two ** required percent-s (%s) formatting strings, xmail will use the VISUAL ** resource. If VISUAL is used, try to accommodate those editors (emacs, ** xedit...) which start their own window in X11. We know for a fact that ** vi and ed variants do not invoke windows. We assume any other editor ** specification does. */ void editMail(void) { String edit, cp; char cmd[BUFSIZ]; Display *ad; bzero(cmd, BUFSIZ); ad = XtDisplay(XtNameToWidget(toplevel, "topBox.statusWindow")); /* ** If editorCommand resource exists, use it (format validated during initialize) */ if (XMail.editorCommand) (void) sprintf(cmd, XMail.editorCommand, DisplayString(ad), tmpName); else { /* ** Otherwise, default to the VISUAL method of starting things */ if (! (edit = GetMailEnv("VISUAL"))) edit = XtNewString(DEFAULT_VISUAL); if ((cp = strrchr(edit, '/')) == NULL) cp = edit; else cp++; if (strcmp(cp, "ed") == 0 || strcmp(cp,"red") == 0 || strcmp(cp, "ex") == 0 || strcmp(cp, "vi") == 0) { (void) sprintf(cmd, "exec xterm -display %s -name XMail -title 'Message entry' -e %s %s", DisplayString(ad), edit, tmpName); } else (void) sprintf(cmd, "exec %s -display %s %s", edit, DisplayString(ad), tmpName); XtFree((String) edit); } editMail_pid = fork(); switch (editMail_pid) { case -1: /* fork failed ... */ if (errno == ENOMEM) Bell("Not enough core for edits\n"); else Bell("No more processes - no edits\n"); break; case 0: /* child starts the message entry session */ (void) close(ConnectionNumber(XtDisplay(toplevel))); (void) execl("/bin/sh", "sh", "-c", cmd, 0); perror("editMail: Failed to start the text editor"); (void) _exit(127); break; default: /* parent waits for editing to conclude */ (void) signal(SIGCHLD, endEdits); break; } } /* editMail */ /* ** @(#)readMail() - callback invoked every time input is pending on mail fd ** ** Calls QueryMail() to read all available data from mail file descriptor, ** and passes output to parse() for analysis and appropriate action. */ /* ARGSUSED */ void readMail(XtPointer client_data, int *source, XtInputId *id) /* unused */ /* unused */ /* unused */ { SetCursor(WATCH); parse(QueryMail("")); } /* readMail */ /* ** @(#)makeHeading() - Create the specified message header windows */ void makeHeading(Widget parent, String label_string, Widget *left, Widget *above, String info, String help_text) { Arg args[11]; char resource_name[10]; Widget input_window; XtSetArg(args[0], XtNfromVert, *left); XtSetArg(args[1], XtNfromHoriz, NULL); XtSetArg(args[2], XtNlabel, label_string); XtSetArg(args[3], XtNborderWidth, 0); XtSetArg(args[4], XtNfont, XMail.buttonFont); XtSetArg(args[5], XtNheight, XMail.buttonHeight + XMail.borderWidth + 7); XtSetArg(args[6], XtNwidth, XMail.buttonWidth); XtSetArg(args[7], XtNjustify, XtJustifyLeft); XtSetArg(args[8], XtNinternalHeight, 0); XtSetArg(args[9], XtNinternalWidth, 1); *left = XtCreateManagedWidget("SubjCc", labelWidgetClass, parent, args, 10); bzero(resource_name, 9); (void) strncpy(resource_name, label_string, strlen(label_string) - 1); input_window = CreateInputWindow(parent, resource_name); XtSetArg(args[0], XtNfromVert, *above); XtSetArg(args[1], XtNfromHoriz, *left); XtSetValues(input_window, args, 2); AddInfoHandler(input_window, info); AddHelpText(input_window, help_text); *above = input_window; } /* makeHeading */ /* ** @(#)makeButton() - Create the specified command button with callback */ void makeButton(Widget parent, String label, XtCallbackProc CBProc, String CBData, String info, String help_text) { Arg args[3]; Widget button; int width = ((((int)XMail.shellWidth-2)/6) - (int)XMail.borderWidth*2) - 4; XtSetArg(args[0], XtNfont, XMail.buttonFont); XtSetArg(args[1], XtNheight, XMail.buttonHeight); XtSetArg(args[2], XtNwidth, width); button = XtCreateManagedWidget(label, commandWidgetClass, parent, args, 3); XtAddCallback(button, XtNcallback, CBProc, CBData); AddInfoHandler(button, info); AddHelpText(button, help_text); } /* makeButton */ /* ** @(#)sendMail() - Create the send window popup for message headers */ void sendMail(Widget parent) { Arg args[11]; Widget Popup, Layout, Box, left, above; Popup = XtNameToWidget(parent, "popup"); if (! Popup) { XtSetArg(args[0], XtNinput, True); XtSetArg(args[1], XtNwidth, XMail.shellWidth - 2); XtSetArg(args[2], XtNheight, XMail.borderWidth*3 + XMail.buttonHeight*5 + 44); Popup = XtCreatePopupShell("popup",transientShellWidgetClass,parent,args,3); XtSetArg(args[0], XtNdefaultDistance, 2); Layout = XtCreateManagedWidget("SubjCc", formWidgetClass, Popup, args, 1); left = above = NULL; makeHeading(Layout, "To:",&left,&above,SendMail_Info[0],To_Help); makeHeading(Layout, "Subject:",&left,&above,SendMail_Info[1],Subject_Help); makeHeading(Layout, "Cc:",&left,&above,SendMail_Info[2],Cc_Help); makeHeading(Layout, "Bcc:",&left,&above,SendMail_Info[3],Bcc_Help); XtRegisterGrabAction(SetAliases, True, ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync); XtSetArg(args[0], XtNfont, XMail.buttonFont); XtSetArg(args[1], XtNheight, XMail.buttonHeight + XMail.borderWidth*2 + 4); XtSetArg(args[2], XtNwidth, XMail.shellWidth - 2); XtSetArg(args[3], XtNfromVert, left); XtSetArg(args[4], XtNfromHoriz, NULL); XtSetArg(args[5], XtNborderWidth, 0); XtSetArg(args[6], XtNresize, False); XtSetArg(args[7], XtNmin, args[1].value); XtSetArg(args[8], XtNmax, args[1].value); XtSetArg(args[9], XtNhSpace, 2); XtSetArg(args[10],XtNvSpace, 2); Box = XtCreateManagedWidget("Box", boxWidgetClass, Layout, args, 11); makeButton(Box, "Autograph", (XtCallbackProc) Autograph, "A", Autograph_Info[0], Sign_Help); makeButton(Box, "autograph", (XtCallbackProc) Autograph, "a", Autograph_Info[1], sign_Help); makeButton(Box, "ReEdit", (XtCallbackProc) ReEdit, "ReEdit", Deliver_Info[1], ReEdit_Help); makeButton(Box, "Cancel", (XtCallbackProc) Done, "cancel", Deliver_Info[2], Cancel_Help); makeButton(Box, "Abort", (XtCallbackProc) Done, "Cancel", Deliver_Info[3], Abort_Help); makeButton(Box, "Deliver", (XtCallbackProc) Done, "Deliver", Deliver_Info[0], Deliver_Help); } } /* sendMail */ /* ** @(#)writeMail() - Write command s to the mail process. */ void writeMail(char *s) { (void) write(mail_fd, s, strlen(s)); } /* writeMail */ .\" .\" @(#)xmail.l 1.5 92/02/20 NSC; .\" .\" Copyright 1990,1991,1992 by National Semiconductor Corporation. .\" .\" Permission to use, copy, modify, and distribute this software and its .\" documentation for any purpose is hereby granted without fee, provided that .\" the above copyright notice appear in all copies and that both that .\" copyright notice and this permission notice appear in supporting .\" documentation, and that the name of National Semiconductor Corporation not .\" be used in advertising or publicity pertaining to distribution of the .\" software without specific, written prior permission. National Semiconductor .\" Corporation makes no representations about the suitability of this software .\" for any purpose. It is provided "as is" without express or implied warranty. .\" .\" NATIONAL SEMICONDUCTOR CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO .\" THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND .\" FITNESS, IN NO EVENT SHALL NATIONAL SEMICONDUCTOR CORPORATION BE LIABLE FOR .\" ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER .\" RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF .\" CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN .\" CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" .\" Author: Michael C. Wagnitz - National Semiconductor Corporation .\" .ds nS National Semiconductor Corporation .ds xM xmail .if n .ds Q \&" .if n .ds U \&" .if t .ds Q `` .if t .ds U '' .. .\" .TH XMAIL 1 "February 20, 1992" "NSC" .SH NAME xmail \- X11 visual interface to the mail program .SH SYNOPSIS .B \*(xM .RB "[\|" \-\fItoolkitoptions\fP "\|]" .RB "[\|" \-\fIxmailoptions\fP "\|]" .SH DESCRIPTION .B \*(xM is an X11 window based visual interface to the standard Berkeley .B Mail program. \*(xM offers functionality similar to the Sunview mailtool, but with some differences. Users may use mouse button actions in the (\fItop\fP) index window to select a message for further processing (\fIby pressing the left mouse button\fP), or automatically read the selected message (\fIby pressing the right mouse button\fP). Folder specification is aided by a selection menu which can walk down through the user's folder directory hierarchy (\fIby pressing the right mouse button in the \fBFolder\fP command button window\fR). A short description of each command button's function is presented in the status window whenever the mouse cursor enters any of the xmail command button windows. Additional help information is presented for any command button or other part of xmail by pressing the middle mouse button while the mouse cursor is within the window or command button. In the case of windows which normally accept the pasting of text via the middle mouse button, help is available while also holding down either \fIShift\fR key. Those special case windows are so indicated by the message displayed in the status window while the mouse cursor is within those particular windows. Message composition and modification are provided by the user's preferred editor (\fB/usr/ucb/vi \fIby default\fR). Editor preference may be specified using either the user's process or Mail environment variable .SB VISUAL, or the xmail command line or application resource \fBeditorCommand\fR. Support can also be provided for displaying the content of an X-Face mail header, should such a header string be present in the received message, and for adding your own X-Face header to outgoing mail, if available. Almost all of the xmail functionality depends upon the existence and proper installation of the XMail default resources file (\fItypically in the directory \fB/usr/lib/X11/app-defaults\fR). Functionality may be modified to some extent by the user's specification of some or all of those resources. .SH OPTIONS An unrecognized or illegal command line option specification will cause display of a usage statement and termination of \*(xM. .TP \fB\-toolkitoptions\fR All standard X11 toolkit options are accepted on the command line. .TP \fB\-xmailoptions\fR \*(xM also accepts the following additional options: .RS .TP \fB\-buttonfont \fIfontname\fR specifies the font to use when creating command buttons. This option overrides the \*(xM resource specification \*Q\fB*buttonFont: \fIfontname\fR\*U. .TP \fB\-e\fR Sets the \*(xM resource specification \*Q\fB*expert: \fITrue\fR\*U. This resource determines whether \*Q\fBconfirm\fR\*U popups will be presented when committing changes to a folder or deleting a new message composition. By default the resource is False, which means confirm popups will be used. This resource may be toggled while running xmail, using the \fIset\fP menu provided with the \*Qpreserve\*U command button. See the section on .SB CHANGING VARIABLES further down in this document, or the on-line help information for the preserve button, for additional details. .TP \fB\-editorCommand \fI\fR Specifies the editor resource that \*(xM should use when editing a message composition. The quoted command must be an \fIsprintf\fR\-able format string containing two string declarations. The first of these declarations will be replaced with the name of the display connection for the xmail process, to allow the edit window to appear on the correct display screen. The second declaration will be replaced with the name of the file to be edited. If \*(xM cannot locate the two separate string declarations in the command, the command will be rejected and processing will default to the older .SM VISUAL methodology. See the additional description of this feature in the .SB SENDING MESSAGES section of this document. .TP \fB\-f\ \fI[+]foldername\fR tells Mail to start by processing the specified folder. This is actually a Mail program option, passed to it during startup. Unlike the regular Mail program, there is \fIno default\fP file for this option, and a foldername \fBmust\fP be included in the specification. The leading \fIplus\fP sign identifies the folder file as existing within the folder directory and is a shorthand notation for the full folder directory path name. This feature can also be specified as an \*(xM resource using the specification \*Q\fB*MFileName: \fI[+]foldername\fR\*U. .TP \fB\-fn\ \fIfontname\fR \- or \- .TP \fB\-font\ \fIfontname\fR tells \*(xM to use the indicated font for \fBall\fR windows and buttons. Different fonts can be specified for buttons, text and help, if desired, using the other appropriate designations. This feature can also be specified as an \*(xM resource using the specification \*Q\fB*Font: \fIfontname\fR\*U. .TP \fB\-h\fR tells \*(xM to include the host name in the icon window when displaying the icon. The option can also be specified as an \*(xM resource using the specification \*Q\fB*icon*useHost: \fITrue\fR\*U. .TP \fB\-helpfont \fIfontname\fR specifies the font to use when displaying help text. This option overrides the \*(xM resource specification \*Q\fB*helpFont: \fIfontname\fR\*U. .TP \fB-iconGeometry \fI[+-]XOff[+-]YOff\fR provides a command line option for specifying the preferred geometry location for the \*(xM icon window. This overrides any \*(xM resource specification for \*Q\fB*iconGeometry: \fI[+-]XOff[+-]YOff\fR\*U. .TP \fB\-ls\fR tells \*(xM to \fBnot\fR show the last message of a folder by default. This option is equivalent to setting the \*(xM resource \fB*Show_Last\fR to \fIFalse\fR. If disabled, \*(xM (\fIactually Mail\fP) will display the default (\fIusually first\fP) message of a folder when switching to or re-reading a folder. By default, \*(xM attempts to read the latest (or last) message of a folder. .TP \fB\-n\fR tells Mail to \fBnot\fR initialize from the system default Mail.rc file. This option is also a Mail program option, passed on to it during startup from \*(xM. The option can also be specified as an \*(xM resource using the specification \*Q\fB*mailopt_n: \fITrue\fR\*U. .TP \fB\-nb\fR tells \*(xM to \fBnot\fR ring the terminal bell when issuing status and error messages. This is equivalent to setting the \*(xM resource specification \*Q\fB*bellRing: \fIFalse\fR\*U. The default will be to ring the bell for error and appropriate status messages. .TP \fB\-noinfo\fR tells \*(xM to \fBnot\fR display the info messages in the status window normally generated whenever the mouse cursor is moved into or out of any \*(xM command button window. By default, text would be displayed to provide specific information about the particular command button currently under the mouse cursor. This option allows you to disable this feature, if desired. This is equivalent to setting the \*(xM resource specification \*Q\fB*show_Info: \fIFalse\fR\*U. .TP \fB\-nx\fR tells \*(xM to \fBnot\fR include any X-Face header strings when displaying the text of an incoming message. This is equivalent to setting the \*(xM resource specification \*Q\fB*No_X_Hdr: \fITrue\fR\*U. The default will be to include all text of the incoming message, including any X-Face header strings. Either setting will not deter the display of the X-Face bitmap if it exists in the message headers (\fIprovided the X_FACE option was specified during compilation\fP). .TP \fB\-rv\fR tells \*(xM to reverse the foreground and background colors of the icon window when displaying the icon. The option can also be specified as an \*(xM resource using the specification \*Q\fB*icon*reverseVideo: \fITrue\fR\*U. This option or resource has no effect if the program is utilizing the .SB XPM full-colored pixmap icons. .TP \fB\-textfont \fIfontname\fR specifies the font to use when writing information in text windows. This option overrides the \*(xM resource specification \*Q\fB*textFont: \fIfontname\fR\*U. .TP \fB\-u\fR tells \*(xM to include the user's login name in the icon window when displaying the icon. The option can also be specified as an \*(xM resource using the specification \*Q\fB*icon*useName: \fITrue\fR\*U. .TP \fB\-U\fR tells Mail to convert internet style addresses into uucp format. This option also is a Mail option, passed on to it during startup. The option can also be specified as an \*(xM resource using the specification \*Q\fB*mailopt_U: \fITrue\fR\*U. .RE .SH USAGE The \*(xM shell appearance is similar in layout to mailtool. A \fItitle bar\fR decorates the top of the shell, and carries the name and version of the program, as well as information about the current mail folder and its content. Immediately below the title bar, an \fIindex window\fR displays header information for the current mail folder. Message selection is indicated by a \fBgreater-than \*Q>\*U\fR symbol located at the beginning of the header line for the particular message. New and unread messages are indicated by \*Q\fBN\fR\*U and \*Q\fBU\fR\*U characters respectively, preceding the message number. Deleted messages not yet removed from the index list have the letter \*Q\fBD\fR\*U preceding the message number. Saved messages are now marked with the letter \*Q\fBS\fR\*U, to denote the fact that such messages in your system folder would normally disappear from that folder when you finally commit the changes. (\fIAlthough messages in other folders that are saved will also be marked with an \*Q\fBS\fR\*U, they do not by default get removed from that folder when the changes are committed. Such messages must be explicitly deleted if so desired.\fR) Messages that are marked for preservation in the system folder are now marked with the letter \*Q\fBP\fR\*U until the folder changes are committed. Keyboard keys can be used to scroll the index window in much the fashion of text display programs such as \fBmore\fP or \fBless\fP, in addition to the more traditional mouse on scrollbar mechanism. Just below the index window, a \fIstatus\fR window displays information, status, and error messages. As the mouse cursor is moved between the various command button windows in the xmail program, a short description of the particular button's function(s) is displayed in the status window. Moving the mouse cursor out of that command button's window restores the default information about obtaining help on any part of xmail. Error and status messages are also displayed in this same status window. The terminal bell is usually rung to draw attention to these messages. The status bell can be disabled using a command line option or resource specification. Immediately below the status window and attached to it, the xmail shell displays a panel with a selection of commonly used Mail commands. Pressing and then releasing (\fIalso known as \*Q\fBclicking\fP\*U\fR) the \fBleft\fR mouse button while the mouse cursor is within a particular command button box invokes that Mail command. A grip at the top right corner of the command panel permits the user to slide the status window/command panel combination up and down in the \*(xM shell, to accommodate those times when the user is reviewing a short list of longer than average messages, or a longer list of relatively short messages. Each button in the command panel also offers an expanded menu of choices related to that particular command. Pressing the \fBright\fR mouse button presents the user with the expanded menu. \fBDragging\fR the cursor over one of these selections \fIwhile still holding down the right mouse button\fR causes the particular menu selection to highlight. A description of the highlighted command's function is also displayed in the status window. \fBReleasing\fR the right mouse button while a selection is highlighted invokes that particular command. Keyboard accelerators for these actions are indicated by appropriate entries in the command menus. Users may take advantage of these accelerators by holding down the Shift and/or Control key(s) prior to clicking the left mouse button on the desired command, in lieu of raising the command popup menu. Messages are displayed in the bottom text window of the \*(xM shell. Like the index window above, scroll bars provide easy access to any portion of the text. Keyboard keys can also be used to scroll the text window. If the displayed message contains an X-Face header string, the content of that string is displayed as a bitmap in the upper right-hand corner of the text window. (\fIThis feature is a compile time option, and requires the existence of the \fBcompface\fP library routines, which are not supplied with the xmail sources. See the section on \s-1X-FACE HEADERS\s+1 for details on acquiring this library.\fR) In addition, both the text window and index window have duplicate keyboard definitions to augment using the mouse on the command buttons for normal \*(xM command operation. Like many of the resources for xmail, these key bindings are now declared in the application resource file, to allow the user to modify them as desired. Upon completion of the editing phase of a send/reply operation, the user is presented with a \fIcompletion\fR popup window which contains areas for specifying the message header addressees, subject, and carbon and blind carbon copy recipients. This information can now also be modified directly within the message composition, by specifying the \fIeditheaders\fP Mail program option. This option is normally declared within the user's \fI\&.mailrc\fP file, but can be \fItoggled\fP on and off using the special \fBSet\fP option menu provided with the \fIpreserve\fP command button. (\fISee the section on .SB CHANGING VARIABLES \fIor the on-line help information for the preserve button for additional details.\fR) Also present in the completion popup are command buttons to add one of two forms of user signature, Re-Edit the message composition, Cancel and save, Abort, or Deliver the message to the indicated recipients. The pressing of these command buttons using the mouse may also be simulated by using the keyboard \fBmeta\fP keys and the first letter of the particular command, with the exception that the adding of autograph signatures is denoted by the use of either the \*Q\fBS\fP\*U (\fIfor upper-case Autograph Signature\fP) or \*Q\fBX\fP\*U (\fIfor the lower-case version\fP) keys, since the \*Q\fBA\fP\*U key is used for effecting the \fBAbort\fP function. When either the Cancel, Abort, or Deliver function is executed, the composition popup is automatically removed from the display. A modified mailWatch widget (\fIala xwatch\fP) is used as the \*(xM icon window. The mailbox flag in the icon window will be raised and mail shown inside the box, whenever new mail arrives while the application is in its iconic state. In the non-iconic state, the \fBNewmail\fR command button is highlighted to signal new mail arrival. Clicking on the Newmail button will reset the flag and highlighting, and deliver the new mail to your display. Pressing the \fBmiddle\fR mouse button while the mouse cursor is within any window or command button of the \*(xM shell (\fIin some cases while also holding down either \fBShift\fP key\fR) will cause help information relating to that window (\fIor button\fP) to be displayed in the (\fIbottom\fP) text window. Releasing the mouse button will cause that help information to be removed. Pressing the \*Q\fB?\fR\*U key in the text window will cause a second page of help information, relating to the default bindings for the keyboard keys, to appear. Pressing the \*Q\fBLineFeed\fR\*U or Control_J key will cause that second help window to be removed. During command execution, the cursor is changed to a watch face to indicate that \*(xM is busy. Upon completion of the activity, the cursor is restored to its previous value. .\" .SH "ENVIRONMENT" Several process environment variables are of a special interest to \*(xM. .sp .RS .TP 3 .SB DEAD Normally specified in the user's \&.mailrc file, this variable indicates the name of the file to use when storing dead or canceled letters. If unspecified, it defaults to \*Qdead.letter\*U in the user's HOME directory. .TP 3 .SB HOME Defines the path to the user's home directory, and is used in determining the complete path for mail folder and dead letter files. If unspecified, this information will be extracted from the user's entry in the password file. .TP 3 .SB MAILRC If defined, denotes the full name of the user preferred Mail program startup file, used to define various mail state variables. By default, Mail (\fIand \*(xM\fP) will look for the file \fI\&.mailrc\fP, in the user's home directory. .TP 3 .SB MBOX Normally specified in the user's \&.mailrc file, this variable denotes the preferred file to use when storing letters that are no longer to be preserved in the system mail folder, and letters copied or saved to no other specific file. .TP 3 .SB VISUAL Normally specified in the user's \&.mailrc file, this variable denotes the preferred editor to use when composing messages in \*(xM. This information can be overridden by specifying a value for the \fIeditorCommand\fP command line or resource declaration. .TP 3 .SB XMAILER If defined, points to the particular executable to be used as the Mail program. Normally, \*(xM establishes connections with Mail in the default path of the process (\fIassumed to be at least \*Q/bin /usr/bin /usr/ucb\*U\fP). If need be, this environment variable can be used to provide a specific path to the Mail or other named program. Note: \*(xM may not work correctly with any mail program other than the intended Berkeley Mail program. .RE .\" .SH FOLDERS If the \fBright\fR mouse button is pressed while the cursor is within the command panel \fBFolder\fR button, \*(xM will display a menu of available mail folders. (\fIIf the user has not set their mail \fRfolders\fP variable, a message so indicating will be displayed instead.\fR) Dragging the cursor while still holding the right mouse button down will allow the user to highlight a particular folder name. Releasing the right button while a name is highlighted causes a copy of that name to be written in the command panel \fIFile\fP window. The menu list is then unmapped. Releasing the right button while outside any folder selection causes the folder menu list to disappear. Folders which are actually directories (\fIthat might possibly contain additional folder files\fP) are displayed with a trailing slash (/) character. Clicking the \fBleft\fR mouse button within a directory folder while still holding down the right mouse button (\fIalso known as \*Q\fBexpanding\fR\*U) causes \*(xM to expand that directory and display (\fIon a new menu level\fP) any files found there. Dragging the cursor over one of these selections and releasing the right mouse button copies the complete folder path name to the file window. This nesting of folder names may be repeated as often as there are legitimate folder directories. Clicking the left mouse button on an empty folder directory rings the terminal bell. Dragging the cursor beyond one of these nested menu levels causes that menu to disappear, without making a selection. Re-clicking the left mouse button on the directory folder redisplays the nested menu. Because of the methodology utilized in determining the folder list menu widget hierarchy, certain restrictions must apply when declaring folder directories. No folder directory name may contain an embedded period (.) or asterisk (*), since these items are utilized by the resource manager (\fIand toolkit function XtNameToWidget\fP) to indicate the potential widget hierarchy. If a folder directory name exists at any level with one or more of these characters embedded in its name, attempts to access that folder directory will result in a beep and no further expansion. The first request for the folder menu extracts (\fIfrom Mail or the system\fP) the necessary information to create the menu. Subsequent requests simply redisplay that menu. To force \*(xM to recalculate the folder menu content, use the \fBNewmail\fR button option which causes \*(xM to destroy all current folder menus. This mechanism provides access to folders created since the startup of \*(xM. Pressing the right mouse button on the Newmail command box will present the Newmail command menu, which has a choice to drop the current folder list. This same option is also available using the designated accelerator key and left mouse button on the Newmail command button box. As message are stored or otherwise delivered to one of the folder files, the \fIaccessed\fP and \fImodified\fP time stamps for that folder file are updated by the system. \*(xM uses that information to indicate (\fIvia the addition of a hatching pattern to the background of a particular folder button label\fP) when a folder has been modified since the last time it was accessed. This feature presents a method of indicating when new messages exists in a particular folder file. Reading the particular folder automatically resets this indicator, although in some instances remotely accessed folder files (\fIsuch as those on an NFS mounted file system\fP) may not properly or consistently update this time information. .\" .SH FONTS Separate fonts may now be specified for mail message (\fIand index\fP) text, help message text, and for the command buttons. (\fISee the options descriptions for a list of the command line options to use.\fP) You may also declare all fonts using the resource declaration \fB*Font: \fP, or the command line option \fB-fn\fP <\fIfontname\fP> or \fB-font\fP <\fIfontname\fP>, which cause all three fonts specifications to utilize the same font. Previous restrictions against the use of proportional width fonts have now been hopefully resolved. Although the result of choosing such a font may still produce less than optimal results, the window shell should be of a reasonable size, and the support menu entries should now be readable. Of course, no amount of coding can overcome inappropriate font selections. .\" .SH ICONIFICATION \*(xM establishes access to a dummy mail folder whenever the application is in the iconified state. This is done to prevent potential corruption of a real mail folder, should the user choose to read their mail from another process while \*(xM is running. Because of this action, iconifying \*(xM \fBalways\fR .SB COMMITS changes made to the current folder, prior to switching to the dummy folder. No confirmation for committing folder changes will occur when iconifying \*(xM. The original folder being read by the user will be automatically reinstated as current whenever \*(xM is again deiconified. This action will flush any deleted messages from the index headers and renumber the remaining messages in the folder. The last message in the folder will then become the current message displayed (\fIunless \*(xM was started with the \fB*Show_Last\fP resource option disabled, in which case the first message would be made current\fR). If the \*Qcurrent\*U folder was the user's system folder, any new mail received since the iconification would be automatically included by the re-access. If some other folder were current (\fIor no folder, due to initial conditions of no mail for the user\fR), deiconification would not cause the reading of any new mail. Under those circumstances the user must press the \fBNewmail\fR command button to change to the system mail folder (\fIand read the new mail\fR). The icon window also supports an auxiliary identification mechanism, for users that might have more than one account, possibly on more than one machine, and that wish to be able to identify otherwise duplicate \*(xM icons. Pressing the \*Q\fBh\fR\*U key while the mouse cursor is within the icon window will cause the icon to be tagged with the machine's hostname. Pressing the \*Q\fBu\fR\*U key will cause the user's login name to be displayed. Pressing the \*Q\fBspace\fR\*U bar will clear the icon window of either name. Changing the tag space content of the icon will also change the title of the application for window managers. This allows the user to distinguish between several xmail invocations from the window (or icon) selection menus of the various window managers. The hostname or login name addition may also be pre-selected using either command line options or resource declarations if desired. Iconification is typically promoted by user definable button events which are particular to the window manager in use at the time. Pressing the \*(nS logo displayed at the left of the title bar will also cause xmail to issue a window manager request for iconification. ICCCM compliant window managers should honor that request by iconifying the xmail application. Pressing the \*Q\fBq\fR\*U key while the mouse cursor is within the \*(xM icon window will cause \*(xM to terminate. \*(xM also honors the .SB ICCCM Window Manager protocol request .SB WM_DELETE_WINDOW to terminate the \*(xM application. .\" .SH "KEYBOARD ACCELERATORS" The index and text windows support two methods of scrolling displayable text. The use of the mouse buttons in the scrollbar region is standard. In addition, keyboard keys have been defined in keeping with conventions used in text display programs such as \*Qmore\*U and \*Qless\*U. These keyboard accelerators will \fBonly\fP be available if the resources are declared either in the application defaults file (\fIwhich must be properly installed\fP) or the user adds the necessary declarations to their local default resources. The following table lists the key definitions and their respective actions. The abbreviation \*QCtrl\*U means to press down and hold the \fBControl\fR key while pressing the specified letter key. \*QMeta\*U likewise refers to the \fBmeta\fR keys (\fIlabeled \*QLeft\*U and \*QRight\*U or with a diamond symbol on Sun type-4 keyboards\fR). .sp .RS .nf Key Name Action Taken -------- ----------------------------- Ctrl V move to the next page space move to the next page Meta V move to the previous page b move to the previous page Ctrl Z scroll one line up Return scroll one line up j scroll one line up Meta Z scroll one line down k scroll one line down - scroll one line down \' move to the beginning of file Meta < move to the beginning of file Meta > move to the end of file Shift G move to the end of file .fi .RE .sp .LP In addition to the scroll key definitions, both windows also support keyboard accelerators for most of the command buttons. Where possible, these keyboard keys replicate the actual commands that would be typed if the user were running the native mail program directly. Thus, to begin sending a mail message to some recipient, the user could press the \*Q\fBm\fR\*U key, and to delete a current message, the user could press the \*Q\fBd\fR\*U key. Certain exceptions and additions have been made, in order to avoid conflicts within the \*(xM program. .sp .RS .nf Key Name Command Action Taken -------- ----------------------------- Shift A reply to all, include the current message Shift C copy the message to the author's name Shift F forward the current mail message Shift M reply to a mail message Shift N bring new mail into your system folder Shift P send the current message to the printer Shift R include the current message in a reply Shift S save the message to the author's name a reply to all recipients of a message c copy the message to the indicated folder d delete the current message f read the full header of the message i incorporate new mail without commit m mail (compose) a new mail message n read the next mail message p read the previous mail message q quit xmail, committing any changes r read the current mail message s save current message in specified folder u undelete the most recently deleted message w writes the message to the indicated file x exit xmail, without committing changes ? displays help for these key definitions removes help for these key definitions .fi .RE .\" .SH RESOURCES Most of the options and features of this version of \*(xM depend heavily on the installation of the application default resources file in the proper location (\fItypically /usr/lib/X11/app-defaults/XMail\fP). If this file is not installed, xmail will still run, but only in a severely restricted manner, and with almost none of the features mentioned in this man page. The resource declarations were moved from the program sources to the defaults file to allow for a greater degree of flexibility in the appearance and actions of \*(xM at the discretion of the user. \*(xM recognizes resource definitions for each of its component windows and command buttons. Wherever possible, button resources have been named for the label (or first word in the label) of the command button. (\fIThe exception is the preserve \*Qset\*U menu, whose resources are identified by the second word in each label.\fR) Thus : .RS .TP 3 \fB*read\fR specifies resources for the \fIread\fR command button .TP 3 \fB*save\fR specifies resources for the \fIsave\fR command button .TP 3 \fB*autoprint\fR specifies resources for the \fIset autoprint\fR command button, and .TP 3 \fB*noautoprint\fR specifies resources for the \fIset noautoprint\fR command button. .RE .LP Color may be added (on a color display device) to enhance the appearance of \*(xM. Example resources in the application defaults file have been left in a commented condition. They may be implemented by uncommenting the appropriate lines in the defaults file, or overridden by designations in the user's \&.Xdefaults file, or (\fIin some cases\fR) by command line options. Resources specified in the user's \&.Xdefaults file should be preceded with either the \fB\*(xM\fR application or \fBXMail\fR Class resource identifier. In addition to those resources named for a particular \*(xM command button, the following additional resource names are recognized: .sp .RS .TP 3 \fB*buttonFont: \fI\fR denotes a preferred font to use when creating the command buttons. The width of the \*(xM shell, and thus its general appearance is controlled by the font specified for buttons. If different fonts are specified for buttons and text, and the font for text is of a larger point size than that specified for buttons, then text in the index and text windows will most likely wrap during display. .TP 3 \fB*Bcc\fR controls resources for the \fIBcc:\fR entry window .TP 3 \fB*bellRing: \fI\fR Normally true, this boolean enables ringing of the terminal bell during status and error message display. .TP 3 \fB*Cc\fR controls resources for the \fICc:\fR entry window .TP 3 \fB*commandPanel\fR controls resources for the \fIcommand panel\fR .TP 3 \fB*customHeader\fR This resource can be used to specify additional mail headers to be included in the headers of all outgoing messages created by the user. The information contained in this resource .SB MUST conform to the format of mail headers, namely a keyword, such as \fBOrganization:\fP (\fIwhich must include the trailing colon character\fP), followed by a space character, and the text of the information. An example custom header resource declaration would be: .RS .nf xmail*customHeader: Organization: Your_Company_Name .fi .RE .TP 3 \fB*editorCommand: \fI\fR Specifies the editor resource that \*(xM should use when editing a message composition. The quoted command must be an \fIsprintf\fR\-able format containing two string declarations. The first of these declarations will be replaced with the name of the display connection for the xmail process, to allow the edit window to appear on the correct display screen. The second declaration will be replaced with the name of the file to be edited. If \*(xM cannot locate the two separate string declarations in the command, the command will be rejected and processing will default to the older .SM VISUAL methodology. See the section on .SB SENDING MESSAGES for additional details. .TP 3 \fB*expert: \fI\fR This boolean defines whether the \*(xM user requires confirmation of folder commits or composed message deletions. Whenever an action would make a permanent un-recoverable change to the \*(xM environment, a popup confirmation window will be presented for the user, to assure that the action should take place. These confirmations include changing a folder when deletions have occurred, or deleting the text of a newly composed message instead of sending it. Setting this resource to True eliminates those confirmation popups. .TP 3 \fB*fileWindow\fR controls resources for the \fIfile window\fR within the command panel .TP 3 \fB*Font\fR provides font specifications for the three optionally separate fonts used in \*(xM, buttonFont, helpFont, and textFont. .TP 3 \fB\&.geometry: \fI[+-]XOff[+-]YOff\fR This resource defines the initial startup location for the \*(xM window. Note the dot (.) just in front of the geometry resource name. Users are cautioned to \fBnot\fR specify this resource with the wildcard (*) designation, as this would force all popup windows (help, menus, and send/reply) to orient to that same starting location, rather than be anchored to the intended window. .TP 3 \fB*helpFont: \fI\fR denotes a preferred font to use when displaying help information. .TP 3 \fB*icon\fR controls resources for the \fIicon\fR window. In addition to specifications of foreground and background colors, it is also possible to specify the following mailWatch widget resources : .RS .TP 3 \fB*icon*useHost: \fI\fR If set to true, tells \*(xM to include the mail host name in the icon window when displaying the icon. This option is now alterable at runtime by keypress in the icon window. \*Q\fBh\fR\*U sets the host name, \*Q\fBu\fR\*U sets the user name, and \*Q\fBspace\fR\*U clears either entry. .TP 3 \fB*icon*useName: \fI\fR If set to true, tells \*(xM to include the user login name in the icon window when displaying the icon. .TP 3 \fB*icon*reverseVideo: \fI\fR If set to true, reverses the foreground and background colors for the icon. Setting this resource has no effect if the \*(xM program is utilizing the .SB XPM full-colored pixmap icons. .TP 3 \fB*icon*update: \fI\fR Specifies the update interval for checking new mail (default is 30 seconds). .TP 3 \fB*icon*bell: \fI\fR If set to False, prevents the mailWatch widget from ringing the bell when new mail arrives. See also the \&.mailrc variable setting for \fIbell\fR. .RE .TP 3 \fB*iconic: \fI\fR This boolean defines whether the \*(xM application should be started in iconic state or not. It is highly recommended that only the application resource identifier be used if specifying this resource. Use of the \fBXMail\fR Class identifier would also constrain any message entry windows to be started iconic, which could prove confusing to the unaware user. .TP 3 \fB*iconGeometry: \fI[+-]XOff[+-]YOff\fR This resource defines an initial location for the icon, whenever the \*(xM application is iconified. .TP 3 \fB*indexWindow\fR controls resources for the \fIindex\fR window .TP 3 \fB*list\fR controls resources for the \fIfolder list\fR popup window .TP 3 \fB*mailFlag:\fP \fI\fP is the resource which defines the icon bitmap (\fIor .SB XPM \fIpixmap\fR) to use when indicating new mail. If the XPixMap compile time option was not specified, a string to bitmap resource converter is supplied which automatically converts the specified string to a bitmap. If the .SM XPM option \fBwas\fR declared at compile time, an internal conversion of string to pixmap is performed. If the string does not define an .SM XPM pixmap, an attempt is made to convert the string to a bitmap. Thus, with the .SM XPM compile time option, either an .SM XPM pixmap or a standard bitmap may be declared. Without the .SM XPM option, only a standard bitmap file may be specified. In either case, if the conversion should fail, the program would default to an appropriate internal representation. .TP 3 \fB*mailopt_n: \fI\fR Normally false, this resource duplicates the effect of the \fI-n\fR command line option. .TP 3 \fB*mailopt_U: \fI\fR Normally false, this resource duplicates the effect of the \fI-U\fR command line option. .TP 3 \fB*menu\fR controls resources for all of the command button popup menus .TP 3 \fB*MFileName: \fI\fR Normally null, this resource duplicates the effect of the \fI-f folder\fR command line option. .TP 3 \fB*noMailFlag:\fP \fI\fP is the resource which defines the icon bitmap to use when indicating that new mail is not available. .TP 3 \fB*No_X_Hdr:\fP \fI\fP Normally False, if set to True this resource tells \*(xM to \fBnot\fP include any X-Face header strings when displaying the text of an incoming message. This is equivalent to specifying the \*(xM command line option \fB-nx\fP. Either setting will not deter the display of the X-Face bitmap if it exists in the message headers. .TP 3 \fB*Show_Info: \fI\fR Normally true, this boolean enables display of command button information messages in the status window, whenever the mouse cursor enters or leaves one of the command button windows. Information messages are also displayed for each of the popup sub-menus as well. Setting this resource to false prevents these information messages from being displayed. .TP 3 \fB*Show_Last: \fI\fR Normally true, this boolean enables display of the last message in a folder, providing no other is newer or unread. Setting this resource to false causes folder displays to start with the first (or new or unread) message. .TP 3 \fB*statusWindow\fR controls resources for the \fIstatus\fR window .TP 3 \fB*Subject\fR controls resources for the \fISubject:\fR entry window .TP 3 \fB*textFont: \fI\fR denotes a preferred font to use when creating text and index windows. .TP 3 \fB*textWindow\fR controls resources for the \fItext\fR window .TP 3 \fB*titleBar\fR controls resources for the \fItitleBar\fR window .TP 3 \fB*To\fR controls resources for the \fITo:\fR entry window .RE A set of default resource definitions are provided in the file \fB/usr/lib/X11/app-defaults/XMail\fR. User's may wish to include appropriate alternate definitions in their .SB $HOME/.Xdefaults file, to tailor preferences for colors and/or fonts. .\" .SH "SENDING MESSAGES" All send and reply operations invoke the user's preferred editor to create or modify the message. The editor preference may be specified using either the .SB VISUAL \&.mailrc environment specification, or the newer \fBeditorCommand\fR resource specification (\fIor \-editorCommand command line option\fR). The editorCommand resource must define a string with two \fBsprintf\fR\-able format declarations, one for the name of the X11 server display connection, and one for the name of the file to be edited. The editorCommand specification must also ensure the proper creation of an appropriate X11 window for completing the desired editing session. The resource may be specified on the command line, either as an option, or as a resource manager string. It may also be specified in the user's applications default file as an xmail resource. Examples of editorCommand specification strings include: .RS .nf \fBxmail\ \-editorCommand\ 'emacs\ \-display\ %s\ \-name\ XMail\ %s' .sp \fBxmail\ \-xrm\ '*editorCommand:\ xterm\ \-display\ %s\ \-e\ vi\ %s' .sp xmail.editorCommand:\ \ xedit\ -name XMail_Edits \-display\ %s\ %s .sp xmail.editorCommand:\ \ emacs\ \-display\ %s\ %s .sp xmail.editorCommand:\ \ xterm\ \-display\ %s\ -name XMail -e vi %s .fi .RE If the editorCommand resource fails to provide the required string declarations for the display and file names, or it is not defined, \*(xM will default to the older method of utilizing the information in the user or Mail process .SB VISUAL environment variable. The \fIdefault\fR editor will be \fBvi\fR, if no .SM VISUAL (\fImailrc or process\fR) environment variable definition exists. Upon completion of the send/reply editing session, a popup window will be displayed containing \fITo:\fR, \fISubject:\fR, \fICc:\fR, and \fIBcc:\fR fields for the current message composition. Help is available for each of these fields, as it is for all of \*(xM. A menu of mail aliases (\fIextracted from the user's .mailrc file\fR) is available for access from any of the To:, Cc:, or Bcc: windows. Pressing the right mouse button while the mouse cursor is in any of these input fields causes the alias names menu to be displayed. If the user has not defined any mail aliases, the terminal bell will be rung instead, to indicate that no alias names menu is available. Like the \fIFile:\fR window used to enter file and mail folder names, the content of the send window popup fields may be modified by the user as needed. Backspace and delete keys remove the previous character, control_W deletes the previous word, and control_U deletes the entire line of information. Pressing the Return key in any of these four fields causes the cursor to automatically warp to the next field. Users may append their \fISign\fP or \fIsign\fP autograph (see \fBMail(1)\fR) once only to the end of the composed message text. If the user does not set a [Ss]ign value in their .mailrc file, this version of xmail will also look in their home directory for either a .signature or .Signature file (\fIdepending on which of the two [Aa]utograph buttons was pressed\fP) to append to the message text. Pressing the \fIRe-Edit\fR button allows the message to be re-edited, while the \fICancel\fR button terminates delivery but saves any partial composition in your dead.letter file. Pressing the \fIAbort\fR button cancels delivery but does not save the composition, while the \fIDeliver\fR button causes the message to be delivered to the sendmail daemon. The pressing of any of these command buttons may also be simulated while the mouse cursor is anywhere within the popup window, by using the keyboard \fBmeta\fP keys and the first letter of the command, with the exception that the adding of autograph signatures is denoted by the use of either the \*Q\fBS\fP\*U (\fIfor upper-case Autograph Signature\fP) or \*Q\fBX\fP\*U (\fIfor the lower-case version\fP) keys, since the \*Q\fBA\fP\*U key is used for effecting the \fBAbort\fP function. When either the Cancel, Abort, or Deliver function is selected, the composition popup is automatically removed from the display. If the user attempts to deliver a message with no designated recipient or no message body and no message Subject line specified, \*(xM will re-display the completion popup, to permit the user to Re-Edit the message body, add a Subject designation and/or recipient, or specifically Abort the message delivery. Mail forwarded to another user will be bracketed by a \*Q\fIBegin Forwarded Message/End Forwarded Message\fR\*U string pair when using the \*Q\fIforward message\fR\*U Send command menu option. Also included will be a \*Q\fIForwarded: Mail from ...\fR\*U line in the mail header. Reply messages will include a \*Q\fIIn-Reply-To: Mail from ...\fR\*U string in the mail header. Like the \*Q\fIForwarded:\fR\*U header described above, it will include the name of the original sender, as well as the date the original message was received. If an X-Face header exists for the user, it will be inserted in the mail header section of the outgoing message. This header must be stored in the file \fB\&.face\fR located in the user's home directory. Users may provide additional custom header information to be applied to all outgoing message compositions, by using the \fB*customHeader\fP \*(xM resource designation. Specified information must conform to the format of mail headers as noted elsewhere in this documentation. .\" .SS "X-FACE HEADERS" X-Face headers are compressed bitmap images, typically of the face of the person owning such a header. The compressed header contains only printable characters, which allows it to be included in a mail message. The \s-1USENIX\s+1 (\fI\s-1UNIX\s+1 Users Association\fR) FaceSaver project is the typical source for these bitmaps, which are compressed into X-Face header format using the \fBcompface\fR software tools written and distributed by James Ashton . The compface library is also included with the distribution of the \fBfaces\fR software, written and distributed by Rich Burridge, and is available from the Rich Burridge Archive Service . .\" .SS "EDITING RESOURCES" The editing session invoked within \*(xM runs as a child process of the \*(xM application. As such, it does not use those resources that were declared for the \*(xm process. Resources for the editing session should be tied to the use of the \fB\-name\fR toolkit option in the editorCommand specification. The default .SM VISUAL mechanism invokes the vi editor in an xterm window, using the \*(xM Class resource as it's name identifier. This allows message composition window resources to be declared using the \*(xM Class resource name followed by the xterm terminal resources identifier \*Qvt100\*U, as in \*Q\fBXMail*vt100.\fI\fR\*U. For example, the author uses the following resource definitions in his \&.Xdefaults file, to control the size and placement of message composition windows. .sp .RS .nf XMail*vt100.geometry: 80x27+30+100 XMail*vt100.font: fg-22 XMail*vt100.foreground: white XMail*vt100.background: blue XMail*vt100.mouse: white .fi .RE .\" .SH "VARIABLES" \*(xM also uses the existence and value of several Mail environment variables (\fIdefined in the user's \&.mailrc file\fP) to aid in controlling it's operation. .sp .RS .TP 3 \fBalwaysignore\fR If set, causes \*(xM to ignore those header fields specified with the \fIignore\fR \&.mailrc environment variable, when printing messages or when including message text in a send/reply composition. This variable can be altered during the execution of \*(xM. (See the section below on \fIChanging Variables\fR.) .TP 3 \fBautoprint\fR If enabled, causes the current message text to be displayed when deleting or undeleting messages. If \fInot\fR enabled, users must select or read the desired message. This variable can also be altered within the current \*(xM execution. .TP 3 \fBbell=\fIvalue\fR If defined, determines the number of times the terminal bell would be rung to indicate the arrival of new mail. A minimum of once and a maximum of five times is the permissible range. Whether the terminal bell rings at all when new mail arrives is controlled by the \*Q\fB*icon*bell: \fI\fR\*U resource (\fIor \fB\-nb\fP command line option\fR) described above. .TP 3 \fBeditheaders\fR Like Mail and mailtool, \*(xM permits the user to set and modify the outgoing messages mail headers while composing the message, if this variable is set. This variable can be toggled during \*(xM execution, using the capabilities of the \fBSet\fR menu provided under the \fBpreserve\fR command button. .TP 3 \fBhold\fR Like mailtool, \*(xM sets \*Qhold\*U on the user's system mail folder, unless \*Qnohold\*U has been \fIexplicitly\fR specified in the user's \&.mailrc file. This variable can also be altered during \*(xM execution. .TP 3 \fBprintmail=\fIprinter command\fR This variable, originally created for the Sunview mailtool, allows the user to specify a preferred command to use when printing messages. The default command is \*Qlpr -p\*U. If the user is not using Sun's version of the mail handler, then the print mechanism will first copy the selected message to a temporary file before printing it. This implies that the printmail command must also remove this temporary file when the print job has been completed. This is typically accomplished by including the \fB\-r\fP (\fIremove\fP) option when specifying the printmail command. This is the default for non-Sun specific printing in the xmail program. .TP 3 \fBsendmail=\fIshell-command\fR If set, specifies an alternate procedure to use in lieu of the default \&/usr/lib/sendmail for delivering mail. User supplied procedures must be prepared to search the message file for recipients and ignore or process unexpected options (which ultimately must be passed on to the real sendmail program). .RE .LP Some Mail variables have no effect on \*(xM operation, and are in fact ignored if found to be set. .RS .TP 3 \fBreplyall\fR has no effect on the meaning of commands within \*(xM. This prevents confusion due to a difference between how a command is labeled, and how it reacts in use. .TP 3 \fBcmd=\fI\fR is ignored, and is always defeated. This provides a mechanism to determine if the pipe command is supported in the user's mail environment, and determines the method to use when printing a message on the system printer (\fIusing the default or user specified\fP \fBprintmail\fP \fIcommand\fP). .TP 3 \fBcrt=\fI\fR is ignored, and always defaults to \fBnocrt\fR. This prevents user specified paging mechanisms from interfering with full message delivery to \*(xM. .TP 3 \fBscreen=\fI\fR The current release of \*(xM can safely handle up to a maximum of 10,000 mail message in any one mail folder. Users with more than 10,000 messages in any one folder should seriously consider either creating some additional sub-folders, or at least deleting older messages. .\" .SS "CHANGING VARIABLES" \*(xM provides a mechanism for altering the state of four of the Mail (\fIand one \*(xM specific\fP) environment variables used to control \*(xM (and Mail) operations. The states of \fBalwaysignore, autoprint, editheaders, hold,\fR and \fBexpert\fR can now be \*Qtoggled\*U from a special menu attached to the \fBpreserve\fR command button. .LP Pressing the right mouse button while the mouse pointer is within the preserve command button box presents a menu of \*Qset\*U commands which indicate the state the variables would be changed to if the mouse button were released while one of these commands was highlighted. .LP Changing the state of the variable alters the next presentation of the menu, such that the opposite state will always be presented as the command option. .RE .\" .SH "SEE ALSO" Mail(1) .\" .SH BUGS Users finding a problem in this xmail application are encouraged to notify the author at the indicated address. A complete (as possible) description of the problem, and a context diff of the changes needed to fix the flaw, if available, would be greatly appreciated. I will make every effort to fix any such bugs reported. Send any bug reports or other requested changes to: .RS .nf Michael C. Wagnitz M/S D3-677 National Semiconductor Corporation 2900 Semiconductor Drive Santa Clara, CA 95052-8090 Domain: michael@berlioz.nsc.com Phone: 408/721-3266 UUCP: {apple|decwrl|hplabs|sun}!nsc!berlioz.nsc.com!michael .fi .RE .\" .SH AUTHOR .ce 3 Copyright 1989, 1990, 1991, 1992 - \*(nS ALL RIGHTS RESERVED Michael Wagnitz, \*(nS, Santa Clara, CA .LP Much of the original design and insight for the development of \*(xM was provided by contributions from the following authors: The xdbx contribution by Po Cheung (po@volta.ece.utexas.edu) .RS Copyright 1989 The University of Texas at Austin .RE The mailWatch widget by Dan Heller (argv@sun.com) was used as the source for the \*(xM icon window. From Anchor.!headwall.Stanford.EDU!agate!usenet.hana.nm.kr!scoupe.postech.ac.kr!wgchoe Wed Mar 16 08:14:10 PST 1994 Article: 2301 of comp.graphics.gnuplot Path: Anchor.!headwall.Stanford.EDU!agate!usenet.hana.nm.kr!scoupe.postech.ac.kr!wgchoe