]> diplodocus.org Git - nmh/blob - uip/install-mh.c
31af64b818a0c12f4900c2dcc6acb80e637aae79
[nmh] / uip / install-mh.c
1 /* install-mh.c -- initialize the nmh environment of a new user
2 *
3 * This code is Copyright (c) 2002, by the authors of nmh. See the
4 * COPYRIGHT file in the root directory of the nmh distribution for
5 * complete copyright information.
6 */
7
8 #include <h/mh.h> /* mh internals */
9 #include "sbr/error.h"
10 #include "h/done.h"
11 #include <h/utils.h>
12 #include "sbr/m_maildir.h"
13 #include "sbr/makedir.h"
14 #include <pwd.h> /* structure for getpwuid() results */
15 #include "sbr/read_line.h"
16
17 #define INSTALLMH_SWITCHES \
18 X("auto", 0, AUTOSW) \
19 X("version", 0, VERSIONSW) \
20 X("help", 0, HELPSW) \
21 X("check", 1, CHECKSW) \
22
23 #define X(sw, minchars, id) id,
24 DEFINE_SWITCH_ENUM(INSTALLMH);
25 #undef X
26
27 #define X(sw, minchars, id) { sw, minchars, id },
28 DEFINE_SWITCH_ARRAY(INSTALLMH, switches);
29 #undef X
30
31
32 int
33 main (int argc, char **argv)
34 {
35 bool autof = false;
36 char *cp, buf[BUFSIZ];
37 const char *pathname;
38 char *dp, **arguments, **argp;
39 struct node *np;
40 struct passwd *pw;
41 struct stat st;
42 FILE *in, *out;
43 bool check;
44
45 if (nmh_init(argv[0], false, false)) { return 1; }
46
47 arguments = getarguments (invo_name, argc, argv, 0);
48 argp = arguments;
49
50 check = false;
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 die("-%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 (0);
65 case VERSIONSW:
66 print_version(invo_name);
67 done (0);
68
69 case AUTOSW:
70 autof = true;
71 continue;
72
73 case CHECKSW:
74 check = true;
75 continue;
76 }
77 } else {
78 die("%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")) == NULL) {
88 if ((pw = getpwuid(getuid())) == NULL || *pw->pw_dir == '\0')
89 die("cannot determine your home directory");
90 mypath = pw->pw_dir;
91 }
92
93 /*
94 * Find the user's profile. Check for the existence of an MH environment
95 * variable first with non-empty contents. Convert any relative path name
96 * found there to an absolute one. Look for the profile in the user's home
97 * directory if the MH environment variable isn't set.
98 */
99
100 if ((cp = getenv("MH")) && *cp != '\0')
101 defpath = path(cp, TFILE);
102 else
103 defpath = concat(mypath, "/", mh_profile, NULL);
104
105 /*
106 * Check for the existence of the profile file. It's an error if it exists and
107 * this isn't an installation check. An installation check fails if it does not
108 * exist, succeeds if it does.
109 */
110
111 if (stat (defpath, &st) != NOTOK) {
112 if (check)
113 done(0);
114 if (autof)
115 die("invocation error");
116 die("You already have an nmh profile, use an editor to modify it");
117 }
118 if (check)
119 done(1);
120
121 if (!autof && read_switch ("Do you want help? ", anoyes)) {
122 (void)printf(
123 "\n"
124 "Prior to using nmh, it is necessary to have a file in your login\n"
125 "directory (%s) named %s which contains information\n"
126 "to direct certain nmh operations. The only item which is required\n"
127 "is the path to use for all nmh folder operations. The suggested nmh\n"
128 "path for you is %s/Mail...\n"
129 "\n", mypath, mh_profile, mypath);
130 }
131
132 cp = concat (mypath, "/", "Mail", NULL);
133 if (stat (cp, &st) != NOTOK) {
134 if (!S_ISDIR(st.st_mode))
135 goto query;
136 cp = concat ("You already have the standard nmh directory \"",
137 cp, "\".\nDo you want to use it for nmh? ", NULL);
138 if (!read_switch (cp, anoyes))
139 goto query;
140 pathname = "Mail";
141 } else {
142 if (autof)
143 puts("I'm going to create the standard nmh path for you.");
144 else
145 cp = concat ("Do you want the standard nmh path \"",
146 mypath, "/", "Mail\"? ", NULL);
147 if (autof || read_switch (cp, anoyes))
148 pathname = "Mail";
149 else {
150 query:
151 if (read_switch ("Do you want a path below your login directory? ",
152 anoyes)) {
153 printf ("What is the path? %s/", mypath);
154 pathname = read_line ();
155 if (pathname == NULL) done (1);
156 } else {
157 fputs("What is the whole path? /", stdout);
158 pathname = read_line ();
159 if (pathname == NULL) done (1);
160 pathname = concat ("/", pathname, NULL);
161 }
162 }
163 }
164
165 if (chdir (mypath) < 0) {
166 advise (mypath, "chdir");
167 }
168 if (chdir (pathname) == NOTOK) {
169 cp = concat ("\"", pathname, "\" doesn't exist; Create it? ", NULL);
170 if (autof || read_switch (cp, anoyes))
171 if (makedir (pathname) == 0)
172 die("unable to create %s", pathname);
173 } else {
174 puts("[Using existing directory]");
175 }
176
177 /*
178 * Add some initial elements to the profile/context list
179 */
180 NEW(np);
181 m_defs = np;
182 np->n_name = mh_xstrdup("Path");
183 np->n_field = mh_xstrdup(pathname);
184 np->n_context = 0;
185 np->n_next = NULL;
186
187 /*
188 * If there is a default profile file in the
189 * nmh `etc' directory, then read it also.
190 */
191 if ((in = fopen (mh_defaults, "r"))) {
192 readconfig (&np->n_next, in, mh_defaults, 0);
193 fclose (in);
194 }
195
196 ctxpath = mh_xstrdup(m_maildir(context = "context"));
197
198 /* Initialize current folder to default */
199 context_replace (pfolder, defaultfolder);
200 context_save ();
201
202 /*
203 * Now write out the initial .mh_profile
204 */
205 if ((out = fopen (defpath, "w")) == NULL)
206 adios (defpath, "unable to write");
207 /*
208 * The main purpose of this first line is to fool file(1).
209 * Without it, if the first line of the profile is Path:,
210 * file 5.19 reports its type as message/news. With it,
211 * it reports the type as text/plain.
212 */
213 fprintf (out, "MH-Profile-Version: 1.0\n");
214 for (np = m_defs; np; np = np->n_next) {
215 if (!np->n_context)
216 fprintf (out, "%s: %s\n", np->n_name, np->n_field);
217 }
218 fclose (out);
219
220 puts ("\nPlease see nmh(7) for an introduction to nmh.\n");
221 print_intro (stdout, false);
222
223 /* Initialize the saved nmh version. The Path profile entry was added
224 above, that's all this needs. */
225 (void) nmh_version_changed (0);
226
227 done (0);
228 return 1;
229 }