int get_via_ftp(const char *xfer_type) { if (do_config_network() != 0) return SET_RETRY; process_menu(MENU_ftpsource, deconst(xfer_type)); /* We'll fetch each file just before installing it */ fetch_fn = ftp_fetch; ftp.xfer_type = xfer_type; snprintf(ext_dir_bin, sizeof ext_dir_bin, "%s/%s", target_prefix(), xfer_dir + (*xfer_dir == '/')); snprintf(ext_dir_src, sizeof ext_dir_src, "%s/%s", target_prefix(), xfer_dir + (*xfer_dir == '/')); return SET_OK; }
int get_via_ftp(const char *xfer_type) { arg_rv arg; arg.rv = -1; arg.arg = deconst(xfer_type); process_menu(MENU_ftpsource, &arg); if (arg.rv == SET_RETRY) return SET_RETRY; /* We'll fetch each file just before installing it */ fetch_fn = ftp_fetch; ftp.xfer_type = xfer_type; snprintf(ext_dir_bin, sizeof ext_dir_bin, "%s/%s", target_prefix(), xfer_dir + (*xfer_dir == '/')); snprintf(ext_dir_src, sizeof ext_dir_src, "%s/%s", target_prefix(), xfer_dir + (*xfer_dir == '/')); return SET_OK; }
static int check_root_password(void) { char *buf; int rval; if (target_already_root()) collect(T_OUTPUT, &buf, "getent passwd root | cut -d: -f2"); else collect(T_OUTPUT, &buf, "chroot %s getent passwd root | " "chroot %s cut -d: -f2", target_prefix(), target_prefix()); if (logfp) fprintf(logfp,"buf %s strlen(buf) %zu\n", buf, strlen(buf)); if (strlen(buf) <= 1) /* newline */ rval = 0; else rval = 1; free(buf); return rval; }
int get_pkgsrc(void) { int rv = -1; process_menu(MENU_pkgsrc, &rv); if (rv == SET_SKIP) return SET_SKIP; fetch_fn = pkgsrc_fetch; snprintf(ext_dir_pkgsrc, sizeof ext_dir_pkgsrc, "%s/%s", target_prefix(), xfer_dir + (*xfer_dir == '/')); return SET_OK; }
int get_pkgsrc(void) { if (!network_up) if (do_config_network() != 0) return SET_RETRY; yesno = 1; process_menu(MENU_pkgsrc, NULL); if (yesno == 0) return SET_SKIP; fetch_fn = pkgsrc_fetch; snprintf(ext_dir_pkgsrc, sizeof ext_dir_pkgsrc, "%s/%s", target_prefix(), xfer_dir + (*xfer_dir == '/')); return SET_OK; }
static void get_rootsh(void) { static char *buf = NULL; if (buf != NULL) free(buf); if (target_already_root()) collect(T_OUTPUT, &buf, "/usr/bin/awk -F: '$1==\"root\" { print $NF; exit }'" " /etc/passwd"); else collect(T_OUTPUT, &buf, "chroot %s /usr/bin/awk -F: '$1==\"root\" { print $NF; exit }'" " /etc/passwd",target_prefix()); config_list[CONFIGOPT_ROOTSH].setting = (const char *)buf; }
/* * Write the network config info the user entered via menus into the * config files in the target disk. Be careful not to lose any * information we don't immediately add back, in case the install * target is the currently-active root. */ void mnt_net_config(void) { char ifconfig_fn[STRSIZE]; char ifconfig_str[STRSIZE]; FILE *ifconf = NULL; if (!network_up) return; process_menu(MENU_yesno, deconst(MSG_mntnetconfig)); if (!yesno) return; /* Write hostname to /etc/rc.conf */ if ((net_dhcpconf & DHCPCONF_HOST) == 0) if (del_rc_conf("hostname") == 0) add_rc_conf("hostname=%s\n", recombine_host_domain()); /* Copy resolv.conf to target. If DHCP was used to create it, * it will be replaced on next boot anyway. */ #ifndef INET6 if (net_namesvr[0] != '\0') dup_file_into_target("/etc/resolv.conf"); #else /* * not sure if it is a good idea, to allow dhcp config to * override IPv6 configuration */ if (net_namesvr[0] != '\0' || net_namesvr6[0] != '\0') dup_file_into_target("/etc/resolv.conf"); #endif /* * bring the interface up, it will be necessary for IPv6, and * it won't make trouble with IPv4 case either */ snprintf(ifconfig_fn, sizeof ifconfig_fn, "/etc/ifconfig.%s", net_dev); ifconf = target_fopen(ifconfig_fn, "w"); if (ifconf != NULL) { scripting_fprintf(NULL, "cat <<EOF >>%s%s\n", target_prefix(), ifconfig_fn); scripting_fprintf(ifconf, "up\n"); if (*net_media != '\0') scripting_fprintf(ifconf, "media %s\n", net_media); scripting_fprintf(NULL, "EOF\n"); } if ((net_dhcpconf & DHCPCONF_IPADDR) == 0) { FILE *hosts; /* Write IPaddr and netmask to /etc/ifconfig.if[0-9] */ if (ifconf != NULL) { scripting_fprintf(NULL, "cat <<EOF >>%s%s\n", target_prefix(), ifconfig_fn); if (*net_media != '\0') scripting_fprintf(ifconf, "%s netmask %s media %s\n", net_ip, net_mask, net_media); else scripting_fprintf(ifconf, "%s netmask %s\n", net_ip, net_mask); scripting_fprintf(NULL, "EOF\n"); } /* * Add IPaddr/hostname to /etc/hosts. * Be careful not to clobber any existing contents. * Relies on ordered search of /etc/hosts. XXX YP? */ hosts = target_fopen("/etc/hosts", "a"); if (hosts != 0) { scripting_fprintf(NULL, "cat <<EOF >>%s/etc/hosts\n", target_prefix()); write_etc_hosts(hosts); (void)fclose(hosts); scripting_fprintf(NULL, "EOF\n"); fclose(hosts); } if (del_rc_conf("defaultroute") == 0) add_rc_conf("defaultroute=\"%s\"\n", net_defroute); } else { if (snprintf(ifconfig_str, sizeof ifconfig_str, "ifconfig_%s", net_dev) > 0 && del_rc_conf(ifconfig_str) == 0) { add_rc_conf("ifconfig_%s=dhcp\n", net_dev); } } #ifdef INET6 if ((net_ip6conf & IP6CONF_AUTOHOST) != 0) { if (del_rc_conf("ip6mode") == 0) add_rc_conf("ip6mode=autohost\n"); if (ifconf != NULL) { scripting_fprintf(NULL, "cat <<EOF >>%s%s\n", target_prefix(), ifconfig_fn); scripting_fprintf(ifconf, "!rtsol $int\n"); scripting_fprintf(NULL, "EOF\n"); } } #endif if (ifconf) fclose(ifconf); fflush(NULL); }
/* * launch a program inside a subwindow, and report its return status when done */ static int launch_subwin(WINDOW **actionwin, char **args, struct winsize *win, int flags, const char *scmd, const char **errstr) { int n, i; int selectfailed; int status, master, slave; fd_set active_fd_set, read_fd_set; pid_t child, pid; char ibuf[MAXBUF]; char pktdata; char *cp, *ncp; struct termios rtt, tt; struct timeval tmo; static int do_tioccons = 2; (void)tcgetattr(STDIN_FILENO, &tt); if (openpty(&master, &slave, NULL, &tt, win) == -1) { *errstr = "openpty() failed"; return -1; } rtt = tt; /* ignore tty signals until we're done with subprocess setup */ ttysig_ignore = 1; ioctl(master, TIOCPKT, &ttysig_ignore); /* Try to get console output into our pipe */ if (do_tioccons) { if (ioctl(slave, TIOCCONS, &do_tioccons) == 0 && do_tioccons == 2) { /* test our output - we don't want it grabbed */ write(1, " \b", 2); ioctl(master, FIONREAD, &do_tioccons); if (do_tioccons != 0) { do_tioccons = 0; ioctl(slave, TIOCCONS, &do_tioccons); } else do_tioccons = 1; } } if (logfp) fflush(logfp); if (script) fflush(script); child = fork(); switch (child) { case -1: ttysig_ignore = 0; refresh(); *errstr = "fork() failed"; return -1; case 0: /* child */ (void)close(STDIN_FILENO); /* silently stop curses */ (void)close(STDOUT_FILENO); (void)open("/dev/null", O_RDWR, 0); dup2(STDIN_FILENO, STDOUT_FILENO); endwin(); (void)close(master); rtt = tt; rtt.c_lflag |= (ICANON|ECHO); (void)tcsetattr(slave, TCSANOW, &rtt); login_tty(slave); if (logfp) { fprintf(logfp, "executing: %s\n", scmd); fclose(logfp); logfp = NULL; } if (script) { fprintf(script, "%s\n", scmd); fclose(script); script = NULL; } if (strcmp(args[0], "cd") == 0 && strcmp(args[2], "&&") == 0) { target_chdir_or_die(args[1]); args += 3; } if (flags & RUN_XFER_DIR) target_chdir_or_die(xfer_dir); /* * If target_prefix == "", the chroot will fail, but * that's ok, since we don't need it then. */ if (flags & RUN_CHROOT && *target_prefix() && chroot(target_prefix()) != 0) warn("chroot(%s) for %s", target_prefix(), *args); else { execvp(*args, args); warn("execvp %s", *args); } _exit(EXIT_FAILURE); // break; /* end of child */ default: /* * parent: we've set up the subprocess. * forward tty signals to its process group. */ ttysig_forward = child; ttysig_ignore = 0; break; } /* * Now loop transferring program output to screen, and keyboard * input to the program. */ FD_ZERO(&active_fd_set); FD_SET(master, &active_fd_set); FD_SET(STDIN_FILENO, &active_fd_set); for (selectfailed = 0;;) { if (selectfailed) { const char mmsg[] = "select(2) failed but no child died?"; if (logfp) (void)fprintf(logfp, mmsg); errx(1, mmsg); } read_fd_set = active_fd_set; tmo.tv_sec = flags & RUN_SILENT ? 20 : 2; tmo.tv_usec = 0; i = select(FD_SETSIZE, &read_fd_set, NULL, NULL, &tmo); if (i == 0 && *actionwin == NULL && (flags & RUN_SILENT) == 0) *actionwin = show_cmd(scmd, win); if (i < 0) { if (errno != EINTR) { warn("select"); if (logfp) (void)fprintf(logfp, "select failure: %s\n", strerror(errno)); selectfailed = 1; } } else for (i = 0; i < FD_SETSIZE; ++i) { if (!FD_ISSET(i, &read_fd_set)) continue; n = read(i, ibuf, sizeof ibuf - 1); if (n <= 0) { if (n < 0) warn("read"); continue; } ibuf[n] = 0; cp = ibuf; if (i == STDIN_FILENO) { (void)write(master, ibuf, (size_t)n); if (!(rtt.c_lflag & ECHO)) continue; } else { pktdata = ibuf[0]; if (pktdata != 0) { if (pktdata & TIOCPKT_IOCTL) memcpy(&rtt, ibuf, sizeof(rtt)); continue; } cp += 1; } if (*cp == 0 || flags & RUN_SILENT) continue; if (logfp) { fprintf(logfp, "%s", cp); fflush(logfp); } if (*actionwin == NULL) *actionwin = show_cmd(scmd, win); /* posix curses is braindead wrt \r\n so... */ for (ncp = cp; (ncp = strstr(ncp, "\r\n")); ncp += 2) { ncp[0] = '\n'; ncp[1] = '\r'; } waddstr(*actionwin, cp); wrefresh(*actionwin); } pid = wait4(child, &status, WNOHANG, 0); if (pid == child && (WIFEXITED(status) || WIFSIGNALED(status))) break; } close(master); close(slave); if (logfp) fflush(logfp); /* from here on out, we take tty signals ourselves */ ttysig_forward = 0; reset_prog_mode(); if (WIFEXITED(status)) { *errstr = msg_string(MSG_Command_failed); return WEXITSTATUS(status); } if (WIFSIGNALED(status)) { *errstr = msg_string(MSG_Command_ended_on_signal); return WTERMSIG(status); } return 0; }
/* * XXXX had to include this to deal with symlinks in some places. * When the target * disk is mounted under /targetroot, absolute symlinks * on it don't work right. * This function will resolve them using the mountpoint as prefix. * Copied verbatim from libc, with added prefix handling. * * char *realpath(const char *path, char resolved_path[MAXPATHLEN]); * * Find the real name of path, by removing all ".", ".." and symlink * components. Returns (resolved) on success, or (NULL) on failure, * in which case the path which caused trouble is left in (resolved). */ static char * target_realpath(const char *path, char *resolved) { struct stat sb; int fd, n, rootd, serrno, nlnk = 0; char *p, *q, wbuf[MAXPATHLEN]; char solidus[2], empty[1]; solidus[0] = '/'; solidus[1] = '\0'; empty[0] = '\0'; /* Save the starting point. */ if ((fd = open(".", O_RDONLY)) < 0) { (void)strlcpy(resolved, ".", MAXPATHLEN); return (NULL); } /* * Find the dirname and basename from the path to be resolved. * Change directory to the dirname component. * lstat the basename part. * if it is a symlink, read in the value and loop. * if it is a directory, then change to that directory. * get the current directory name and append the basename. */ if (target_prefix() != NULL && strcmp(target_prefix(), "") != 0) snprintf(resolved, MAXPATHLEN, "%s/%s", target_prefix(), path); else if (strlcpy(resolved, path, MAXPATHLEN) >= MAXPATHLEN) { errno = ENAMETOOLONG; goto err1; } loop: q = strrchr(resolved, '/'); if (q != NULL) { p = q + 1; if (q == resolved) q = solidus; else { do { --q; } while (q > resolved && *q == '/'); q[1] = '\0'; q = resolved; } if (chdir(q) < 0) goto err1; } else p = resolved; /* Deal with the last component. */ if (lstat(p, &sb) == 0) { if (S_ISLNK(sb.st_mode)) { if (nlnk++ >= MAXSYMLINKS) { errno = ELOOP; goto err1; } n = readlink(p, wbuf, MAXPATHLEN - 1); if (n < 0) goto err1; wbuf[n] = '\0'; if (wbuf[0] == '/') snprintf(resolved, MAXPATHLEN, "%s%s", target_prefix(), wbuf); else strlcpy(resolved, wbuf, MAXPATHLEN); goto loop; } if (S_ISDIR(sb.st_mode)) { if (chdir(p) < 0) goto err1; p = empty; } } /* * Save the last component name and get the full pathname of * the current directory. */ if (strlcpy(wbuf, p, sizeof(wbuf)) >= sizeof(wbuf)) { errno = ENAMETOOLONG; goto err1; } /* * Call the internal internal version of getcwd which * does a physical search rather than using the $PWD short-cut */ if (getcwd(resolved, MAXPATHLEN) == 0) goto err1; /* * Join the two strings together, ensuring that the right thing * happens if the last component is empty, or the dirname is root. */ if (resolved[0] == '/' && resolved[1] == '\0') rootd = 1; else rootd = 0; if (*wbuf) { if (strlen(resolved) + strlen(wbuf) + (rootd ? 0 : 1) + 1 > MAXPATHLEN) { errno = ENAMETOOLONG; goto err1; } if (rootd == 0) if (strlcat(resolved, "/", MAXPATHLEN) >= MAXPATHLEN) { errno = ENAMETOOLONG; goto err1; } if (strlcat(resolved, wbuf, MAXPATHLEN) >= MAXPATHLEN) { errno = ENAMETOOLONG; goto err1; } } /* Go back to where we came from. */ if (fchdir(fd) < 0) { serrno = errno; goto err2; } /* It's okay if the close fails, what's an fd more or less? */ (void)close(fd); return (resolved); err1: serrno = errno; (void)fchdir(fd); err2: (void)close(fd); errno = serrno; return (NULL); }
/* * Write the network config info the user entered via menus into the * config files in the target disk. Be careful not to lose any * information we don't immediately add back, in case the install * target is the currently-active root. */ void mnt_net_config(void) { char ifconfig_fn[STRSIZE]; FILE *ifconf = NULL; if (!network_up) return; if (!ask_yesno(MSG_mntnetconfig)) return; /* Write hostname to /etc/rc.conf */ if ((net_dhcpconf & DHCPCONF_HOST) == 0) if (del_rc_conf("hostname") == 0) add_rc_conf("hostname=%s\n", recombine_host_domain()); /* Copy resolv.conf to target. If DHCP was used to create it, * it will be replaced on next boot anyway. */ if (net_namesvr[0] != '\0') dup_file_into_target("/etc/resolv.conf"); /* * bring the interface up, it will be necessary for IPv6, and * it won't make trouble with IPv4 case either */ snprintf(ifconfig_fn, sizeof ifconfig_fn, "/etc/ifconfig.%s", net_dev); ifconf = target_fopen(ifconfig_fn, "w"); if (ifconf != NULL) { scripting_fprintf(NULL, "cat <<EOF >>%s%s\n", target_prefix(), ifconfig_fn); scripting_fprintf(ifconf, "up\n"); if (*net_media != '\0') scripting_fprintf(ifconf, "media %s\n", net_media); scripting_fprintf(NULL, "EOF\n"); } if ((net_dhcpconf & DHCPCONF_IPADDR) == 0) { FILE *hosts; /* Write IPaddr and netmask to /etc/ifconfig.if[0-9] */ if (ifconf != NULL) { scripting_fprintf(NULL, "cat <<EOF >>%s%s\n", target_prefix(), ifconfig_fn); if (*net_media != '\0') scripting_fprintf(ifconf, "%s netmask %s media %s\n", net_ip, net_mask, net_media); else scripting_fprintf(ifconf, "%s netmask %s\n", net_ip, net_mask); scripting_fprintf(NULL, "EOF\n"); } /* * Add IPaddr/hostname to /etc/hosts. * Be careful not to clobber any existing contents. * Relies on ordered search of /etc/hosts. XXX YP? */ hosts = target_fopen("/etc/hosts", "a"); if (hosts != 0) { scripting_fprintf(NULL, "cat <<EOF >>%s/etc/hosts\n", target_prefix()); write_etc_hosts(hosts); (void)fclose(hosts); scripting_fprintf(NULL, "EOF\n"); } if (del_rc_conf("defaultroute") == 0) add_rc_conf("defaultroute=\"%s\"\n", net_defroute); } else { /* * Start dhcpcd quietly and in master mode, but restrict * it to our interface */ add_rc_conf("dhcpcd=YES\n"); add_rc_conf("dhcpcd_flags=\"-qM %s\"\n", net_dev); } if (ifconf) fclose(ifconf); fflush(NULL); }