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