Split nmh dir into mmh dir (~/.mmh) and mail storage (~/Mail).
[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 = mhbasename(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
84         ** variable first, the home directory field in the password file
85         ** if that's not found.
86         */
87
88         if ((mypath = getenv("HOME")) == NULL) {
89                 if ((pw = getpwuid(getuid())) == (struct passwd *)0 ||
90                                 *pw->pw_dir == '\0')
91                         adios(NULL, "cannot determine your home directory");
92                 else
93                         mypath = pw->pw_dir;
94         }
95
96         /*
97         ** Find the user's profile.  Check for the existence of an
98         ** MH environment variable first with non-empty contents.
99         ** Convert any relative path name found there to an absolute one.
100         ** Look for the profile in the user's home directory if the MH
101         ** environment variable isn't set.
102         */
103
104         if ((cp = getenv("MH")) && *cp != '\0')
105                 defpath = getcpy(expanddir(cp));
106         else
107                 defpath = concat(mypath, "/", mh_profile, NULL);
108
109         /*
110         ** Check for the existence of the profile file.  It's an
111         ** error if it exists and this isn't an installation check.
112         ** An installation check fails if it does not exist, succeeds
113         ** if it does.
114         */
115
116         if (stat(defpath, &st) != NOTOK) {
117                 if (check)
118                         done(0);
119
120                 else if (autof)
121                         adios(NULL, "invocation error");
122                 else
123                         adios(NULL, "You already have an nmh profile, use an editor to modify it");
124         } else if (check) {
125                 done(1);
126         }
127
128         if (!autof && gans("Do you want help? ", anoyes)) {
129                 printf("\n"
130                  "Prior to using nmh, it is necessary to have a file in your login\n"
131                  "directory (%s) named %s which contains information\n"
132                  "to direct certain nmh operations.  The only item which is required\n"
133                  "is the path to use for all nmh folder operations.  The suggested nmh\n"
134                  "path for you is %s/Mail...\n"
135                  "\n", mypath, mh_profile, mypath);
136         }
137
138         cp = concat(mypath, "/", "Mail", NULL);
139         if (stat(cp, &st) != NOTOK) {
140                 if (S_ISDIR(st.st_mode)) {
141                         cp = concat("You already have the standard nmh directory \"",
142                                 cp, "\".\nDo you want to use it for nmh? ", NULL);
143                         if (gans(cp, anoyes))
144                                 pathname = "Mail";
145                         else
146                                 goto query;
147                 } else {
148                         goto query;
149                 }
150         } else {
151                 if (autof)
152                         printf("I'm going to create the standard nmh path for you.\n");
153                 else
154                         cp = concat("Do you want the standard nmh path \"",
155                                         mypath, "/", "Mail\"? ", NULL);
156                 if (autof || gans(cp, anoyes))
157                         pathname = "Mail";
158                 else {
159 query:
160                         if (gans("Do you want a path below your login directory? ", anoyes)) {
161                                 printf("What is the path?  %s/", mypath);
162                                 pathname = geta();
163                         } else {
164                                 printf("What is the whole path?  /");
165                                 pathname = concat("/", geta(), NULL);
166                         }
167                 }
168         }
169
170         chdir(mypath);
171         if (chdir(pathname) == NOTOK) {
172                 cp = concat("\"", pathname, "\" doesn't exist; Create it? ",
173                                 NULL);
174                 if (autof || gans(cp, anoyes))
175                         if (makedir(pathname) == 0)
176                                 adios(NULL, "unable to create %s", pathname);
177         } else {
178                 printf("[Using existing directory]\n");
179         }
180
181         /*
182         ** Add some initial elements to the profile/context list
183         */
184         m_defs = (struct node *) mh_xmalloc(sizeof *np);
185         np = m_defs;
186         np->n_name = getcpy("Path");
187         np->n_field = getcpy(pathname);
188         np->n_context = 0;
189         np->n_next = NULL;
190
191         /*
192         ** If there is a default profile file in the
193         ** nmh `etc' directory, then read it also.
194         */
195         if ((in = fopen(mh_defaults, "r"))) {
196                 readconfig(&np->n_next, in, mh_defaults, 0);
197                 fclose(in);
198         }
199
200         ctxpath = getcpy(toabsdir(context = "context"));
201
202         /* Initialize current folder to default */
203         context_replace(curfolder, defaultfolder);
204         context_save();
205
206         /*
207         ** Now write out the initial .mh_profile
208         */
209         if ((out = fopen(defpath, "w")) == NULL)
210                 adios(defpath, "unable to write");
211         for (np = m_defs; np; np = np->n_next) {
212                 if (!np->n_context)
213                         fprintf(out, "%s: %s\n", np->n_name, np->n_field);
214         }
215         fclose(out);
216         done(0);
217         return 1;
218 }
219
220
221 static char *
222 geta(void)
223 {
224         char *cp;
225         static char line[BUFSIZ];
226
227         fflush(stdout);
228         if (fgets(line, sizeof(line), stdin) == NULL)
229                 done(1);
230         if ((cp = strchr(line, '\n')))
231                 *cp = 0;
232         return line;
233 }