Annotation of src/distrib/utils/sysinst/configmenu.c, Revision 1.7
1.7 ! garbled 1: /* $NetBSD: configmenu.c,v 1.6 2013/03/19 22:16:53 garbled Exp $ */
1.1 riz 2:
3: /*-
4: * Copyright (c) 2012 The NetBSD Foundation, Inc.
5: * All rights reserved.
6: *
7: * This code is derived from software contributed to The NetBSD Foundation
8: * by Jeffrey C. Rizzo
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29: * POSSIBILITY OF SUCH DAMAGE.
30: */
31:
32: /* configmenu.c -- post-installation system configuration menu. */
33:
34: #include <stdio.h>
35: #include <curses.h>
36: #include <unistd.h>
37: #include "defs.h"
38: #include "msg_defs.h"
39: #include "menu_defs.h"
40:
41:
42: static int set_network(struct menudesc*, void *);
43: static int set_timezone_menu(struct menudesc *, void *);
44: static int set_root_shell(struct menudesc *, void *);
45: static int change_root_password(struct menudesc *, void *);
1.6 garbled 46: static int add_new_user(struct menudesc *, void *);
1.1 riz 47: static int set_binpkg(struct menudesc *, void *);
48: static int set_pkgsrc(struct menudesc *, void *);
49: static void config_list_init(void);
50: static void get_rootsh(void);
51: static int toggle_rcvar(struct menudesc *, void *);
52: static void configmenu_hdr(struct menudesc *, void *);
53: static int check_root_password(void);
54:
55: char pkgpath[STRSIZE];
56: char pkgsrcpath[STRSIZE];
57:
58: extern const char *tz_default;
59:
60: enum {
61: CONFIGOPT_NETCONF,
62: CONFIGOPT_TZ,
63: CONFIGOPT_ROOTSH,
64: CONFIGOPT_ROOTPW,
65: CONFIGOPT_BINPKG,
66: CONFIGOPT_PKGSRC,
67: CONFIGOPT_SSHD,
68: CONFIGOPT_NTPD,
69: CONFIGOPT_NTPDATE,
70: CONFIGOPT_MDNSD,
1.6 garbled 71: CONFIGOPT_ADDUSER,
1.1 riz 72: CONFIGOPT_LAST
73: };
74:
75: typedef struct configinfo {
76: const char *optname;
77: uint opt;
78: const char *rcvar;
79: int (*action)(struct menudesc *, void *);
80: const char *setting;
81: } configinfo;
82:
83:
84: configinfo config_list[] = {
85: {MSG_Configure_network, CONFIGOPT_NETCONF, NULL, set_network, MSG_configure},
86: {MSG_timezone, CONFIGOPT_TZ, NULL, set_timezone_menu, NULL},
87: {MSG_Root_shell, CONFIGOPT_ROOTSH, NULL, set_root_shell, NULL},
88: {MSG_change_rootpw, CONFIGOPT_ROOTPW, NULL, change_root_password, MSG_change},
89: {MSG_enable_binpkg, CONFIGOPT_BINPKG, NULL, set_binpkg, MSG_configure},
90: {MSG_get_pkgsrc, CONFIGOPT_PKGSRC, NULL, set_pkgsrc, MSG_install},
91: {MSG_enable_sshd, CONFIGOPT_SSHD, "sshd", toggle_rcvar, NULL},
92: {MSG_enable_ntpd, CONFIGOPT_NTPD, "ntpd", toggle_rcvar, NULL},
93: {MSG_run_ntpdate, CONFIGOPT_NTPDATE, "ntpdate", toggle_rcvar, NULL},
94: {MSG_enable_mdnsd, CONFIGOPT_MDNSD, "mdnsd", toggle_rcvar, NULL},
1.7 ! garbled 95: {MSG_add_a_user, CONFIGOPT_ADDUSER, NULL, add_new_user, ""},
1.1 riz 96: {NULL, CONFIGOPT_LAST, NULL, NULL, NULL}
97: };
98:
99: static void
100: config_list_init(void)
101: {
102: int i;
103:
104: for (i=0; i < CONFIGOPT_LAST; i++) {
105: switch (i) {
106: case CONFIGOPT_TZ:
107: get_tz_default();
108: config_list[CONFIGOPT_TZ].setting = tz_default;
109: break;
110: case CONFIGOPT_ROOTSH:
111: get_rootsh();
112: break;
113: case CONFIGOPT_ROOTPW:
114: if (check_root_password())
115: config_list[i].setting = MSG_password_set;
116: else
117: config_list[i].setting = MSG_empty;
118: break;
119: default:
120: if (config_list[i].rcvar != NULL) {
121: if (check_rcvar(config_list[i].rcvar))
122: config_list[i].setting = MSG_YES;
123: else
124: config_list[i].setting = MSG_NO;
125: }
126: break;
127: }
128: }
129: }
130:
131: static void
132: get_rootsh(void)
133: {
134: static char *buf = NULL;
135:
136: if (buf != NULL)
137: free(buf);
138:
1.5 jdf 139: if (target_already_root())
140: collect(T_OUTPUT, &buf,
141: "/usr/bin/awk -F: '$1==\"root\" { print $NF; exit }'"
142: " /etc/passwd");
143: else
144: collect(T_OUTPUT, &buf,
145: "chroot %s /usr/bin/awk -F: '$1==\"root\" { print $NF; exit }'"
146: " /etc/passwd",target_prefix());
1.1 riz 147:
148: config_list[CONFIGOPT_ROOTSH].setting = (const char *)buf;
149: }
150:
151: static void
152: set_config(menudesc *menu, int opt, void *arg)
153: {
154: configinfo **configp = arg;
155: configinfo *config = configp[opt];
156: const char *optname, *setting;
157:
158: optname = config->optname;
159: setting = msg_string(config->setting);
160:
161: wprintw(menu->mw, "%-50s %-10s", msg_string(optname), setting);
162: }
163:
164: static int
165: init_config_menu(configinfo *conf, menu_ent *me, configinfo **ce)
166: {
167: int opt;
168: int configopts;
169:
170: for (configopts = 0; ; conf++) {
171: opt = conf->opt;
172: if (opt == CONFIGOPT_LAST)
173: break;
174: *ce = conf;
175: me->opt_menu = OPT_NOMENU;
176: me->opt_flags = 0;
177: me->opt_name = NULL; /* NULL so set_config will draw */
178: me->opt_action = conf->action;
179: configopts++;
180: ce++;
181: me++;
182: }
183:
184: return configopts;
185: }
186:
187: static int
188: /*ARGSUSED*/
189: set_timezone_menu(struct menudesc *menu, void *arg)
190: {
191: configinfo **confp = arg;
192: set_timezone();
193: get_tz_default();
194: confp[menu->cursel]->setting = tz_default;
195: return 0;
196: }
197:
198: static int
199: set_root_shell(struct menudesc *menu, void *arg)
200: {
201: configinfo **confp = arg;
202:
203: process_menu(MENU_rootsh, &confp[menu->cursel]->setting);
204: run_program(RUN_PROGRESS | RUN_CHROOT,
205: "chpass -s %s root", confp[menu->cursel]->setting);
206: return 0;
207: }
208:
209: static int
210: set_network(struct menudesc *menu, void *arg)
211: {
212: network_up = 0;
213: if (config_network())
214: mnt_net_config();
215: return 0;
216: }
217:
218: static int
219: check_root_password(void)
220: {
221: char *buf;
222: int rval;
223:
1.5 jdf 224: if (target_already_root())
225: collect(T_OUTPUT, &buf, "getent passwd root | cut -d: -f2");
226: else
227: collect(T_OUTPUT, &buf, "chroot %s getent passwd root | "
228: "chroot %s cut -d: -f2",
229: target_prefix(), target_prefix());
1.1 riz 230:
231: if (logfp)
232: fprintf(logfp,"buf %s strlen(buf) %zu\n", buf, strlen(buf));
233:
234: if (strlen(buf) <= 1) /* newline */
235: rval = 0;
236: else
237: rval = 1;
238: free(buf);
239: return rval;
240: }
241:
242: static int
1.6 garbled 243: add_new_user(struct menudesc *menu, void *arg)
244: {
245: char username[STRSIZE];
246: int inwheel=0;
247:
248: msg_prompt(MSG_addusername, NULL, username, sizeof username -1);
249: process_menu(MENU_yesno, deconst(MSG_addusertowheel));
250: inwheel = yesno;
251: ushell = "/bin/csh";
252: process_menu(MENU_usersh, NULL);
253: if (inwheel)
254: run_program(RUN_PROGRESS | RUN_CHROOT,
255: "/usr/sbin/useradd -m -s %s -G wheel %s",
256: ushell, username);
257: else
258: run_program(RUN_PROGRESS | RUN_CHROOT,
259: "/usr/sbin/useradd -m -s %s %s", ushell, username);
260: run_program(RUN_DISPLAY | RUN_PROGRESS | RUN_CHROOT,
261: "passwd -l %s", username);
262: return 0;
263: }
264:
265: static int
1.1 riz 266: change_root_password(struct menudesc *menu, void *arg)
267: {
268: configinfo **confp = arg;
269:
270: msg_display(MSG_rootpw);
271: process_menu(MENU_yesno, NULL);
272: if (yesno)
273: run_program(RUN_DISPLAY | RUN_PROGRESS | RUN_CHROOT,
274: "passwd -l root");
275: confp[menu->cursel]->setting = MSG_password_set;
276: return 0;
277: }
278:
279: static int
280: set_binpkg(struct menudesc *menu, void *arg)
281: {
282: configinfo **confp = arg;
283:
284: char pattern[STRSIZE];
285:
1.3 riz 286: /* binary pkg config requires network at this point, so if
287: it's not already configured, do it. */
288: if (network_up == 0) {
289: if (config_network())
290: mnt_net_config();
291: }
292:
1.1 riz 293: process_menu(MENU_binpkg, NULL);
294: make_url(pkgpath, &pkg, pkg_dir);
295: if ( run_program(RUN_DISPLAY | RUN_PROGRESS | RUN_CHROOT,
296: "pkg_add %s/pkgin", pkgpath) != 0) {
297: msg_display(MSG_pkgin_failed);
298: process_menu(MENU_ok, NULL);
299: confp[menu->cursel]->setting = MSG_failed;
300: return 0;
301: }
302:
1.2 riz 303: /* configure pkgin to use $pkgpath as a repository */
304: snprintf(pattern, STRSIZE, "s,^[^#].*$,%s,", pkgpath);
305: replace("/usr/pkg/etc/pkgin/repositories.conf", pattern);
306:
1.1 riz 307: run_program(RUN_DISPLAY | RUN_PROGRESS | RUN_CHROOT,
1.4 riz 308: "/usr/pkg/bin/pkgin -y update");
1.1 riz 309:
310: msg_display(MSG_binpkg_installed);
311: process_menu(MENU_ok, NULL);
312:
313: confp[menu->cursel]->setting = MSG_DONE;
314: return 0;
315: }
316:
317: static int
318: set_pkgsrc(struct menudesc *menu, void *arg)
319: {
320: configinfo **confp = arg;
321: distinfo dist;
322:
323: dist.name = "pkgsrc";
324: dist.set = SET_PKGSRC;
325: dist.desc = "source for 3rd-party packages";
326: dist.marker_file = NULL;
327:
328: int status = SET_RETRY;
329:
330: do {
331: status = get_pkgsrc();
332: if (status == SET_OK) {
333: status = extract_file(&dist, 0);
334: continue;
335: } else if (status == SET_SKIP) {
336: confp[menu->cursel]->setting = MSG_abandoned;
337: return 0;
338: }
339: process_menu(MENU_yesno, deconst(MSG_retry_pkgsrc_network));
340: if (!yesno) {
341: confp[menu->cursel]->setting = MSG_abandoned;
342: return 1;
343: }
344: }
345: while (status == SET_RETRY);
346:
347:
348: confp[menu->cursel]->setting = MSG_DONE;
349: return 0;
350: }
351:
352: static int
353: toggle_rcvar(struct menudesc *menu, void *arg)
354: {
355: configinfo **confp = arg;
356: int s;
357: const char *setting, *varname;
358: char pattern[STRSIZE];
359: char buf[STRSIZE];
360: char *cp;
361: int found = 0;
362: FILE *fp;
363:
364: varname = confp[menu->cursel]->rcvar;
365:
366: s = check_rcvar(varname);
367:
368: /* we're toggling, so invert the sense */
369: if (s) {
370: confp[menu->cursel]->setting = MSG_NO;
371: setting = "NO";
372: } else {
373: confp[menu->cursel]->setting = MSG_YES;
374: setting = "YES";
375: }
376:
377: if (!(fp = fopen(target_expand("/etc/rc.conf"), "r"))) {
378: msg_display(MSG_rcconf_delete_failed, varname);
379: process_menu(MENU_ok, NULL);
380: return -1;
381: }
382:
383: while (fgets(buf, sizeof buf, fp) != NULL) {
384: cp = buf + strspn(buf, " \t"); /* Skip initial spaces */
385: if (strncmp(cp, varname, strlen(varname)) == 0) {
386: cp += strlen(varname);
387: if (*cp != '=')
388: continue;
389: buf[strlen(buf) - 1] = 0;
390: snprintf(pattern, sizeof pattern,
391: "s,^%s$,%s=%s,",
392: buf, varname, setting);
393: found = 1;
394: break;
395: }
396: }
397:
398: fclose(fp);
399:
400: if (!found) {
401: add_rc_conf("%s=%s\n", varname, setting);
402: if (logfp) {
403: fprintf(logfp, "adding %s=%s\n", varname, setting);
404: fflush(logfp);
405: }
406: } else {
407: if (logfp) {
408: fprintf(logfp, "replacement pattern is %s\n", pattern);
409: fflush(logfp);
410: }
411: replace("/etc/rc.conf", pattern);
412: }
413:
414: return 0;
415: }
416:
417: static void
418: configmenu_hdr(struct menudesc *menu, void *arg)
419: {
420: msg_display(MSG_configmenu);
421: }
422:
423: void
424: do_configmenu()
425: {
426: int menu_no;
427: int opts;
428: menu_ent me[CONFIGOPT_LAST];
429: configinfo *ce[CONFIGOPT_LAST];
430:
431: wrefresh(curscr);
432: wmove(stdscr, 0, 0);
433: wclear(stdscr);
434: wrefresh(stdscr);
435:
436: /* if the target isn't mounted already, figure it out. */
437: if (target_mounted() == 0) {
438: if (find_disks(msg_string(MSG_configure_prior)) < 0)
439: return;
440:
441: if (mount_disks() != 0)
442: return;
443: }
444:
445: config_list_init();
446: make_url(pkgpath, &pkg, pkg_dir);
447: opts = init_config_menu(config_list, me, ce);
448:
449: menu_no = new_menu(NULL, me, opts, 0, -4, 0, 70,
450: MC_SCROLL | MC_NOBOX | MC_DFLTEXIT,
451: configmenu_hdr, set_config, NULL, "XXX Help String",
452: MSG_doneconfig);
453:
454: process_menu(menu_no, ce);
455: free_menu(menu_no);
456:
457: sanity_check();
458:
459: }
CVSweb <webmaster@jp.NetBSD.org>