#include <sys/param.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <dirent.h>
#include <fcntl.h>
#include <libgen.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#ifdef ENABLE_NLS
#include <libintl.h>
#define _(String) gettext (String)
#else
#define _(String) (String)
#endif
#include "libaura/mem.h"
#include "libaura/dict.h"
#include "libaura/fspred.h"
#include "libdfui/dfui.h"
#include "libdfui/system.h"
#include "libinstaller/commands.h"
#include "libinstaller/confed.h"
#include "libinstaller/diskutil.h"
#include "libinstaller/functions.h"
#include "libinstaller/uiutil.h"
#include "fn.h"
#include "flow.h"
#include "pathnames.h"
struct config_vars *rc_conf;
struct config_vars *resolv_conf;
#define GECOS_NOT_ALLOWED ":,\\\""
#define FILENAME_NOT_ALLOWED ":;`~!#$^&*()={}[]\\|?<>'\" "
#define MEMBERSHIPS_NOT_ALLOWED ":;`~!@#$%^&*()+={}[]\\|/?<>'\" "
#define USERNAME_NOT_ALLOWED (MEMBERSHIPS_NOT_ALLOWED ",")
void
fn_add_user(struct i_fn_args *a)
{
struct dfui_dataset *ds, *new_ds;
struct dfui_form *f;
struct dfui_response *r;
struct commands *cmds;
struct command *cmd;
const char *username, *home, *passwd_1, *passwd_2, *gecos;
const char *shell, *uid, *group, *groups;
const char *passwd_env = "passwd";
int done = 0;
f = dfui_form_create(
"add_user",
_("Add user"),
_("Here you can add a user to an installed system.\n\n"
"You can leave the Home Directory, User ID, and Login Group "
"fields empty if you want these items to be automatically "
"allocated by the system."),
"",
"f", "username", _("Username"),
_("Enter the username the user will log in as"), "",
"f", "gecos", _("Real Name"),
_("Enter the real name (or GECOS field) of this user"), "",
"f", "passwd_1", _("Password"),
_("Enter the user's password (will not be displayed)"), "",
"p", "obscured", "true",
"f", "passwd_2", _("Password (Again)"),
_("Re-enter the user's password to confirm"), "",
"p", "obscured", "true",
"f", "shell", _("Shell"),
_("Enter the full path to the user's shell program"), "",
"f", "home", _("Home Directory"),
_("Enter the full path to the user's home directory, or leave blank"), "",
"f", "uid", _("User ID"),
_("Enter this account's numeric user id, or leave blank"), "",
"f", "group", _("Login Group"),
_("Enter the primary group for this account, or leave blank"), "",
"f", "groups", _("Other Group Memberships"),
_("Enter a comma-separated list of other groups "
"that this user should belong to"), "",
"a", "ok", _("Accept and Add"), "", "",
"a", "cancel", _("Return to Configure Menu"), "", "",
"p", "accelerator", "ESC",
NULL
);
ds = dfui_dataset_new();
dfui_dataset_celldata_add(ds, "username", "");
dfui_dataset_celldata_add(ds, "gecos", "");
dfui_dataset_celldata_add(ds, "passwd_1", "");
dfui_dataset_celldata_add(ds, "passwd_2", "");
dfui_dataset_celldata_add(ds, "shell", "/bin/tcsh");
dfui_dataset_celldata_add(ds, "home", "");
dfui_dataset_celldata_add(ds, "uid", "");
dfui_dataset_celldata_add(ds, "group", "");
dfui_dataset_celldata_add(ds, "groups", "");
dfui_form_dataset_add(f, ds);
while (!done) {
if (!dfui_be_present(a->c, f, &r))
abort_backend();
if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
done = 1;
dfui_response_free(r);
break;
}
new_ds = dfui_dataset_dup(dfui_response_dataset_get_first(r));
dfui_form_datasets_free(f);
dfui_form_dataset_add(f, new_ds);
username = dfui_dataset_get_value(new_ds, "username");
home = dfui_dataset_get_value(new_ds, "home");
gecos = dfui_dataset_get_value(new_ds, "gecos");
shell = dfui_dataset_get_value(new_ds, "shell");
passwd_1 = dfui_dataset_get_value(new_ds, "passwd_1");
passwd_2 = dfui_dataset_get_value(new_ds, "passwd_2");
uid = dfui_dataset_get_value(new_ds, "uid");
group = dfui_dataset_get_value(new_ds, "group");
groups = dfui_dataset_get_value(new_ds, "groups");
if (strlen(username) == 0) {
inform(a->c, _("You must enter a username."));
done = 0;
} else if (strcmp(passwd_1, passwd_2) != 0) {
inform(a->c, _("The passwords do not match."));
done = 0;
} else if (!assert_clean(a->c, _("Username"), username, USERNAME_NOT_ALLOWED) ||
!assert_clean(a->c, _("Real Name"), gecos, GECOS_NOT_ALLOWED) ||
!assert_clean(a->c, _("Shell"), shell, FILENAME_NOT_ALLOWED) ||
!assert_clean(a->c, _("Home Directory"), home, FILENAME_NOT_ALLOWED) ||
!assert_clean(a->c, _("User ID"), uid, USERNAME_NOT_ALLOWED) ||
!assert_clean(a->c, _("Login Group"), group, USERNAME_NOT_ALLOWED) ||
!assert_clean(a->c, _("Group Memberships"), groups, MEMBERSHIPS_NOT_ALLOWED)) {
done = 0;
} else if (setenv(passwd_env, passwd_1, 1) != 0) {
inform(a->c, _("setenv() failed."));
done = 0;
} else if (!is_program("%s%s", a->os_root, shell) &&
strcmp(shell, "/nonexistent") != 0) {
inform(a->c, _("Chosen shell does not exist on the system."));
done = 0;
} else {
cmds = commands_new();
command_add(cmds, "%s%s %smnt/ /%s useradd "
"'%s' %s%s %s%s -c \"%s\" %s%s -s %s %s%s %s",
a->os_root, cmd_name(a, "CHROOT"),
a->os_root, cmd_name(a, "PW"),
username,
strlen(uid) == 0 ? "" : "-u ", uid,
strlen(group) == 0 ? "" : "-g ", group,
gecos,
strlen(home) == 0 ? "" : "-d ", home,
shell,
strlen(groups) == 0 ? "" : "-G ", groups,
(strlen(home) == 0 || !is_dir("%s", home)) ?
"-m -k /usr/share/skel" : "");
cmd = command_add(cmds, "%s%s \"$%s\" | "
"%s%s %smnt/ /%s usermod '%s' -h 0",
a->os_root, cmd_name(a, "ECHO"),
passwd_env,
a->os_root, cmd_name(a, "CHROOT"),
a->os_root, cmd_name(a, "PW"),
username);
command_set_desc(cmd, _("Setting password..."));
if (commands_execute(a, cmds)) {
inform(a->c, _("User `%s' was added."), username);
done = 1;
} else {
inform(a->c, _("User was not successfully added."));
done = 0;
}
unsetenv(passwd_env);
commands_free(cmds);
}
dfui_response_free(r);
}
dfui_form_free(f);
}
void
fn_root_passwd(struct i_fn_args *a)
{
struct dfui_dataset *ds, *new_ds;
struct dfui_form *f;
struct dfui_response *r;
struct commands *cmds;
struct command *cmd;
const char *root_passwd_1, *root_passwd_2;
const char *passwd_env = "passwd";
int done = 0;
f = dfui_form_create(
"root_passwd",
_("Set Root Password"),
_("Here you can set the super-user (root) password."),
"",
"f", "root_passwd_1", _("Root password"),
_("Enter the root password you would like to use"), "",
"p", "obscured", "true",
"f", "root_passwd_2", _("Root password again"),
_("Enter the root password again to confirm"), "",
"p", "obscured", "true",
"a", "ok", _("Accept and Set Password"), "", "",
"a", "cancel", _("Return to Configure Menu"), "", "",
"p", "accelerator", "ESC",
NULL
);
ds = dfui_dataset_new();
dfui_dataset_celldata_add(ds, "root_passwd_1", "");
dfui_dataset_celldata_add(ds, "root_passwd_2", "");
dfui_form_dataset_add(f, ds);
while (!done) {
if (!dfui_be_present(a->c, f, &r))
abort_backend();
if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
done = 1;
dfui_response_free(r);
break;
}
new_ds = dfui_dataset_dup(dfui_response_dataset_get_first(r));
dfui_form_datasets_free(f);
dfui_form_dataset_add(f, new_ds);
root_passwd_1 = dfui_dataset_get_value(new_ds, "root_passwd_1");
root_passwd_2 = dfui_dataset_get_value(new_ds, "root_passwd_2");
if (strlen(root_passwd_1) == 0) {
inform(a->c, _("You must enter a password."));
done = 0;
} else if (strcmp(root_passwd_1, root_passwd_2) != 0) {
inform(a->c, _("The passwords do not match."));
done = 0;
} else if (setenv(passwd_env, root_passwd_1, 1) != 0) {
inform(a->c, _("setenv() failed."));
done = 0;
} else {
cmds = commands_new();
cmd = command_add(cmds, "%s%s \"$%s\" | "
"%s%s %smnt/ /%s usermod root -h 0",
a->os_root, cmd_name(a, "ECHO"),
passwd_env,
a->os_root, cmd_name(a, "CHROOT"),
a->os_root, cmd_name(a, "PW"));
command_set_desc(cmd, _("Setting password..."));
if (commands_execute(a, cmds)) {
inform(a->c, _("The root password has been changed."));
done = 1;
} else {
inform(a->c, _("An error occurred when "
"setting the root password."));
done = 0;
}
unsetenv(passwd_env);
commands_free(cmds);
}
dfui_response_free(r);
}
dfui_form_free(f);
}
void
fn_get_passphrase(struct i_fn_args *a, int confirm)
{
struct dfui_dataset *ds, *new_ds;
struct dfui_form *f;
struct dfui_response *r;
const char *passphrase_1, *passphrase_2;
int fd;
int done = 0;
if (confirm) {
f = dfui_form_create(
"crypt_passphrase",
_("Set Passphrase for Encryption"),
_("Please specify the passphrase to be used for the encrypted "
"filesystems.\n\n"
"Please note that in the LiveCD environment the keymap is "
"set to \"US ISO\". "
"If you prefer a different keymap for entering the passphrase "
"here, you will need to set it manually using kbdcontrol(1)."),
"",
"f", "passphrase_1", _("Passphrase"),
_("Enter the passphrase you would like to use for encryption"), "",
"p", "obscured", "true",
"f", "passphrase_2", _("Passphrase again"),
_("Enter the passphrase again to confirm"), "",
"p", "obscured", "true",
"a", "ok", _("Accept and Set Passphrase"), "", "",
"p", "accelerator", "ESC",
NULL
);
} else {
f = dfui_form_create(
"crypt_passphrase",
_("Specify Decryption Passphrase"),
_("Please enter the passphrase to decrypt and mount the "
"filesystems.\n\n"
"Please note that in the LiveCD environment the keymap is "
"set to \"US ISO\". "
"If you prefer a different keymap for entering the passphrase "
"here, you will need to set it manually using kbdcontrol(1)."),
"",
"f", "passphrase_1", _("Passphrase"),
_("Enter the passphrase"), "",
"p", "obscured", "true",
"a", "ok", _("OK"), "", "",
"p", "accelerator", "ESC",
NULL
);
}
ds = dfui_dataset_new();
dfui_dataset_celldata_add(ds, "passphrase_1", "");
if (confirm)
dfui_dataset_celldata_add(ds, "passphrase_2", "");
dfui_form_dataset_add(f, ds);
while (!done) {
if (!dfui_be_present(a->c, f, &r))
abort_backend();
if (strcmp(dfui_response_get_action_id(r), "ok") == 0) {
new_ds = dfui_dataset_dup(dfui_response_dataset_get_first(r));
dfui_form_datasets_free(f);
dfui_form_dataset_add(f, new_ds);
passphrase_1 = dfui_dataset_get_value(new_ds, "passphrase_1");
passphrase_2 = passphrase_1;
if (confirm)
passphrase_2 = dfui_dataset_get_value(new_ds, "passphrase_2");
if (strlen(passphrase_1) == 0 && strlen(passphrase_2) == 0) {
done = 0;
} else if (strcmp(passphrase_1, passphrase_2) == 0) {
fd = open("/tmp/t1", O_RDWR | O_CREAT | O_TRUNC,
S_IRUSR);
if (fd != -1) {
write(fd, passphrase_1, strlen(passphrase_1));
close(fd);
done = 1;
} else {
inform(a->c, _("write() error"));
done = 0;
}
} else {
inform(a->c, _("The passphrases do not match."));
done = 0;
}
}
dfui_response_free(r);
}
dfui_form_free(f);
}
char *
fn_select_file(const char *title, const char *desc, const char *help, const char *cancel,
const char *dir, const char *ext, const struct i_fn_args *a)
{
DIR *d;
struct dfui_form *f;
struct dfui_action *k;
struct dfui_response *r;
struct dirent *de;
char *s;
struct aura_dict *dict;
char *rk;
size_t rk_len;
f = dfui_form_create(
"select_file",
title, desc, help,
"p", "role", "menu",
NULL
);
dict = aura_dict_new(1, AURA_DICT_SORTED_LIST);
d = opendir(dir);
while ((de = readdir(d)) != NULL) {
if (strcmp(de->d_name, ".") == 0 ||
strcmp(de->d_name, "..") == 0 ||
strstr(de->d_name, ext) == NULL)
continue;
aura_dict_store(dict, de->d_name, strlen(de->d_name) + 1, "", 1);
}
closedir(d);
aura_dict_rewind(dict);
while (!aura_dict_eof(dict)) {
aura_dict_get_current_key(dict, (void **)&rk, &rk_len),
dfui_form_action_add(f, rk,
dfui_info_new(rk, "", ""));
aura_dict_next(dict);
}
aura_dict_free(dict);
k = dfui_form_action_add(f, "cancel",
dfui_info_new(cancel, "", ""));
dfui_action_property_set(k, "accelerator", "ESC");
if (!dfui_be_present(a->c, f, &r))
abort_backend();
s = aura_strdup(dfui_response_get_action_id(r));
dfui_form_free(f);
dfui_response_free(r);
return(s);
}
void
fn_set_kbdmap(struct i_fn_args *a)
{
struct commands *cmds;
char *s;
char filename[256], keymapname[256];
s = fn_select_file(_("Select Keyboard Map"),
_("Select a keyboard map appropriate to your keyboard layout."),
"", _("Return to Utilities Menu"), "/usr/share/syscons/keymaps",
".kbd", a);
if (strcmp(s, "cancel") != 0) {
cmds = commands_new();
command_add(cmds, "%s%s -l "
"/usr/share/syscons/keymaps/%s < /dev/ttyv0",
a->os_root, cmd_name(a, "KBDCONTROL"),
s);
if (commands_execute(a, cmds)) {
snprintf(filename, 256, "/usr/share/syscons/keymaps/%s", s);
snprintf(keymapname, 256, "%s", filename_noext(basename(filename)));
config_var_set(rc_conf, "keymap", keymapname);
} else {
inform(a->c, _("Keyboard map not successfully set."));
}
commands_free(cmds);
}
free(s);
}
void
fn_set_vidfont(struct i_fn_args *a)
{
struct commands *cmds;
char *s;
char filename[256], variable[256], fontname[256];
int by = 0;
s = fn_select_file(_("Select Console Font"),
_("Select a font appropriate to your video monitor and language."),
"", _("Return to Utilities Menu"), "/usr/share/syscons/fonts",
".fnt", a);
if (strcmp(s, "cancel") != 0) {
cmds = commands_new();
command_add(cmds, "%s%s -f "
"/usr/share/syscons/fonts/%s < /dev/ttyv0",
a->os_root, cmd_name(a, "VIDCONTROL"),
s);
if (commands_execute(a, cmds)) {
if (strstr(s, "8x16") != NULL)
by = 16;
else if (strstr(s, "8x14") != NULL)
by = 14;
else
by = 8;
snprintf(variable, 256, "font8x%d", by);
snprintf(filename, 256, "/usr/share/syscons/fonts/%s", s);
snprintf(fontname, 256, "%s", filename_noext(basename(filename)));
config_var_set(rc_conf, variable, fontname);
} else {
inform(a->c, _("Video font not successfully set."));
}
commands_free(cmds);
}
free(s);
}
void
fn_set_scrnmap(struct i_fn_args *a)
{
struct commands *cmds;
char *s;
char filename[256], scrnmapname[256];
s = fn_select_file(_("Select Screen Map"),
_("Select a mapping for translating characters as they appear "
"on your video console screen."),
"", _("Return to Utilities Menu"), "/usr/share/syscons/scrnmaps",
".scm", a);
if (strcmp(s, "cancel") != 0) {
cmds = commands_new();
command_add(cmds, "%s%s -l "
"/usr/share/syscons/scrnmaps/%s < /dev/ttyv0",
a->os_root, cmd_name(a, "VIDCONTROL"),
s);
if (commands_execute(a, cmds)) {
snprintf(filename, 256, "/usr/share/syscons/scrnmaps/%s", s);
snprintf(scrnmapname, 256, "%s", filename_noext(basename(filename)));
config_var_set(rc_conf, "scrnmap", scrnmapname);
} else {
inform(a->c, _("Video font not successfully set."));
}
commands_free(cmds);
}
free(s);
}
void
fn_set_timezone(struct i_fn_args *a)
{
struct commands *cmds;
char *s = NULL;
char current_path[256], selection[256], temp[256];
int found_file = 0;
int result;
result = dfui_be_present_dialog(a->c, _("Local or UTC (Greenwich Mean Time) clock"),
_("Yes|No"),
_("Is this machine's CMOS clock set to UTC?\n\n"
"If it is set to local time, or you don't know, please choose NO here!"));
if (result < 1)
abort_backend();
cmds = commands_new();
switch (result) {
case 1:
command_add(cmds, "%s%s -f %s%setc/wall_cmos_clock",
a->os_root, cmd_name(a, "RM"),
a->os_root, a->cfg_root);
break;
case 2:
command_add(cmds, "%s%s %s%setc/wall_cmos_clock",
a->os_root, cmd_name(a, "TOUCH"),
a->os_root, a->cfg_root);
break;
}
commands_execute(a, cmds);
snprintf(current_path, 256, "%s%susr/share/zoneinfo",
a->os_root, a->cfg_root);
while (!found_file) {
if (s != NULL)
free(s);
s = fn_select_file(_("Select Time Zone"),
_("Select a Time Zone appropriate to your physical location."),
"", _("Return to Utilities Menu"), current_path,
"", a);
if (is_dir("%s/%s", current_path, s)) {
snprintf(temp, 256, "%s/%s", current_path, s);
strlcpy(current_path, temp, 256);
} else {
if (is_file("%s/%s", current_path, s)) {
snprintf(selection, 256, "%s/%s", current_path, s);
found_file = 1;
}
if (strcmp(s, "cancel") == 0) {
strlcpy(selection, "cancel", 256);
found_file = 1;
}
}
}
free(s);
if (strcmp(selection, "cancel") != 0) {
command_add(cmds, "%s%s %s %s%setc/localtime",
a->os_root, cmd_name(a, "CP"),
selection,
a->os_root, a->cfg_root);
if (commands_execute(a, cmds)) {
inform(a->c, _("The Time Zone has been set to %s."), selection);
setenv("TZ", selection, 1);
tzset();
}
}
commands_free(cmds);
}
void
fn_assign_datetime(struct i_fn_args *a)
{
struct commands *cmds;
struct dfui_dataset *ds, *new_ds;
struct dfui_form *f;
struct dfui_response *r;
struct tm *tp;
char temp[256];
int year, month, dayofmonth, hour, minutes;
int valid = 1;
time_t now;
now = time(NULL);
tp = localtime(&now);
f = dfui_form_create(
"set_datetime",
_("Set Time/Date"),
_("Enter the date-time in your timezone."),
"",
"f", "year", _("Enter year"),
_("Enter the current year (e.g. `2004')"), "",
"f", "month", _("Month"),
_("Enter the current month (e.g. `07')"), "",
"f", "dayofmonth", "dayofmonth",
_("Enter the current day of month (e.g. `30')"), "",
"f", "hour", "hour",
_("Enter the current hour (e.g. `07')"), "",
"f", "minutes", "minutes",
_("Enter the current minutes (e.g. `59')"), "",
"a", "ok", _("OK"), "", "",
"a", "cancel", _("Cancel"), "", "",
"p", "accelerator", "ESC",
NULL
);
ds = dfui_dataset_new();
snprintf(temp, 256, "%i", (tp->tm_year+1900));
dfui_dataset_celldata_add(ds, "year", temp);
snprintf(temp, 256, "%i", (tp->tm_mon+1));
dfui_dataset_celldata_add(ds, "month", temp);
snprintf(temp, 256, "%i", tp->tm_mday);
dfui_dataset_celldata_add(ds, "dayofmonth", temp);
snprintf(temp, 256, "%i", tp->tm_hour);
dfui_dataset_celldata_add(ds, "hour", temp);
snprintf(temp, 256, "%i", tp->tm_min);
dfui_dataset_celldata_add(ds, "minutes", temp);
dfui_form_dataset_add(f, ds);
if (!dfui_be_present(a->c, f, &r))
abort_backend();
if (strcmp(dfui_response_get_action_id(r), "ok") == 0) {
new_ds = dfui_response_dataset_get_first(r);
if ((year = atoi(dfui_dataset_get_value(new_ds, "year"))) <= 0)
valid = 0;
month = atoi(dfui_dataset_get_value(new_ds, "month"));
if (month < 1 || month > 12)
valid = 0;
dayofmonth = atoi(dfui_dataset_get_value(new_ds, "dayofmonth"));
if (dayofmonth < 1 || dayofmonth > 31)
valid = 0;
hour = atoi(dfui_dataset_get_value(new_ds, "hour"));
if (hour < 0 || hour > 23)
valid = 0;
minutes = atoi(dfui_dataset_get_value(new_ds, "minutes"));
if (minutes < 0 || minutes > 59)
valid = 0;
if (valid) {
cmds = commands_new();
command_add(cmds, "%s%s -n %04d%02d%02d%02d%02d",
a->os_root, cmd_name(a, "DATE"),
year, month, dayofmonth, hour, minutes);
if (commands_execute(a, cmds)) {
inform(a->c, _("The date and time have been set."));
}
commands_free(cmds);
} else {
inform(a->c, _("Please enter numbers within acceptable ranges "
"for year, month, day of month, hour, and minute."));
}
}
}
static void
strip_domain(char *hostname, const char *domain)
{
size_t hlen, dlen;
if (domain == NULL || domain[0] == '\0')
return;
hlen = strlen(hostname);
dlen = strlen(domain);
if (hlen > dlen + 1 &&
hostname[hlen - dlen - 1] == '.' &&
strcmp(hostname + hlen - dlen, domain) == 0) {
hostname[hlen - dlen - 1] = '\0';
}
}
void
fn_assign_hostname_domain(struct i_fn_args *a)
{
struct dfui_form *f;
struct dfui_response *r;
struct dfui_dataset *ds, *new_ds;
const char *domain, *hostname;
char *fqdn, buf[MAXHOSTNAMELEN];
domain = config_var_get(resolv_conf, "search");
snprintf(buf, sizeof(buf), "%s", config_var_get(rc_conf, "hostname"));
strip_domain(buf, domain);
hostname = buf;
f = dfui_form_create(
"set_hostname_domain",
_("Set Hostname/Domain"),
_("Please enter this machine's hostname and domain name."),
"",
"f", "hostname", _("Hostname"),
_("Enter the Hostname (e.g. `machine')"), "",
"f", "domain", _("Domain"),
_("Enter the Domain Name (e.g. `network.lan')"), "",
"a", "ok", _("OK"), "", "",
"a", "cancel", _("Cancel"), "", "",
"p", "accelerator", "ESC",
NULL
);
ds = dfui_dataset_new();
dfui_dataset_celldata_add(ds, "hostname", hostname);
dfui_dataset_celldata_add(ds, "domain", domain);
dfui_form_dataset_add(f, ds);
if (!dfui_be_present(a->c, f, &r))
abort_backend();
if (strcmp(dfui_response_get_action_id(r), "ok") == 0) {
new_ds = dfui_response_dataset_get_first(r);
hostname = dfui_dataset_get_value(new_ds, "hostname");
domain = dfui_dataset_get_value(new_ds, "domain");
if (strlen(domain) == 0)
asprintf(&fqdn, "%s", hostname);
else
asprintf(&fqdn, "%s.%s", hostname, domain);
config_var_set(rc_conf, "hostname", fqdn);
free(fqdn);
config_var_set(resolv_conf, "search", domain);
}
dfui_form_free(f);
dfui_response_free(r);
}
static int
set_interface_router(char *router, size_t len, const char *ip, const char *netmask)
{
struct in_addr in_ip, in_netmask, in_gw;
memset(router, 0, len);
if (ip == NULL || strlen(ip) == 0)
return(0);
if (netmask == NULL || strlen(netmask) == 0)
return(0);
if (inet_pton(AF_INET, ip, &in_ip) != 1)
return(-1);
if (inet_pton(AF_INET, netmask, &in_netmask) != 1)
return(-1);
in_gw.s_addr = ntohl(in_ip.s_addr) & ntohl(in_netmask.s_addr);
in_gw.s_addr = htonl(in_gw.s_addr + 1);
inet_ntop(AF_INET, &in_gw, router, len);
return(0);
}
static int
cb_field_interface_ip(struct dfui_form *form, struct dfui_field *field __unused,
const char *new_value, void *userdata __unused)
{
struct dfui_dataset *ds;
const char *netmask;
char router[INET_ADDRSTRLEN];
if (new_value == NULL || strlen(new_value) == 0)
return(0);
ds = dfui_form_dataset_get_first(form);
netmask = dfui_dataset_get_value(ds, "interface_netmask");
if (set_interface_router(router, sizeof(router), new_value, netmask) != 0)
return(-1);
dfui_dataset_set_value(ds, "defaultrouter", router);
return(0);
}
static int
cb_field_interface_netmask(struct dfui_form *form,
struct dfui_field *field __unused,
const char *new_value, void *userdata __unused)
{
struct dfui_dataset *ds;
const char *ip;
char router[INET_ADDRSTRLEN];
if (new_value == NULL || strlen(new_value) == 0)
return(0);
ds = dfui_form_dataset_get_first(form);
ip = dfui_dataset_get_value(ds, "interface_ip");
if (set_interface_router(router, sizeof(router), ip, new_value) != 0)
return(-1);
dfui_dataset_set_value(ds, "defaultrouter", router);
return(0);
}
void
fn_assign_ip(struct i_fn_args *a)
{
FILE *p;
struct commands *cmds;
struct command *cmd;
struct dfui_dataset *ds, *new_ds;
struct dfui_form *f;
struct dfui_field *fi;
struct dfui_action *k;
struct dfui_response *r;
const char *domain, *hostname;
const char *interface_ip, *interface_netmask, *defaultrouter, *dns_resolver;
char *string, *string1;
char *word;
char interface[256];
char line[256], buf[MAXHOSTNAMELEN];
int write_config;
p = popen("/sbin/ifconfig -l", "r");
while (fgets(line, 255, p) != NULL)
line[strlen(line) - 1] = '\0';
pclose(p);
f = dfui_form_create(
"assign_ip",
_("Assign IP Address"),
_("Please select which interface you would like to configure:"),
"",
"p", "role", "menu",
NULL
);
word = strtok(line, " \t");
while (word != NULL) {
dfui_form_action_add(f, word,
dfui_info_new(word, "", ""));
word = strtok(NULL, " ");
}
k = dfui_form_action_add(f, "cancel",
dfui_info_new("Cancel", "", ""));
dfui_action_property_set(k, "accelerator", "ESC");
if (!dfui_be_present(a->c, f, &r))
abort_backend();
if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
dfui_form_free(f);
dfui_response_free(r);
return;
}
strlcpy(interface, dfui_response_get_action_id(r), 256);
domain = config_var_get(resolv_conf, "search");
snprintf(buf, sizeof(buf), "%s", config_var_get(rc_conf, "hostname"));
strip_domain(buf, domain);
hostname = buf;
switch (dfui_be_present_dialog(a->c, _("Use DHCP?"),
_("Use DHCP|Configure Manually"),
_("DHCP allows the interface to automatically obtain "
"an IP address from a nearby DHCP server.\n\n"
"Would you like to enable DHCP for %s?"), interface)) {
case 1:
write_config = 0;
cmds = commands_new();
cmd = command_add(cmds, "%s%s dhclient",
a->os_root, cmd_name(a, "KILLALL"));
command_set_failure_mode(cmd, COMMAND_FAILURE_IGNORE);
command_add(cmds, "%s%s %s",
a->os_root, cmd_name(a, "DHCLIENT"),
interface);
if (commands_execute(a, cmds)) {
show_ifconfig(a->c, interface);
write_config = 1;
} else {
switch (dfui_be_present_dialog(a->c, _("DHCP Failure"),
_("Yes|No"),
_("Warning: could not enable dhclient for %s.\n\n"
"Write the corresponding settings to rc.conf "
"anyway?"), interface)) {
case 1:
write_config = 1;
break;
case 2:
write_config = 0;
break;
default:
abort_backend();
}
}
commands_free(cmds);
if (write_config) {
asprintf(&string, "ifconfig_%s", interface);
config_var_set(rc_conf, string, "DHCP");
free(string);
}
break;
case 2:
dfui_form_free(f);
dfui_response_free(r);
f = dfui_form_create(
"assign_ip",
_("Assign IP Address"),
_("Configuring Interface:"),
"",
"f", "interface_ip", _("IP Address"),
_("Enter the IP Address you would like to use"), "",
"f", "interface_netmask", _("Netmask"),
_("Enter the netmask of the IP address"), "",
"f", "defaultrouter", _("Default Router"),
_("Enter the IP address of the default router"), "",
"f", "dns_resolver", _("Primary DNS Server"),
_("Enter the IP address of primary DNS Server"), "",
"f", "hostname", _("Hostname"),
_("Enter the Hostname"), "",
"f", "domain", _("Domain"),
_("Enter the Domain Name"), "",
"a", "ok", _("Configure Interface"),
"", "",
"a", "cancel", _("Return to Utilities Menu"),
"", "",
"p", "accelerator", "ESC",
NULL
);
ds = dfui_dataset_new();
dfui_dataset_celldata_add(ds, "interface_ip", "");
dfui_dataset_celldata_add(ds, "interface_netmask",
"255.255.255.0");
dfui_dataset_celldata_add(ds, "defaultrouter", "");
dfui_dataset_celldata_add(ds, "dns_resolver",
config_var_get(resolv_conf, "nameserver"));
dfui_dataset_celldata_add(ds, "hostname", hostname);
dfui_dataset_celldata_add(ds, "domain", domain);
dfui_form_dataset_add(f, ds);
fi = dfui_form_field_find(f, "interface_ip");
dfui_field_set_callback(fi, cb_field_interface_ip, NULL);
fi = dfui_form_field_find(f, "interface_netmask");
dfui_field_set_callback(fi, cb_field_interface_netmask, NULL);
if (!dfui_be_present(a->c, f, &r))
abort_backend();
if (strcmp(dfui_response_get_action_id(r), "cancel") == 0)
break;
new_ds = dfui_response_dataset_get_first(r);
interface_ip = dfui_dataset_get_value(
new_ds, "interface_ip");
interface_netmask = dfui_dataset_get_value(
new_ds, "interface_netmask");
defaultrouter = dfui_dataset_get_value(
new_ds, "defaultrouter");
dns_resolver = dfui_dataset_get_value(
new_ds, "dns_resolver");
hostname = dfui_dataset_get_value(
new_ds, "hostname");
domain = dfui_dataset_get_value(
new_ds, "domain");
cmds = commands_new();
command_add(cmds, "%s%s %s %s netmask %s",
a->os_root, cmd_name(a, "IFCONFIG"),
interface, interface_ip, interface_netmask);
command_add(cmds, "%s%s add default %s",
a->os_root, cmd_name(a, "ROUTE"),
defaultrouter);
write_config = 0;
if (commands_execute(a, cmds)) {
show_ifconfig(a->c, interface);
write_config = 1;
} else {
switch (dfui_be_present_dialog(a->c,
_("ifconfig Failure"),
_("Yes|No"),
_("Warning: could not assign IP address "
"or default gateway.\n\n"
"Write the corresponding settings to "
"rc.conf anyway?"))) {
case 1:
write_config = 1;
break;
case 2:
write_config = 0;
break;
default:
abort_backend();
}
}
commands_free(cmds);
if (write_config) {
asprintf(&string, "ifconfig_%s", interface);
asprintf(&string1, "inet %s netmask %s",
interface_ip, interface_netmask);
config_var_set(rc_conf, string, string1);
free(string);
free(string1);
config_var_set(rc_conf, "defaultrouter", defaultrouter);
if (strlen(domain) == 0)
asprintf(&string, "%s", hostname);
else
asprintf(&string, "%s.%s", hostname, domain);
config_var_set(rc_conf, "hostname", string);
free(string);
config_var_set(resolv_conf, "search", domain);
config_var_set(resolv_conf, "nameserver", dns_resolver);
}
break;
default:
abort_backend();
}
dfui_form_free(f);
dfui_response_free(r);
}
int
mount_target_system(struct i_fn_args *a)
{
FILE *crypttab, *fstab;
struct commands *cmds;
struct command *cmd;
struct subpartition *a_subpart;
struct subpartition *d_subpart;
char name[256], device[256];
char *filename, line[256];
char *word;
cmds = commands_new();
unmount_all_under(a, cmds, "%smnt", a->os_root);
subpartitions_free(storage_get_selected_slice(a->s));
a_subpart = subpartition_new_ufs(storage_get_selected_slice(a->s),
"/dummy", 0, 0, 0, 0, 0, 0);
subpartition_new_ufs(storage_get_selected_slice(a->s),
"swap", 0, 0, 0, 0, 0, 0);
d_subpart = subpartition_new_ufs(storage_get_selected_slice(a->s),
"/dummy", 0, 0, 0, 0, 0, 0);
{
command_add(cmds, "%s%s /dev/%s %sboot",
a->os_root, cmd_name(a, "MOUNT"),
subpartition_get_device_name(a_subpart),
a->os_root);
cmd = command_add(cmds,
"%s%s -f %st2;"
"%s%s \"^vfs\\.root\\.realroot=\" %sboot/loader.conf >%st2",
a->os_root, cmd_name(a, "RM"), a->tmp,
a->os_root, cmd_name(a, "GREP"),
a->os_root, a->tmp);
command_set_failure_mode(cmd, COMMAND_FAILURE_IGNORE);
}
if (!commands_execute(a, cmds)) {
commands_free(cmds);
return(0);
}
commands_free(cmds);
cmds = commands_new();
{
struct stat sb = { .st_size = 0 };
const char *fsname;
const char *mountid;
switch (use_hammer) {
case 1:
fsname = "hammer";
mountid = "MOUNT_HAMMER";
break;
case 2:
fsname = "hammer2";
mountid = "MOUNT_HAMMER2";
break;
case 0:
default:
fsname = "ufs";
mountid = "MOUNT";
break;
}
stat("/tmp/t2", &sb);
if (sb.st_size > 0) {
command_add(cmds, "%s%s %sboot",
a->os_root, cmd_name(a, "UMOUNT"),
a->os_root);
fn_get_passphrase(a, 0);
command_add(cmds,
"%s%s -d /tmp/t1 luksOpen /dev/`%s%s \"^vfs\\.root\\.realroot=\" %st2 |"
"%s%s -F%s: '{print $2;}' |"
"%s%s -F: '{print $1;}'` %s",
a->os_root, cmd_name(a, "CRYPTSETUP"),
a->os_root, cmd_name(a, "GREP"),
a->tmp,
a->os_root, cmd_name(a, "AWK"),
fsname,
a->os_root, cmd_name(a, "AWK"),
subpartition_get_mapper_name(d_subpart, -1));
command_add(cmds,
"%s%s %s %s%s",
a->os_root,
cmd_name(a, mountid),
subpartition_get_mapper_name(d_subpart, 1),
a->os_root, a->cfg_root);
} else {
command_add(cmds,
"%s%s /dev/`%s%s \"^vfs\\.root\\.mountfrom\" %sboot/loader.conf |"
"%s%s -F%s: '{print $2;}' |"
"%s%s 's/\"//'` %s%s",
a->os_root,
cmd_name(a, mountid),
a->os_root, cmd_name(a, "GREP"),
a->os_root,
a->os_root, cmd_name(a, "AWK"),
fsname,
a->os_root, cmd_name(a, "SED"),
a->os_root, a->cfg_root);
command_add(cmds, "%s%s %sboot",
a->os_root, cmd_name(a, "UMOUNT"),
a->os_root);
}
}
if (!commands_execute(a, cmds)) {
commands_free(cmds);
unlink("/tmp/t1");
return(0);
}
commands_free(cmds);
cmds = commands_new();
subpartitions_free(storage_get_selected_slice(a->s));
asprintf(&filename, "%s%s/etc/crypttab", a->os_root, a->cfg_root);
crypttab = fopen(filename, "r");
free(filename);
if (crypttab != NULL) {
while (fgets(line, 256, crypttab) != NULL) {
if (first_non_space_char_is(line, '#'))
continue;
if ((word = strtok(line, " \t")) == NULL)
continue;
strlcpy(name, word, 256);
if (strcmp(name, "swap") == 0)
continue;
if (strcmp(name, subpartition_get_mapper_name(d_subpart, -1)) == 0)
continue;
if ((word = strtok(NULL, " \t")) == NULL)
continue;
strlcpy(device, word, 256);
command_add(cmds,
"%s%s -d /tmp/t1 luksOpen %s %s",
a->os_root, cmd_name(a, "CRYPTSETUP"),
device, name);
continue;
}
fclose(crypttab);
}
if (!commands_execute(a, cmds)) {
commands_free(cmds);
unlink("/tmp/t1");
return(0);
}
commands_free(cmds);
unlink("/tmp/t1");
asprintf(&filename, "%s%s/etc/fstab", a->os_root, a->cfg_root);
fstab = fopen(filename, "r");
free(filename);
if (fstab == NULL) {
inform(a->c, _("Filesystem table on installed system could not be read."));
cmds = commands_new();
command_add(cmds, "%s%s %s%s",
a->os_root, cmd_name(a, "UMOUNT"),
a->os_root, a->cfg_root);
if (!commands_execute(a, cmds)) {
inform(a->c, _("Warning: Installed system was not properly unmounted."));
}
commands_free(cmds);
return(0);
}
fclose(fstab);
return 1;
}