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