2 * Copyright (c)2004 The DragonFly Project. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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
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.
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>
55 #define _(String) gettext (String)
57 #define _(String) (String)
60 #include "libaura/mem.h"
61 #include "libaura/dict.h"
62 #include "libaura/fspred.h"
64 #include "libdfui/dfui.h"
65 #include "libdfui/system.h"
67 #include "libinstaller/commands.h"
68 #include "libinstaller/confed.h"
69 #include "libinstaller/diskutil.h"
70 #include "libinstaller/functions.h"
71 #include "libinstaller/package.h"
72 #include "libinstaller/uiutil.h"
76 #include "pathnames.h"
78 static const char *yes_to_y(const char *);
79 static char *convert_tmpfs_options(char *);
81 /** CONFIGURE FUNCTIONS **/
83 #define PW_NOT_ALLOWED ":;,`~!@#$%^&*()+={}[]\\|/?<>'\" "
84 #define GECOS_NOT_ALLOWED ":,\\\""
85 #define FILENAME_NOT_ALLOWED ":;`~!#$^&*()={}[]\\|?<>'\" "
86 #define MEMBERSHIPS_NOT_ALLOWED ":;`~!@#$%^&*()+={}[]\\|/?<>'\" "
89 fn_add_user(struct i_fn_args *a)
91 struct dfui_dataset *ds, *new_ds;
93 struct dfui_response *r;
94 struct commands *cmds;
96 const char *username, *home, *passwd_1, *passwd_2, *gecos;
97 const char *shell, *uid, *group, *groups;
100 f = dfui_form_create(
103 _("Here you can add a user to an installed system.\n\n"
104 "You can leave the Home Directory, User ID, and Login Group "
105 "fields empty if you want these items to be automatically "
106 "allocated by the system.\n\n"
107 "Note: this user's password will appear in the install log. "
108 "If this is a problem, please add the user manually after "
109 "rebooting into the installed system instead."),
111 "f", "username", _("Username"),
112 _("Enter the username the user will log in as"), "",
113 "f", "gecos", _("Real Name"),
114 _("Enter the real name (or GECOS field) of this user"), "",
115 "f", "passwd_1", _("Password"),
116 _("Enter the user's password (will not be displayed)"), "",
117 "p", "obscured", "true",
118 "f", "passwd_2", _("Password (Again)"),
119 _("Re-enter the user's password to confirm"), "",
120 "p", "obscured", "true",
121 "f", "shell", _("Shell"),
122 _("Enter the full path to the user's shell program"), "",
123 "f", "home", _("Home Directory"),
124 _("Enter the full path to the user's home directory, or leave blank"), "",
125 "f", "uid", _("User ID"),
126 _("Enter this account's numeric user id, or leave blank"), "",
127 "f", "group", _("Login Group"),
128 _("Enter the primary group for this account, or leave blank"), "",
129 "f", "groups", _("Other Group Memberships"),
130 _("Enter a comma-separated list of other groups "
131 "that this user should belong to"), "",
132 "a", "ok", _("Accept and Add"), "", "",
133 "a", "cancel", _("Return to Configure Menu"), "", "",
134 "p", "accelerator", "ESC",
138 ds = dfui_dataset_new();
139 dfui_dataset_celldata_add(ds, "username", "");
140 dfui_dataset_celldata_add(ds, "gecos", "");
141 dfui_dataset_celldata_add(ds, "passwd_1", "");
142 dfui_dataset_celldata_add(ds, "passwd_2", "");
143 dfui_dataset_celldata_add(ds, "shell", "/bin/tcsh");
144 dfui_dataset_celldata_add(ds, "home", "");
145 dfui_dataset_celldata_add(ds, "uid", "");
146 dfui_dataset_celldata_add(ds, "group", "");
147 dfui_dataset_celldata_add(ds, "groups", "");
148 dfui_form_dataset_add(f, ds);
151 if (!dfui_be_present(a->c, f, &r))
154 if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
156 dfui_response_free(r);
160 new_ds = dfui_dataset_dup(dfui_response_dataset_get_first(r));
161 dfui_form_datasets_free(f);
162 dfui_form_dataset_add(f, new_ds);
164 /* Fetch form field values. */
166 username = dfui_dataset_get_value(new_ds, "username");
167 home = dfui_dataset_get_value(new_ds, "home");
168 gecos = dfui_dataset_get_value(new_ds, "gecos");
169 shell = dfui_dataset_get_value(new_ds, "shell");
170 passwd_1 = dfui_dataset_get_value(new_ds, "passwd_1");
171 passwd_2 = dfui_dataset_get_value(new_ds, "passwd_2");
172 uid = dfui_dataset_get_value(new_ds, "uid");
173 group = dfui_dataset_get_value(new_ds, "group");
174 groups = dfui_dataset_get_value(new_ds, "groups");
176 if (strlen(username) == 0) {
177 inform(a->c, _("You must enter a username."));
179 } else if (strcmp(passwd_1, passwd_2) != 0) {
180 /* Passwords don't match; tell the user. */
181 inform(a->c, _("The passwords do not match."));
183 } else if (!assert_clean(a->c, _("Username"), username, PW_NOT_ALLOWED) ||
184 !assert_clean(a->c, _("Real Name"), gecos, GECOS_NOT_ALLOWED) ||
185 !assert_clean(a->c, _("Password"), passwd_1, PW_NOT_ALLOWED) ||
186 !assert_clean(a->c, _("Shell"), shell, FILENAME_NOT_ALLOWED) ||
187 !assert_clean(a->c, _("Home Directory"), home, FILENAME_NOT_ALLOWED) ||
188 !assert_clean(a->c, _("User ID"), uid, PW_NOT_ALLOWED) ||
189 !assert_clean(a->c, _("Login Group"), group, PW_NOT_ALLOWED) ||
190 !assert_clean(a->c, _("Group Memberships"), groups, MEMBERSHIPS_NOT_ALLOWED)) {
192 } else if (!is_program("%s%s", a->os_root, shell) &&
193 strcmp(shell, "/nonexistent") != 0) {
194 inform(a->c, _("Chosen shell does not exist on the system."));
197 cmds = commands_new();
199 command_add(cmds, "%s%s %smnt/ /%s useradd "
200 "'%s' %s%s %s%s -c \"%s\" %s%s -s %s %s%s %s",
201 a->os_root, cmd_name(a, "CHROOT"),
202 a->os_root, cmd_name(a, "PW"),
204 strlen(uid) == 0 ? "" : "-u ", uid,
205 strlen(group) == 0 ? "" : "-g ", group,
207 strlen(home) == 0 ? "" : "-d ", home,
209 strlen(groups) == 0 ? "" : "-G ", groups,
210 (strlen(home) == 0 || !is_dir(home)) ?
211 "-m -k /usr/share/skel" : "");
213 cmd = command_add(cmds, "%s%s '%s' | "
214 "%s%s %smnt/ /%s usermod '%s' -h 0",
215 a->os_root, cmd_name(a, "ECHO"),
217 a->os_root, cmd_name(a, "CHROOT"),
218 a->os_root, cmd_name(a, "PW"),
220 command_set_desc(cmd, _("Setting password..."));
222 if (commands_execute(a, cmds)) {
223 inform(a->c, _("User `%s' was added."), username);
226 inform(a->c, _("User was not successfully added."));
233 dfui_response_free(r);
240 fn_root_passwd(struct i_fn_args *a)
242 struct dfui_dataset *ds, *new_ds;
244 struct dfui_response *r;
245 struct commands *cmds;
247 const char *root_passwd_1, *root_passwd_2;
250 f = dfui_form_create(
252 _("Set Root Password"),
253 _("Here you can set the super-user (root) password.\n\n"
254 "Note: root's new password will appear in the install log. "
255 "If this is a problem, please set root's password manually "
256 "after rebooting into the installed system instead."),
259 "f", "root_passwd_1", _("Root password"),
260 _("Enter the root password you would like to use"), "",
261 "p", "obscured", "true",
262 "f", "root_passwd_2", _("Root password again"),
263 _("Enter the root password again to confirm"), "",
264 "p", "obscured", "true",
266 "a", "ok", _("Accept and Set Password"), "", "",
267 "a", "cancel", _("Return to Configure Menu"), "", "",
268 "p", "accelerator", "ESC",
273 ds = dfui_dataset_new();
274 dfui_dataset_celldata_add(ds, "root_passwd_1", "");
275 dfui_dataset_celldata_add(ds, "root_passwd_2", "");
276 dfui_form_dataset_add(f, ds);
279 if (!dfui_be_present(a->c, f, &r))
282 if (strcmp(dfui_response_get_action_id(r), "ok") == 0) {
283 new_ds = dfui_dataset_dup(dfui_response_dataset_get_first(r));
284 dfui_form_datasets_free(f);
285 dfui_form_dataset_add(f, new_ds);
288 * Fetch form field values.
291 root_passwd_1 = dfui_dataset_get_value(new_ds, "root_passwd_1");
292 root_passwd_2 = dfui_dataset_get_value(new_ds, "root_passwd_2");
294 if (!assert_clean(a->c, _("Root password"), root_passwd_1, PW_NOT_ALLOWED)) {
296 } else if (strlen(root_passwd_1) == 0 && strlen(root_passwd_2) == 0) {
298 } else if (strcmp(root_passwd_1, root_passwd_2) == 0) {
300 * Passwords match, so set the root password.
302 cmds = commands_new();
303 cmd = command_add(cmds, "%s%s '%s' | "
304 "%s%s %smnt/ /%s usermod root -h 0",
305 a->os_root, cmd_name(a, "ECHO"),
307 a->os_root, cmd_name(a, "CHROOT"),
308 a->os_root, cmd_name(a, "PW"));
309 command_set_desc(cmd, _("Setting password..."));
310 if (commands_execute(a, cmds)) {
311 inform(a->c, _("The root password has been changed."));
314 inform(a->c, _("An error occurred when "
315 "setting the root password."));
321 * Passwords don't match - tell the user, let them try again.
323 inform(a->c, _("The passwords do not match."));
333 dfui_response_free(r);
340 fn_install_packages(struct i_fn_args *a)
343 struct commands *cmds;
344 struct dfui_celldata *cd;
345 struct dfui_dataset *ds;
346 struct dfui_field *fi;
348 struct dfui_response *r;
351 char msg_buf[1][1024];
352 struct aura_dict *seen;
354 snprintf(msg_buf[0], sizeof(msg_buf[0]),
355 _("Select optional software packages that you want "
356 "installed on this system. This form lists only the "
357 "software packages installed on the LiveCD; thousands "
358 "more are available via the internet once %s "
360 OPERATING_SYSTEM_NAME);
362 f = dfui_form_create(
364 _("Install Packages"),
368 "p", "special", "dfinstaller_install_packages",
373 ds = dfui_dataset_new();
374 snprintf(command, 256, "ls %svar/db/pkg", a->os_root);
375 if ((pipe = popen(command, "r")) != NULL) {
376 while (fgets(pkg_name, 255, pipe) != NULL) {
377 while (strlen(pkg_name) > 0 &&
378 isspace(pkg_name[strlen(pkg_name) - 1])) {
379 pkg_name[strlen(pkg_name) - 1] = '\0';
381 fi = dfui_form_field_add(f, pkg_name,
382 dfui_info_new(pkg_name, "", ""));
383 dfui_field_property_set(fi, "control", "checkbox");
384 dfui_dataset_celldata_add(ds,
389 dfui_form_dataset_add(f, ds);
391 dfui_form_action_add(f, "ok",
392 dfui_info_new(_("Accept and Install"), "", ""));
393 dfui_form_action_add(f, "cancel",
394 dfui_info_new(_("Return to Configure Menu"), "", ""));
396 if (!dfui_be_present(a->c, f, &r))
399 if (strcmp(dfui_response_get_action_id(r), "ok") == 0) {
400 cmds = commands_new();
401 seen = aura_dict_new(23, AURA_DICT_HASH);
403 cd = dfui_dataset_celldata_get_first(dfui_response_dataset_get_first(r));
406 strlcpy(pkg_name, dfui_celldata_get_field_id(cd), 256);
407 if (!strcasecmp(dfui_celldata_get_value(cd), "Y")) {
408 if (!pkg_copy(a, cmds, pkg_name, seen)) {
409 inform(a->c, _("Couldn't install package `%s'."), pkg_name);
413 cd = dfui_celldata_get_next(cd);
416 if (!commands_execute(a, cmds)) {
417 inform(a->c, _("Packages were not fully installed."));
419 inform(a->c, _("Packages were successfully installed!"));
422 aura_dict_free(seen);
427 dfui_response_free(r);
431 fn_remove_packages(struct i_fn_args *a)
434 struct commands *cmds;
435 struct dfui_celldata *cd;
436 struct dfui_dataset *ds;
437 struct dfui_field *fi;
439 struct dfui_response *r;
442 struct aura_dict *seen;
444 f = dfui_form_create(
446 _("Remove Packages"),
447 _("Select the installed software packages that you want "
448 "removed from this system."),
451 "p", "special", "dfinstaller_remove_packages",
456 ds = dfui_dataset_new();
457 snprintf(command, 256, "ls %smnt/var/db/pkg", a->os_root);
458 if ((pipe = popen(command, "r")) != NULL) {
459 while (fgets(pkg_name, 255, pipe)) {
460 pkg_name[strlen(pkg_name) - 1] = '\0';
461 fi = dfui_form_field_add(f, pkg_name,
462 dfui_info_new(pkg_name, "", ""));
463 dfui_field_property_set(fi, "control", "checkbox");
464 dfui_dataset_celldata_add(ds,
469 dfui_form_dataset_add(f, ds);
471 dfui_form_action_add(f, "ok",
472 dfui_info_new(_("Accept and Remove"), "", ""));
473 dfui_form_action_add(f, "cancel",
474 dfui_info_new(_("Return to Configure Menu"), "", ""));
476 if (!dfui_be_present(a->c, f, &r))
479 if (strcmp(dfui_response_get_action_id(r), "ok") == 0) {
480 cmds = commands_new();
481 seen = aura_dict_new(23, AURA_DICT_HASH);
483 cd = dfui_dataset_celldata_get_first(dfui_response_dataset_get_first(r));
486 strlcpy(pkg_name, dfui_celldata_get_field_id(cd), 256);
487 if (!strcasecmp(dfui_celldata_get_value(cd), "Y")) {
488 if (!pkg_remove(a, cmds, pkg_name, seen)) {
489 inform(a->c, _("Couldn't remove package `%s'."), pkg_name);
493 cd = dfui_celldata_get_next(cd);
496 if (!commands_execute(a, cmds)) {
497 inform(a->c, _("Packages were not fully removed."));
499 inform(a->c, _("Packages were successfully removed."));
502 aura_dict_free(seen);
507 dfui_response_free(r);
510 /** LIVECD UTILITIES FUNCTIONS **/
513 * String returned by this function must be deallocated by the caller.
516 fn_select_file(const char *title, const char *desc, const char *help, const char *cancel,
517 const char *dir, const char *ext, const struct i_fn_args *a)
521 struct dfui_action *k;
522 struct dfui_response *r;
525 struct aura_dict *dict;
529 f = dfui_form_create(
536 dict = aura_dict_new(1, AURA_DICT_SORTED_LIST);
538 while ((de = readdir(d)) != NULL) {
539 if (strcmp(de->d_name, ".") == 0 ||
540 strcmp(de->d_name, "..") == 0 ||
541 strstr(de->d_name, ext) == NULL)
543 aura_dict_store(dict, de->d_name, strlen(de->d_name) + 1, "", 1);
547 aura_dict_rewind(dict);
548 while (!aura_dict_eof(dict)) {
549 aura_dict_get_current_key(dict, (void **)&rk, &rk_len),
550 dfui_form_action_add(f, rk,
551 dfui_info_new(rk, "", ""));
552 aura_dict_next(dict);
554 aura_dict_free(dict);
556 k = dfui_form_action_add(f, "cancel",
557 dfui_info_new(cancel, "", ""));
558 dfui_action_property_set(k, "accelerator", "ESC");
560 if (!dfui_be_present(a->c, f, &r))
563 s = aura_strdup(dfui_response_get_action_id(r));
566 dfui_response_free(r);
572 fn_set_kbdmap(struct i_fn_args *a)
574 struct commands *cmds;
576 char filename[256], keymapname[256];
578 s = fn_select_file(_("Select Keyboard Map"),
579 _("Select a keyboard map appropriate to your keyboard layout."),
580 "", _("Return to Utilities Menu"), "/usr/share/syscons/keymaps",
583 if (strcmp(s, "cancel") != 0) {
584 cmds = commands_new();
585 command_add(cmds, "%s%s -l "
586 "/usr/share/syscons/keymaps/%s < /dev/ttyv0",
587 a->os_root, cmd_name(a, "KBDCONTROL"),
589 if (commands_execute(a, cmds)) {
590 snprintf(filename, 256, "/usr/share/syscons/keymaps/%s", s);
591 snprintf(keymapname, 256, filename_noext(basename(filename)));
592 config_var_set(rc_conf, "keymap", keymapname);
594 inform(a->c, _("Keyboard map not successfully set."));
603 fn_set_vidfont(struct i_fn_args *a)
605 struct commands *cmds;
607 char filename[256], variable[256], fontname[256];
611 s = fn_select_file(_("Select Console Font"),
612 _("Select a font appropriate to your video monitor and language."),
613 "", _("Return to Utilities Menu"), "/usr/share/syscons/fonts",
616 if (strcmp(s, "cancel") != 0) {
617 cmds = commands_new();
618 command_add(cmds, "%s%s -f "
619 "/usr/share/syscons/fonts/%s < /dev/ttyv0",
620 a->os_root, cmd_name(a, "VIDCONTROL"),
622 if (commands_execute(a, cmds)) {
623 if (strstr(s, "8x16") != NULL)
625 else if (strstr(s, "8x14") != NULL)
630 snprintf(variable, 256, "font8x%d", by);
631 snprintf(filename, 256, "/usr/share/syscons/fonts/%s", s);
632 snprintf(fontname, 256, filename_noext(basename(filename)));
633 config_var_set(rc_conf, variable, fontname);
636 inform(a->c, _("Video font not successfully set."));
645 fn_set_scrnmap(struct i_fn_args *a)
647 struct commands *cmds;
649 char filename[256], scrnmapname[256];
651 s = fn_select_file(_("Select Screen Map"),
652 _("Select a mapping for translating characters as they appear "
653 "on your video console screen."),
654 "", _("Return to Utilities Menu"), "/usr/share/syscons/scrnmaps",
657 if (strcmp(s, "cancel") != 0) {
658 cmds = commands_new();
659 command_add(cmds, "%s%s -l "
660 "/usr/share/syscons/scrnmaps/%s < /dev/ttyv0",
661 a->os_root, cmd_name(a, "VIDCONTROL"),
663 if (commands_execute(a, cmds)) {
664 snprintf(filename, 256, "/usr/share/syscons/scrnmaps/%s", s);
665 snprintf(scrnmapname, 256, filename_noext(basename(filename)));
666 config_var_set(rc_conf, "scrnmap", scrnmapname);
668 inform(a->c, _("Video font not successfully set."));
676 fn_set_timezone(struct i_fn_args *a)
678 struct commands *cmds;
680 char current_path[256], selection[256], temp[256];
683 cmds = commands_new();
685 switch (dfui_be_present_dialog(a->c, _("Local or UTC (Greenwich Mean Time) clock"),
687 _("Is this machine's CMOS clock set to UTC?\n\n"
688 "If it is set to local time, or you don't know, please choose NO here!"))) {
690 cmds = commands_new();
691 command_add(cmds, "%s%s %s%setc/wall_cmos_clock",
692 a->os_root, cmd_name(a, "TOUCH"),
693 a->os_root, a->cfg_root);
694 commands_execute(a, cmds);
697 snprintf(current_path, 256, "%s%susr/share/zoneinfo",
698 a->os_root, a->cfg_root);
699 while (!found_file) {
702 s = fn_select_file(_("Select Time Zone"),
703 _("Select a Time Zone appropriate to your physical location."),
704 "", _("Return to Utilities Menu"), current_path,
706 if (is_dir("%s/%s", current_path, s)) {
707 snprintf(temp, 256, "%s/%s", current_path, s);
708 strlcpy(current_path, temp, 256);
710 if (is_file("%s/%s", current_path, s)) {
711 snprintf(selection, 256, "%s/%s", current_path, s);
714 if (strcmp(s, "cancel") == 0) {
715 strlcpy(selection, "cancel", 256);
722 if (strcmp(selection, "cancel") != 0) {
723 command_add(cmds, "%s%s %s %s%setc/localtime",
724 a->os_root, cmd_name(a, "CP"),
726 a->os_root, a->cfg_root);
727 if (commands_execute(a, cmds))
728 inform(a->c, _("The Time Zone has been set to %s."), selection);
734 fn_assign_datetime(struct i_fn_args *a)
736 struct commands *cmds;
737 struct dfui_dataset *ds, *new_ds;
739 struct dfui_response *r;
742 int year, month, dayofmonth, hour, minutes;
747 tp = localtime(&now);
749 f = dfui_form_create(
752 _("Enter the current time and date."),
755 "f", "year", _("Enter year"),
756 _("Enter the current year (e.g. `2004')"), "",
757 "f", "month", _("Month"),
758 _("Enter the current month (e.g. `07')"), "",
759 "f", "dayofmonth", "dayofmonth",
760 _("Enter the current day of month (e.g. `30')"), "",
762 _("Enter the current hour (e.g. `07')"), "",
763 "f", "minutes", "minutes",
764 _("Enter the current minutes (e.g. `59')"), "",
766 "a", "ok", _("OK"), "", "",
767 "a", "cancel", _("Cancel"), "", "",
768 "p", "accelerator", "ESC",
773 ds = dfui_dataset_new();
774 snprintf(temp, 256, "%i", (tp->tm_year+1900));
775 dfui_dataset_celldata_add(ds, "year", temp);
776 snprintf(temp, 256, "%i", (tp->tm_mon+1));
777 dfui_dataset_celldata_add(ds, "month", temp);
778 snprintf(temp, 256, "%i", tp->tm_mday);
779 dfui_dataset_celldata_add(ds, "dayofmonth", temp);
780 snprintf(temp, 256, "%i", tp->tm_hour);
781 dfui_dataset_celldata_add(ds, "hour", temp);
782 snprintf(temp, 256, "%i", tp->tm_min);
783 dfui_dataset_celldata_add(ds, "minutes", temp);
784 dfui_form_dataset_add(f, ds);
786 if (!dfui_be_present(a->c, f, &r))
789 if (strcmp(dfui_response_get_action_id(r), "ok") == 0) {
790 new_ds = dfui_response_dataset_get_first(r);
792 if ((year = atoi(dfui_dataset_get_value(new_ds, "year"))) <= 0)
794 month = atoi(dfui_dataset_get_value(new_ds, "month"));
795 if (month < 1 || month > 12)
797 dayofmonth = atoi(dfui_dataset_get_value(new_ds, "dayofmonth"));
798 if (dayofmonth < 1 || dayofmonth > 31)
800 hour = atoi(dfui_dataset_get_value(new_ds, "hour"));
801 if (hour < 0 || hour > 23)
803 minutes = atoi(dfui_dataset_get_value(new_ds, "minutes"));
804 if (minutes < 0 || minutes > 59)
808 cmds = commands_new();
809 command_add(cmds, "%s%s -n %04d%02d%02d%02d%02d",
810 a->os_root, cmd_name(a, "DATE"),
811 year, month, dayofmonth, hour, minutes);
812 if (commands_execute(a, cmds)) {
813 inform(a->c, _("The date and time have been set."));
817 inform(a->c, _("Please enter numbers within acceptable ranges "
818 "for year, month, day of month, hour, and minute."));
824 fn_assign_hostname_domain(struct i_fn_args *a)
827 struct dfui_response *r;
828 struct dfui_dataset *ds, *new_ds;
829 struct config_vars *resolv_conf;
830 const char *domain, *hostname;
833 f = dfui_form_create(
834 "set_hostname_domain",
835 _("Set Hostname/Domain"),
836 _("Please enter this machine's hostname and domain name."),
839 "f", "hostname", _("Hostname"),
840 _("Enter the Hostname (e.g. `machine')"), "",
841 "f", "domain", _("Domain"),
842 _("Enter the Domain Name (e.g. `network.lan')"), "",
844 "a", "ok", _("OK"), "", "",
845 "a", "cancel", _("Cancel"), "", "",
846 "p", "accelerator", "ESC",
851 ds = dfui_dataset_new();
852 dfui_dataset_celldata_add(ds, "hostname", "");
853 dfui_dataset_celldata_add(ds, "domain", "");
854 dfui_form_dataset_add(f, ds);
856 if (!dfui_be_present(a->c, f, &r))
859 if (strcmp(dfui_response_get_action_id(r), "ok") == 0) {
860 new_ds = dfui_response_dataset_get_first(r);
862 hostname = dfui_dataset_get_value(new_ds, "hostname");
863 domain = dfui_dataset_get_value(new_ds, "domain");
864 if (strlen(domain) == 0)
865 asprintf(&fqdn, "%s", hostname);
867 asprintf(&fqdn, "%s.%s", hostname, domain);
869 resolv_conf = config_vars_new();
871 config_var_set(rc_conf, "hostname", fqdn);
872 config_var_set(resolv_conf, "search", domain);
873 config_vars_write(resolv_conf, CONFIG_TYPE_RESOLV,
874 "%s%setc/resolv.conf", "/", a->cfg_root);
876 config_vars_free(resolv_conf);
882 dfui_response_free(r);
886 fn_assign_ip(struct i_fn_args *a)
889 struct commands *cmds;
891 struct config_vars *resolv_conf;
892 struct dfui_dataset *ds, *new_ds;
894 struct dfui_action *k;
895 struct dfui_response *r;
896 const char *domain, *hostname;
897 const char *interface_ip, *interface_netmask, *defaultrouter, *dns_resolver;
898 char *string, *string1;
902 int write_config = 0;
905 * Get interface list.
907 p = popen("/sbin/ifconfig -l", "r");
908 /* XXX it's possible (though extremely unlikely) this will fail. */
909 while (fgets(line, 255, p) != NULL)
910 line[strlen(line) - 1] = '\0';
914 f = dfui_form_create(
916 _("Assign IP Address"),
917 _("Please select which interface you would like to configure:"),
923 /* Loop through array. */
924 word = strtok(line, " \t");
925 while (word != NULL) {
926 dfui_form_action_add(f, word,
927 dfui_info_new(word, "", ""));
928 word = strtok(NULL, " ");
931 k = dfui_form_action_add(f, "cancel",
932 dfui_info_new("Cancel", "", ""));
933 dfui_action_property_set(k, "accelerator", "ESC");
935 if (!dfui_be_present(a->c, f, &r))
938 if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
940 dfui_response_free(r);
944 strlcpy(interface, dfui_response_get_action_id(r), 256);
946 resolv_conf = config_vars_new();
948 switch (dfui_be_present_dialog(a->c, _("Use DHCP?"),
949 _("Use DHCP|Configure Manually"),
950 _("DHCP allows the interface to automatically obtain "
951 "an IP address from a nearby DHCP server.\n\n"
952 "Would you like to enable DHCP for %s?"), interface)) {
954 asprintf(&string, "ifconfig_%s", interface);
956 cmds = commands_new();
957 cmd = command_add(cmds, "%s%s dhclient",
958 a->os_root, cmd_name(a, "KILLALL"));
959 command_set_failure_mode(cmd, COMMAND_FAILURE_IGNORE);
960 command_add(cmds, "%s%s %s",
961 a->os_root, cmd_name(a, "DHCLIENT"),
963 if (commands_execute(a, cmds)) {
965 show_ifconfig(a->c, interface);
968 switch (dfui_be_present_dialog(a->c, _("DHCP Failure"),
970 _("Warning: could not enable dhclient for %s.\n\n"
971 "Write the corresponding settings to rc.conf "
972 "anyway?"), interface)) {
984 config_var_set(rc_conf, string, "DHCP");
989 dfui_response_free(r);
990 f = dfui_form_create(
992 _("Assign IP Address"),
993 _("Configuring Interface:"),
996 "f", "interface_ip", _("IP Address"),
997 _("Enter the IP Address you would like to use"), "",
998 "f", "interface_netmask", _("Netmask"),
999 _("Enter the netmask of the IP address"), "",
1000 "f", "defaultrouter", _("Default Router"),
1001 _("Enter the IP address of the default router"), "",
1002 "f", "dns_resolver", _("Primary DNS Server"),
1003 _("Enter the IP address of primary DNS Server"), "",
1004 "f", "hostname", _("Hostname"),
1005 _("Enter the Hostname"), "",
1006 "f", "domain", _("Domain"),
1007 _("Enter the Domain Name"), "",
1009 "a", "ok", _("Configure Interface"),
1011 "a", "cancel", _("Return to Utilities Menu"),
1013 "p", "accelerator", "ESC",
1018 ds = dfui_dataset_new();
1019 dfui_dataset_celldata_add(ds, "interface_netmask", "");
1020 dfui_dataset_celldata_add(ds, "defaultrouter", "");
1021 dfui_dataset_celldata_add(ds, "dns_resolver", "");
1022 dfui_dataset_celldata_add(ds, "hostname", "");
1023 dfui_dataset_celldata_add(ds, "domain", "");
1024 dfui_dataset_celldata_add(ds, "interface_ip", "");
1025 dfui_form_dataset_add(f, ds);
1027 if (!dfui_be_present(a->c, f, &r))
1030 if (strcmp(dfui_response_get_action_id(r), "ok") == 0) {
1031 new_ds = dfui_response_dataset_get_first(r);
1033 interface_ip = dfui_dataset_get_value(new_ds, "interface_ip");
1034 interface_netmask = dfui_dataset_get_value(new_ds, "interface_netmask");
1035 defaultrouter = dfui_dataset_get_value(new_ds, "defaultrouter");
1036 dns_resolver = dfui_dataset_get_value(new_ds, "dns_resolver");
1037 hostname = dfui_dataset_get_value(new_ds, "hostname");
1038 domain = dfui_dataset_get_value(new_ds, "domain");
1040 asprintf(&string, "ifconfig_%s", interface);
1041 asprintf(&string1, "inet %s netmask %s",
1042 interface_ip, interface_netmask);
1044 cmds = commands_new();
1045 command_add(cmds, "%s%s %s %s netmask %s",
1046 a->os_root, cmd_name(a, "IFCONFIG"),
1047 interface, interface_ip, interface_netmask);
1048 command_add(cmds, "%s%s add default %s",
1049 a->os_root, cmd_name(a, "ROUTE"),
1052 if (commands_execute(a, cmds)) {
1054 show_ifconfig(a->c, interface);
1057 switch (dfui_be_present_dialog(a->c,
1058 _("ifconfig Failure"),
1060 _("Warning: could not assign IP address "
1061 "or default gateway.\n\n"
1062 "Write the corresponding settings to "
1063 "rc.conf anyway?"))) {
1074 commands_free(cmds);
1076 config_var_set(rc_conf, string, string1);
1077 config_var_set(rc_conf, "defaultrouter", defaultrouter);
1082 asprintf(&string, "%s.%s", hostname, domain);
1083 config_var_set(rc_conf, "hostname", string);
1086 config_var_set(resolv_conf, "search", domain);
1087 config_var_set(resolv_conf, "nameserver", dns_resolver);
1096 * Save out changes to /etc/rc.conf and /etc/resolv.conf.
1098 config_vars_write(resolv_conf, CONFIG_TYPE_RESOLV,
1099 "%s%setc/resolv.conf", a->os_root, a->cfg_root);
1102 config_vars_free(resolv_conf);
1105 dfui_response_free(r);
1109 yes_to_y(const char *value)
1111 return(strcasecmp(value, "YES") == 0 ? "Y" : "N");
1115 fn_select_services(struct i_fn_args *a)
1117 struct dfui_dataset *ds;
1118 struct dfui_form *f;
1119 struct dfui_response *r;
1121 if (!config_vars_read(a, rc_conf, CONFIG_TYPE_SH, "%setc/rc.conf", a->cfg_root)) {
1122 inform(a->c, _("Couldn't read %s%setc/rc.conf."),
1123 a->os_root, a->cfg_root);
1128 f = dfui_form_create(
1130 _("Select Services"),
1131 _("Please select which services you would like started at boot time."),
1134 "f", "syslogd", "syslogd",
1135 _("System Logging Daemon"), "",
1136 "p", "control", "checkbox",
1137 "f", "inetd", "inetd",
1138 _("Internet Super-Server"), "",
1139 "p", "control", "checkbox",
1140 "f", "named", "named",
1141 _("BIND Name Server"), "",
1142 "p", "control", "checkbox",
1143 "f", "ntpd", "ntpd",
1144 _("Network Time Protocol Daemon"), "",
1145 "p", "control", "checkbox",
1146 "f", "sshd", "sshd",
1147 _("Secure Shell Daemon"), "",
1148 "p", "control", "checkbox",
1150 "a", "ok", _("Enable/Disable Services"),
1152 "a", "cancel", _("Return to Utilities Menu"),
1154 "p", "accelerator", "ESC",
1159 ds = dfui_dataset_new();
1160 dfui_dataset_celldata_add(ds, "syslogd",
1161 yes_to_y(config_var_get(rc_conf, "syslogd_enable")));
1162 dfui_dataset_celldata_add(ds, "inetd",
1163 yes_to_y(config_var_get(rc_conf, "inetd_enable")));
1164 dfui_dataset_celldata_add(ds, "named",
1165 yes_to_y(config_var_get(rc_conf, "named_enable")));
1166 dfui_dataset_celldata_add(ds, "ntpd",
1167 yes_to_y(config_var_get(rc_conf, "ntpd_enable")));
1168 dfui_dataset_celldata_add(ds, "sshd",
1169 yes_to_y(config_var_get(rc_conf, "sshd_enable")));
1170 dfui_form_dataset_add(f, ds);
1172 if (!dfui_be_present(a->c, f, &r))
1175 if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
1177 dfui_response_free(r);
1182 dfui_response_free(r);
1185 /*** NON-fn_ FUNCTIONS ***/
1188 * Caller is responsible for deallocation.
1191 convert_tmpfs_options(char *line)
1193 char *result, *word;
1196 result = malloc(256);
1199 for (; (word = strsep(&line, ",")) != NULL; ) {
1200 if (word[0] == '-') {
1202 * Don't bother trying to honour the -C
1203 * option, since we can't copy files from
1204 * the right place anyway.
1206 if (strcmp(word, "-C") != 0) {
1207 for (i = 0; word[i] != '\0'; i++) {
1211 strlcat(result, word, 256);
1212 strlcat(result, " ", 256);
1221 * Uses ss->selected_{disk,slice} as the target system.
1224 mount_target_system(struct i_fn_args *a)
1227 struct commands *cmds;
1228 struct subpartition *a_subpart;
1229 char device[256], mtpt[256], fstype[256], options[256];
1230 char *filename, line[256];
1231 const char *try_mtpt[5] = {"/var", "/tmp", "/usr", "/home", NULL};
1232 char *word, *cvtoptions;
1236 * Mount subpartitions from this installation if they are
1237 * not already mounted. Tricky, as we need to honour the
1238 * installation's loader.conf and fstab.
1240 cmds = commands_new();
1243 * First, unmount anything already mounted on /mnt.
1245 unmount_all_under(a, cmds, "%smnt", a->os_root);
1248 * Reset and clear out subpartitions so that system
1249 * can make a "dummy" subpart.
1251 subpartitions_free(storage_get_selected_slice(a->s));
1254 * Create a temporary dummy subpartition - that we
1258 a_subpart = subpartition_new(storage_get_selected_slice(a->s),
1259 "/dummy", 0, 0, 0, 0, 0);
1262 * Mount the target's / and read its /etc/fstab.
1264 if (use_hammer == 0) {
1265 command_add(cmds, "%s%s %sdev/%s %s%s",
1266 a->os_root, cmd_name(a, "MOUNT"),
1268 subpartition_get_device_name(a_subpart),
1269 a->os_root, a->cfg_root);
1271 command_add(cmds, "%s%s %sdev/%s %sboot",
1272 a->os_root, cmd_name(a, "MOUNT"),
1274 subpartition_get_device_name(a_subpart),
1277 "%s%s %sdev/`%s%s \"^vfs\\.root\\.mountfrom\" %sboot/loader.conf |"
1278 "%s%s -Fhammer: '{print $2;}' |"
1279 "%s%s 's/\"//'` %s%s",
1280 a->os_root, cmd_name(a, "MOUNT_HAMMER"),
1282 a->os_root, cmd_name(a, "GREP"),
1284 a->os_root, cmd_name(a, "AWK"),
1285 a->os_root, cmd_name(a, "SED"),
1286 a->os_root, a->cfg_root);
1287 command_add(cmds, "%s%s %sboot",
1288 a->os_root, cmd_name(a, "UMOUNT"),
1291 if (!commands_execute(a, cmds)) {
1292 commands_free(cmds);
1295 commands_free(cmds);
1298 * Get rid of the dummy subpartition.
1300 subpartitions_free(storage_get_selected_slice(a->s));
1302 asprintf(&filename, "%s%s/etc/fstab", a->os_root, a->cfg_root);
1303 fstab = fopen(filename, "r");
1305 if (fstab == NULL) {
1306 inform(a->c, _("Filesystem table on installed system could not be read."));
1307 cmds = commands_new();
1308 command_add(cmds, "%s%s %s%s",
1309 a->os_root, cmd_name(a, "UMOUNT"),
1310 a->os_root, a->cfg_root);
1311 if (!commands_execute(a, cmds)) {
1312 inform(a->c, _("Warning: Installed system was not properly unmounted."));
1314 commands_free(cmds);
1318 cmds = commands_new();
1320 while (fgets(line, 256, fstab) != NULL) {
1322 * Parse the fstab line.
1324 if (first_non_space_char_is(line, '#'))
1326 if ((word = strtok(line, " \t")) == NULL)
1328 strlcpy(device, word, 256);
1329 if ((word = strtok(NULL, " \t")) == NULL)
1331 strlcpy(mtpt, word, 256);
1332 if ((word = strtok(NULL, " \t")) == NULL)
1334 strlcpy(fstype, word, 256);
1335 if ((word = strtok(NULL, " \t")) == NULL)
1337 strlcpy(options, word, 256);
1340 * Now, if the mountpoint has /usr, /var, /tmp, or /home
1341 * as a prefix, mount it under a->cfg_root.
1343 for (i = 0; try_mtpt[i] != NULL; i++) {
1344 if (strstr(mtpt, try_mtpt[i]) == mtpt) {
1346 * Don't mount it if it's optional.
1348 if (strstr(options, "noauto") != NULL)
1352 * Don't mount it if device doesn't start
1353 * with /dev/ or /pfs and it isn't 'tmpfs'.
1355 if (strstr(device, "/dev/") != NULL &&
1356 strstr(device, "/pfs/") != NULL &&
1357 strcmp(device, "tmpfs") != 0)
1361 * If the device is 'tmpfs', mount_tmpfs it instead.
1363 if (strcmp(device, "tmpfs") == 0) {
1364 cvtoptions = convert_tmpfs_options(options);
1366 "%s%s %s tmpfs %s%s%s",
1367 a->os_root, cmd_name(a, "MOUNT_TMPFS"),
1368 cvtoptions, a->os_root, a->cfg_root, mtpt);
1371 if (use_hammer == 0) {
1373 "%s%s -o %s %s%s %s%s%s",
1374 a->os_root, cmd_name(a, "MOUNT"),
1376 a->os_root, device, a->os_root,
1380 "%s%s -o %s %s%s%s %s%s%s",
1381 a->os_root, cmd_name(a, "MOUNT_NULL"),
1383 a->os_root, a->cfg_root, device, a->os_root,
1392 if (!commands_execute(a, cmds)) {
1393 commands_free(cmds);
1396 commands_free(cmds);