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