1/*
2 * The new sysinstall program.
3 *
4 * This is probably the last attempt in the `sysinstall' line, the next
5 * generation being slated for what's essentially a complete rewrite.
6 *
7 * $FreeBSD$
8 *
9 * Copyright (c) 1995
10 *	Jordan Hubbard.  All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 *    notice, this list of conditions and the following disclaimer,
17 *    verbatim and that no modifications are made prior to this
18 *    point in the file.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 *    notice, this list of conditions and the following disclaimer in the
21 *    documentation and/or other materials provided with the distribution.
22 *
23 * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 */
36
37#include "sysinstall.h"
38#include <ctype.h>
39#include <curses.h>
40#include <term.h>
41
42int fixitTtyWhich(dialogMenuItem *);
43
44static char *
45varCheck(Option *opt)
46{
47    char *cp = NULL;
48
49    if (opt->aux)
50	cp = variable_get((char *)opt->aux);
51    if (!cp)
52	return "NO";
53    return cp;
54}
55
56/* Show our little logo */
57static char *
58resetLogo(Option *opt)
59{
60    return "[RESET!]";
61}
62
63static char *
64mediaCheck(Option *opt)
65{
66    if (mediaDevice) {
67	switch(mediaDevice->type) {
68	case DEVICE_TYPE_UFS:
69	case DEVICE_TYPE_DISK:
70	    return "File system";
71
72	case DEVICE_TYPE_FLOPPY:
73	    return "Floppy";
74
75	case DEVICE_TYPE_FTP:
76	    return "FTP";
77
78	case DEVICE_TYPE_HTTP:
79	    return "HTTP Proxy";
80
81	case DEVICE_TYPE_HTTP_DIRECT:
82	    return "HTTP Direct";
83
84	case DEVICE_TYPE_CDROM:
85	    return "CDROM";
86
87	case DEVICE_TYPE_USB:
88	    return "USB";
89
90	case DEVICE_TYPE_DOS:
91	    return "DOS";
92
93	case DEVICE_TYPE_NFS:
94	    return "NFS";
95
96	case DEVICE_TYPE_NONE:
97	case DEVICE_TYPE_NETWORK:
98	case DEVICE_TYPE_ANY:
99	default:
100	    return "<unknown>";
101	}
102    }
103    return "<not yet set>";
104}
105
106#define NEWFS_PROMPT	"Please enter newfs(8) parameters:"
107#define RELNAME_PROMPT	"Please specify the release you wish to load or\n\"any\" for a generic release install:"
108#define BPKG_PROMPT	"Please specify the name of the HTML browser package:"
109#define BBIN_PROMPT	"Please specify a full pathname to the HTML browser binary:"
110#define EDITOR_PROMPT	"Please specify the name of the text editor you wish to use:"
111#define PKG_PROMPT	"Please specify a temporary directory with lots of free space:"
112#define INSTROOT_PROMPT	"Please specify a root directory if installing somewhere other than /"
113#define TIMEOUT_PROMPT	"Please specify the number of seconds to wait for slow media:"
114
115static Option Options[] = {
116{ "NFS Secure",		"NFS server talks only on a secure port",
117      OPT_IS_VAR,	NULL,			VAR_NFS_SECURE,		varCheck	},
118{ "NFS Slow",		"User is using a slow PC or ethernet card",
119      OPT_IS_VAR,	NULL,			VAR_SLOW_ETHER,		varCheck	},
120{ "NFS TCP",		"Use TCP protocol for NFS",
121      OPT_IS_VAR,	NULL,			VAR_NFS_TCP,		varCheck	},
122{ "NFS version 3",	"Use NFS version 3",
123      OPT_IS_VAR,	NULL,			VAR_NFS_V3,		varCheck	},
124{ "Debugging",		"Emit extra debugging output on VTY2 (ALT-F2)",
125      OPT_IS_VAR,	NULL,			VAR_DEBUG,		varCheck	},
126{ "No Warnings",	"Don't Warn the user when a setting seems incorrect",
127      OPT_IS_VAR,	NULL,			VAR_NO_WARN,		varCheck	},
128{ "Yes to All",		"Assume \"Yes\" answers to all non-critical dialogs",
129      OPT_IS_VAR,	NULL,			VAR_NO_CONFIRM,		varCheck	},
130{ "DHCP",		"Attempt automatic DHCP configuration of interfaces",
131      OPT_IS_VAR,	NULL,			VAR_TRY_DHCP,		varCheck	},
132{ "IPv6",		"Attempt IPv6 configuration of interfaces",
133      OPT_IS_VAR,	NULL,			VAR_TRY_RTSOL,		varCheck	},
134{ "FTP username",	"Username and password to use instead of anonymous",
135      OPT_IS_FUNC,	mediaSetFTPUserPass,	VAR_FTP_USER,		varCheck	},
136{ "Editor",		"Which text editor to use during installation",
137      OPT_IS_VAR,	EDITOR_PROMPT,		VAR_EDITOR,		varCheck	},
138{ "Extract Detail",	"How verbosely to display file name information during extractions",
139      OPT_IS_FUNC,	mediaSetCPIOVerbosity,	VAR_CPIO_VERBOSITY,	varCheck	},
140{ "Release Name",	"Which release to attempt to load from installation media",
141      OPT_IS_VAR,	RELNAME_PROMPT,		VAR_RELNAME,		varCheck	},
142{ "Install Root",	"Which directory to unpack distributions or packages relative to",
143      OPT_IS_VAR,	INSTROOT_PROMPT,	VAR_INSTALL_ROOT,	varCheck	},
144{ "Browser package",	"This is the browser package that will be used for viewing HTML docs",
145      OPT_IS_VAR,	BPKG_PROMPT,		VAR_BROWSER_PACKAGE,	varCheck	},
146{ "Browser Exec",	"This is the path to the main binary of the browser package",
147      OPT_IS_VAR,	BBIN_PROMPT,		VAR_BROWSER_BINARY,	varCheck	},
148{ "Media Type",		"The current installation media type.",
149      OPT_IS_FUNC,	mediaGetType,		VAR_MEDIA_TYPE,		mediaCheck	},
150{ "Media Timeout",	"Timeout value in seconds for slow media.",
151      OPT_IS_VAR,	TIMEOUT_PROMPT,		VAR_MEDIA_TIMEOUT,	varCheck	},
152{ "Package Temp",	"The directory where package temporary files should go",
153      OPT_IS_VAR,	PKG_PROMPT,		VAR_PKG_TMPDIR,		varCheck	},
154{ "Newfs Args",	 	"Default parameters for newfs(8)",
155      OPT_IS_VAR,	NEWFS_PROMPT,		VAR_NEWFS_ARGS,		varCheck	},
156{ "Fixit Console",	"Which tty to use for the Fixit action.",
157      OPT_IS_FUNC,	fixitTtyWhich,		VAR_FIXIT_TTY,		varCheck	},
158{ "Re-scan Devices",	"Re-run sysinstall's initial device probe",
159      OPT_IS_FUNC,	deviceRescan,		NULL,			NULL		},
160{ "Use Defaults",	"Reset all values to startup defaults",
161      OPT_IS_FUNC,	installVarDefaults,	NULL,			resetLogo	},
162{ NULL, NULL, 0, NULL, NULL, NULL },
163};
164
165#define OPT_START_ROW	4
166#define OPT_END_ROW	19
167#define OPT_NAME_COL	0
168#define OPT_VALUE_COL	16
169#define GROUP_OFFSET	40
170
171static char *
172value_of(Option opt)
173{
174    static char ival[40];
175
176    switch (opt.type) {
177    case OPT_IS_STRING:
178	return (char *)opt.data;
179
180    case OPT_IS_INT:
181	sprintf(ival, "%lu", (long)opt.data);
182	return ival;
183
184    case OPT_IS_FUNC:
185    case OPT_IS_VAR:
186	if (opt.check)
187	    return opt.check(&opt);
188	else
189	    return "<*>";
190    }
191    return "<unknown>";
192}
193
194static int
195fire(Option opt)
196{
197    int status = 0;
198
199    if (opt.type == OPT_IS_FUNC) {
200	int (*cp)(char *) = opt.data, rcode;
201
202	rcode = cp(NULL);
203	status = 1;
204    }
205    else if (opt.type == OPT_IS_VAR) {
206	if (opt.data) {
207	    (void)variable_get_value(opt.aux, opt.data, -1);
208	    status = 1;
209	}
210	else if (variable_get(opt.aux)) {
211	    if (!variable_cmp(opt.aux, "YES"))
212		variable_set2(opt.aux, "NO", -1);
213	    else
214		variable_set2(opt.aux, "YES", -1);
215	}
216	else
217	    variable_set2(opt.aux, "YES", 0);
218    }
219    if (opt.check)
220	opt.check(&opt);
221    refresh();
222    return status;
223}
224
225int
226optionsEditor(dialogMenuItem *self)
227{
228    int i, optcol, optrow, key;
229    static int currOpt = 0;
230    WINDOW *w = savescr();
231
232    dialog_clear();
233    clear();
234
235    while (1) {
236	/* Whap up the header */
237	attrset(A_REVERSE); mvaddstr(0, 0, "Options Editor"); attrset(A_NORMAL);
238	for (i = 0; i < 2; i++) {
239	    mvaddstr(OPT_START_ROW - 2, OPT_NAME_COL + (i * GROUP_OFFSET), "Name");
240	    mvaddstr(OPT_START_ROW - 1, OPT_NAME_COL + (i * GROUP_OFFSET), "----");
241
242	    mvaddstr(OPT_START_ROW - 2, OPT_VALUE_COL + (i * GROUP_OFFSET), "Value");
243	    mvaddstr(OPT_START_ROW - 1, OPT_VALUE_COL + (i * GROUP_OFFSET), "-----");
244	}
245	/* And the footer */
246	mvprintw(OPT_END_ROW + 1, 0, "Use SPACE to select/toggle an option, arrow keys to move,");
247	mvprintw(OPT_END_ROW + 2, 0, "? or F1 for more help.  When you're done, type Q to Quit.");
248
249	optrow = OPT_START_ROW;
250	optcol = OPT_NAME_COL;
251	for (i = 0; Options[i].name; i++) {
252	    /* Names are painted somewhat gratuitously each time, but it's easier this way */
253	    mvprintw(optrow, OPT_NAME_COL + optcol, Options[i].name);
254	    if (currOpt == i)
255		attrset(ATTR_SELECTED);
256	    mvprintw(optrow++, OPT_VALUE_COL + optcol, value_of(Options[i]));
257	    if (currOpt == i)
258		attrset(A_NORMAL);
259	    if (optrow == OPT_END_ROW) {
260		optrow = OPT_START_ROW;
261		optcol += GROUP_OFFSET;
262	    }
263	    clrtoeol();
264	}
265	attrset(ATTR_TITLE);
266	mvaddstr(OPT_END_ROW + 4, 0, Options[currOpt].desc);
267	attrset(A_NORMAL);
268	clrtoeol();
269	move(0, 14);
270        refresh();
271
272	/* Start the edit loop */
273	key = toupper(getch());
274	switch (key) {
275	case KEY_F(1):
276	case '?':
277	    systemDisplayHelp("options");
278	    clear();
279	    break;
280
281	case '\020':	/* ^P */
282	case KEY_UP:
283	    if (currOpt)
284		--currOpt;
285	    else
286		for (currOpt = 0; Options[currOpt + 1].name; currOpt++);
287	    continue;
288
289	case '\016':	/* ^N */
290	case KEY_DOWN:
291	    if (Options[currOpt + 1].name)
292		++currOpt;
293	    else
294		currOpt = 0;
295	    continue;
296
297	case KEY_HOME:
298	    currOpt = 0;
299	    continue;
300
301	case KEY_END:
302	    while (Options[currOpt + 1].name)
303		++currOpt;
304	    continue;
305
306	case ' ':
307	    if (fire(Options[currOpt]))
308	    	clear();
309	    continue;
310
311	case '\033':	/* ESC */
312	case 'Q':
313	    clear();
314	    dialog_clear();
315	    restorescr(w);
316	    return DITEM_SUCCESS | DITEM_CONTINUE;
317
318	default:
319	    beep();
320	}
321    }
322    /* NOTREACHED */
323    return DITEM_SUCCESS;
324}
325
326int
327fixitTtyWhich(dialogMenuItem *self)
328{
329    char *cp = variable_get(VAR_FIXIT_TTY);
330
331    if (!cp) {
332	msgConfirm("The Fix-it TTY setting is not set to anything!");
333	return DITEM_FAILURE;
334    }
335    else {
336	if (!strcmp(cp, "standard"))
337	    variable_set2(VAR_FIXIT_TTY, "serial", 0);
338	else /* must be "serial" - wrap around */
339	    variable_set2(VAR_FIXIT_TTY, "standard", 0);
340    }
341    return DITEM_SUCCESS;
342}
343