X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/6c42153ad9362cc676ea66563bf400d7511b3b68..394a751fd883d2bbfc769fed7e254e008a2ef45e:/uip/install-mh.c diff --git a/uip/install-mh.c b/uip/install-mh.c index ff50d359..ac2c5c98 100644 --- a/uip/install-mh.c +++ b/uip/install-mh.c @@ -1,60 +1,65 @@ - -/* - * install-mh.c -- initialize the nmh environment of a new user - * - * $Id$ +/* install-mh.c -- initialize the nmh environment of a new user * * 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. */ -#include +#include "h/mh.h" +#include "sbr/getarguments.h" +#include "sbr/read_switch.h" +#include "sbr/concat.h" +#include "sbr/smatch.h" +#include "sbr/context_save.h" +#include "sbr/context_replace.h" +#include "sbr/readconfig.h" +#include "sbr/ambigsw.h" +#include "sbr/path.h" +#include "sbr/print_version.h" +#include "sbr/print_help.h" +#include "sbr/error.h" +#include "h/done.h" +#include "h/utils.h" +#include "sbr/m_maildir.h" +#include "sbr/makedir.h" #include +#include "sbr/read_line.h" -static struct swit switches[] = { -#define AUTOSW 0 - { "auto", 0 }, -#define VERSIONSW 1 - { "version", 0 }, -#define HELPSW 2 - { "help", 0 }, - { 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 - */ -static char *geta(void); +#define INSTALLMH_SWITCHES \ + X("auto", 0, AUTOSW) \ + X("version", 0, VERSIONSW) \ + X("help", 0, HELPSW) \ + X("check", 1, CHECKSW) \ + +#define X(sw, minchars, id) id, +DEFINE_SWITCH_ENUM(INSTALLMH); +#undef X + +#define X(sw, minchars, id) { sw, minchars, id }, +DEFINE_SWITCH_ARRAY(INSTALLMH, switches); +#undef X int main (int argc, char **argv) { - int i, autof = 0; - char *cp, *path, buf[BUFSIZ]; + bool autof = false; + char *cp, buf[BUFSIZ]; + const char *pathname; char *dp, **arguments, **argp; struct node *np; struct passwd *pw; struct stat st; FILE *in, *out; + bool check; + + if (nmh_init(argv[0], false, false)) { return 1; } -#ifdef LOCALE - setlocale(LC_ALL, ""); -#endif - invo_name = r1bindex (argv[0], '/'); arguments = getarguments (invo_name, argc, argv, 0); argp = arguments; + check = false; + while ((dp = *argp++)) { if (*dp == '-') { switch (smatch (++dp, switches)) { @@ -62,110 +67,131 @@ main (int argc, char **argv) ambigsw (dp, switches); done (1); case UNKWNSW: - adios (NULL, "-%s unknown\n", dp); + die("-%s unknown\n", dp); case HELPSW: snprintf (buf, sizeof(buf), "%s [switches]", invo_name); print_help (buf, switches, 0); - done (1); + done (0); case VERSIONSW: print_version(invo_name); - done (1); + done (0); case AUTOSW: - autof++; + autof = true; + continue; + + case CHECKSW: + check = true; continue; } } else { - adios (NULL, "%s is invalid argument", dp); + die("%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")) == NULL) { + if ((pw = getpwuid(getuid())) == NULL || *pw->pw_dir == '\0') + die("cannot determine your home directory"); + 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 (check) + done(0); if (autof) - adios (NULL, "invocation error"); - else - adios (NULL, - "You already have an nmh profile, use an editor to modify it"); + die("invocation error"); + die("You already have an nmh profile, use an editor to modify it"); } - - 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'); + if (check) + done(1); + + if (!autof && read_switch ("Do you want help? ", anoyes)) { + (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); if (stat (cp, &st) != NOTOK) { - if (S_ISDIR(st.st_mode)) { - 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"; - else - goto query; - } else { + if (!S_ISDIR(st.st_mode)) goto query; - } + cp = concat ("You already have the standard nmh directory \"", + cp, "\".\nDo you want to use it for nmh? ", NULL); + if (!read_switch (cp, anoyes)) + goto query; + pathname = "Mail"; } else { if (autof) - printf ("I'm going to create the standard nmh path for you.\n"); + puts("I'm going to create the standard nmh path for you."); else cp = concat ("Do you want the standard nmh path \"", mypath, "/", "Mail\"? ", NULL); - if (autof || gans (cp, anoyes)) - path = "Mail"; + if (autof || read_switch (cp, anoyes)) + pathname = "Mail"; else { query: - if (gans ("Do you want a path below your login directory? ", + if (read_switch ("Do you want a path below your login directory? ", anoyes)) { printf ("What is the path? %s/", mypath); - path = geta (); + pathname = read_line (); + if (pathname == NULL) done (1); } else { - printf ("What is the whole path? /"); - path = concat ("/", geta (), NULL); + fputs("What is the whole path? /", stdout); + pathname = read_line (); + if (pathname == NULL) done (1); + pathname = concat ("/", pathname, NULL); } } } - chdir (mypath); - if (chdir (path) == NOTOK) { - cp = concat ("\"", path, "\" doesn't exist; Create it? ", NULL); - if (autof || gans (cp, anoyes)) - if (makedir (path) == 0) - adios (NULL, "unable to create %s", path); + if (chdir (mypath) < 0) { + advise (mypath, "chdir"); + } + if (chdir (pathname) == NOTOK) { + cp = concat ("\"", pathname, "\" doesn't exist; Create it? ", NULL); + if (autof || read_switch (cp, anoyes)) + if (makedir (pathname) == 0) + die("unable to create %s", pathname); } else { - printf ("[Using existing directory]\n"); + puts("[Using existing directory]"); } /* * Add some initial elements to the profile/context list */ - if (!(m_defs = (struct node *) malloc (sizeof *np))) - adios (NULL, "unable to allocate profile storage"); - np = m_defs; - np->n_name = getcpy ("Path"); - np->n_field = getcpy (path); + NEW(np); + m_defs = np; + np->n_name = mh_xstrdup("Path"); + np->n_field = mh_xstrdup(pathname); np->n_context = 0; np->n_next = NULL; @@ -178,7 +204,7 @@ query: fclose (in); } - ctxpath = getcpy (m_maildir (context = "context")); + ctxpath = mh_xstrdup(m_maildir(context = "context")); /* Initialize current folder to default */ context_replace (pfolder, defaultfolder); @@ -189,25 +215,26 @@ query: */ if ((out = fopen (defpath, "w")) == NULL) adios (defpath, "unable to write"); + /* + * The main purpose of this first line is to fool file(1). + * Without it, if the first line of the profile is Path:, + * file 5.19 reports its type as message/news. With it, + * it reports the type as text/plain. + */ + fprintf (out, "MH-Profile-Version: 1.0\n"); for (np = m_defs; np; np = np->n_next) { if (!np->n_context) fprintf (out, "%s: %s\n", np->n_name, np->n_field); } fclose (out); - return done (0); -} + puts ("\nPlease see nmh(7) for an introduction to nmh.\n"); + print_intro (stdout, false); -static char * -geta (void) -{ - char *cp; - static char line[BUFSIZ]; - - fflush(stdout); - if (fgets(line, sizeof(line), stdin) == NULL) - done (1); - if ((cp = strchr(line, '\n'))) - *cp = 0; - return line; + /* Initialize the saved nmh version. The Path profile entry was added + above, that's all this needs. */ + (void) nmh_version_changed (0); + + done (0); + return 1; }