84189e5aae94bbc8383095f16a8418ce3485188b
[dragonfly.git] / usr.sbin / installer / dfuibe_installer / fn_configure.c
1 /*
2  * Copyright (c)2004,2015 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.
10  *
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.
15  *
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.
19  *
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.
32  */
33
34 /*
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 $
40  */
41
42 #include <sys/stat.h>
43 #include <sys/types.h>
44
45 #include <ctype.h>
46 #include <dirent.h>
47 #include <fcntl.h>
48 #include <libgen.h>
49 #include <stdarg.h>
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #include <time.h>
54 #include <unistd.h>
55
56 #ifdef ENABLE_NLS
57 #include <libintl.h>
58 #define _(String) gettext (String)
59 #else
60 #define _(String) (String)
61 #endif
62
63 #include "libaura/mem.h"
64 #include "libaura/dict.h"
65 #include "libaura/fspred.h"
66
67 #include "libdfui/dfui.h"
68 #include "libdfui/system.h"
69
70 #include "libinstaller/commands.h"
71 #include "libinstaller/confed.h"
72 #include "libinstaller/diskutil.h"
73 #include "libinstaller/functions.h"
74 #include "libinstaller/package.h"
75 #include "libinstaller/uiutil.h"
76
77 #include "fn.h"
78 #include "flow.h"
79 #include "pathnames.h"
80
81 static const char       *yes_to_y(const char *);
82
83 /** CONFIGURE FUNCTIONS **/
84
85 #define PW_NOT_ALLOWED          ":;,`~!@#$%^&*()+={}[]\\|/?<>'\" "
86 #define GECOS_NOT_ALLOWED       ":,\\\""
87 #define FILENAME_NOT_ALLOWED    ":;`~!#$^&*()={}[]\\|?<>'\" "
88 #define MEMBERSHIPS_NOT_ALLOWED ":;`~!@#$%^&*()+={}[]\\|/?<>'\" "
89
90 void
91 fn_add_user(struct i_fn_args *a)
92 {
93         struct dfui_dataset *ds, *new_ds;
94         struct dfui_form *f;
95         struct dfui_response *r;
96         struct commands *cmds;
97         struct command *cmd;
98         const char *username, *home, *passwd_1, *passwd_2, *gecos;
99         const char *shell, *uid, *group, *groups;
100         int done = 0;
101
102         f = dfui_form_create(
103             "add_user",
104             _("Add user"),
105             _("Here you can add a user to an installed system.\n\n"
106             "You can leave the Home Directory, User ID, and Login Group "
107             "fields empty if you want these items to be automatically "
108             "allocated by the system.\n\n"
109             "Note: this user's password will appear in the install log. "
110             "If this is a problem, please add the user manually after "
111             "rebooting into the installed system instead."),
112             "",
113             "f", "username", _("Username"),
114             _("Enter the username the user will log in as"), "",
115             "f", "gecos", _("Real Name"),
116             _("Enter the real name (or GECOS field) of this user"), "",
117             "f", "passwd_1", _("Password"),
118             _("Enter the user's password (will not be displayed)"), "",
119             "p", "obscured", "true",
120             "f", "passwd_2", _("Password (Again)"),
121             _("Re-enter the user's password to confirm"), "",
122             "p", "obscured", "true",
123             "f", "shell", _("Shell"),
124             _("Enter the full path to the user's shell program"), "",
125             "f", "home", _("Home Directory"),
126             _("Enter the full path to the user's home directory, or leave blank"), "",
127             "f", "uid", _("User ID"),
128             _("Enter this account's numeric user id, or leave blank"), "",
129             "f", "group", _("Login Group"),
130             _("Enter the primary group for this account, or leave blank"), "",
131             "f", "groups", _("Other Group Memberships"),
132             _("Enter a comma-separated list of other groups "
133             "that this user should belong to"), "",
134             "a", "ok", _("Accept and Add"), "", "",
135             "a", "cancel", _("Return to Configure Menu"), "", "",
136             "p", "accelerator", "ESC",
137             NULL
138         );
139
140         ds = dfui_dataset_new();
141         dfui_dataset_celldata_add(ds, "username", "");
142         dfui_dataset_celldata_add(ds, "gecos", "");
143         dfui_dataset_celldata_add(ds, "passwd_1", "");
144         dfui_dataset_celldata_add(ds, "passwd_2", "");
145         dfui_dataset_celldata_add(ds, "shell", "/bin/tcsh");
146         dfui_dataset_celldata_add(ds, "home", "");
147         dfui_dataset_celldata_add(ds, "uid", "");
148         dfui_dataset_celldata_add(ds, "group", "");
149         dfui_dataset_celldata_add(ds, "groups", "");
150         dfui_form_dataset_add(f, ds);
151
152         while (!done) {
153                 if (!dfui_be_present(a->c, f, &r))
154                         abort_backend();
155
156                 if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
157                         done = 1;
158                         dfui_response_free(r);
159                         break;
160                 }
161
162                 new_ds = dfui_dataset_dup(dfui_response_dataset_get_first(r));
163                 dfui_form_datasets_free(f);
164                 dfui_form_dataset_add(f, new_ds);
165
166                 /* Fetch form field values. */
167
168                 username = dfui_dataset_get_value(new_ds, "username");
169                 home = dfui_dataset_get_value(new_ds, "home");
170                 gecos = dfui_dataset_get_value(new_ds, "gecos");
171                 shell = dfui_dataset_get_value(new_ds, "shell");
172                 passwd_1 = dfui_dataset_get_value(new_ds, "passwd_1");
173                 passwd_2 = dfui_dataset_get_value(new_ds, "passwd_2");
174                 uid = dfui_dataset_get_value(new_ds, "uid");
175                 group = dfui_dataset_get_value(new_ds, "group");
176                 groups = dfui_dataset_get_value(new_ds, "groups");
177
178                 if (strlen(username) == 0) {
179                         inform(a->c, _("You must enter a username."));
180                         done = 0;
181                 } else if (strcmp(passwd_1, passwd_2) != 0) {
182                         /* Passwords don't match; tell the user. */
183                         inform(a->c, _("The passwords do not match."));
184                         done = 0;
185                 } else if (!assert_clean(a->c, _("Username"), username, PW_NOT_ALLOWED) ||
186                     !assert_clean(a->c, _("Real Name"), gecos, GECOS_NOT_ALLOWED) ||
187                     !assert_clean(a->c, _("Password"), passwd_1, PW_NOT_ALLOWED) ||
188                     !assert_clean(a->c, _("Shell"), shell, FILENAME_NOT_ALLOWED) ||
189                     !assert_clean(a->c, _("Home Directory"), home, FILENAME_NOT_ALLOWED) ||
190                     !assert_clean(a->c, _("User ID"), uid, PW_NOT_ALLOWED) ||
191                     !assert_clean(a->c, _("Login Group"), group, PW_NOT_ALLOWED) ||
192                     !assert_clean(a->c, _("Group Memberships"), groups, MEMBERSHIPS_NOT_ALLOWED)) {
193                         done = 0;
194                 } else if (!is_program("%s%s", a->os_root, shell) &&
195                     strcmp(shell, "/nonexistent") != 0) {
196                         inform(a->c, _("Chosen shell does not exist on the system."));
197                         done = 0;
198                 } else {
199                         cmds = commands_new();
200
201                         command_add(cmds, "%s%s %smnt/ /%s useradd "
202                             "'%s' %s%s %s%s -c \"%s\" %s%s -s %s %s%s %s",
203                             a->os_root, cmd_name(a, "CHROOT"),
204                             a->os_root, cmd_name(a, "PW"),
205                             username,
206                             strlen(uid) == 0 ? "" : "-u ", uid,
207                             strlen(group) == 0 ? "" : "-g ", group,
208                             gecos,
209                             strlen(home) == 0 ? "" : "-d ", home,
210                             shell,
211                             strlen(groups) == 0 ? "" : "-G ", groups,
212                             (strlen(home) == 0 || !is_dir("%s", home)) ?
213                             "-m -k /usr/share/skel" : "");
214
215                         cmd = command_add(cmds, "%s%s '%s' | "
216                             "%s%s %smnt/ /%s usermod '%s' -h 0",
217                             a->os_root, cmd_name(a, "ECHO"),
218                             passwd_1,
219                             a->os_root, cmd_name(a, "CHROOT"),
220                             a->os_root, cmd_name(a, "PW"),
221                             username);
222                         command_set_desc(cmd, _("Setting password..."));
223
224                         if (commands_execute(a, cmds)) {
225                                 inform(a->c, _("User `%s' was added."), username);
226                                 done = 1;
227                         } else {
228                                 inform(a->c, _("User was not successfully added."));
229                                 done = 0;
230                         }
231
232                         commands_free(cmds);
233                 }
234
235                 dfui_response_free(r);
236         }
237
238         dfui_form_free(f);
239 }
240
241 void
242 fn_root_passwd(struct i_fn_args *a)
243 {
244         struct dfui_dataset *ds, *new_ds;
245         struct dfui_form *f;
246         struct dfui_response *r;
247         struct commands *cmds;
248         struct command *cmd;
249         const char *root_passwd_1, *root_passwd_2;
250         int done = 0;
251
252         f = dfui_form_create(
253             "root_passwd",
254             _("Set Root Password"),
255             _("Here you can set the super-user (root) password.\n\n"
256             "Note: root's new password will appear in the install log. "
257             "If this is a problem, please set root's password manually "
258             "after rebooting into the installed system instead."),
259             "",
260
261             "f", "root_passwd_1", _("Root password"),
262             _("Enter the root password you would like to use"), "",
263             "p", "obscured", "true",
264             "f", "root_passwd_2", _("Root password again"),
265             _("Enter the root password again to confirm"), "",
266             "p", "obscured", "true",
267
268             "a", "ok", _("Accept and Set Password"), "", "",
269             "a", "cancel", _("Return to Configure Menu"), "", "",
270             "p", "accelerator", "ESC",
271
272             NULL
273         );
274
275         ds = dfui_dataset_new();
276         dfui_dataset_celldata_add(ds, "root_passwd_1", "");
277         dfui_dataset_celldata_add(ds, "root_passwd_2", "");
278         dfui_form_dataset_add(f, ds);
279
280         while (!done) {
281                 if (!dfui_be_present(a->c, f, &r))
282                         abort_backend();
283
284                 if (strcmp(dfui_response_get_action_id(r), "ok") == 0) {
285                         new_ds = dfui_dataset_dup(dfui_response_dataset_get_first(r));
286                         dfui_form_datasets_free(f);
287                         dfui_form_dataset_add(f, new_ds);
288
289                         /*
290                          * Fetch form field values.
291                          */
292
293                         root_passwd_1 = dfui_dataset_get_value(new_ds, "root_passwd_1");
294                         root_passwd_2 = dfui_dataset_get_value(new_ds, "root_passwd_2");
295
296                         if (!assert_clean(a->c, _("Root password"), root_passwd_1, PW_NOT_ALLOWED)) {
297                                 done = 0;
298                         } else if (strlen(root_passwd_1) == 0 && strlen(root_passwd_2) == 0) {
299                                 done = 0;
300                         } else if (strcmp(root_passwd_1, root_passwd_2) == 0) {
301                                 /*
302                                  * Passwords match, so set the root password.
303                                  */
304                                 cmds = commands_new();
305                                 cmd = command_add(cmds, "%s%s '%s' | "
306                                     "%s%s %smnt/ /%s usermod root -h 0",
307                                     a->os_root, cmd_name(a, "ECHO"),
308                                     root_passwd_1,
309                                     a->os_root, cmd_name(a, "CHROOT"),
310                                     a->os_root, cmd_name(a, "PW"));
311                                 command_set_desc(cmd, _("Setting password..."));
312                                 if (commands_execute(a, cmds)) {
313                                         inform(a->c, _("The root password has been changed."));
314                                         done = 1;
315                                 } else {
316                                         inform(a->c, _("An error occurred when "
317                                             "setting the root password."));
318                                         done = 0;
319                                 }
320                                 commands_free(cmds);
321                         } else {
322                                 /*
323                                  * Passwords don't match - tell the user, let them try again.
324                                  */
325                                 inform(a->c, _("The passwords do not match."));
326                                 done = 0;
327                         }
328                 } else {
329                         /*
330                          * Cancelled by user
331                          */
332                         done = 1;
333                 }
334
335                 dfui_response_free(r);
336         }
337
338         dfui_form_free(f);
339 }
340
341 void
342 fn_get_passphrase(struct i_fn_args *a)
343 {
344         struct dfui_dataset *ds, *new_ds;
345         struct dfui_form *f;
346         struct dfui_response *r;
347         const char *passphrase_1, *passphrase_2;
348         int fd;
349         int done = 0;
350
351         f = dfui_form_create(
352             "crypt_passphrase",
353             _("Set Passphrase For Encryption"),
354             _("Please specify the passphrase to be used for the encrypted "
355             "filesystems.\n\n"
356             "Please note that in the LiveCD environment the keymap is set to "
357             "\"US ISO\". "
358             "If you prefer a different keymap for entering the passphrase "
359             "here, you will need to set it manually using kbdcontrol(1)."),
360             "",
361
362             "f", "passphrase_1", _("Passphrase"),
363             _("Enter the passphrase you would like to use for encryption"), "",
364             "p", "obscured", "true",
365             "f", "passphrase_2", _("Passphrase again"),
366             _("Enter the passphrase again to confirm"), "",
367             "p", "obscured", "true",
368
369             "a", "ok", _("Accept and Set Passphrase"), "", "",
370             "p", "accelerator", "ESC",
371
372             NULL
373         );
374
375         ds = dfui_dataset_new();
376         dfui_dataset_celldata_add(ds, "passphrase_1", "");
377         dfui_dataset_celldata_add(ds, "passphrase_2", "");
378         dfui_form_dataset_add(f, ds);
379
380         while (!done) {
381                 if (!dfui_be_present(a->c, f, &r))
382                         abort_backend();
383
384                 if (strcmp(dfui_response_get_action_id(r), "ok") == 0) {
385                         new_ds = dfui_dataset_dup(dfui_response_dataset_get_first(r));
386                         dfui_form_datasets_free(f);
387                         dfui_form_dataset_add(f, new_ds);
388
389                         /*
390                          * Fetch form field values.
391                          */
392
393                         passphrase_1 = dfui_dataset_get_value(new_ds, "passphrase_1");
394                         passphrase_2 = dfui_dataset_get_value(new_ds, "passphrase_2");
395
396                         if (strlen(passphrase_1) == 0 && strlen(passphrase_2) == 0) {
397                                 done = 0;
398                         } else if (strcmp(passphrase_1, passphrase_2) == 0) {
399                                 /*
400                                  * Passphrases match, write it out.
401                                  */
402                                 fd = open("/tmp/t1", O_RDWR | O_CREAT | O_TRUNC,
403                                     S_IRUSR);
404                                 if (fd != -1) {
405                                         write(fd, passphrase_1, strlen(passphrase_1));
406                                         close(fd);
407                                         done = 1;
408                                 } else {
409                                         inform(a->c, _("write() error"));
410                                         done = 0;
411                                 }
412                         } else {
413                                 /*
414                                  * Passphrases don't match, tell the user,
415                                  * let them try again.
416                                  */
417                                 inform(a->c, _("The passphrases do not match."));
418                                 done = 0;
419                         }
420                 }
421
422                 dfui_response_free(r);
423         }
424
425         dfui_form_free(f);
426 }
427
428 void
429 fn_install_packages(struct i_fn_args *a)
430 {
431         FILE *pfp;
432         struct commands *cmds;
433         struct dfui_celldata *cd;
434         struct dfui_dataset *ds;
435         struct dfui_field *fi;
436         struct dfui_form *f;
437         struct dfui_response *r;
438         char command[256];
439         char pkg_name[256];
440         char msg_buf[1][1024];
441         struct aura_dict *seen;
442
443         snprintf(msg_buf[0], sizeof(msg_buf[0]),
444             _("Select optional software packages that you want "
445             "installed on this system.  This form lists only the "
446             "software packages installed on the LiveCD; thousands "
447             "more are available via the internet once %s "
448             "is installed."),
449             OPERATING_SYSTEM_NAME);
450
451         f = dfui_form_create(
452             "install_packages",
453             _("Install Packages"),
454             msg_buf[0],
455             "",
456
457             "p", "special", "dfinstaller_install_packages",
458
459             NULL
460         );
461
462         ds = dfui_dataset_new();
463         snprintf(command, 256, "ls %svar/db/pkg", a->os_root);
464         if ((pfp = popen(command, "r")) != NULL) {
465                 while (fgets(pkg_name, 255, pfp) != NULL) {
466                         while (strlen(pkg_name) > 0 &&
467                                isspace(pkg_name[strlen(pkg_name) - 1])) {
468                                 pkg_name[strlen(pkg_name) - 1] = '\0';
469                         }
470                         fi = dfui_form_field_add(f, pkg_name,
471                             dfui_info_new(pkg_name, "", ""));
472                         dfui_field_property_set(fi, "control", "checkbox");
473                         dfui_dataset_celldata_add(ds,
474                             pkg_name, "Y");
475                 }
476                 pclose(pfp);
477         }
478         dfui_form_dataset_add(f, ds);
479
480         dfui_form_action_add(f, "ok",
481             dfui_info_new(_("Accept and Install"), "", ""));
482         dfui_form_action_add(f, "cancel",
483             dfui_info_new(_("Return to Configure Menu"), "", ""));
484
485         if (!dfui_be_present(a->c, f, &r))
486                 abort_backend();
487
488         if (strcmp(dfui_response_get_action_id(r), "ok") == 0) {
489                 cmds = commands_new();
490                 seen = aura_dict_new(23, AURA_DICT_HASH);
491
492                 cd = dfui_dataset_celldata_get_first(dfui_response_dataset_get_first(r));
493
494                 while (cd != NULL) {
495                         strlcpy(pkg_name, dfui_celldata_get_field_id(cd), 256);
496                         if (!strcasecmp(dfui_celldata_get_value(cd), "Y")) {
497                                 if (!pkg_copy(a, cmds, pkg_name, seen)) {
498                                         inform(a->c, _("Couldn't install package `%s'."), pkg_name);
499                                         break;
500                                 }
501                         }
502                         cd = dfui_celldata_get_next(cd);
503                 }
504
505                 if (!commands_execute(a, cmds)) {
506                         inform(a->c, _("Packages were not fully installed."));
507                 } else {
508                         inform(a->c, _("Packages were successfully installed!"));
509                 }
510
511                 aura_dict_free(seen);
512                 commands_free(cmds);
513         }
514
515         dfui_form_free(f);
516         dfui_response_free(r);
517 }
518
519 void
520 fn_remove_packages(struct i_fn_args *a)
521 {
522         FILE *pfp;
523         struct commands *cmds;
524         struct dfui_celldata *cd;
525         struct dfui_dataset *ds;
526         struct dfui_field *fi;
527         struct dfui_form *f;
528         struct dfui_response *r;
529         char command[256];
530         char pkg_name[256];
531         struct aura_dict *seen;
532
533         f = dfui_form_create(
534             "remove_packages",
535             _("Remove Packages"),
536             _("Select the installed software packages that you want "
537             "removed from this system."),
538             "",
539
540             "p", "special", "dfinstaller_remove_packages",
541
542             NULL
543         );
544
545         ds = dfui_dataset_new();
546         snprintf(command, 256, "ls %smnt/var/db/pkg", a->os_root);
547         if ((pfp = popen(command, "r")) != NULL) {
548                 while (fgets(pkg_name, 255, pfp)) {
549                         pkg_name[strlen(pkg_name) - 1] = '\0';
550                         fi = dfui_form_field_add(f, pkg_name,
551                             dfui_info_new(pkg_name, "", ""));
552                         dfui_field_property_set(fi, "control", "checkbox");
553                         dfui_dataset_celldata_add(ds,
554                             pkg_name, "N");
555                 }
556                 pclose(pfp);
557         }
558         dfui_form_dataset_add(f, ds);
559
560         dfui_form_action_add(f, "ok",
561             dfui_info_new(_("Accept and Remove"), "", ""));
562         dfui_form_action_add(f, "cancel",
563             dfui_info_new(_("Return to Configure Menu"), "", ""));
564
565         if (!dfui_be_present(a->c, f, &r))
566                 abort_backend();
567
568         if (strcmp(dfui_response_get_action_id(r), "ok") == 0) {
569                 cmds = commands_new();
570                 seen = aura_dict_new(23, AURA_DICT_HASH);
571
572                 cd = dfui_dataset_celldata_get_first(dfui_response_dataset_get_first(r));
573
574                 while (cd != NULL) {
575                         strlcpy(pkg_name, dfui_celldata_get_field_id(cd), 256);
576                         if (!strcasecmp(dfui_celldata_get_value(cd), "Y")) {
577                                 if (!pkg_remove(a, cmds, pkg_name, seen)) {
578                                         inform(a->c, _("Couldn't remove package `%s'."), pkg_name);
579                                         break;
580                                 }
581                         }
582                         cd = dfui_celldata_get_next(cd);
583                 }
584
585                 if (!commands_execute(a, cmds)) {
586                         inform(a->c, _("Packages were not fully removed."));
587                 } else {
588                         inform(a->c, _("Packages were successfully removed."));
589                 }
590
591                 aura_dict_free(seen);
592                 commands_free(cmds);
593         }
594
595         dfui_form_free(f);
596         dfui_response_free(r);
597 }
598
599 /** LIVECD UTILITIES FUNCTIONS **/
600
601 /*
602  * String returned by this function must be deallocated by the caller.
603  */
604 char *
605 fn_select_file(const char *title, const char *desc, const char *help, const char *cancel,
606                const char *dir, const char *ext, const struct i_fn_args *a)
607 {
608         DIR *d;
609         struct dfui_form *f;
610         struct dfui_action *k;
611         struct dfui_response *r;
612         struct dirent *de;
613         char *s;
614         struct aura_dict *dict;
615         char *rk;
616         size_t rk_len;
617
618         f = dfui_form_create(
619             "select_file",
620             title, desc, help,
621             "p", "role", "menu",
622             NULL
623         );
624
625         dict = aura_dict_new(1, AURA_DICT_SORTED_LIST);
626         d = opendir(dir);
627         while ((de = readdir(d)) != NULL) {
628                 if (strcmp(de->d_name, ".") == 0 ||
629                     strcmp(de->d_name, "..") == 0 ||
630                     strstr(de->d_name, ext) == NULL)
631                         continue;
632                 aura_dict_store(dict, de->d_name, strlen(de->d_name) + 1, "", 1);
633         }
634         closedir(d);
635
636         aura_dict_rewind(dict);
637         while (!aura_dict_eof(dict)) {
638                 aura_dict_get_current_key(dict, (void **)&rk, &rk_len),
639                 dfui_form_action_add(f, rk,
640                     dfui_info_new(rk, "", ""));
641                 aura_dict_next(dict);
642         }
643         aura_dict_free(dict);
644
645         k = dfui_form_action_add(f, "cancel",
646             dfui_info_new(cancel, "", ""));
647         dfui_action_property_set(k, "accelerator", "ESC");
648
649         if (!dfui_be_present(a->c, f, &r))
650                 abort_backend();
651
652         s = aura_strdup(dfui_response_get_action_id(r));
653
654         dfui_form_free(f);
655         dfui_response_free(r);
656
657         return(s);
658 }
659
660 void
661 fn_set_kbdmap(struct i_fn_args *a)
662 {
663         struct commands *cmds;
664         char *s;
665         char filename[256], keymapname[256];
666
667         s = fn_select_file(_("Select Keyboard Map"),
668             _("Select a keyboard map appropriate to your keyboard layout."),
669             "", _("Return to Utilities Menu"), "/usr/share/syscons/keymaps",
670             ".kbd", a);
671
672         if (strcmp(s, "cancel") != 0) {
673                 cmds = commands_new();
674                 command_add(cmds, "%s%s -l "
675                     "/usr/share/syscons/keymaps/%s < /dev/ttyv0",
676                     a->os_root, cmd_name(a, "KBDCONTROL"),
677                     s);
678                 if (commands_execute(a, cmds)) {
679                         snprintf(filename, 256, "/usr/share/syscons/keymaps/%s", s);
680                         snprintf(keymapname, 256, "%s", filename_noext(basename(filename)));
681                         config_var_set(rc_conf, "keymap", keymapname);
682                 } else {
683                         inform(a->c, _("Keyboard map not successfully set."));
684                 }
685                 commands_free(cmds);
686         }
687
688         free(s);
689 }
690
691 void
692 fn_set_vidfont(struct i_fn_args *a)
693 {
694         struct commands *cmds;
695         char *s;
696         char filename[256], variable[256], fontname[256];
697         int by = 0;
698
699
700         s = fn_select_file(_("Select Console Font"),
701             _("Select a font appropriate to your video monitor and language."),
702             "", _("Return to Utilities Menu"), "/usr/share/syscons/fonts",
703             ".fnt", a);
704
705         if (strcmp(s, "cancel") != 0) {
706                 cmds = commands_new();
707                 command_add(cmds, "%s%s -f "
708                     "/usr/share/syscons/fonts/%s < /dev/ttyv0",
709                     a->os_root, cmd_name(a, "VIDCONTROL"),
710                     s);
711                 if (commands_execute(a, cmds)) {
712                         if (strstr(s, "8x16") != NULL)
713                                 by = 16;
714                         else if (strstr(s, "8x14") != NULL)
715                                 by = 14;
716                         else
717                                 by = 8;
718
719                         snprintf(variable, 256, "font8x%d", by);
720                         snprintf(filename, 256, "/usr/share/syscons/fonts/%s", s);
721                         snprintf(fontname, 256, "%s", filename_noext(basename(filename)));
722                         config_var_set(rc_conf, variable, fontname);
723
724                 } else {
725                         inform(a->c, _("Video font not successfully set."));
726                 }
727                 commands_free(cmds);
728         }
729
730         free(s);
731 }
732
733 void
734 fn_set_scrnmap(struct i_fn_args *a)
735 {
736         struct commands *cmds;
737         char *s;
738         char filename[256], scrnmapname[256];
739
740         s = fn_select_file(_("Select Screen Map"),
741             _("Select a mapping for translating characters as they appear "
742             "on your video console screen."),
743             "", _("Return to Utilities Menu"), "/usr/share/syscons/scrnmaps",
744             ".scm", a);
745
746         if (strcmp(s, "cancel") != 0) {
747                 cmds = commands_new();
748                 command_add(cmds, "%s%s -l "
749                     "/usr/share/syscons/scrnmaps/%s < /dev/ttyv0",
750                     a->os_root, cmd_name(a, "VIDCONTROL"),
751                     s);
752                 if (commands_execute(a, cmds)) {
753                         snprintf(filename, 256, "/usr/share/syscons/scrnmaps/%s", s);
754                         snprintf(scrnmapname, 256, "%s", filename_noext(basename(filename)));
755                         config_var_set(rc_conf, "scrnmap", scrnmapname);
756                 } else {
757                         inform(a->c, _("Video font not successfully set."));
758                 }
759                 commands_free(cmds);
760         }
761         free(s);
762 }
763
764 void
765 fn_set_timezone(struct i_fn_args *a)
766 {
767         struct commands *cmds;
768         char *s = NULL;
769         char current_path[256], selection[256], temp[256];
770         int found_file = 0;
771         int result;
772
773         result = dfui_be_present_dialog(a->c, _("Local or UTC (Greenwich Mean Time) clock"),
774             _("Yes|No"),
775             _("Is this machine's CMOS clock set to UTC?\n\n"
776             "If it is set to local time, or you don't know, please choose NO here!"));
777         if (result < 1)
778                 abort_backend();
779
780         cmds = commands_new();
781         switch (result) {
782                 case 1:
783                         command_add(cmds, "%s%s -f %s%setc/wall_cmos_clock",
784                             a->os_root, cmd_name(a, "RM"),
785                             a->os_root, a->cfg_root);
786                         break;
787                 case 2:
788                         command_add(cmds, "%s%s %s%setc/wall_cmos_clock",
789                             a->os_root, cmd_name(a, "TOUCH"),
790                             a->os_root, a->cfg_root);
791                         break;
792         }
793         commands_execute(a, cmds);
794
795         snprintf(current_path, 256, "%s%susr/share/zoneinfo",
796             a->os_root, a->cfg_root);
797         while (!found_file) {
798                 if (s != NULL)
799                         free(s);
800                 s = fn_select_file(_("Select Time Zone"),
801                     _("Select a Time Zone appropriate to your physical location."),
802                     "", _("Return to Utilities Menu"), current_path,
803                     "", a);
804                 if (is_dir("%s/%s", current_path, s)) {
805                         snprintf(temp, 256, "%s/%s", current_path, s);
806                         strlcpy(current_path, temp, 256);
807                 } else {
808                         if (is_file("%s/%s", current_path, s)) {
809                                 snprintf(selection, 256, "%s/%s", current_path, s);
810                                 found_file = 1;
811                         }
812                         if (strcmp(s, "cancel") == 0) {
813                                 strlcpy(selection, "cancel", 256);
814                                 found_file = 1;
815                         }
816                 }
817         }
818         free(s);
819
820         if (strcmp(selection, "cancel") != 0) {
821                 command_add(cmds, "%s%s %s %s%setc/localtime",
822                     a->os_root, cmd_name(a, "CP"),
823                     selection,
824                     a->os_root, a->cfg_root);
825                 if (commands_execute(a, cmds)) {
826                         inform(a->c, _("The Time Zone has been set to %s."), selection);
827                         setenv("TZ", selection, 1);
828                         tzset();
829                 }
830         }
831         commands_free(cmds);
832 }
833
834 void
835 fn_assign_datetime(struct i_fn_args *a)
836 {
837         struct commands *cmds;
838         struct dfui_dataset *ds, *new_ds;
839         struct dfui_form *f;
840         struct dfui_response *r;
841         struct tm *tp;
842         char temp[256];
843         int year, month, dayofmonth, hour, minutes;
844         int valid = 1;
845         time_t now;
846
847         now = time(NULL);
848         tp = localtime(&now);
849
850         f = dfui_form_create(
851             "set_datetime",
852             _("Set Time/Date"),
853             _("Enter the date-time in your timezone."),
854             "",
855
856             "f", "year", _("Enter year"),
857             _("Enter the current year (e.g. `2004')"), "",
858             "f", "month", _("Month"),
859             _("Enter the current month (e.g. `07')"), "",
860             "f", "dayofmonth", "dayofmonth",
861             _("Enter the current day of month (e.g. `30')"), "",
862             "f", "hour", "hour",
863             _("Enter the current hour (e.g. `07')"), "",
864             "f", "minutes", "minutes",
865             _("Enter the current minutes (e.g. `59')"), "",
866
867             "a", "ok", _("OK"), "", "",
868             "a", "cancel", _("Cancel"), "", "",
869             "p", "accelerator", "ESC",
870
871             NULL
872         );
873
874         ds = dfui_dataset_new();
875         snprintf(temp, 256, "%i", (tp->tm_year+1900));
876         dfui_dataset_celldata_add(ds, "year", temp);
877         snprintf(temp, 256, "%i", (tp->tm_mon+1));
878         dfui_dataset_celldata_add(ds, "month", temp);
879         snprintf(temp, 256, "%i", tp->tm_mday);
880         dfui_dataset_celldata_add(ds, "dayofmonth", temp);
881         snprintf(temp, 256, "%i", tp->tm_hour);
882         dfui_dataset_celldata_add(ds, "hour", temp);
883         snprintf(temp, 256, "%i", tp->tm_min);
884         dfui_dataset_celldata_add(ds, "minutes", temp);
885         dfui_form_dataset_add(f, ds);
886
887         if (!dfui_be_present(a->c, f, &r))
888                 abort_backend();
889
890         if (strcmp(dfui_response_get_action_id(r), "ok") == 0) {
891                 new_ds = dfui_response_dataset_get_first(r);
892
893                 if ((year = atoi(dfui_dataset_get_value(new_ds, "year"))) <= 0)
894                         valid = 0;
895                 month = atoi(dfui_dataset_get_value(new_ds, "month"));
896                 if (month < 1 || month > 12)
897                         valid = 0;
898                 dayofmonth = atoi(dfui_dataset_get_value(new_ds, "dayofmonth"));
899                 if (dayofmonth < 1 || dayofmonth > 31)
900                         valid = 0;
901                 hour = atoi(dfui_dataset_get_value(new_ds, "hour"));
902                 if (hour < 0 || hour > 23)
903                         valid = 0;
904                 minutes = atoi(dfui_dataset_get_value(new_ds, "minutes"));
905                 if (minutes < 0 || minutes > 59)
906                         valid = 0;
907
908                 if (valid) {
909                         cmds = commands_new();
910                         command_add(cmds, "%s%s -n %04d%02d%02d%02d%02d",
911                             a->os_root, cmd_name(a, "DATE"),
912                             year, month, dayofmonth, hour, minutes);
913                         if (commands_execute(a, cmds)) {
914                                 inform(a->c, _("The date and time have been set."));
915                         }
916                         commands_free(cmds);
917                 } else {
918                         inform(a->c, _("Please enter numbers within acceptable ranges "
919                                 "for year, month, day of month, hour, and minute."));
920                 }
921         }
922 }
923
924 void
925 fn_assign_hostname_domain(struct i_fn_args *a)
926 {
927         struct dfui_form *f;
928         struct dfui_response *r;
929         struct dfui_dataset *ds, *new_ds;
930         struct config_vars *resolv_conf;
931         const char *domain, *hostname;
932         char *fqdn;
933
934         f = dfui_form_create(
935             "set_hostname_domain",
936             _("Set Hostname/Domain"),
937             _("Please enter this machine's hostname and domain name."),
938             "",
939
940             "f", "hostname", _("Hostname"),
941             _("Enter the Hostname (e.g. `machine')"), "",
942             "f", "domain", _("Domain"),
943             _("Enter the Domain Name (e.g. `network.lan')"), "",
944
945             "a", "ok", _("OK"), "", "",
946             "a", "cancel", _("Cancel"), "", "",
947             "p", "accelerator", "ESC",
948
949             NULL
950         );
951
952         ds = dfui_dataset_new();
953         dfui_dataset_celldata_add(ds, "hostname", "");
954         dfui_dataset_celldata_add(ds, "domain", "");
955         dfui_form_dataset_add(f, ds);
956
957         if (!dfui_be_present(a->c, f, &r))
958                 abort_backend();
959
960         if (strcmp(dfui_response_get_action_id(r), "ok") == 0) {
961                 new_ds = dfui_response_dataset_get_first(r);
962
963                 hostname = dfui_dataset_get_value(new_ds, "hostname");
964                 domain = dfui_dataset_get_value(new_ds, "domain");
965                 if (strlen(domain) == 0)
966                         asprintf(&fqdn, "%s", hostname);
967                 else
968                         asprintf(&fqdn, "%s.%s", hostname, domain);
969
970                 resolv_conf = config_vars_new();
971
972                 config_var_set(rc_conf, "hostname", fqdn);
973                 config_var_set(resolv_conf, "search", domain);
974                 config_vars_write(resolv_conf, CONFIG_TYPE_RESOLV,
975                     "%s%setc/resolv.conf", a->os_root, a->cfg_root);
976
977                 config_vars_free(resolv_conf);
978
979                 free(fqdn);
980         }
981
982         dfui_form_free(f);
983         dfui_response_free(r);
984 }
985
986 void
987 fn_assign_ip(struct i_fn_args *a)
988 {
989         FILE *p;
990         struct commands *cmds;
991         struct command *cmd;
992         struct config_vars *resolv_conf;
993         struct dfui_dataset *ds, *new_ds;
994         struct dfui_form *f;
995         struct dfui_action *k;
996         struct dfui_response *r;
997         const char *domain, *hostname;
998         const char *interface_ip, *interface_netmask, *defaultrouter, *dns_resolver;
999         char *string, *string1;
1000         char *word;
1001         char interface[256];
1002         char line[256];
1003         int write_config = 0;
1004
1005         /*
1006          * Get interface list.
1007          */
1008         p = popen("/sbin/ifconfig -l", "r");
1009         /* XXX it's possible (though extremely unlikely) this will fail. */
1010         while (fgets(line, 255, p) != NULL)
1011                 line[strlen(line) - 1] = '\0';
1012
1013         pclose(p);
1014
1015         f = dfui_form_create(
1016             "assign_ip",
1017             _("Assign IP Address"),
1018             _("Please select which interface you would like to configure:"),
1019             "",
1020             "p",        "role", "menu",
1021             NULL
1022         );
1023
1024         /* Loop through array. */
1025         word = strtok(line, " \t");
1026         while (word != NULL) {
1027                 dfui_form_action_add(f, word,
1028                     dfui_info_new(word, "", ""));
1029                 word = strtok(NULL, " ");
1030         }
1031
1032         k = dfui_form_action_add(f, "cancel",
1033             dfui_info_new("Cancel", "", ""));
1034         dfui_action_property_set(k, "accelerator", "ESC");
1035
1036         if (!dfui_be_present(a->c, f, &r))
1037                 abort_backend();
1038
1039         if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
1040                 dfui_form_free(f);
1041                 dfui_response_free(r);
1042                 return;
1043         }
1044
1045         strlcpy(interface, dfui_response_get_action_id(r), 256);
1046
1047         resolv_conf = config_vars_new();
1048
1049         switch (dfui_be_present_dialog(a->c, _("Use DHCP?"),
1050             _("Use DHCP|Configure Manually"),
1051             _("DHCP allows the interface to automatically obtain "
1052             "an IP address from a nearby DHCP server.\n\n"
1053             "Would you like to enable DHCP for %s?"), interface)) {
1054         case 1:
1055                 asprintf(&string, "ifconfig_%s", interface);
1056
1057                 cmds = commands_new();
1058                 cmd = command_add(cmds, "%s%s dhclient",
1059                     a->os_root, cmd_name(a, "KILLALL"));
1060                 command_set_failure_mode(cmd, COMMAND_FAILURE_IGNORE);
1061                 command_add(cmds, "%s%s %s",
1062                     a->os_root, cmd_name(a, "DHCLIENT"),
1063                     interface);
1064                 if (commands_execute(a, cmds)) {
1065                         /* XXX sleep(3); */
1066                         show_ifconfig(a->c, interface);
1067                         write_config = 1;
1068                 } else {
1069                         switch (dfui_be_present_dialog(a->c, _("DHCP Failure"),
1070                             _("Yes|No"),
1071                             _("Warning: could not enable dhclient for %s.\n\n"
1072                               "Write the corresponding settings to rc.conf "
1073                               "anyway?"), interface)) {
1074                         case 1:
1075                                 write_config = 1;
1076                                 break;
1077                         case 2:
1078                                 write_config = 0;
1079                                 break;
1080                         default:
1081                                 abort_backend();
1082                         }
1083                 }
1084                 commands_free(cmds);
1085                 config_var_set(rc_conf, string, "DHCP");
1086                 free(string);
1087                 break;
1088         case 2:
1089                 dfui_form_free(f);
1090                 dfui_response_free(r);
1091                 f = dfui_form_create(
1092                     "assign_ip",
1093                     _("Assign IP Address"),
1094                     _("Configuring Interface:"),
1095                     "",
1096
1097                     "f", "interface_ip", _("IP Address"),
1098                     _("Enter the IP Address you would like to use"), "",
1099                     "f", "interface_netmask",   _("Netmask"),
1100                     _("Enter the netmask of the IP address"), "",
1101                     "f", "defaultrouter", _("Default Router"),
1102                     _("Enter the IP address of the default router"), "",
1103                     "f", "dns_resolver", _("Primary DNS Server"),
1104                     _("Enter the IP address of primary DNS Server"), "",
1105                     "f", "hostname", _("Hostname"),
1106                     _("Enter the Hostname"), "",
1107                     "f", "domain", _("Domain"),
1108                     _("Enter the Domain Name"), "",
1109
1110                     "a", "ok", _("Configure Interface"),
1111                     "", "",
1112                     "a", "cancel", _("Return to Utilities Menu"),
1113                     "", "",
1114                     "p", "accelerator", "ESC",
1115
1116                     NULL
1117                 );
1118
1119                 ds = dfui_dataset_new();
1120                 dfui_dataset_celldata_add(ds, "interface_netmask", "");
1121                 dfui_dataset_celldata_add(ds, "defaultrouter", "");
1122                 dfui_dataset_celldata_add(ds, "dns_resolver", "");
1123                 dfui_dataset_celldata_add(ds, "hostname", "");
1124                 dfui_dataset_celldata_add(ds, "domain", "");
1125                 dfui_dataset_celldata_add(ds, "interface_ip", "");
1126                 dfui_form_dataset_add(f, ds);
1127
1128                 if (!dfui_be_present(a->c, f, &r))
1129                         abort_backend();
1130
1131                 if (strcmp(dfui_response_get_action_id(r), "ok") == 0) {
1132                         new_ds = dfui_response_dataset_get_first(r);
1133
1134                         interface_ip = dfui_dataset_get_value(
1135                                                 new_ds, "interface_ip");
1136                         interface_netmask = dfui_dataset_get_value(
1137                                                 new_ds, "interface_netmask");
1138                         defaultrouter = dfui_dataset_get_value(
1139                                                 new_ds, "defaultrouter");
1140                         dns_resolver = dfui_dataset_get_value(
1141                                                 new_ds, "dns_resolver");
1142                         hostname = dfui_dataset_get_value(
1143                                                 new_ds, "hostname");
1144                         domain = dfui_dataset_get_value(
1145                                                 new_ds, "domain");
1146
1147                         asprintf(&string, "ifconfig_%s", interface);
1148                         asprintf(&string1, "inet %s netmask %s",
1149                             interface_ip, interface_netmask);
1150
1151                         cmds = commands_new();
1152                         command_add(cmds, "%s%s %s %s netmask %s",
1153                             a->os_root, cmd_name(a, "IFCONFIG"),
1154                             interface, interface_ip, interface_netmask);
1155                         command_add(cmds, "%s%s add default %s",
1156                             a->os_root, cmd_name(a, "ROUTE"),
1157                             defaultrouter);
1158
1159                         if (commands_execute(a, cmds)) {
1160                                 /* XXX sleep(3); */
1161                                 show_ifconfig(a->c, interface);
1162                                 write_config = 1;
1163                         } else {
1164                                 switch (dfui_be_present_dialog(a->c,
1165                                     _("ifconfig Failure"),
1166                                     _("Yes|No"),
1167                                     _("Warning: could not assign IP address "
1168                                       "or default gateway.\n\n"
1169                                       "Write the corresponding settings to "
1170                                       "rc.conf anyway?"))) {
1171                                 case 1:
1172                                         write_config = 1;
1173                                         break;
1174                                 case 2:
1175                                         write_config = 0;
1176                                         break;
1177                                 default:
1178                                         abort_backend();
1179                                 }
1180                         }
1181                         commands_free(cmds);
1182
1183                         config_var_set(rc_conf, string, string1);
1184                         config_var_set(rc_conf, "defaultrouter", defaultrouter);
1185
1186                         free(string);
1187                         free(string1);
1188
1189                         asprintf(&string, "%s.%s", hostname, domain);
1190                         config_var_set(rc_conf, "hostname", string);
1191                         free(string);
1192
1193                         config_var_set(resolv_conf, "search", domain);
1194                         config_var_set(resolv_conf, "nameserver", dns_resolver);
1195                 }
1196                 break;
1197         default:
1198                 abort_backend();
1199         }
1200
1201         if (write_config) {
1202                 /*
1203                  * Save out changes to /etc/rc.conf and /etc/resolv.conf.
1204                  */
1205                 config_vars_write(resolv_conf, CONFIG_TYPE_RESOLV,
1206                     "%s%setc/resolv.conf", a->os_root, a->cfg_root);
1207         }
1208
1209         config_vars_free(resolv_conf);
1210
1211         dfui_form_free(f);
1212         dfui_response_free(r);
1213 }
1214
1215 static const char *
1216 yes_to_y(const char *value)
1217 {
1218         return(strcasecmp(value, "YES") == 0 ? "Y" : "N");
1219 }
1220
1221 void
1222 fn_select_services(struct i_fn_args *a)
1223 {
1224         struct dfui_dataset *ds;
1225         struct dfui_form *f;
1226         struct dfui_response *r;
1227
1228         if (!config_vars_read(a, rc_conf, CONFIG_TYPE_SH, "%s%setc/rc.conf",
1229                 a->os_root, a->cfg_root)) {
1230                 inform(a->c, _("Couldn't read %s%setc/rc.conf."),
1231                     a->os_root, a->cfg_root);
1232                 a->result = 0;
1233                 return;
1234         }
1235
1236         f = dfui_form_create(
1237             "select_services",
1238             _("Select Services"),
1239             _("Please select which services you would like "
1240               "started at boot time."),
1241             "",
1242
1243             "f", "syslogd", "syslogd",
1244                 _("System Logging Daemon"), "",
1245                 "p", "control", "checkbox",
1246             "f", "inetd", "inetd",
1247                 _("Internet Super-Server"), "",
1248                 "p", "control", "checkbox",
1249             "f", "named", "named",
1250                 _("BIND Name Server"), "",
1251                 "p", "control", "checkbox",
1252             "f", "ntpd", "ntpd",
1253                 _("Network Time Protocol Daemon"), "",
1254                 "p", "control", "checkbox",
1255             "f", "sshd", "sshd",
1256                 _("Secure Shell Daemon"), "",
1257                 "p", "control", "checkbox",
1258
1259             "a", "ok", _("Enable/Disable Services"),
1260                 "", "",
1261             "a", "cancel", _("Return to Utilities Menu"),
1262                 "", "",
1263                 "p", "accelerator", "ESC",
1264
1265             NULL
1266         );
1267
1268         ds = dfui_dataset_new();
1269         dfui_dataset_celldata_add(ds, "syslogd",
1270             yes_to_y(config_var_get(rc_conf, "syslogd_enable")));
1271         dfui_dataset_celldata_add(ds, "inetd",
1272             yes_to_y(config_var_get(rc_conf, "inetd_enable")));
1273         dfui_dataset_celldata_add(ds, "named",
1274             yes_to_y(config_var_get(rc_conf, "named_enable")));
1275         dfui_dataset_celldata_add(ds, "ntpd",
1276             yes_to_y(config_var_get(rc_conf, "ntpd_enable")));
1277         dfui_dataset_celldata_add(ds, "sshd",
1278             yes_to_y(config_var_get(rc_conf, "sshd_enable")));
1279         dfui_form_dataset_add(f, ds);
1280
1281         if (!dfui_be_present(a->c, f, &r))
1282                 abort_backend();
1283
1284         if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
1285                 dfui_form_free(f);
1286                 dfui_response_free(r);
1287                 return;
1288         }
1289
1290         dfui_form_free(f);
1291         dfui_response_free(r);
1292 }
1293
1294 /*** NON-fn_ FUNCTIONS ***/
1295
1296 /*
1297  * Uses ss->selected_{disk,slice} as the target system.
1298  *
1299  * XXX We now assume that the root mount has enough of the topology
1300  *     to handle any configuration actions.
1301  */
1302 int
1303 mount_target_system(struct i_fn_args *a)
1304 {
1305         FILE *crypttab, *fstab;
1306         struct commands *cmds;
1307         struct command *cmd;
1308         struct subpartition *a_subpart;
1309         struct subpartition *d_subpart;
1310         char name[256], device[256];
1311         char *filename, line[256];
1312         char *word;
1313
1314         /*
1315          * Mount subpartitions from this installation if they are
1316          * not already mounted.  Tricky, as we need to honour the
1317          * installation's loader.conf and fstab.
1318          */
1319         cmds = commands_new();
1320
1321         /*
1322          * First, unmount anything already mounted on /mnt.
1323          */
1324         unmount_all_under(a, cmds, "%smnt", a->os_root);
1325
1326         /*
1327          * Reset and clear out subpartitions so that system
1328          * can make a "dummy" subpart.
1329          */
1330         subpartitions_free(storage_get_selected_slice(a->s));
1331
1332         /*
1333          * Create a temporary dummy subpartition - that we
1334          * assume exists
1335          */
1336         a_subpart = subpartition_new_ufs(storage_get_selected_slice(a->s),
1337                                          "/dummy", 0, 0, 0, 0, 0, 0);
1338         subpartition_new_ufs(storage_get_selected_slice(a->s),
1339                                          "swap", 0, 0, 0, 0, 0, 0);
1340         d_subpart = subpartition_new_ufs(storage_get_selected_slice(a->s),
1341                                          "/dummy", 0, 0, 0, 0, 0, 0);
1342
1343         /*
1344          * Mount the target's / and read its /etc/fstab.
1345          *
1346          * XXX NEEDS TO BE REWRITTEN XXX
1347          */
1348 #if 0
1349         if (use_hammer == 0) {
1350                 command_add(cmds, "%s%s /dev/%s %s%s",
1351                     a->os_root, cmd_name(a, "MOUNT"),
1352                     subpartition_get_device_name(d_subpart),
1353                     a->os_root, a->cfg_root);
1354                 cmd = command_add(cmds,
1355                     "%s%s -f %st2;"
1356                     "%s%s \"^[^#]\" %s%s/etc/crypttab >%st2",
1357                     a->os_root, cmd_name(a, "RM"), a->tmp,
1358                     a->os_root, cmd_name(a, "GREP"),
1359                     a->os_root, a->cfg_root, a->tmp);
1360                 command_set_failure_mode(cmd, COMMAND_FAILURE_IGNORE);
1361         } else
1362 #endif
1363         {
1364                 command_add(cmds, "%s%s /dev/%s %sboot",
1365                     a->os_root, cmd_name(a, "MOUNT"),
1366                     subpartition_get_device_name(a_subpart),
1367                     a->os_root);
1368                 cmd = command_add(cmds,
1369                     "%s%s -f %st2;"
1370                     "%s%s \"^vfs\\.root\\.realroot=\" %sboot/loader.conf >%st2",
1371                     a->os_root, cmd_name(a, "RM"), a->tmp,
1372                     a->os_root, cmd_name(a, "GREP"),
1373                     a->os_root, a->tmp);
1374                 command_set_failure_mode(cmd, COMMAND_FAILURE_IGNORE);
1375         }
1376         if (!commands_execute(a, cmds)) {
1377                 commands_free(cmds);
1378                 return(0);
1379         }
1380         commands_free(cmds);
1381         cmds = commands_new();
1382
1383         /*
1384          * XXX NEEDS TO BE REWRITTEN XXX
1385          */
1386         {
1387                 struct stat sb = { .st_size = 0 };
1388                 const char *fsname = use_hammer ? "hammer" : "ufs";
1389
1390                 stat("/tmp/t2", &sb);
1391                 if (sb.st_size > 0) {
1392                         command_add(cmds, "%s%s %sboot",
1393                             a->os_root, cmd_name(a, "UMOUNT"),
1394                             a->os_root);
1395                         fn_get_passphrase(a);
1396                         command_add(cmds,
1397                             "%s%s -d /tmp/t1 luksOpen /dev/`%s%s \"^vfs\\.root\\.realroot=\" %st2 |"
1398                             "%s%s -F%s: '{print $2;}' |"
1399                             "%s%s -F: '{print $1;}'` %s",
1400                             a->os_root, cmd_name(a, "CRYPTSETUP"),
1401                             a->os_root, cmd_name(a, "GREP"),
1402                             a->tmp,
1403                             a->os_root, cmd_name(a, "AWK"),
1404                             fsname,
1405                             a->os_root, cmd_name(a, "AWK"),
1406                             fn_mapper_name(subpartition_get_device_name(d_subpart), -1)
1407                             );
1408                         command_add(cmds,
1409                             "%s%s %s %s%s",
1410                             a->os_root,
1411                              (use_hammer ? cmd_name(a, "MOUNT_HAMMER") :
1412                                            cmd_name(a, "MOUNT")),
1413                             fn_mapper_name(subpartition_get_device_name(d_subpart), 1),
1414                             a->os_root, a->cfg_root);
1415                 } else {
1416                         command_add(cmds,
1417                             "%s%s /dev/`%s%s \"^vfs\\.root\\.mountfrom\" %sboot/loader.conf |"
1418                             "%s%s -F%s: '{print $2;}' |"
1419                             "%s%s 's/\"//'` %s%s",
1420                             a->os_root,
1421                              (use_hammer ? cmd_name(a, "MOUNT_HAMMER") :
1422                                            cmd_name(a, "MOUNT")),
1423                             a->os_root, cmd_name(a, "GREP"),
1424                             a->os_root,
1425                             a->os_root, cmd_name(a, "AWK"),
1426                             fsname,
1427                             a->os_root, cmd_name(a, "SED"),
1428                             a->os_root, a->cfg_root);
1429                         command_add(cmds, "%s%s %sboot",
1430                             a->os_root, cmd_name(a, "UMOUNT"),
1431                             a->os_root);
1432                 }
1433         }
1434         if (!commands_execute(a, cmds)) {
1435                 commands_free(cmds);
1436                 return(0);
1437         }
1438         commands_free(cmds);
1439         cmds = commands_new();
1440
1441         /*
1442          * Get rid of the dummy subpartition.
1443          */
1444         subpartitions_free(storage_get_selected_slice(a->s));
1445
1446         /*
1447          * See if an /etc/crypttab exists.
1448          *
1449          * Scan and open the related mappings (currently not used since
1450          * we removed the additional mounts from the fstab scan, but we
1451          * might put those back in at a future date so leave this in for
1452          * now).
1453          */
1454         asprintf(&filename, "%s%s/etc/crypttab", a->os_root, a->cfg_root);
1455         crypttab = fopen(filename, "r");
1456         free(filename);
1457         if (crypttab != NULL) {
1458                 while (fgets(line, 256, crypttab) != NULL) {
1459                         /*
1460                          * Parse the crypttab line.
1461                          */
1462                         if (first_non_space_char_is(line, '#'))
1463                                 continue;
1464                         if ((word = strtok(line, " \t")) == NULL)
1465                                 continue;
1466                         strlcpy(name, word, 256);
1467
1468                         /* don't mount encrypted swap */
1469                         if (strcmp(name, "swap") == 0)
1470                                 continue;
1471                         /* encrypted root already mounted */
1472                         if (strcmp(name, fn_mapper_name(subpartition_get_device_name(d_subpart), -1)) == 0)
1473                                 continue;
1474
1475                         if ((word = strtok(NULL, " \t")) == NULL)
1476                                 continue;
1477                         strlcpy(device, word, 256);
1478
1479                         command_add(cmds,
1480                             "%s%s -d /tmp/t1 luksOpen %s %s",
1481                             a->os_root, cmd_name(a, "CRYPTSETUP"),
1482                             device, name);
1483
1484                         continue;
1485                 }
1486                 fclose(crypttab);
1487         }
1488         if (!commands_execute(a, cmds)) {
1489                 commands_free(cmds);
1490                 return(0);
1491         }
1492         commands_free(cmds);
1493
1494         /*
1495          * (current we do not mount the other partitions, everything needed
1496          *  for system configuration should be on the already-mounted root).
1497          */
1498         asprintf(&filename, "%s%s/etc/fstab", a->os_root, a->cfg_root);
1499         fstab = fopen(filename, "r");
1500         free(filename);
1501         if (fstab == NULL) {
1502                 inform(a->c, _("Filesystem table on installed system could not be read."));
1503                 cmds = commands_new();
1504                 command_add(cmds, "%s%s %s%s",
1505                     a->os_root, cmd_name(a, "UMOUNT"),
1506                     a->os_root, a->cfg_root);
1507                 if (!commands_execute(a, cmds)) {
1508                         inform(a->c, _("Warning: Installed system was not properly unmounted."));
1509                 }
1510                 commands_free(cmds);
1511                 return(0);
1512         }
1513         fclose(fstab);
1514
1515         return 1;
1516 }