Clean up code in inc.c
[mmh] / uip / install-mh.c
1 /*
2  * install-mh.c -- initialize the nmh environment of a new user
3  *
4  * This code is Copyright (c) 2002, by the authors of nmh.  See the
5  * COPYRIGHT file in the root directory of the nmh distribution for
6  * complete copyright information.
7  */
8
9 #include <h/mh.h>                               /* mh internals */
10 #include <h/utils.h>
11 #include <pwd.h>                                /* structure for getpwuid() results */
12
13 static struct swit switches[] = {
14 #define AUTOSW     0
15     { "auto", 0 },
16 #define VERSIONSW  1
17     { "version", 0 },
18 #define HELPSW     2
19     { "help", 0 },
20 #define CHECKSW     3
21     { "check", 1 },
22     { NULL, 0 }
23 };
24
25 /*
26  * static prototypes
27  */
28 static char *geta(void);
29
30
31 int
32 main (int argc, char **argv)
33 {
34     int autof = 0;
35     char *cp, *pathname, buf[BUFSIZ];
36     char *dp, **arguments, **argp;
37     struct node *np;
38     struct passwd *pw;
39     struct stat st;
40     FILE *in, *out;
41     int         check;
42
43 #ifdef LOCALE
44     setlocale(LC_ALL, "");
45 #endif
46     invo_name = r1bindex (argv[0], '/');
47     arguments = getarguments (invo_name, argc, argv, 0);
48     argp = arguments;
49
50     check = 0;
51
52     while ((dp = *argp++)) {
53         if (*dp == '-') {
54             switch (smatch (++dp, switches)) {
55                 case AMBIGSW:
56                     ambigsw (dp, switches);
57                     done (1);
58                 case UNKWNSW:
59                     adios (NULL, "-%s unknown\n", dp);
60
61                 case HELPSW:
62                     snprintf (buf, sizeof(buf), "%s [switches]", invo_name);
63                     print_help (buf, switches, 0);
64                     done (1);
65                 case VERSIONSW:
66                     print_version(invo_name);
67                     done (1);
68
69                 case AUTOSW:
70                     autof++;
71                     continue;
72
73                 case CHECKSW:
74                     check = 1;
75                     continue;
76             }
77         } else {
78             adios (NULL, "%s is invalid argument", dp);
79         }
80     }
81
82     /*
83      *  Find user's home directory.  Try the HOME environment variable first,
84      *  the home directory field in the password file if that's not found.
85      */
86
87     if ((mypath = getenv("HOME")) == (char *)0) {
88         if ((pw = getpwuid(getuid())) == (struct passwd *)0 || *pw->pw_dir == '\0')
89             adios(NULL, "cannot determine your home directory");
90         else
91             mypath = pw->pw_dir;
92     }
93
94     /*
95      *  Find the user's profile.  Check for the existence of an MH environment
96      *  variable first with non-empty contents.  Convert any relative path name
97      *  found there to an absolute one.  Look for the profile in the user's home
98      *  directory if the MH environment variable isn't set.
99      */
100
101     if ((cp = getenv("MH")) && *cp != '\0')
102         defpath = path(cp, TFILE);
103     else
104         defpath = concat(mypath, "/", mh_profile, NULL);
105
106     /*
107      *  Check for the existence of the profile file.  It's an error if it exists and
108      *  this isn't an installation check.  An installation check fails if it does not
109      *  exist, succeeds if it does.
110      */
111
112     if (stat (defpath, &st) != NOTOK) {
113         if (check)
114             done(0);
115
116         else if (autof)
117             adios (NULL, "invocation error");
118         else
119             adios (NULL, "You already have an nmh profile, use an editor to modify it");
120     }
121     else if (check) {
122         done(1);
123     }
124
125     if (!autof && gans ("Do you want help? ", anoyes)) {
126         (void)printf(
127          "\n"
128          "Prior to using nmh, it is necessary to have a file in your login\n"
129          "directory (%s) named %s which contains information\n"
130          "to direct certain nmh operations.  The only item which is required\n"
131          "is the path to use for all nmh folder operations.  The suggested nmh\n"
132          "path for you is %s/Mail...\n"
133          "\n", mypath, mh_profile, mypath);
134     }
135
136     cp = concat (mypath, "/", "Mail", NULL);
137     if (stat (cp, &st) != NOTOK) {
138         if (S_ISDIR(st.st_mode)) {
139             cp = concat ("You already have the standard nmh directory \"",
140                     cp, "\".\nDo you want to use it for nmh? ", NULL);
141             if (gans (cp, anoyes))
142                 pathname = "Mail";
143             else
144                 goto query;
145         } else {
146             goto query;
147         }
148     } else {
149         if (autof)
150             printf ("I'm going to create the standard nmh path for you.\n");
151         else
152             cp = concat ("Do you want the standard nmh path \"",
153                     mypath, "/", "Mail\"? ", NULL);
154         if (autof || gans (cp, anoyes))
155             pathname = "Mail";
156         else {
157 query:
158             if (gans ("Do you want a path below your login directory? ",
159                         anoyes)) {
160                 printf ("What is the path?  %s/", mypath);
161                 pathname = geta ();
162             } else {
163                 printf ("What is the whole path?  /");
164                 pathname = concat ("/", geta (), NULL);
165             }
166         }
167     }
168
169     chdir (mypath);
170     if (chdir (pathname) == NOTOK) {
171         cp = concat ("\"", pathname, "\" doesn't exist; Create it? ", NULL);
172         if (autof || gans (cp, anoyes))
173             if (makedir (pathname) == 0)
174                 adios (NULL, "unable to create %s", pathname);
175     } else {
176         printf ("[Using existing directory]\n");
177     }
178
179     /*
180      * Add some initial elements to the profile/context list
181      */
182     m_defs = (struct node *) mh_xmalloc (sizeof *np);
183     np = m_defs;
184     np->n_name = getcpy ("Path");
185     np->n_field = getcpy (pathname);
186     np->n_context = 0;
187     np->n_next = NULL;
188
189     /*
190      * If there is a default profile file in the
191      * nmh `etc' directory, then read it also.
192      */
193     if ((in = fopen (mh_defaults, "r"))) {
194         readconfig (&np->n_next, in, mh_defaults, 0);
195         fclose (in);
196     }
197
198     ctxpath = getcpy (m_maildir (context = "context"));
199
200     /* Initialize current folder to default */
201     context_replace (pfolder, defaultfolder);
202     context_save ();
203
204     /*
205      * Now write out the initial .mh_profile
206      */
207     if ((out = fopen (defpath, "w")) == NULL)
208         adios (defpath, "unable to write");
209     for (np = m_defs; np; np = np->n_next) {
210         if (!np->n_context)
211             fprintf (out, "%s: %s\n", np->n_name, np->n_field);
212     }
213     fclose (out);
214     done (0);
215     return 1;
216 }
217
218
219 static char *
220 geta (void)
221 {
222     char *cp;
223     static char line[BUFSIZ];
224
225     fflush(stdout);
226     if (fgets(line, sizeof(line), stdin) == NULL)
227         done (1);
228     if ((cp = strchr(line, '\n')))
229         *cp = 0;
230     return line;
231 }