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