--- loader/Makefile.am | 2 +- loader/init.c | 208 +------------------------------------------------ loader/loader.c | 5 + loader/serial.c | 220 ++++++++++++++++++++++++++++++++++++++++++++++++++++ loader/serial.h | 9 ++ 5 files changed, 237 insertions(+), 207 deletions(-) create mode 100644 loader/serial.c create mode 100644 loader/serial.h diff --git a/loader/Makefile.am b/loader/Makefile.am index 02ab6cf..243817c 100644 --- a/loader/Makefile.am +++ b/loader/Makefile.am @@ -50,7 +50,7 @@ loader_SOURCES = loader.c copy.c moduleinfo.c loadermisc.c \ getparts.c dirbrowser.c fwloader.c ibft.c hardware.c \ method.c cdinstall.c hdinstall.c nfsinstall.c \ urlinstall.c net.c urls.c rpmextract.c readvars.c \ - unpack.c + serial.c unpack.c dirbrowser_CFLAGS = $(COMMON_CFLAGS) -DSTANDALONE dirbrowser_LDADD = $(NEWT_LIBS) diff --git a/loader/init.c b/loader/init.c index 429eada..d4f9c0d 100644 --- a/loader/init.c +++ b/loader/init.c @@ -83,71 +83,6 @@ static void fatal_error(int usePerror) { #endif } -static int setupTerminal(int fd) { - struct winsize winsize; - gpointer value = NULL; - - if (ioctl(fd, TIOCGWINSZ, &winsize)) { - printf("failed to get winsize"); - fatal_error(1); - } - - winsize.ws_row = 24; - winsize.ws_col = 80; - - if (ioctl(fd, TIOCSWINSZ, &winsize)) { - printf("failed to set winsize"); - fatal_error(1); - } - - if (!strcmp(ttyname(fd), "/dev/hvc0")) { - /* using an HMC on a POWER system, use vt320 */ - env[ENV_TERM] = "TERM=vt320"; - } else { - /* use the no-advanced-video vt100 definition */ - env[ENV_TERM] = "TERM=vt100-nav"; - - /* unless the user specifies that they want utf8 */ - if (g_hash_table_lookup_extended(cmdline, "utf8", NULL, &value)) { - env[ENV_TERM] = "TERM=vt100"; - } - } - - return 0; -} -#if defined(__sparc__) -static int termcmp(struct termios *a, struct termios *b) { - if (a->c_iflag != b->c_iflag || a->c_oflag != b->c_oflag || - a->c_cflag != b->c_cflag || a->c_lflag != b->c_lflag) - return 1; - return memcmp(a->c_cc, b->c_cc, sizeof(a->c_cc)); -} -#endif - -#if !defined(__s390__) && !defined(__s390x__) && !defined(__sparc__) -static int termcmp(struct termios *a, struct termios *b) { - if (a->c_iflag != b->c_iflag || a->c_oflag != b->c_oflag || - a->c_cflag != b->c_cflag || a->c_lflag != b->c_lflag || - a->c_ispeed != b->c_ispeed || a->c_ospeed != b->c_ospeed) - return 1; - return memcmp(a->c_cc, b->c_cc, sizeof(a->c_cc)); -} -#endif - -static void termReset(void) { - /* change to tty1 */ - ioctl(0, VT_ACTIVATE, 1); - /* reset terminal */ - tcsetattr(0, TCSANOW, &ts); - /* Shift in, default color, move down 100 lines */ - /* ^O ^[[0m ^[[100E */ - printf("\017\033[0m\033[100E\n"); -} - -static void copyErrorFn (char *msg) { - printf(msg); -} - static char *setupMallocPerturb(char *value) { FILE *f; @@ -211,7 +146,6 @@ static void setupEnv(void) int main(int argc, char **argv) { pid_t installpid; int waitStatus; - int fd = -1; int doShutdown =0; reboot_action shutdown_method = HALT; int isSerial = 0; @@ -220,9 +154,7 @@ int main(int argc, char **argv) { int doKill = 1; char * argvc[15]; char ** argvp = argvc; - char twelve = 12; - struct serial_struct si; - int i, disable_keys; + int i; int ret; gpointer value = NULL; @@ -239,14 +171,6 @@ int main(int argc, char **argv) { printf("anaconda installer init version %s starting\n", VERSION); - /* these args are only for testing from commandline */ - for (i = 1; i < argc; i++) { - if (!strcmp (argv[i], "serial")) { - isSerial = 1; - break; - } - } - /* if anaconda dies suddenly we are doomed, so at least make a coredump */ struct rlimit corelimit = { RLIM_INFINITY, RLIM_INFINITY}; ret = setrlimit(RLIMIT_CORE, &corelimit); @@ -254,130 +178,6 @@ int main(int argc, char **argv) { perror("setrlimit failed - no coredumps will be available"); } -#if !defined(__s390__) && !defined(__s390x__) - static struct termios orig_cmode; - static int orig_flags; - struct termios cmode, mode; - int cfd; - - cfd = open("/dev/console", O_RDONLY); - tcgetattr(cfd,&orig_cmode); - orig_flags = fcntl(cfd, F_GETFL); - close(cfd); - - cmode = orig_cmode; - cmode.c_lflag &= (~ECHO); - - cfd = open("/dev/console", O_WRONLY); - tcsetattr(cfd,TCSANOW,&cmode); - close(cfd); - - /* handle weird consoles */ -#if defined(__powerpc__) - char * consoles[] = { "/dev/hvc0", /* hvc for JS20 */ - - "/dev/hvsi0", "/dev/hvsi1", - "/dev/hvsi2", /* hvsi for POWER5 */ - NULL }; -#elif defined (__ia64__) - char * consoles[] = { "/dev/ttySG0", "/dev/xvc0", "/dev/hvc0", NULL }; -#elif defined (__i386__) || defined (__x86_64__) - char * consoles[] = { "/dev/xvc0", "/dev/hvc0", NULL }; -#else - char * consoles[] = { NULL }; -#endif - for (i = 0; consoles[i] != NULL; i++) { - if ((fd = open(consoles[i], O_RDWR)) >= 0 && !tcgetattr(fd, &mode) && !termcmp(&cmode, &mode)) { - printf("anaconda installer init version %s using %s as console\n", - VERSION, consoles[i]); - isSerial = 3; - console = strdup(consoles[i]); - break; - } - close(fd); - } - - cfd = open("/dev/console", O_WRONLY); - tcsetattr(cfd,TCSANOW,&orig_cmode); - close(cfd); - - if ((fd < 0) && (ioctl (0, TIOCLINUX, &twelve) < 0)) { - isSerial = 2; - - if (ioctl(0, TIOCGSERIAL, &si) == -1) { - isSerial = 0; - } - } - - if (isSerial && (isSerial != 3)) { - char *device = "/dev/ttyS0"; - - printf("anaconda installer init version %s using a serial console\n", - VERSION); - - if (isSerial == 2) - device = "/dev/console"; - fd = open(device, O_RDWR, 0); - if (fd < 0) - device = "/dev/tts/0"; - - if (fd < 0) { - printf("failed to open %s\n", device); - fatal_error(1); - } - - setupTerminal(fd); - } else if (isSerial == 3) { - setupTerminal(fd); - } else if (fd < 0) { - fd = open("/dev/tty1", O_RDWR, 0); - if (fd < 0) - fd = open("/dev/vc/1", O_RDWR, 0); - - if (fd < 0) { - printf("failed to open /dev/tty1 and /dev/vc/1"); - fatal_error(1); - } - } - - setsid(); - if (ioctl(0, TIOCSCTTY, NULL)) { - printf("could not set new controlling tty\n"); - } - - dup2(fd, 0); - dup2(fd, 1); - dup2(fd, 2); - if (fd > 2) - close(fd); -#else - dup2(0, 1); - dup2(0, 2); -#endif - - /* disable Ctrl+Z, Ctrl+C, etc ... but not in rescue mode */ - disable_keys = 1; - if (argc > 1) - if (strstr(argv[1], "rescue")) - disable_keys = 0; - - if (disable_keys) { - tcgetattr(0, &ts); - ts.c_iflag &= ~BRKINT; - ts.c_iflag |= IGNBRK; - ts.c_iflag &= ~ISIG; - tcsetattr(0, TCSANOW, &ts); - } - - - /* Go into normal init mode - keep going, and then do a orderly shutdown - when: - - 1) /bin/install exits - 2) we receive a SIGHUP - */ - - printf("running install...\n"); if (!(installpid = fork())) { /* child */ @@ -407,11 +207,7 @@ int main(int argc, char **argv) { if (!WIFEXITED(waitStatus) || (WIFEXITED(waitStatus) && WEXITSTATUS(waitStatus))) { - /* Restore terminal */ - cfd = open("/dev/console", O_RDONLY); - tcsetattr(cfd, TCSANOW, &orig_cmode); - fcntl(cfd, F_SETFL, orig_flags); - close(cfd); + restore_console(&orig_cmode, orig_flags); shutdown_method = DELAYED_REBOOT; printf("install exited abnormally [%d/%d] ", WIFEXITED(waitStatus), diff --git a/loader/loader.c b/loader/loader.c index 5043994..db5445b 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -61,6 +61,7 @@ #include <mcheck.h> #endif +#include "serial.h" #include "copy.h" #include "getparts.h" #include "loader.h" @@ -1892,6 +1893,8 @@ int main(int argc, char ** argv) { char * outputKSFile = NULL; struct loaderData_s loaderData; + struct termios orig_cmode; + int orig_flags; char *path, *fmt; GSList *dd, *dditer; @@ -1969,6 +1972,8 @@ int main(int argc, char ** argv) { logMessage(INFO, "anaconda version %s on %s starting", VERSION, getProductArch()); + init_serial(&orig_cmode, &orig_flags, cmdline); + if ((FL_SERIAL(flags) || FL_VIRTPCONSOLE(flags)) && !hasGraphicalOverride()) { logMessage(INFO, "text mode forced due to serial/virtpconsole"); diff --git a/loader/serial.c b/loader/serial.c new file mode 100644 index 0000000..2e9fa5b --- /dev/null +++ b/loader/serial.c @@ -0,0 +1,220 @@ +#include <fcntl.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <termios.h> +#include <unistd.h> + +#include <linux/serial.h> + +#include <sys/ioctl.h> + +#include <glib.h> + +#include "../pyanaconda/isys/log.h" + +#if defined(__sparc__) +static int termcmp(struct termios *a, struct termios *b) { + if (a->c_iflag != b->c_iflag || a->c_oflag != b->c_oflag || + a->c_cflag != b->c_cflag || a->c_lflag != b->c_lflag) + return 1; + return memcmp(a->c_cc, b->c_cc, sizeof(a->c_cc)); +} +#endif + +#if !defined(__s390__) && !defined(__s390x__) && !defined(__sparc__) +static int termcmp(struct termios *a, struct termios *b) { + if (a->c_iflag != b->c_iflag || a->c_oflag != b->c_oflag || + a->c_cflag != b->c_cflag || a->c_lflag != b->c_lflag || + a->c_ispeed != b->c_ispeed || a->c_ospeed != b->c_ospeed) + return 1; + return memcmp(a->c_cc, b->c_cc, sizeof(a->c_cc)); +} +#endif + +void get_mode_and_flags(struct termios *cmode, int *flags) { + int fd; + + fd = open("/dev/console", O_RDONLY); + tcgetattr(fd, cmode); + *flags = fcntl(fd, F_GETFL); + close(fd); +} + +void set_mode(struct termios *cmode) { + int fd; + + fd = open("/dev/console", O_WRONLY); + tcsetattr(fd, TCSANOW, cmode); + close(fd); +} + +void restore_mode(struct termios *orig_cmode) { + int fd; + + fd = open("/dev/console", O_WRONLY); + tcsetattr(fd, TCSANOW, orig_cmode); + close(fd); +} + +void restore_flags(int orig_flags) { + int fd; + + fd = open("/dev/console", O_WRONLY); + fcntl(fd, F_SETFL, orig_flags); + close(fd); +} + +static int serial_requested(GHashTable *cmdline) { + if (cmdline && g_hash_table_lookup_extended(cmdline, "serial", NULL, NULL)) + return 1; + else + return 0; +} + +static int get_serial_fd() { + int i, fd = -1; + int weird = 0; + char twelve = 12; + char *console = NULL; + static struct serial_struct si; + + struct termios orig_cmode, cmode, mode; + int orig_flags; + + get_mode_and_flags(&orig_cmode, &orig_flags); + + cmode = orig_cmode; + cmode.c_lflag &= (~ECHO); + + set_mode(&cmode); + + /* handle weird consoles */ +#if defined(__powerpc__) + char * consoles[] = { "/dev/hvc0", /* hvc for JS20 */ + + "/dev/hvsi0", "/dev/hvsi1", + "/dev/hvsi2", /* hvsi for POWER5 */ + NULL }; +#elif defined (__i386__) || defined (__x86_64__) + char * consoles[] = { "/dev/xvc0", "/dev/hvc0", NULL }; +#else + char * consoles[] = { NULL }; +#endif + for (i = 0; consoles[i] != NULL; i++) { + if ((fd = open(consoles[i], O_RDWR)) >= 0 && !tcgetattr(fd, &mode) && !termcmp(&cmode, &mode)) { + console = strdup(consoles[i]); + logMessage(INFO, "set console to %s at %d", console, __LINE__); + weird = 1; + break; + } + close(fd); + } + + restore_mode(&orig_cmode); + + if (fd < 0 && ioctl(0, TIOCLINUX, &twelve) < 0) { + console = "/dev/console"; + + if (ioctl(0, TIOCGSERIAL, &si) == -1) + console = NULL; + } + else + console = "/dev/ttyS0"; + + if (console && !weird) { + fd = open(console, O_RDWR, 0); + if (fd < 0) + console = "/dev/tts/0"; + + if (fd < 0) { + logMessage(ERROR, "failed to open %s", console); + return -1; + } + } + + return fd; +} + +static void set_term(int fd, GHashTable *cmdline) { + if (!strcmp(ttyname(fd), "/dev/hvc0")) { + /* using an HMC on a POWER system, use vt320 */ + setenv("TERM", "vt320", 1); + } else { + if (cmdline && g_hash_table_lookup_extended(cmdline, "utf8", NULL, NULL)) + setenv("TERM", "vt100", 1); + else + /* use the no-advanced-video vt100 definition */ + setenv("TERM", "vt100-nav", 1); + } +} + +void init_serial(struct termios *orig_cmode, int *orig_flags, GHashTable *cmdline) { +#if !defined(__s390__) && !defined(__s390x__) + int fd; + + /* We need to get the original mode and flags here (in addition to inside + * get_serial) so we'll have them for later when we restore the console + * prior to rebooting. + */ + get_mode_and_flags(orig_cmode, orig_flags); + + if (!serial_requested(cmdline) || (fd = get_serial_fd()) == -1) { + /* This is not a serial console install. */ + if ((fd = open("/dev/tty1", O_RDWR, 0)) < 0) { + if ((fd = open("/dev/vc/1", O_RDWR, 0)) < 0) { + fprintf(stderr, "failed to open /dev/tty1 and /dev/vc/1"); + exit(1); + } + } + } + else { + struct winsize winsize; + + if (ioctl(fd, TIOCGWINSZ, &winsize)) { + logMessage(ERROR, "failed to get window size"); + exit(1); + } + + winsize.ws_row = 24; + winsize.ws_col = 80; + + if (ioctl(fd, TIOCSWINSZ, &winsize)) { + logMessage(ERROR, "failed to set window size"); + exit(1); + } + + set_term(fd, cmdline); + } + + setsid(); + if (ioctl(0, TIOCSCTTY, NULL)) + fprintf(stderr, "could not set new controlling tty\n"); + + if (dup2(fd, 0) == -1) + logMessage(ERROR, "dup2(%d): %m", __LINE__); + + if (dup2(fd, 1) == -1) + logMessage(ERROR, "dup2(%d): %m", __LINE__); + + if (dup2(fd, 2) == -1) + logMessage(ERROR, "dup2(%d): %m", __LINE__); + + if (fd > 2) + close(fd); +#else + dup2(0, 1); + dup2(0, 2); +#endif + + /* disable Ctrl+Z, Ctrl+C, etc ... but not in rescue mode */ + if (cmdline && !g_hash_table_lookup_extended(cmdline, "rescue", NULL, NULL)) { + struct termios ts; + + tcgetattr(0, &ts); + ts.c_iflag &= ~BRKINT; + ts.c_iflag |= IGNBRK; + ts.c_iflag &= ~ISIG; + tcsetattr(0, TCSANOW, &ts); + } +} diff --git a/loader/serial.h b/loader/serial.h new file mode 100644 index 0000000..82e086c --- /dev/null +++ b/loader/serial.h @@ -0,0 +1,9 @@ +#include <termios.h> +#include <unistd.h> + +#include <glib.h> + +void get_mode_and_flags(struct termios *cmode, int *flags); +void set_mode(struct termios *cmode); +void restore_console(struct termios *orig_cmode, int orig_flags); +void init_serial(struct termios *orig_cmode, int *orig_flags, GHashTable *cmdline); -- 1.7.4.1 _______________________________________________ Anaconda-devel-list mailing list Anaconda-devel-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/anaconda-devel-list