Remove the -1 option from the installer.
[dragonfly.git] / contrib / bsdinstaller-1.1.6 / src / backend / installer / fn_configure.c
blobf3160b386026a1e797c1cdf0dc3bf27da57b7a53
1 /*
2 * Copyright (c)2004 The DragonFly Project. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
14 * distribution.
16 * Neither the name of the DragonFly Project nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 * OF THE POSSIBILITY OF SUCH DAMAGE.
35 * fn_configure.c
36 * Configuration functions for installer.
37 * This includes both Configure the LiveCD Environment, and
38 * Configure an Installed System (there is considerable overlap.)
39 * $Id: fn_configure.c,v 1.82 2005/03/25 05:24:00 cpressey Exp $
42 #include <sys/types.h>
44 #include <ctype.h>
45 #include <dirent.h>
46 #include <libgen.h>
47 #include <stdarg.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <time.h>
53 #ifdef ENABLE_NLS
54 #include <libintl.h>
55 #define _(String) gettext (String)
56 #else
57 #define _(String) (String)
58 #endif
60 #include "aura/mem.h"
61 #include "aura/dict.h"
62 #include "aura/fspred.h"
64 #include "dfui/dfui.h"
65 #include "dfui/system.h"
67 #include "installer/commands.h"
68 #include "installer/confed.h"
69 #include "installer/diskutil.h"
70 #include "installer/functions.h"
71 #include "installer/package.h"
72 #include "installer/uiutil.h"
74 #include "fn.h"
75 #include "pathnames.h"
77 static const char *yes_to_y(const char *);
78 static char *convert_swap_options(char *);
80 /** CONFIGURE FUNCTIONS **/
82 #define PW_NOT_ALLOWED ":;,`~!@#$%^&*()+={}[]\\|/?<>'\" "
83 #define GECOS_NOT_ALLOWED ":,\\\""
84 #define FILENAME_NOT_ALLOWED ":;`~!#$^&*()={}[]\\|?<>'\" "
85 #define MEMBERSHIPS_NOT_ALLOWED ":;`~!@#$%^&*()+={}[]\\|/?<>'\" "
87 void
88 fn_add_user(struct i_fn_args *a)
90 struct dfui_dataset *ds, *new_ds;
91 struct dfui_form *f;
92 struct dfui_response *r;
93 struct commands *cmds;
94 struct command *cmd;
95 const char *username, *home, *passwd_1, *passwd_2, *gecos;
96 const char *shell, *uid, *group, *groups;
97 int done = 0;
99 f = dfui_form_create(
100 "add_user",
101 _("Add user"),
102 _("Here you can add a user to an installed system.\n\n"
103 "You can leave the Home Directory, User ID, and Login Group "
104 "fields empty if you want these items to be automatically "
105 "allocated by the system.\n\n"
106 "Note: this user's password will appear in the install log. "
107 "If this is a problem, please add the user manually after "
108 "rebooting into the installed system instead."),
110 "f", "username", _("Username"),
111 _("Enter the username the user will log in as"), "",
112 "f", "gecos", _("Real Name"),
113 _("Enter the real name (or GECOS field) of this user"), "",
114 "f", "passwd_1", _("Password"),
115 _("Enter the user's password (will not be displayed)"), "",
116 "p", "obscured", "true",
117 "f", "passwd_2", _("Password (Again)"),
118 _("Re-enter the user's password to confirm"), "",
119 "p", "obscured", "true",
120 "f", "shell", _("Shell"),
121 _("Enter the full path to the user's shell program"), "",
122 "f", "home", _("Home Directory"),
123 _("Enter the full path to the user's home directory, or leave blank"), "",
124 "f", "uid", _("User ID"),
125 _("Enter this account's numeric user id, or leave blank"), "",
126 "f", "group", _("Login Group"),
127 _("Enter the primary group for this account, or leave blank"), "",
128 "f", "groups", _("Other Group Memberships"),
129 _("Enter a comma-separated list of other groups "
130 "that this user should belong to"), "",
131 "a", "ok", _("Accept and Add"), "", "",
132 "a", "cancel", _("Return to Configure Menu"), "", "",
133 "p", "accelerator", "ESC",
134 NULL
137 ds = dfui_dataset_new();
138 dfui_dataset_celldata_add(ds, "username", "");
139 dfui_dataset_celldata_add(ds, "gecos", "");
140 dfui_dataset_celldata_add(ds, "passwd_1", "");
141 dfui_dataset_celldata_add(ds, "passwd_2", "");
142 dfui_dataset_celldata_add(ds, "shell", "/bin/tcsh");
143 dfui_dataset_celldata_add(ds, "home", "");
144 dfui_dataset_celldata_add(ds, "uid", "");
145 dfui_dataset_celldata_add(ds, "group", "");
146 dfui_dataset_celldata_add(ds, "groups", "");
147 dfui_form_dataset_add(f, ds);
149 while (!done) {
150 if (!dfui_be_present(a->c, f, &r))
151 abort_backend();
153 if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
154 done = 1;
155 dfui_response_free(r);
156 break;
159 new_ds = dfui_dataset_dup(dfui_response_dataset_get_first(r));
160 dfui_form_datasets_free(f);
161 dfui_form_dataset_add(f, new_ds);
163 /* Fetch form field values. */
165 username = dfui_dataset_get_value(new_ds, "username");
166 home = dfui_dataset_get_value(new_ds, "home");
167 gecos = dfui_dataset_get_value(new_ds, "gecos");
168 shell = dfui_dataset_get_value(new_ds, "shell");
169 passwd_1 = dfui_dataset_get_value(new_ds, "passwd_1");
170 passwd_2 = dfui_dataset_get_value(new_ds, "passwd_2");
171 uid = dfui_dataset_get_value(new_ds, "uid");
172 group = dfui_dataset_get_value(new_ds, "group");
173 groups = dfui_dataset_get_value(new_ds, "groups");
175 if (strlen(username) == 0) {
176 inform(a->c, _("You must enter a username."));
177 done = 0;
178 } else if (strcmp(passwd_1, passwd_2) != 0) {
179 /* Passwords don't match; tell the user. */
180 inform(a->c, _("The passwords do not match."));
181 done = 0;
182 } else if (!assert_clean(a->c, _("Username"), username, PW_NOT_ALLOWED) ||
183 !assert_clean(a->c, _("Real Name"), gecos, GECOS_NOT_ALLOWED) ||
184 !assert_clean(a->c, _("Password"), passwd_1, PW_NOT_ALLOWED) ||
185 !assert_clean(a->c, _("Shell"), shell, FILENAME_NOT_ALLOWED) ||
186 !assert_clean(a->c, _("Home Directory"), home, FILENAME_NOT_ALLOWED) ||
187 !assert_clean(a->c, _("User ID"), uid, PW_NOT_ALLOWED) ||
188 !assert_clean(a->c, _("Login Group"), group, PW_NOT_ALLOWED) ||
189 !assert_clean(a->c, _("Group Memberships"), groups, MEMBERSHIPS_NOT_ALLOWED)) {
190 done = 0;
191 } else if (!is_program("%s%s", a->os_root, shell) &&
192 strcmp(shell, "/nonexistent") != 0) {
193 inform(a->c, _("Chosen shell does not exist on the system."));
194 done = 0;
195 } else {
196 cmds = commands_new();
198 command_add(cmds, "%s%s %smnt/ /%s useradd "
199 "'%s' %s%s %s%s -c \"%s\" %s%s -s %s %s%s %s",
200 a->os_root, cmd_name(a, "CHROOT"),
201 a->os_root, cmd_name(a, "PW"),
202 username,
203 strlen(uid) == 0 ? "" : "-u ", uid,
204 strlen(group) == 0 ? "" : "-g ", group,
205 gecos,
206 strlen(home) == 0 ? "" : "-d ", home,
207 shell,
208 strlen(groups) == 0 ? "" : "-G ", groups,
209 (strlen(home) == 0 || !is_dir(home)) ?
210 "-m -k /usr/share/skel" : "");
212 cmd = command_add(cmds, "%s%s '%s' | "
213 "%s%s %smnt/ /%s usermod '%s' -h 0",
214 a->os_root, cmd_name(a, "ECHO"),
215 passwd_1,
216 a->os_root, cmd_name(a, "CHROOT"),
217 a->os_root, cmd_name(a, "PW"),
218 username);
219 command_set_desc(cmd, _("Setting password..."));
221 if (commands_execute(a, cmds)) {
222 inform(a->c, _("User `%s' was added."), username);
223 done = 1;
224 } else {
225 inform(a->c, _("User was not successfully added."));
226 done = 0;
229 commands_free(cmds);
232 dfui_response_free(r);
235 dfui_form_free(f);
238 void
239 fn_root_passwd(struct i_fn_args *a)
241 struct dfui_dataset *ds, *new_ds;
242 struct dfui_form *f;
243 struct dfui_response *r;
244 struct commands *cmds;
245 struct command *cmd;
246 const char *root_passwd_1, *root_passwd_2;
247 int done = 0;
249 f = dfui_form_create(
250 "root_passwd",
251 _("Set Root Password"),
252 _("Here you can set the super-user (root) password.\n\n"
253 "Note: root's new password will appear in the install log. "
254 "If this is a problem, please set root's password manually "
255 "after rebooting into the installed system instead."),
258 "f", "root_passwd_1", _("Root password"),
259 _("Enter the root password you would like to use"), "",
260 "p", "obscured", "true",
261 "f", "root_passwd_2", _("Root password again"),
262 _("Enter the root password again to confirm"), "",
263 "p", "obscured", "true",
265 "a", "ok", _("Accept and Set Password"), "", "",
266 "a", "cancel", _("Return to Configure Menu"), "", "",
267 "p", "accelerator", "ESC",
269 NULL
272 ds = dfui_dataset_new();
273 dfui_dataset_celldata_add(ds, "root_passwd_1", "");
274 dfui_dataset_celldata_add(ds, "root_passwd_2", "");
275 dfui_form_dataset_add(f, ds);
277 while (!done) {
278 if (!dfui_be_present(a->c, f, &r))
279 abort_backend();
281 if (strcmp(dfui_response_get_action_id(r), "ok") == 0) {
282 new_ds = dfui_dataset_dup(dfui_response_dataset_get_first(r));
283 dfui_form_datasets_free(f);
284 dfui_form_dataset_add(f, new_ds);
287 * Fetch form field values.
290 root_passwd_1 = dfui_dataset_get_value(new_ds, "root_passwd_1");
291 root_passwd_2 = dfui_dataset_get_value(new_ds, "root_passwd_2");
293 if (!assert_clean(a->c, _("Root password"), root_passwd_1, PW_NOT_ALLOWED)) {
294 done = 0;
295 } else if (strlen(root_passwd_1) == 0 && strlen(root_passwd_2) == 0) {
296 done = 0;
297 } else if (strcmp(root_passwd_1, root_passwd_2) == 0) {
299 * Passwords match, so set the root password.
301 cmds = commands_new();
302 cmd = command_add(cmds, "%s%s '%s' | "
303 "%s%s %smnt/ /%s usermod root -h 0",
304 a->os_root, cmd_name(a, "ECHO"),
305 root_passwd_1,
306 a->os_root, cmd_name(a, "CHROOT"),
307 a->os_root, cmd_name(a, "PW"));
308 command_set_desc(cmd, _("Setting password..."));
309 if (commands_execute(a, cmds)) {
310 inform(a->c, _("The root password has been changed."));
311 done = 1;
312 } else {
313 inform(a->c, _("An error occurred when "
314 "setting the root password."));
315 done = 0;
317 commands_free(cmds);
318 } else {
320 * Passwords don't match - tell the user, let them try again.
322 inform(a->c, _("The passwords do not match."));
323 done = 0;
325 } else {
327 * Cancelled by user
329 done = 1;
332 dfui_response_free(r);
335 dfui_form_free(f);
338 void
339 fn_cvsup_sources(struct i_fn_args *a)
341 struct commands *cmds;
343 inform(a->c, _("The system has issued a cvsup command in the background.\n\nPlease tail /tmp/cvsupdate.log if you wish to follow the progress."));
345 // TODO: This needs a lot more work.
347 cmds = commands_new();
348 command_add(cmds, "%s%s -h cvsup.dragonflybsd.com -b /usr "
349 "/usr/share/examples/cvsup/DragonFly-supfile >/tmp/cvsupdate.log",
350 a->os_root, cmd_name(a, "CVSUP"));
351 if (!commands_execute(a, cmds))
352 inform(a->c, _("Warning: could not launch cvsup"));
354 commands_free(cmds);
357 void
358 fn_install_packages(struct i_fn_args *a)
360 FILE *pipe;
361 struct commands *cmds;
362 struct dfui_celldata *cd;
363 struct dfui_dataset *ds;
364 struct dfui_field *fi;
365 struct dfui_form *f;
366 struct dfui_response *r;
367 char command[256];
368 char pkg_name[256];
369 char msg_buf[1][1024];
370 struct aura_dict *seen;
372 snprintf(msg_buf[0], sizeof(msg_buf[0]),
373 _("Select optional software packages that you want "
374 "installed on this system. This form lists only the "
375 "software packages installed on the LiveCD; thousands "
376 "more are available via the internet once %s "
377 "is installed."),
378 OPERATING_SYSTEM_NAME);
380 f = dfui_form_create(
381 "install_packages",
382 _("Install Packages"),
383 msg_buf[0],
386 "p", "special", "dfinstaller_install_packages",
388 NULL
391 ds = dfui_dataset_new();
392 snprintf(command, 256, "ls %svar/db/pkg", a->os_root);
393 if ((pipe = popen(command, "r")) != NULL) {
394 while (fgets(pkg_name, 255, pipe) != NULL) {
395 while (strlen(pkg_name) > 0 &&
396 isspace(pkg_name[strlen(pkg_name) - 1])) {
397 pkg_name[strlen(pkg_name) - 1] = '\0';
399 fi = dfui_form_field_add(f, pkg_name,
400 dfui_info_new(pkg_name, "", ""));
401 dfui_field_property_set(fi, "control", "checkbox");
402 dfui_dataset_celldata_add(ds,
403 pkg_name, "Y");
405 pclose(pipe);
407 dfui_form_dataset_add(f, ds);
409 dfui_form_action_add(f, "ok",
410 dfui_info_new(_("Accept and Install"), "", ""));
411 dfui_form_action_add(f, "cancel",
412 dfui_info_new(_("Return to Configure Menu"), "", ""));
414 if (!dfui_be_present(a->c, f, &r))
415 abort_backend();
417 if (strcmp(dfui_response_get_action_id(r), "ok") == 0) {
418 cmds = commands_new();
419 seen = aura_dict_new(23, AURA_DICT_HASH);
421 cd = dfui_dataset_celldata_get_first(dfui_response_dataset_get_first(r));
423 while (cd != NULL) {
424 strlcpy(pkg_name, dfui_celldata_get_field_id(cd), 256);
425 if (!strcasecmp(dfui_celldata_get_value(cd), "Y")) {
426 if (!pkg_copy(a, cmds, pkg_name, seen)) {
427 inform(a->c, _("Couldn't install package `%s'."), pkg_name);
428 break;
431 cd = dfui_celldata_get_next(cd);
434 if (!commands_execute(a, cmds)) {
435 inform(a->c, _("Packages were not fully installed."));
436 } else {
437 inform(a->c, _("Packages were successfully installed!"));
440 aura_dict_free(seen);
441 commands_free(cmds);
444 dfui_form_free(f);
445 dfui_response_free(r);
448 void
449 fn_remove_packages(struct i_fn_args *a)
451 FILE *pipe;
452 struct commands *cmds;
453 struct dfui_celldata *cd;
454 struct dfui_dataset *ds;
455 struct dfui_field *fi;
456 struct dfui_form *f;
457 struct dfui_response *r;
458 char command[256];
459 char pkg_name[256];
460 struct aura_dict *seen;
462 f = dfui_form_create(
463 "remove_packages",
464 _("Remove Packages"),
465 _("Select the installed software packages that you want "
466 "removed from this system."),
469 "p", "special", "dfinstaller_remove_packages",
471 NULL
474 ds = dfui_dataset_new();
475 snprintf(command, 256, "ls %smnt/var/db/pkg", a->os_root);
476 if ((pipe = popen(command, "r")) != NULL) {
477 while (fgets(pkg_name, 255, pipe)) {
478 pkg_name[strlen(pkg_name) - 1] = '\0';
479 fi = dfui_form_field_add(f, pkg_name,
480 dfui_info_new(pkg_name, "", ""));
481 dfui_field_property_set(fi, "control", "checkbox");
482 dfui_dataset_celldata_add(ds,
483 pkg_name, "N");
485 pclose(pipe);
487 dfui_form_dataset_add(f, ds);
489 dfui_form_action_add(f, "ok",
490 dfui_info_new(_("Accept and Remove"), "", ""));
491 dfui_form_action_add(f, "cancel",
492 dfui_info_new(_("Return to Configure Menu"), "", ""));
494 if (!dfui_be_present(a->c, f, &r))
495 abort_backend();
497 if (strcmp(dfui_response_get_action_id(r), "ok") == 0) {
498 cmds = commands_new();
499 seen = aura_dict_new(23, AURA_DICT_HASH);
501 cd = dfui_dataset_celldata_get_first(dfui_response_dataset_get_first(r));
503 while (cd != NULL) {
504 strlcpy(pkg_name, dfui_celldata_get_field_id(cd), 256);
505 if (!strcasecmp(dfui_celldata_get_value(cd), "Y")) {
506 if (!pkg_remove(a, cmds, pkg_name, seen)) {
507 inform(a->c, _("Couldn't remove package `%s'."), pkg_name);
508 break;
511 cd = dfui_celldata_get_next(cd);
514 if (!commands_execute(a, cmds)) {
515 inform(a->c, _("Packages were not fully removed."));
516 } else {
517 inform(a->c, _("Packages were successfully removed."));
520 aura_dict_free(seen);
521 commands_free(cmds);
524 dfui_form_free(f);
525 dfui_response_free(r);
528 /** LIVECD UTILITIES FUNCTIONS **/
531 * String returned by this function must be deallocated by the caller.
533 char *
534 fn_select_file(const char *title, const char *desc, const char *help, const char *cancel,
535 const char *dir, const char *ext, const struct i_fn_args *a)
537 DIR *d;
538 struct dfui_form *f;
539 struct dfui_action *k;
540 struct dfui_response *r;
541 struct dirent *de;
542 char *s;
543 struct aura_dict *dict;
544 char *rk;
545 size_t rk_len;
547 f = dfui_form_create(
548 "select_file",
549 title, desc, help,
550 "p", "role", "menu",
551 NULL
554 dict = aura_dict_new(1, AURA_DICT_SORTED_LIST);
555 d = opendir(dir);
556 while ((de = readdir(d)) != NULL) {
557 if (strcmp(de->d_name, ".") == 0 ||
558 strcmp(de->d_name, "..") == 0 ||
559 strstr(de->d_name, ext) == NULL)
560 continue;
561 aura_dict_store(dict, de->d_name, strlen(de->d_name) + 1, "", 1);
563 closedir(d);
565 aura_dict_rewind(dict);
566 while (!aura_dict_eof(dict)) {
567 aura_dict_get_current_key(dict, (void **)&rk, &rk_len),
568 dfui_form_action_add(f, rk,
569 dfui_info_new(rk, "", ""));
570 aura_dict_next(dict);
572 aura_dict_free(dict);
574 k = dfui_form_action_add(f, "cancel",
575 dfui_info_new(cancel, "", ""));
576 dfui_action_property_set(k, "accelerator", "ESC");
578 if (!dfui_be_present(a->c, f, &r))
579 abort_backend();
581 s = aura_strdup(dfui_response_get_action_id(r));
583 dfui_form_free(f);
584 dfui_response_free(r);
586 return(s);
589 void
590 fn_set_kbdmap(struct i_fn_args *a)
592 struct commands *cmds;
593 char *s;
594 char filename[256], keymapname[256];
596 s = fn_select_file(_("Select Keyboard Map"),
597 _("Select a keyboard map appropriate to your keyboard layout."),
598 "", _("Return to Utilities Menu"), "/usr/share/syscons/keymaps",
599 ".kbd", a);
601 if (strcmp(s, "cancel") != 0) {
602 cmds = commands_new();
603 command_add(cmds, "%s%s -l "
604 "/usr/share/syscons/keymaps/%s < /dev/ttyv0",
605 a->os_root, cmd_name(a, "KBDCONTROL"),
607 if (commands_execute(a, cmds)) {
608 snprintf(filename, 256, "/usr/share/syscons/keymaps/%s", s);
609 snprintf(keymapname, 256, filename_noext(basename(filename)));
610 config_var_set(rc_conf, "keymap", keymapname);
611 } else {
612 inform(a->c, _("Keyboard map not successfully set."));
614 commands_free(cmds);
617 free(s);
620 void
621 fn_set_vidfont(struct i_fn_args *a)
623 struct commands *cmds;
624 char *s;
625 char filename[256], variable[256], fontname[256];
626 int by = 0;
629 s = fn_select_file(_("Select Console Font"),
630 _("Select a font appropriate to your video monitor and language."),
631 "", _("Return to Utilities Menu"), "/usr/share/syscons/fonts",
632 ".fnt", a);
634 if (strcmp(s, "cancel") != 0) {
635 cmds = commands_new();
636 command_add(cmds, "%s%s -f "
637 "/usr/share/syscons/fonts/%s < /dev/ttyv0",
638 a->os_root, cmd_name(a, "VIDCONTROL"),
640 if (commands_execute(a, cmds)) {
641 if (strstr(s, "8x16") != NULL)
642 by = 16;
643 else if (strstr(s, "8x14") != NULL)
644 by = 14;
645 else
646 by = 8;
648 snprintf(variable, 256, "font8x%d", by);
649 snprintf(filename, 256, "/usr/share/syscons/fonts/%s", s);
650 snprintf(fontname, 256, filename_noext(basename(filename)));
651 config_var_set(rc_conf, variable, fontname);
653 } else {
654 inform(a->c, _("Video font not successfully set."));
656 commands_free(cmds);
659 free(s);
662 void
663 fn_set_scrnmap(struct i_fn_args *a)
665 struct commands *cmds;
666 char *s;
667 char filename[256], scrnmapname[256];
669 s = fn_select_file(_("Select Screen Map"),
670 _("Select a mapping for translating characters as they appear "
671 "on your video console screen."),
672 "", _("Return to Utilities Menu"), "/usr/share/syscons/scrnmaps",
673 ".scm", a);
675 if (strcmp(s, "cancel") != 0) {
676 cmds = commands_new();
677 command_add(cmds, "%s%s -l "
678 "/usr/share/syscons/scrnmaps/%s < /dev/ttyv0",
679 a->os_root, cmd_name(a, "VIDCONTROL"),
681 if (commands_execute(a, cmds)) {
682 snprintf(filename, 256, "/usr/share/syscons/scrnmaps/%s", s);
683 snprintf(scrnmapname, 256, filename_noext(basename(filename)));
684 config_var_set(rc_conf, "scrnmap", scrnmapname);
685 } else {
686 inform(a->c, _("Video font not successfully set."));
688 commands_free(cmds);
690 free(s);
693 void
694 fn_set_timezone(struct i_fn_args *a)
696 struct commands *cmds;
697 char *s = NULL;
698 char current_path[256], selection[256], temp[256];
699 int found_file = 0;
701 cmds = commands_new();
703 switch (dfui_be_present_dialog(a->c, _("Local or UTC (Greenwich Mean Time) clock"),
704 _("Yes|No"),
705 _("Is this machine's CMOS clock set to UTC?\n"),
706 _("If it is set to local time, or you don't know, please choose NO here!"))) {
707 case 1:
708 cmds = commands_new();
709 command_add(cmds, "%s%s %s%setc/wall_cmos_clock",
710 a->os_root, cmd_name(a, "TOUCH"),
711 a->os_root, a->cfg_root);
712 commands_execute(a, cmds);
715 snprintf(current_path, 256, "%s%susr/share/zoneinfo",
716 a->os_root, a->cfg_root);
717 while (!found_file) {
718 if (s != NULL)
719 free(s);
720 s = fn_select_file(_("Select Time Zone"),
721 _("Select a Time Zone appropriate to your physical location."),
722 "", _("Return to Utilities Menu"), current_path,
723 "", a);
724 if (is_dir("%s/%s", current_path, s)) {
725 snprintf(temp, 256, "%s/%s", current_path, s);
726 strlcpy(current_path, temp, 256);
727 } else {
728 if (is_file("%s/%s", current_path, s)) {
729 snprintf(selection, 256, "%s/%s", current_path, s);
730 found_file = 1;
732 if (strcmp(s, "cancel") == 0) {
733 strlcpy(selection, "cancel", 256);
734 found_file = 1;
738 free(s);
740 if (strcmp(selection, "cancel") != 0) {
741 command_add(cmds, "%s%s %s %s%setc/localtime",
742 a->os_root, cmd_name(a, "CP"),
743 selection,
744 a->os_root, a->cfg_root);
745 if (commands_execute(a, cmds))
746 inform(a->c, _("The Time Zone has been set to %s."), selection);
748 commands_free(cmds);
751 void
752 fn_assign_datetime(struct i_fn_args *a)
754 struct commands *cmds;
755 struct dfui_dataset *ds, *new_ds;
756 struct dfui_form *f;
757 struct dfui_response *r;
758 struct tm *tp;
759 char temp[256];
760 int year, month, dayofmonth, hour, minutes;
761 int valid = 1;
762 time_t now;
764 now = time(NULL);
765 tp = localtime(&now);
767 f = dfui_form_create(
768 "set_datetime",
769 _("Set Time/Date"),
770 _("Enter the current time and date."),
773 "f", "year", _("Enter year"),
774 _("Enter the current year (e.g. `2004')"), "",
775 "f", "month", _("Month"),
776 _("Enter the current month (e.g. `07')"), "",
777 "f", "dayofmonth", "dayofmonth",
778 _("Enter the current day of month (e.g. `30')"), "",
779 "f", "hour", "hour",
780 _("Enter the current hour (e.g. `07')"), "",
781 "f", "minutes", "minutes",
782 _("Enter the current minutes (e.g. `59')"), "",
784 "a", "ok", _("OK"), "", "",
785 "a", "cancel", _("Cancel"), "", "",
786 "p", "accelerator", "ESC",
788 NULL
791 ds = dfui_dataset_new();
792 snprintf(temp, 256, "%i", (tp->tm_year+1900));
793 dfui_dataset_celldata_add(ds, "year", temp);
794 snprintf(temp, 256, "%i", (tp->tm_mon+1));
795 dfui_dataset_celldata_add(ds, "month", temp);
796 snprintf(temp, 256, "%i", tp->tm_mday);
797 dfui_dataset_celldata_add(ds, "dayofmonth", temp);
798 snprintf(temp, 256, "%i", tp->tm_hour);
799 dfui_dataset_celldata_add(ds, "hour", temp);
800 snprintf(temp, 256, "%i", tp->tm_min);
801 dfui_dataset_celldata_add(ds, "minutes", temp);
802 dfui_form_dataset_add(f, ds);
804 if (!dfui_be_present(a->c, f, &r))
805 abort_backend();
807 if (strcmp(dfui_response_get_action_id(r), "ok") == 0) {
808 new_ds = dfui_response_dataset_get_first(r);
810 if ((year = atoi(dfui_dataset_get_value(new_ds, "year"))) <= 0)
811 valid = 0;
812 month = atoi(dfui_dataset_get_value(new_ds, "month"));
813 if (month < 1 || month > 12)
814 valid = 0;
815 dayofmonth = atoi(dfui_dataset_get_value(new_ds, "dayofmonth"));
816 if (dayofmonth < 1 || dayofmonth > 31)
817 valid = 0;
818 hour = atoi(dfui_dataset_get_value(new_ds, "hour"));
819 if (hour < 0 || hour > 23)
820 valid = 0;
821 minutes = atoi(dfui_dataset_get_value(new_ds, "minutes"));
822 if (minutes < 0 || minutes > 59)
823 valid = 0;
825 if (valid) {
826 cmds = commands_new();
827 command_add(cmds, "%s%s -n %04d%02d%02d%02d%02d",
828 a->os_root, cmd_name(a, "DATE"),
829 year, month, dayofmonth, hour, minutes);
830 if (commands_execute(a, cmds)) {
831 inform(a->c, _("The date and time have been set."));
833 commands_free(cmds);
834 } else {
835 inform(a->c, _("Please enter numbers within acceptable ranges "
836 "for year, month, day of month, hour, and minute."));
841 void
842 fn_assign_hostname_domain(struct i_fn_args *a)
844 struct dfui_form *f;
845 struct dfui_response *r;
846 struct dfui_dataset *ds, *new_ds;
847 struct config_vars *resolv_conf;
848 const char *domain, *hostname;
849 char *fqdn;
851 f = dfui_form_create(
852 "set_hostname_domain",
853 _("Set Hostname/Domain"),
854 _("Please enter this machine's hostname and domain name."),
857 "f", "hostname", _("Hostname"),
858 _("Enter the Hostname (e.g. `machine')"), "",
859 "f", "domain", _("Domain"),
860 _("Enter the Domain Name (e.g. `network.lan')"), "",
862 "a", "ok", _("OK"), "", "",
863 "a", "cancel", _("Cancel"), "", "",
864 "p", "accelerator", "ESC",
866 NULL
869 ds = dfui_dataset_new();
870 dfui_dataset_celldata_add(ds, "hostname", "");
871 dfui_dataset_celldata_add(ds, "domain", "");
872 dfui_form_dataset_add(f, ds);
874 if (!dfui_be_present(a->c, f, &r))
875 abort_backend();
877 if (strcmp(dfui_response_get_action_id(r), "ok") == 0) {
878 new_ds = dfui_response_dataset_get_first(r);
880 hostname = dfui_dataset_get_value(new_ds, "hostname");
881 domain = dfui_dataset_get_value(new_ds, "domain");
882 asprintf(&fqdn, "%s.%s", hostname, domain);
884 resolv_conf = config_vars_new();
886 config_var_set(rc_conf, "hostname", fqdn);
887 config_var_set(resolv_conf, "search", domain);
888 config_vars_write(resolv_conf, CONFIG_TYPE_RESOLV,
889 "%s%setc/resolv.conf", "/", a->cfg_root);
891 config_vars_free(resolv_conf);
893 free(fqdn);
896 dfui_form_free(f);
897 dfui_response_free(r);
900 void
901 fn_assign_ip(struct i_fn_args *a)
903 FILE *p;
904 struct commands *cmds;
905 struct command *cmd;
906 struct config_vars *resolv_conf;
907 struct dfui_dataset *ds, *new_ds;
908 struct dfui_form *f;
909 struct dfui_action *k;
910 struct dfui_response *r;
911 const char *domain, *hostname;
912 const char *interface_ip, *interface_netmask, *defaultrouter, *dns_resolver;
913 char *string, *string1;
914 char *word;
915 char interface[256];
916 char line[256];
917 int write_config = 0;
920 * Get interface list.
922 p = popen("/sbin/ifconfig -l", "r");
923 /* XXX it's possible (though extremely unlikely) this will fail. */
924 while (fgets(line, 255, p) != NULL)
925 line[strlen(line) - 1] = '\0';
927 pclose(p);
929 f = dfui_form_create(
930 "assign_ip",
931 _("Assign IP Address"),
932 _("Please select which interface you would like to configure:"),
934 "p", "role", "menu",
935 NULL
938 /* Loop through array. */
939 word = strtok(line, " \t");
940 while (word != NULL) {
941 dfui_form_action_add(f, word,
942 dfui_info_new(word, "", ""));
943 word = strtok(NULL, " ");
946 k = dfui_form_action_add(f, "cancel",
947 dfui_info_new("Cancel", "", ""));
948 dfui_action_property_set(k, "accelerator", "ESC");
950 if (!dfui_be_present(a->c, f, &r))
951 abort_backend();
953 if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
954 dfui_form_free(f);
955 dfui_response_free(r);
956 return;
959 strlcpy(interface, dfui_response_get_action_id(r), 256);
961 resolv_conf = config_vars_new();
963 switch (dfui_be_present_dialog(a->c, _("Use DHCP?"),
964 _("Use DHCP|Configure Manually"),
965 _("DHCP allows the interface to automatically obtain "
966 "an IP address from a nearby DHCP server.\n\n"
967 "Would you like to enable DHCP for this interface?"))) {
968 case 1:
969 cmds = commands_new();
970 cmd = command_add(cmds, "%s%s dhclient",
971 a->os_root, cmd_name(a, "KILLALL"));
972 command_set_failure_mode(cmd, COMMAND_FAILURE_IGNORE);
973 command_add(cmds, "%s%s %s",
974 a->os_root, cmd_name(a, "DHCLIENT"),
975 interface);
976 if (commands_execute(a, cmds)) {
977 /* XXX sleep(3); */
978 show_ifconfig(a->c, interface);
979 write_config = 1;
980 } else {
981 switch (dfui_be_present_dialog(a->c, _("DHCP Failure"),
982 _("Yes|No"),
983 _("Warning: could not enable dhclient for %s.\n\n"
984 "Write the corresponding settings to rc.conf "
985 "anyway?"), interface)) {
986 case 1:
987 write_config = 1;
988 break;
989 case 2:
990 write_config = 0;
991 break;
992 default:
993 abort_backend();
996 commands_free(cmds);
997 asprintf(&string, "ifconfig_%s", interface);
998 config_var_set(rc_conf, string, "DHCP");
999 free(string);
1000 break;
1001 case 2:
1002 dfui_form_free(f);
1003 dfui_response_free(r);
1004 f = dfui_form_create(
1005 "assign_ip",
1006 _("Assign IP Address"),
1007 _("Configuring Interface:"),
1010 "f", "interface_ip", _("IP Address"),
1011 _("Enter the IP Address you would like to use"), "",
1012 "f", "interface_netmask", _("Netmask"),
1013 _("Enter the netmask of the IP address"), "",
1014 "f", "defaultrouter", _("Default Router"),
1015 _("Enter the IP address of the default router"), "",
1016 "f", "dns_resolver", _("Primary DNS Server"),
1017 _("Enter the IP address of primary DNS Server"), "",
1018 "f", "hostname", _("Hostname"),
1019 _("Enter the Hostname"), "",
1020 "f", "domain", _("Domain"),
1021 _("Enter the Domain Name"), "",
1023 "a", "ok", _("Configure Interface"),
1024 "", "",
1025 "a", "cancel", _("Return to Utilities Menu"),
1026 "", "",
1027 "p", "accelerator", "ESC",
1029 NULL
1032 ds = dfui_dataset_new();
1033 dfui_dataset_celldata_add(ds, "interface_netmask", "");
1034 dfui_dataset_celldata_add(ds, "defaultrouter", "");
1035 dfui_dataset_celldata_add(ds, "dns_resolver", "");
1036 dfui_dataset_celldata_add(ds, "hostname", "");
1037 dfui_dataset_celldata_add(ds, "domain", "");
1038 dfui_dataset_celldata_add(ds, "interface_ip", "");
1039 dfui_form_dataset_add(f, ds);
1041 if (!dfui_be_present(a->c, f, &r))
1042 abort_backend();
1044 if (strcmp(dfui_response_get_action_id(r), "ok") == 0) {
1045 new_ds = dfui_response_dataset_get_first(r);
1047 interface_ip = dfui_dataset_get_value(new_ds, "interface_ip");
1048 interface_netmask = dfui_dataset_get_value(new_ds, "interface_netmask");
1049 defaultrouter = dfui_dataset_get_value(new_ds, "defaultrouter");
1050 dns_resolver = dfui_dataset_get_value(new_ds, "dns_resolver");
1051 hostname = dfui_dataset_get_value(new_ds, "hostname");
1052 domain = dfui_dataset_get_value(new_ds, "domain");
1054 cmds = commands_new();
1055 command_add(cmds, "%s%s %s %s netmask %s",
1056 a->os_root, cmd_name(a, "IFCONFIG"),
1057 interface, interface_ip, interface_netmask);
1058 command_add(cmds, "%s%s add default %s",
1059 a->os_root, cmd_name(a, "ROUTE"),
1060 defaultrouter);
1062 if (commands_execute(a, cmds)) {
1063 /* XXX sleep(3); */
1064 show_ifconfig(a->c, interface);
1065 write_config = 1;
1066 } else {
1067 switch (dfui_be_present_dialog(a->c,
1068 _("ifconfig Failure"),
1069 _("Yes|No"),
1070 _("Warning: could not assign IP address "
1071 "or default gateway.\n\n"
1072 "Write the corresponding settings to "
1073 "rc.conf anyway?"))) {
1074 case 1:
1075 write_config = 1;
1076 break;
1077 case 2:
1078 write_config = 0;
1079 break;
1080 default:
1081 abort_backend();
1084 commands_free(cmds);
1086 asprintf(&string, "ifconfig_%s", interface);
1087 asprintf(&string1, "inet %s netmask %s",
1088 interface_ip, interface_netmask);
1090 config_var_set(rc_conf, string, string1);
1091 config_var_set(rc_conf, "defaultrouter", defaultrouter);
1093 free(string);
1094 free(string1);
1096 asprintf(&string, "%s.%s", hostname, domain);
1097 config_var_set(rc_conf, "hostname", string);
1098 free(string);
1100 config_var_set(resolv_conf, "search", domain);
1101 config_var_set(resolv_conf, "nameserver", dns_resolver);
1103 break;
1104 default:
1105 abort_backend();
1108 if (write_config) {
1110 * Save out changes to /etc/rc.conf and /etc/resolv.conf.
1112 config_vars_write(resolv_conf, CONFIG_TYPE_RESOLV,
1113 "%s%setc/resolv.conf", a->os_root, a->cfg_root);
1116 config_vars_free(resolv_conf);
1118 dfui_form_free(f);
1119 dfui_response_free(r);
1122 static const char *
1123 yes_to_y(const char *value)
1125 return(strcasecmp(value, "YES") == 0 ? "Y" : "N");
1128 void
1129 fn_select_services(struct i_fn_args *a)
1131 struct dfui_dataset *ds;
1132 struct dfui_form *f;
1133 struct dfui_response *r;
1135 if (!config_vars_read(a, rc_conf, CONFIG_TYPE_SH, "%setc/rc.conf", a->cfg_root)) {
1136 inform(a->c, _("Couldn't read %s%setc/rc.conf."),
1137 a->os_root, a->cfg_root);
1138 a->result = 0;
1139 return;
1142 f = dfui_form_create(
1143 "select_services",
1144 _("Select Services"),
1145 _("Please select which services you would like started at boot time."),
1148 "f", "syslogd", "syslogd",
1149 _("System Logging Daemon"), "",
1150 "p", "control", "checkbox",
1151 "f", "inetd", "inetd",
1152 _("Internet Super-Server"), "",
1153 "p", "control", "checkbox",
1154 "f", "named", "named",
1155 _("BIND Name Server"), "",
1156 "p", "control", "checkbox",
1157 "f", "ntpd", "ntpd",
1158 _("Network Time Protocol Daemon"), "",
1159 "p", "control", "checkbox",
1160 "f", "sshd", "sshd",
1161 _("Secure Shell Daemon"), "",
1162 "p", "control", "checkbox",
1164 "a", "ok", _("Enable/Disable Services"),
1165 "", "",
1166 "a", "cancel", _("Return to Utilities Menu"),
1167 "", "",
1168 "p", "accelerator", "ESC",
1170 NULL
1173 ds = dfui_dataset_new();
1174 dfui_dataset_celldata_add(ds, "syslogd",
1175 yes_to_y(config_var_get(rc_conf, "syslogd_enable")));
1176 dfui_dataset_celldata_add(ds, "inetd",
1177 yes_to_y(config_var_get(rc_conf, "inetd_enable")));
1178 dfui_dataset_celldata_add(ds, "named",
1179 yes_to_y(config_var_get(rc_conf, "named_enable")));
1180 dfui_dataset_celldata_add(ds, "ntpd",
1181 yes_to_y(config_var_get(rc_conf, "ntpd_enable")));
1182 dfui_dataset_celldata_add(ds, "sshd",
1183 yes_to_y(config_var_get(rc_conf, "sshd_enable")));
1184 dfui_form_dataset_add(f, ds);
1186 if (!dfui_be_present(a->c, f, &r))
1187 abort_backend();
1189 if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
1190 dfui_form_free(f);
1191 dfui_response_free(r);
1192 return;
1195 dfui_form_free(f);
1196 dfui_response_free(r);
1199 /*** NON-fn_ FUnCTIONS ***/
1202 * Caller is responsible for deallocation.
1204 static char *
1205 convert_swap_options(char *line)
1207 char *result, *word;
1208 int i;
1210 result = malloc(256);
1211 result[0] = '\0';
1213 for (; (word = strsep(&line, ",")) != NULL; ) {
1214 if (word[0] == '-') {
1216 * Don't bother trying to honour the -C
1217 * option, since we can't copy files from
1218 * the right place anyway.
1220 if (strcmp(word, "-C") != 0) {
1221 for (i = 0; word[i] != '\0'; i++) {
1222 if (word[i] == '=')
1223 word[i] = ' ';
1225 strlcat(result, word, 256);
1226 strlcat(result, " ", 256);
1231 return(result);
1235 * Uses ss->selected_{disk,slice} as the target system.
1238 mount_target_system(struct i_fn_args *a)
1240 FILE *fstab;
1241 struct commands *cmds;
1242 struct subpartition *a_subpart;
1243 char device[256], mtpt[256], fstype[256], options[256];
1244 char *filename, line[256];
1245 const char *try_mtpt[5] = {"/var", "/tmp", "/usr", "/home", NULL};
1246 char *word, *cvtoptions;
1247 int i;
1250 * Mount subpartitions from this installation if they are
1251 * not already mounted. Tricky, as we need to honour the
1252 * installation's fstab.
1254 cmds = commands_new();
1257 * First, unmount anything already mounted on /mnt.
1259 unmount_all_under(a, cmds, "%smnt", a->os_root);
1262 * Reset and clear out subpartitions so that system
1263 * can make a "dummy" subpart.
1265 subpartitions_free(storage_get_selected_slice(a->s));
1268 * Create a temporary dummy subpartition - that we
1269 * assume exists - for the benefit of ensure_dev et al.
1272 a_subpart = subpartition_new(storage_get_selected_slice(a->s),
1273 "/dummy", 0, 0, 0, 0, 0);
1276 * Ensure that the devices we'll be using exist.
1278 command_add_ensure_dev(a, cmds,
1279 disk_get_device_name(storage_get_selected_disk(a->s)));
1280 command_add_ensure_dev(a, cmds,
1281 slice_get_device_name(storage_get_selected_slice(a->s)));
1282 command_add_ensure_dev(a, cmds,
1283 subpartition_get_device_name(a_subpart));
1286 * Mount the target's / and read its /etc/fstab.
1288 command_add(cmds, "%s%s %sdev/%s %s%s",
1289 a->os_root, cmd_name(a, "MOUNT"),
1290 a->os_root,
1291 subpartition_get_device_name(a_subpart),
1292 a->os_root, a->cfg_root);
1293 if (!commands_execute(a, cmds)) {
1294 commands_free(cmds);
1295 return(0);
1297 commands_free(cmds);
1300 * Get rid of the dummy subpartition.
1302 subpartitions_free(storage_get_selected_slice(a->s));
1304 asprintf(&filename, "%s%s/etc/fstab", a->os_root, a->cfg_root);
1305 fstab = fopen(filename, "r");
1306 free(filename);
1307 if (fstab == NULL) {
1308 inform(a->c, _("Filesystem table on installed system could not be read."));
1309 cmds = commands_new();
1310 command_add(cmds, "%s%s %s%s",
1311 a->os_root, cmd_name(a, "UMOUNT"),
1312 a->os_root, a->cfg_root);
1313 if (!commands_execute(a, cmds)) {
1314 inform(a->c, _("Warning: Installed system was not properly unmounted."));
1316 commands_free(cmds);
1317 return(0);
1320 cmds = commands_new();
1322 while (fgets(line, 256, fstab) != NULL) {
1324 * Parse the fstab line.
1326 if (first_non_space_char_is(line, '#'))
1327 continue;
1328 if ((word = strtok(line, " \t")) == NULL)
1329 continue;
1330 strlcpy(device, word, 256);
1331 if ((word = strtok(NULL, " \t")) == NULL)
1332 continue;
1333 strlcpy(mtpt, word, 256);
1334 if ((word = strtok(NULL, " \t")) == NULL)
1335 continue;
1336 strlcpy(fstype, word, 256);
1337 if ((word = strtok(NULL, " \t")) == NULL)
1338 continue;
1339 strlcpy(options, word, 256);
1342 * Now, if the mountpoint has /usr, /var, /tmp, or /home
1343 * as a prefix, mount it under a->cfg_root.
1345 for (i = 0; try_mtpt[i] != NULL; i++) {
1346 if (strstr(mtpt, try_mtpt[i]) == mtpt) {
1348 * Don't mount it if it's optional.
1350 if (strstr(options, "noauto") != NULL)
1351 continue;
1354 * Don't mount it if device doesn't start
1355 * with /dev/ and it isn't 'swap'.
1357 if (strstr(device, "/dev/") == NULL &&
1358 strcmp(device, "swap") != 0)
1359 continue;
1362 * If the device is 'swap', mount_mfs it instead.
1364 if (strcmp(device, "swap") == 0) {
1365 cvtoptions = convert_swap_options(options);
1366 command_add(cmds,
1367 "%s%s %s swap %s%s%s",
1368 a->os_root, cmd_name(a, "MOUNT_MFS"),
1369 cvtoptions, a->os_root, a->cfg_root, mtpt);
1370 free(cvtoptions);
1371 } else {
1372 command_add_ensure_dev(a, cmds, device);
1373 command_add(cmds,
1374 "%s%s -o %s %s%s %s%s%s",
1375 a->os_root, cmd_name(a, "MOUNT"),
1376 options, /* XXX */
1377 a->os_root, device, a->os_root,
1378 a->cfg_root, mtpt);
1383 fclose(fstab);
1385 if (!commands_execute(a, cmds)) {
1386 commands_free(cmds);
1387 return(0);
1389 commands_free(cmds);
1391 return(1);