The file README-ATTACHMENTS was removed - it has been moved to the docs
authorJon Steinhart <jon@fourwinds.com>
Mon, 18 Nov 2002 18:25:00 +0000 (18:25 +0000)
committerJon Steinhart <jon@fourwinds.com>
Mon, 18 Nov 2002 18:25:00 +0000 (18:25 +0000)
subdirectory.  I thought that this had already been done but I guess not.
It's unrelated to the rest of these changes.

The remainder of these changes affect the way that nmh is installed.  Nmh
has historically prompted the user for installation when any nmh command
is invoked if it doesn't think that it's installed.  This is a problem for
programs that want to, for example, interact with nmh programs via pipes.

These changes alter this behavior.  Now, when an nmh program thinks that
nmh isn't installed, it tells the user to run install-mh to install it.
A -check option has been added to install-mh that allows the existence of
an installation to be silently checked and indicated via the exit status.

The bulk of this change is in sbr/read_context.c.  In the process of making
these changes, I noticed a fair amount of useless code that I removed.  In
particular:

1. The program started with a test for whether or not defpath had already
been set.  This could only happen if context_read() was called more
than once, which it isn't.  This check also existed and was removed
from the following places:
sbr/context_del.c
sbr/context_find.c
sbr/context_replace.c
sbr/seq_read.c
sbr/seq_save.c
uip/flist.c
uip/folder.c
uip/rmf.c

2. A similar test for mypath was removed.  No need to test it since it
doesn't happen.  I'm just not a believer that

a = 1;

if (a != 1)
error();

is a good way to write code!

3. I removed the code makes a copy of the $HOME environment variable as
returned by getenv().  It's never changed, so it doesn't need copying.

4. I removed code that copied the pw_dir member of the passwd structure
returned by getpwuid() if $HOME isn't set.  Yes, the returned structure
is static, but since the function is never called again the returned
values stay valid and don't need copying.

5. I removed the test for a NULL pw_dir member in the passwd structure
returned by getpwuid() since that never happens.

6. I removed code that removed a trailing / from mypath if mypath is more
than one character long.  Unnecessary as // is interpreted as / anyway.
mypath never shows up in an error message, so nobody will ever see it.
Besides, this code didn't handle the case of multiple trailing slashes.

7. I removed code that replaced the MH environment variable contents with
an absolute path if it was a relative one.  I'm a bit nervous about this
one, only testing will tell.  Any nmh program that's invoked will use
the same context_read() code to convert a relative path to an absolute
one anyway.  And there's no guarantee (or discussion) of this feature
in any of the documentation.

8. Althout context_read() tested the MH environment variable, install-mh
didn't.  This means that the behavior was not consistent between
install-mh and all other nmh programs.  I changed install-mh to be
consistent with context_read().

9. install-mh has been installed in the lib directory, not bin.  So a
user would be unlikely to find it when prompted to run it.  The
installation has been changed to add a link from bin to lib.

14 files changed:
README-ATTACHMENTS [deleted file]
man/install-mh.man
man/nmh.man
sbr/context_del.c
sbr/context_find.c
sbr/context_read.c
sbr/context_replace.c
sbr/seq_read.c
sbr/seq_save.c
uip/Makefile.in
uip/flist.c
uip/folder.c
uip/install-mh.c
uip/rmf.c

