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