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