diff --git a/README-ATTACHMENTS b/README-ATTACHMENTS
deleted file mode 100644 (file)
index ff9db2a..0000000
+++ /dev/null
@@ -1,281 +0,0 @@
-Jon Steinhart's (jon@fourwinds.com) Attachment Handling Mods
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-A bunch of changes have been made to improve the nmh user interface for
-handling MIME attachments.
-
-Why Did I Do This?
-~~~~~~~~~~~~~~~~~~
-
-Although nmh contains the necessary functionality for MIME message handing,
-the interface to this functionality is pretty obtuse.  There's no way that
-I'm ever going to convince my partner to write mhbuild composition files!
-And even though I know how to write them, I often screw up when sending a
-message that contains a shell script because I forget that I have to double
-any # at the start of a line, which shell scripts have galore.
-
-These changes simplify the task of managing attachments on draft files.
-They allow attachments to be added, listed, and deleted.  MIME messages are
-automatically created when drafts with attachments are sent.
-
-The Simple Setup
-~~~~~~~~~~~~~~~~
-
-The gory details are all given below.  Here's how to set things up simply.  This
-only works if you're using the "standard" interface, i.e., whatnow.  Life is more
-complicated if you run mh-e.
-
-Add the following to your .mh_profile:
-
-       send: -attach X-MH-Attachment
-       whatnow: -attach X-MH-Attachment
-
-You may already have send and whatnow lines in your .mh_profile; if you do, just add
-the new stuff to the end of the line.  For example, mine looks like:
-
-       send: -alias aliases -attach X-MH-Attachment
-       whatnow: -attach X-MH-Attachment
-
-That's it.  Next time you want to send an attachment, say "attach filename" at the
-whatnow prompt and you're done.  You can check your attachments by saying "alist".
-
-Did I Do This Correctly?
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-Hard to say.  Despite lots of time looking at the nmh code, I can't say that
-I get the philosophy behind its structure.
-
-I am aware of two deviations from what I saw in the nmh code.
-
- 1.  I commented my changes.
-
- 2.  It's been years since I've used a VT-100, so I don't try to make code
-     fit into 80 columns anymore.  Seems silly to me.
-
-What Did I Do?
-~~~~~~~~~~~~~~
-
-I made changes to the following files:
-
-       h/
-               prototypes.h
-       man/
-               anno.man
-               send.man
-               whatnow.man
-       uip/
-               Makefile.in
-               anno.c
-               annosbr.c
-               send.c
-               sendsbr.c
-               viamail.c       (needed change for new sendsbr argument)
-               whatnowsbr.c
-
-Attachments are associated with messages using header fields.  For example, a
-draft that looks like this
-
-       To: jon
-       Subject: test of attachments
-       X-MH-Attachment: /export/home/jon/foo
-       X-MH-Attachment: /export/home/jon/bar
-       X-MH-Attachment: /export/home/jon/test/foo
-       --------
-
-has the files "foo", "bar", and foo as attachments.
-
-Although I use the header field name "X-MH-Attachment" to indicate
-attachments, the implementation allows any header field name.
-
-The advantage of using header fields is that the list of attachments
-travels with the draft so it remains valid across editing sessions.
-
-Note that the header fields for attachments are removed from the message
-before it is sent.
-
-Since I was adding header fields to messages, it seemed sensible to use the
-existing anno program to do this for me.  This required several changes to
-generalize anno:
-
- o  I added a -draft option that permits annotations (header fields) to
-    be added to the draft instead of a message sequence.
-
- o  I added a -delete option that allows annotations to be deleted.
-
- o  I added a -list option that allows annotations to be listed.
-
- o  I added a -number option that modifies the behavior of -delete and -list.
-
- o  I added a -append option so that annotations are appended to the headers
-    instead of the default prepend.  Without this, attachments come out in
-    reverse order.
-
-Using the modified anno, the example above could be created (assuming that the
-draft exists) by
-
-       prompt% anno -draft -comp X-MH-Attachment -text /export/home/jon/foo -nodate -append
-       prompt% anno -draft -comp X-MH-Attachment -text /export/home/jon/bar -nodate -append
-       prompt% anno -draft -comp X-MH-Attachment -text /export/home/jon/test/foo -nodate -append
-
-One can quite easily make an "attach" command using shell scripts, aliases or functions.
-For example, here's a bash function that does the job:
-
-       function attach() { for i in $*; do anno -append -nodate -draft -comp X-MH-Attachment -text "$i"; done; }
-
-The following examples show the different ways in which attachments can be
-listed.
-
-       prompt% anno -list -draft -comp X-MH-Attachment
-       foo
-       bar
-       foo
-
-       prompt% anno -list -draft -comp X-MH-Attachment -text /
-       /export/home/jon/foo
-       /export/home/jon/bar
-       /export/home/jon/test/foo
-
-       prompt% anno -list -draft -comp X-MH-Attachment -number
-       1       foo
-       2       bar
-       3       foo
-
-       prompt% anno -list -draft -comp X-MH-Attachment -text / -number
-       1       /export/home/jon/foo
-       2       /export/home/jon/bar
-       3       /export/home/jon/test/foo
-
-       prompt%
-
-Why all these listing options?
-
-I feel that the listing as produced by the first example is what most people
-would want most of the time.
-
-The listing as produced by the second example seemed necessary for situations
-where there were several attachments with the same file name in different
-directories.
-
-I included the numbering option so that attachments could be deleted by number
-which might be easier in situations where there were several attachments with
-the same file name in different directories, as in the above example.
-
-Attachments are deleted using the -delete option.
-
-       prompt% anno -delete -draft -comp X-MH-Attachment -text foo
-
-deletes the first attachment since the foo matches the basename of the attachment
-name.
-
-       prompt% anno -delete -draft -comp X-MH-Attachment -text /export/home/jon/test/foo
-
-deletes the third attachment since the text is a full path name and matches.
-
-       prompt% anno -delete -draft -comp X-MH-Attachment -number 2
-
-deletes the second attachment.
-
-The attachment annotations are converted to a MIME message by send.  I'm not
-completely sure that this is the right place to do it, as opposed to doing
-it in post, but both would work.  It seemed to me to make more sense to do
-it in send so that all of the various post options would apply to the MIME
-message instead of the original draft file.
-
-I added an -attach option to send that specifies the header field name used
-for attachments.  Send performs the following additional steps if this option
-is set:
-
- o  It scans the header of the draft for attachments.  Normal behavior applies
-    if none exist.
-
- o  A temporary mhbuild composition file is created if there are attachments.
-
- o  All non-attachment headers are copied from the draft file to the
-    composition file.
-
- o  The body of the draft is copied to a temporary body file if it contains at
-    least one non-whitespace character.  A mhbuild directive for this file is
-    appended to the composition file.  Note that this eliminates the problem
-    of lines beginning with the # character in the message body.
-
- o  A mhbuild directive is appended to the composition file for each attachment
-    header.
-
- o  mhbuild is run on the composition file, converting it to a MIME message.
-
- o  The converted composition file is substituted for the original draft file
-    and run through the rest of send.
-
- o  The original draft file is renamed instead of the converted composition
-    file.  This preserves the original message instead of the composition file
-    which is really what a user would want.
-
- o  The ,file.orig file created by mhbuild is removed as it's a nuisance.
-
-The mhbuild directives appended to the composition file are constructed as
-follows:
-
- o  The content-type a file with a dot-suffix is obtained from the list of
-    mhshow-suffix- entries in the profile.
-
- o  A file with no dot-suffix or no entry in the profile is assigned a
-    content-type of application/octet-stream if it contains any non-ASCII
-    characters.
-
- o  A file with no dot-suffix or no entry in the profile is assigned a
-    content-type of text/plain if it contains only ASCII characters.
-
- o  The directive is of the form:
-
-       #content-type; name="basename"; x-unix-mode=mode [ description ] filename
-
-    The content type is derived as discussed above.  The basename is the
-    last component of the pathname given in the body of the attachment header
-    field.  The mode is file permissions.  The description is obtained by
-    running the file command on the attachment file.  The filename is the
-    field body from the attachment header field.
-
-I added an -attach option to whatnow that specifies the header field name for
-attachments.
-
-I added to the commands available at the whatnow prompt to provide an interface
-to the attachment mechanism.
-
-I'm not completely happy with some of these additions because they duplicate
-shell functionality.  I'm not sure that there's a good way around it other than
-to not use whatnow.
-
-The first three additions (the ones I'm not happy with) are cd, ls, and pwd.
-These do the same thing as their system counterparts.  As a matter of fact,
-these are implemented by running the commands in a subshell.  I did this because
-I wanted proper interpretation of shell-specific things like ~ and wildcard
-expansion.
-
-The next command is attach.  This takes a list of files and adds them to the draft
-as attachments using the same code as the modified anno.  The list of files is
-run through ls using the user's shell, so wildcard expansion and all that works.
-
-The alist command lists the attachments on the current draft using listing function
-that I added to anno.  It takes two optional options, -l for a long listing meaning
-full path names, and -n for a numbered listing.
-
-The detach command removes attachments from the current draft, again using the
-modified anno.  The arguments are interpreted as numbers if the -n option is used,
-otherwise they're interpreted as file names.  File names are shoveled through ls
-using the user's shell in the directory containing the file for wildcard expansion
-and such.  File names are matched against the last pathname component unless they
-begin with a / in which case they're matched against the entire name.
-
-What's Left To Do?
-~~~~~~~~~~~~~~~~~~
-
-Nothing on this stuff.  When I get time I'd like to improve the interface
-for reading messages with attachments.  It's my opinion that, because of the
-command line nature of nmh, it makes the most sense to treat attachments as
-separate messages.  In other words one should be able to read the next
-attachment using next, and the previous one using prev.  One should be able
-to show and scan attachments.  This would probably involve a major change
-in the message numbering scheme to allow something like 123.4 to indicate
-attachment 4 on message 123.
-
-       Jon Steinhart
index 97e0ff7..c3c87fa 100644 (file)
@@ -10,6 +10,13 @@ install-mh \- initialize the nmh environment
 .na
 .B %libdir%/install\-mh
 .RB [ \-auto ]
+.RB [ \-check ]
+.RB [ \-version ]
+.RB [ \-help ]
+.HP 5
+.B install\-mh
+.RB [ \-auto ]
+.RB [ \-check ]
 .RB [ \-version ]
 .RB [ \-help ]
 .ad
@@ -20,38 +27,34 @@ is the
 program to create the initial setup
 for a first\-time
 .B nmh
-user.  It is typically invoked by other
-.B nmh
-commands, and should NOT be directly invoked by the user.
+user.
+.B Install\-mh
+lives in two places for historical reasons.
 .PP
-When a user runs any
-.B nmh
-program for the first time, the program will invoke
-.B install\-mh
-(with the `\-auto' switch) to query the user for the initial
-.B nmh
-environment.  The user is asked
+The \fB\-auto\fP option does things as automatically as possible and
+makes \fBinstall\-mh\fP less chatty.
+.PP
+The user is asked
 for the name of the directory that will be designated as the user's
 .B nmh
 directory.  If this directory does not exist, the user is
 asked if it should be created.  Normally, this directory should be
 under the user's home directory, and has the default name of
-.RI \*(lq Mail/ \*(rq.
-After
-.B install\-mh
-has written the initial
+\fI``Mail''\fP.
+.B Install\-mh
+writes an initial
 .I \&.mh\(ruprofile
-for the user, control returns to the original
-.B nmh
-program.
+for the user.
 .PP
 As with all
 .B nmh
 commands,
 .B install\-mh
-first consults the
+first checks for the existence of the \fB$MH\fP environment variable
+since that gives the profile path if set.
+If it isn't set, the
 .B $HOME
-environment variable to determine the user's home directory.
+environment variable is consulted to determine the user's home directory.
 If
 .B $HOME
 is not set, then the
@@ -65,6 +68,11 @@ will check for the existence of a global profile
 .IR %etcdir%/mh.profile .
 If found, this will be used to initialize the new
 .IR \&.mh\(ruprofile .
+.PP
+The \fB\-check\fP option can be used to check whether or not nmh has
+been installed.
+This can be used by other programs to determine whether or not nmh has
+been installed without their having to know the internals of nmh.
 
 .SH FILES
 .fc ^ ~
index 17d73e2..0f552b0 100644 (file)
@@ -44,12 +44,13 @@ on your
 This is best done in one of the files:
 .IR \&.profile ,
 .IR \&.login ,
+.IR \&.bashrc ,
 or
 .I \&.cshrc
 in your home directory.  (Check the
 manual entry for the shell you use, in case you don't know how to
 do this.)  Run the
-.B inc
+.B install-mh
 command.  If you've never used
 .B nmh
 before, it will create the necessary default files and directories after
index e55d683..b38d822 100644 (file)
@@ -21,10 +21,6 @@ context_del (char *key)
 {
     register struct node *np, *pp;
 
-    /* sanity check - check that context has been read */
-    if (defpath == NULL)
-       adios (NULL, "oops, context hasn't been read yet");
-
     for (np = m_defs, pp = NULL; np; pp = np, np = np->n_next) {
        if (!strcasecmp (np->n_name, key)) {
            if (!np->n_context)
index 96f28f9..efac368 100644 (file)
@@ -17,10 +17,6 @@ context_find (char *str)
 {
     struct node *np;
 
-    /* sanity check - check that context has been read */
-    if (defpath == NULL)
-       adios (NULL, "oops, context hasn't been read yet");
-
     for (np = m_defs; np; np = np->n_next)
        if (!strcasecmp (np->n_name, str))
            return (np->n_field);
index 49b4fc3..e6cdfff 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  * context_read.c -- find and read profile and context files
  *
  * This code is Copyright (c) 2002, by the authors of nmh.  See the
  * COPYRIGHT file in the root directory of the nmh distribution for
  * complete copyright information.
+ *
+ *     This function must be called early on in any nmh utility, and
+ *     may only be called once.  It does the following:
+ *
+ *      o  Sets the global variable "mypath" to the home directory path.
+ *
+ *      o  Sets the global variable "defpath" to the absolute path of
+ *         the profile file.
+ *
+ *      o  Reads in the profile file.  Bails out if it can't.
+ *
+ *      o  Makes sure that the mail directory exists, prompting for
+ *         creation if it doesn't.
+ *
+ *      o  Reads the context file either as set by the MHCONTEXT
+ *         environment variable or by the profile.
  */
 
-#include <h/mh.h>
-#include <errno.h>
-#include <pwd.h>
+#include <h/mh.h>                              /* mh internals */
+#include <errno.h>                             /* system call errors */
+#include <pwd.h>                               /* structure for getpwuid() results */
 
-extern int errno;
+extern int     errno;                          /* system call error number */
 
 void
 context_read (void)
 {
-    pid_t pid;
-    register char *cp, *pp;
-    char buf[BUFSIZ];
-    struct stat st;
-    register struct passwd *pw;
-    register FILE *ib;
-
-    if (defpath)
-       return;
+    char                       buf[BUFSIZ];    /* path name buffer */
+    char                       *cp;            /* miscellaneous pointer */
+    char                       *nd;            /* nmh directory pointer */
+    struct     stat            st;             /* stat() results */
+    register   struct  passwd  *pw;            /* getpwuid() results */
+    register   FILE            *ib;            /* profile and context file pointer */
 
     /*
-     * Find user's home directory
+     * Find user's home directory.  Try the HOME environment variable first,
+     * the home directory field in the password file if that's not found.
      */
-    if (!mypath) {
-       if ((mypath = getenv ("HOME")))
-           mypath = getcpy (mypath);
+
+    if ((mypath = getenv("HOME")) == (char *)0) {
+       if ((pw = getpwuid(getuid())) == (struct passwd *)0 || *pw->pw_dir == '\0')
+           adios(NULL, "cannot determine your home directory");
        else
-           if ((pw = getpwuid (getuid ())) == NULL
-                   || pw->pw_dir == NULL
-                   || *pw->pw_dir == 0)
-               adios (NULL, "no HOME envariable");
-           else
-               mypath = getcpy (pw->pw_dir);
-       if ((cp = mypath + strlen (mypath) - 1) > mypath && *cp == '/')
-           *cp = 0;
+           mypath = pw->pw_dir;
     }
 
     /*
-     * open and read user's profile
+     * Find and read user's profile.  Check for the existence of an MH environment
+     * variable first with non-empty contents.  Convert any relative path name
+     * found there to an absolute one.  Look for the profile in the user's home
+     * directory if the MH environment variable isn't set.
      */
-    if ((cp = getenv ("MH")) && *cp != '\0') {
-       defpath = path (cp, TFILE);
-       if ((ib = fopen (defpath, "r")) == NULL)
-           adios (defpath, "unable to read");
-       if (*cp != '/')
-           m_putenv ("MH", defpath);
-    } else {
-       defpath = concat (mypath, "/", mh_profile, NULL);
-
-       if ((ib = fopen (defpath, "r")) == NULL) {
-           switch (pid = vfork ()) {
-               case -1:
-                   adios ("fork", "unable to");
-
-               case 0:
-                   setgid (getgid ());
-                   setuid (getuid ());
-
-                   execlp (installproc, "install-mh", "-auto", NULL);
-                   fprintf (stderr, "unable to exec ");
-                   perror (installproc);
-                   _exit (-1);
-
-               default:
-                   if (pidwait (pid, 0)
-                           || (ib = fopen (defpath, "r")) == NULL)
-                       adios (NULL, "[install-mh aborted]");
-           }
-       }
+
+    if ((cp = getenv("MH")) && *cp != '\0') {
+       defpath = path(cp, TFILE);
+
+       if (stat(defpath, &st) != -1 && (st.st_mode & S_IFREG) == 0)
+               adios((char *)0, "`%s' specified by your MH environment variable is not a normal file", cp);
+
+       if ((ib = fopen(defpath, "r")) == (FILE *)0)
+           adios((char *)0, "unable to read the `%s' profile specified by your MH environment variable", defpath);
+    }
+    else {
+       defpath = concat(mypath, "/", mh_profile, NULL);
+
+       if ((ib = fopen(defpath, "r")) == (FILE *)0)
+           adios((char *)0, "Doesn't look like nmh is installed.  Run install-mh to do so.");
+
+       cp = mh_profile;
     }
-    readconfig (&m_defs, ib, mh_profile, 0);
+
+    readconfig (&m_defs, ib, cp, 0);
     fclose (ib);
 
     /*
-     * Find user's nmh directory
+     * Find the user's nmh directory, which is specified by the "path" profile component.
+     * Convert a relative path name to an absolute one rooted in the home directory.
      */
-    if ((pp = context_find ("path")) && *pp != '\0') {
-       if (*pp != '/')
-           snprintf (buf, sizeof(buf), "%s/%s", mypath, pp);
-       else
-           strncpy (buf, pp, sizeof(buf));
-       if (stat(buf, &st) == -1) {
-           if (errno != ENOENT)
-               adios (buf, "error opening");
-           cp = concat ("Your MH-directory \"", buf,
-               "\" doesn't exist; Create it? ", NULL);
-           if (!getanswer(cp))
-               adios (NULL, "unable to access MH-directory \"%s\"", buf);
-           free (cp);
-           if (!makedir (buf))
-               adios (NULL, "unable to create", buf);
-       }
+
+    if ((cp = context_find ("path")) == (char *)0)
+       adios(NULL, "Your %s file does not contain a path entry.", defpath);
+
+    if (*cp == '\0')
+       adios(NULL, "Your `%s' profile file does not contain a valid path entry.", defpath);
+
+    if (*cp != '/')
+       (void)snprintf (nd = buf, sizeof(buf), "%s/%s", mypath, cp);
+    else
+       nd = cp;
+
+    if (stat(nd, &st) == -1) {
+       if (errno != ENOENT)
+           adios (nd, "error opening");
+
+       cp = concat ("Your MH-directory \"", nd, "\" doesn't exist; Create it? ", NULL);
+
+       if (!getanswer(cp))
+           adios (NULL, "unable to access MH-directory \"%s\"", nd);
+
+       free (cp);
+
+       if (!makedir (nd))
+           adios (NULL, "unable to create", nd);
     }
 
+    else if ((st.st_mode & S_IFDIR) == 0)
+       adios ((char *)0, "`%s' is not a directory", nd);
+
     /*
-     * open and read user's context file
+     * Open and read user's context file.  The name of the context file comes from the
+     * profile unless overridden by the MHCONTEXT environment variable.
      */
-    if (!(cp = getenv ("MHCONTEXT")) || *cp == '\0')
+
+    if ((cp = getenv ("MHCONTEXT")) == (char *)0 || *cp == '\0')
        cp = context;
+
     ctxpath = getcpy (m_maildir (cp));
+
     if ((ib = fopen (ctxpath, "r"))) {
        readconfig ((struct node **) 0, ib, cp, 1);
        fclose (ib);
     }
+
+    return;
 }
index 541253d..b723cb4 100644 (file)
@@ -17,10 +17,6 @@ context_replace (char *key, char *value)
 {
     register struct node *np;
 
-    /* sanity check - check that context has been read */
-    if (defpath == NULL)
-       adios (NULL, "oops, context hasn't been read yet");
-
     /*
      * If list is emtpy, allocate head of profile/context list.
      */
index b1dc3a5..d085d53 100644 (file)
@@ -29,10 +29,6 @@ static void seq_private (struct msgs *);
 void
 seq_read (struct msgs *mp)
 {
-    /* sanity check - check that context has been read */
-    if (defpath == NULL)
-       adios (NULL, "oops, context hasn't been read yet");
-
     /*
      * Initialize the list of sequence names.  Go ahead and
      * add the "cur" sequence to the list of sequences.
index 6366e5e..f8de9ed 100644 (file)
@@ -31,10 +31,6 @@ seq_save (struct msgs *mp)
     FILE *fp;
     sigset_t set, oset;
 
-    /* sanity check - check that context has been read */
-    if (defpath == NULL)
-       adios (NULL, "oops, context hasn't been read yet");
-
     /* check if sequence information has changed */
     if (!(mp->msgflags & SEQMOD))
        return;
index 905c33d..6d971d5 100644 (file)
@@ -251,7 +251,7 @@ whom: whom.o distsbr.o $(LOCALLIBS)
 # ========== DEPENDENCIES FOR INSTALLING ==========
 
 # install everything
-install: install-cmds install-lcmds install-misc install-scmds
+install: install-cmds install-misc install-lcmds install-scmds
 
 # install commands
 install-cmds:
@@ -270,6 +270,7 @@ install-lcmds:
        $(LN) $(bindir)/folder $(bindir)/folders
        $(LN) $(bindir)/show   $(bindir)/prev
        $(LN) $(bindir)/show   $(bindir)/next
+       $(LN) $(libdir)/install-mh   $(bindir)/install-mh
 
 # install misc support binaries
 install-misc:
index dac84d5..a79c842 100644 (file)
@@ -697,10 +697,6 @@ do_readonly_folders (void)
     char atrcur[BUFSIZ];
     register struct node *np;
 
-    /* sanity check - check that context has been read */
-    if (defpath == NULL)
-       adios (NULL, "oops, context hasn't been read yet");
-
     snprintf (atrcur, sizeof(atrcur), "atr-%s-", current);
     atrlen = strlen (atrcur);
 
index 2cc9bde..7706f90 100644 (file)
@@ -818,10 +818,6 @@ readonly_folders (void)
     char atrcur[BUFSIZ];
     register struct node *np;
 
-    /* sanity check - check that context has been read */
-    if (defpath == NULL)
-       adios (NULL, "oops, context hasn't been read yet");
-
     snprintf (atrcur, sizeof(atrcur), "atr-%s-", current);
     atrlen = strlen (atrcur);
 
index ff50d35..34aed95 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  * install-mh.c -- initialize the nmh environment of a new user
  *
@@ -9,8 +8,8 @@
  * complete copyright information.
  */
 
-#include <h/mh.h>
-#include <pwd.h>
+#include <h/mh.h>                              /* mh internals */
+#include <pwd.h>                               /* structure for getpwuid() results */
 
 static struct swit switches[] = {
 #define AUTOSW     0
@@ -19,18 +18,11 @@ static struct swit switches[] = {
     { "version", 0 },
 #define HELPSW     2
     { "help", 0 },
+#define CHECKSW     3
+    { "check", 1 },
     { NULL, 0 }
 };
 
-static char *message[] = {
-    "Prior to using nmh, it is necessary to have a file in your login",
-    "directory (%s) named %s which contains information",
-    "to direct certain nmh operations.  The only item which is required",
-    "is the path to use for all nmh folder operations.  The suggested nmh",
-    "path for you is %s/Mail...",
-    NULL
-};
-
 /*
  * static prototypes
  */
@@ -40,13 +32,14 @@ static char *geta(void);
 int
 main (int argc, char **argv)
 {
-    int i, autof = 0;
-    char *cp, *path, buf[BUFSIZ];
+    int autof = 0;
+    char *cp, *pathname, buf[BUFSIZ];
     char *dp, **arguments, **argp;
     struct node *np;
     struct passwd *pw;
     struct stat st;
     FILE *in, *out;
+    int                check;
 
 #ifdef LOCALE
     setlocale(LC_ALL, "");
@@ -55,6 +48,8 @@ main (int argc, char **argv)
     arguments = getarguments (invo_name, argc, argv, 0);
     argp = arguments;
 
+    check = 0;
+
     while ((dp = *argp++)) {
        if (*dp == '-') {
            switch (smatch (++dp, switches)) {
@@ -75,44 +70,68 @@ main (int argc, char **argv)
                case AUTOSW:
                    autof++;
                    continue;
+
+               case CHECKSW:
+                   check = 1;
+                   continue;
            }
        } else {
            adios (NULL, "%s is invalid argument", dp);
        }
     }
 
-    /* straight from context_read ... */
-    if (mypath == NULL) {
-       if ((mypath = getenv ("HOME"))) {
-           mypath = getcpy (mypath);
-       } else {
-           if ((pw = getpwuid (getuid ())) == NULL
-                   || pw->pw_dir == NULL
-                   || *pw->pw_dir == 0)
-               adios (NULL, "no HOME envariable");
-           else
-               mypath = getcpy (pw->pw_dir);
-       }
-       if ((cp = mypath + strlen (mypath) - 1) > mypath && *cp == '/')
-           *cp = 0;
+    /*
+     * Find user's home directory.  Try the HOME environment variable first,
+     * the home directory field in the password file if that's not found.
+     */
+
+    if ((mypath = getenv("HOME")) == (char *)0) {
+       if ((pw = getpwuid(getuid())) == (struct passwd *)0 || *pw->pw_dir == '\0')
+           adios(NULL, "cannot determine your home directory");
+       else
+           mypath = pw->pw_dir;
     }
-    defpath = concat (mypath, "/", mh_profile, NULL);
+
+    /*
+     * Find the user's profile.  Check for the existence of an MH environment
+     * variable first with non-empty contents.  Convert any relative path name
+     * found there to an absolute one.  Look for the profile in the user's home
+     * directory if the MH environment variable isn't set.
+     */
+
+    if ((cp = getenv("MH")) && *cp != '\0')
+       defpath = path(cp, TFILE);
+    else
+       defpath = concat(mypath, "/", mh_profile, NULL);
+
+    /*
+     * Check for the existence of the profile file.  It's an error if it exists and
+     * this isn't an installation check.  An installation check fails if it does not
+     * exist, succeeds if it does.
+     */
 
     if (stat (defpath, &st) != NOTOK) {
-       if (autof)
+       if (check)
+           done(0);
+
+       else if (autof)
            adios (NULL, "invocation error");
        else
-           adios (NULL,
-                   "You already have an nmh profile, use an editor to modify it");
+           adios (NULL, "You already have an nmh profile, use an editor to modify it");
+    }
+    else if (check) {
+       done(1);
     }
 
     if (!autof && gans ("Do you want help? ", anoyes)) {
-       putchar ('\n');
-       for (i = 0; message[i]; i++) {
-           printf (message[i], mypath, mh_profile);
-           putchar ('\n');
-       }
-       putchar ('\n');
+       (void)printf(
+        "\n"
+        "Prior to using nmh, it is necessary to have a file in your login\n"
+        "directory (%s) named %s which contains information\n"
+        "to direct certain nmh operations.  The only item which is required\n"
+        "is the path to use for all nmh folder operations.  The suggested nmh\n"
+        "path for you is %s/Mail...\n"
+        "\n", mypath, mh_profile, mypath);
     }
 
     cp = concat (mypath, "/", "Mail", NULL);
@@ -121,7 +140,7 @@ main (int argc, char **argv)
            cp = concat ("You already have the standard nmh directory \"",
                    cp, "\".\nDo you want to use it for nmh? ", NULL);
            if (gans (cp, anoyes))
-               path = "Mail";
+               pathname = "Mail";
            else
                goto query;
        } else {
@@ -134,26 +153,26 @@ main (int argc, char **argv)
            cp = concat ("Do you want the standard nmh path \"",
                    mypath, "/", "Mail\"? ", NULL);
        if (autof || gans (cp, anoyes))
-           path = "Mail";
+           pathname = "Mail";
        else {
 query:
            if (gans ("Do you want a path below your login directory? ",
                        anoyes)) {
                printf ("What is the path?  %s/", mypath);
-               path = geta ();
+               pathname = geta ();
            } else {
                printf ("What is the whole path?  /");
-               path = concat ("/", geta (), NULL);
+               pathname = concat ("/", geta (), NULL);
            }
        }
     }
 
     chdir (mypath);
-    if (chdir (path) == NOTOK) {
-       cp = concat ("\"", path, "\" doesn't exist; Create it? ", NULL);
+    if (chdir (pathname) == NOTOK) {
+       cp = concat ("\"", pathname, "\" doesn't exist; Create it? ", NULL);
        if (autof || gans (cp, anoyes))
-           if (makedir (path) == 0)
-               adios (NULL, "unable to create %s", path);
+           if (makedir (pathname) == 0)
+               adios (NULL, "unable to create %s", pathname);
     } else {
        printf ("[Using existing directory]\n");
     }
@@ -165,7 +184,7 @@ query:
        adios (NULL, "unable to allocate profile storage");
     np = m_defs;
     np->n_name = getcpy ("Path");
-    np->n_field = getcpy (path);
+    np->n_field = getcpy (pathname);
     np->n_context = 0;
     np->n_next = NULL;
 
index 2909196..5fe4708 100644 (file)
--- a/uip/rmf.c
+++ b/uip/rmf.c
@@ -223,10 +223,6 @@ rma (char *folder)
     register char *cp;
     register struct node *np, *pp;
 
-    /* sanity check - check that context has been read */
-    if (defpath == NULL)
-       adios (NULL, "oops, context hasn't been read yet");
-
     alen = strlen ("atr-");
     plen = strlen (cp = m_mailpath (folder)) + 1;