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