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