From owner-freebsd-bugs@FreeBSD.ORG Wed Aug 4 07:40:47 2004 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 4475416A4CE for ; Wed, 4 Aug 2004 07:40:47 +0000 (GMT) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 1AB7843D5C for ; Wed, 4 Aug 2004 07:40:47 +0000 (GMT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.12.11/8.12.11) with ESMTP id i747eO2k024617 for ; Wed, 4 Aug 2004 07:40:24 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.11/8.12.11/Submit) id i747eOAk024616; Wed, 4 Aug 2004 07:40:24 GMT (envelope-from gnats) Resent-Date: Wed, 4 Aug 2004 07:40:24 GMT Resent-Message-Id: <200408040740.i747eOAk024616@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, dada@sbox.tugraz.at Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 3FD1516A4CE for ; Wed, 4 Aug 2004 07:31:08 +0000 (GMT) Received: from mailrelay01.tugraz.at (mailrelay.tu-graz.ac.at [129.27.3.7]) by mx1.FreeBSD.org (Postfix) with ESMTP id 1ABDD43D5C for ; Wed, 4 Aug 2004 07:31:07 +0000 (GMT) (envelope-from dada@sbox.tugraz.at) Received: from webmail.tugraz.at (webmail02.tu-graz.ac.at [129.27.3.144]) by mailrelay01.tugraz.at (8.13.1/8.13.1) with ESMTP id i747UlXJ021388 for ; Wed, 4 Aug 2004 09:30:47 +0200 (CEST) Received: from ARP410.kfunigraz.ac.at (ARP410.kfunigraz.ac.at ; Wed, 4 Aug 2004 09:30:47 +0200 Message-Id: <20040804093047.gowo4o8oo44gkwws@webmail.tugraz.at> Date: Wed, 4 Aug 2004 09:30:47 +0200 From: dada@sbox.tugraz.at To: FreeBSD problem reports Subject: bin/69986: [patch] sysinstall: No job control in fixit shell on serial console X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 04 Aug 2004 07:40:47 -0000 >Number: 69986 >Category: bin >Synopsis: [patch] sysinstall: No job control in fixit shell on serial console >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Wed Aug 04 07:40:24 GMT 2004 >Closed-Date: >Last-Modified: >Originator: Martin Kammerhofer >Release: FreeBSD 4.10-STABLE i386 >Organization: Graz UNI >Environment: System: FreeBSD Martin.liebt.Susi 4.10-STABLE FreeBSD 4.10-STABLE #0: Sat Jul 24 15:53:45 CEST 2004 toor@Martin.liebt.Susi:/usr/src/sys/compile/GEIDORF4 i386 >Description: Running a fixit shell on a serial console is dangerous. Suppose a program hangs (e.g. mount_nfs) and the user types Cntrl-C to stop it ==> game over. INTR will be delivered to sysinstall, the blocking process will persist, sysinstall will not unmount the fixit media and therefore further attempts to spawn a fixit shell will fail. The user has to reboot. >How-To-Repeat: Boot with serial console into sysinstall. (Option "-h" to boot2 or "set console=comconsole" in loader.) Invoke one of the fixit options (DVD, Floppy, Shell). Start a program (e.g. "ls -R /") and stop it with INTR (i.e. type Cntrl-C). >Fix: Explanation of patch: The code path for the usual case (running on syscons) is almost unchanged. Two ioctls calls are omitted. TIOCNOTTY was futile since it _only_ works on /dev/tty (and invoking it on /dev/tty would not help in any way here). TIOCSCTTY was redundant because login_tty(3) calls setsid(2) (creating a new session without a controlling terminal) and sets the controlling terminal afterwards. The code path for the serial console keeps console descriptors 0 and 1 (rather than closing and reopening them). Stderr is duplicated from stdout because sysinstall redirected it. Calling setsid(2) was wrong: A terminal can be the controlling terminal for at most one session! The serial console is already the controlling terminal for sysinstall's session. There is _no_ way to make it the controlling terminal for another session too. Rather than creating a new session we keep things as they are. Job control and signals will work as expected for the fixit shell. We only have to reset the foreground process group after the fixit shell exited. This ensures that keyboard generated signals will reach sysinstall again. Index: install.c =================================================================== RCS file: /home/ncvs/src/usr.sbin/sysinstall/install.c,v retrieving revision 1.354 diff -u -t -r1.354 install.c --- install.c 15 May 2004 05:06:19 -0000 1.354 +++ install.c 2 Aug 2004 18:14:12 -0000 @@ -449,6 +449,7 @@ { pid_t child; int waitstatus; + sig_t sigttou; if (!directory_exists("/var/tmp/vi.recover")) { if (DITEM_STATUS(Mkdir("/var/tmp/vi.recover")) != DITEM_SUCCESS) { @@ -470,6 +471,7 @@ msgConfirm("Couldn't symlink the /etc/ files! I'm not sure I like this.."); if (!file_readable(TERMCAP_FILE)) create_termcap(); + sigttou = signal(SIGTTOU, SIG_IGN); if (strcmp(variable_get(VAR_FIXIT_TTY), "serial") == 0) systemSuspendDialog(); /* must be before the fork() */ if (!(child = fork())) { @@ -477,37 +479,34 @@ struct termios foo; extern int login_tty(int); - ioctl(0, TIOCNOTTY, NULL); - for (i = getdtablesize(); i >= 0; --i) + for (i = getdtablesize(); i >= 2; --i) close(i); - - if (strcmp(variable_get(VAR_FIXIT_TTY), "serial") == 0) - fd = open("/dev/console", O_RDWR); - else - fd = open("/dev/ttyv3", O_RDWR); - ioctl(0, TIOCSCTTY, &fd); - dup2(0, 1); - dup2(0, 2); DebugFD = 2; - if (login_tty(fd) == -1) - msgDebug("fixit: I can't set the controlling terminal.\n"); - - signal(SIGTTOU, SIG_IGN); - if (tcgetattr(0, &foo) != -1) { - foo.c_cc[VERASE] = '\010'; - if (tcsetattr(0, TCSANOW, &foo) == -1) - msgDebug("fixit shell: Unable to set erase character.\n"); - } - else - msgDebug("fixit shell: Unable to get terminal attributes!\n"); - setenv("PATH", "/bin:/sbin:/usr/bin:/usr/sbin:/stand:" - "/mnt2/stand:/mnt2/bin:/mnt2/sbin:/mnt2/usr/bin:/mnt2/usr/sbin", 1); if (strcmp(variable_get(VAR_FIXIT_TTY), "serial") == 0) { printf("Waiting for fixit shell to exit.\n" "When you are done, type ``exit'' to exit\n" "the fixit shell and be returned here.\n\n"); fflush(stdout); + dup2(1, 2); /* connect stderr to comconsole */ } + else { + close(0); + fd = open("/dev/ttyv3", O_RDWR); + dup2(0, 1); + dup2(0, 2); + if (login_tty(fd) == -1) + msgDebug("fixit: I can't set the controlling terminal.\n"); + + if (tcgetattr(0, &foo) != -1) { + foo.c_cc[VERASE] = '\010'; + if (tcsetattr(0, TCSANOW, &foo) == -1) + msgDebug("fixit shell: Unable to set erase character.\n"); + } + else + msgDebug("fixit shell: Unable to get terminal attributes!\n"); + } + setenv("PATH", "/bin:/sbin:/usr/bin:/usr/sbin:/stand:" + "/mnt2/stand:/mnt2/bin:/mnt2/sbin:/mnt2/usr/bin:/mnt2/usr/sbin", 1); /* use the .profile from the fixit medium */ setenv("HOME", "/mnt2", 1); @@ -524,6 +523,8 @@ "the fixit shell and be returned here\n."); } (void)waitpid(child, &waitstatus, 0); + tcsetpgrp(0, getpgrp()); /* go back to foreground group */ + (void)signal(SIGTTOU, sigttou); if (strcmp(variable_get(VAR_FIXIT_TTY), "serial") == 0) systemResumeDialog(); } Index: system.c =================================================================== RCS file: /home/ncvs/src/usr.sbin/sysinstall/system.c,v retrieving revision 1.123 diff -u -t -r1.123 system.c --- system.c 11 Mar 2004 11:58:16 -0000 1.123 +++ system.c 2 Aug 2004 18:30:45 -0000 @@ -462,6 +462,7 @@ systemCreateHoloshell(void) { int waitstatus; + sig_t sigttou; if ((FixItMode || OnVTY) && RunningAsInit) { @@ -485,41 +486,40 @@ (void) waitpid(ehs_pid, &pstat, WNOHANG); } + sigttou = signal(SIGTTOU, SIG_IGN); if (strcmp(variable_get(VAR_FIXIT_TTY), "serial") == 0) systemSuspendDialog(); /* must be before the fork() */ if ((ehs_pid = fork()) == 0) { int i, fd; struct termios foo; extern int login_tty(int); - - ioctl(0, TIOCNOTTY, NULL); - for (i = getdtablesize(); i >= 0; --i) + + for (i = getdtablesize(); i >= 2; --i) close(i); - if (strcmp(variable_get(VAR_FIXIT_TTY), "serial") == 0) - fd = open("/dev/console", O_RDWR); - else - fd = open("/dev/ttyv3", O_RDWR); - ioctl(0, TIOCSCTTY, &fd); - dup2(0, 1); - dup2(0, 2); DebugFD = 2; - if (login_tty(fd) == -1) - msgDebug("Doctor: I can't set the controlling terminal.\n"); - signal(SIGTTOU, SIG_IGN); - if (tcgetattr(fd, &foo) != -1) { - foo.c_cc[VERASE] = '\010'; - if (tcsetattr(fd, TCSANOW, &foo) == -1) - msgDebug("Doctor: I'm unable to set the erase character.\n"); - } - else - msgDebug("Doctor: I'm unable to get the terminal attributes!\n"); if (strcmp(variable_get(VAR_FIXIT_TTY), "serial") == 0) { - printf("Type ``exit'' in this fixit shell to resume sysinstall.\n\n"); + printf("Type ``exit'' in this fixit shell to resume sysinstall.\n\n"); fflush(stdout); + dup2(1, 2); /* connect stderr to comconsole */ + } + else { + close(0); + fd = open("/dev/ttyv3", O_RDWR); + dup2(0, 1); + dup2(0, 2); + if (login_tty(fd) == -1) + msgDebug("Doctor: I can't set the controlling terminal.\n"); + if (tcgetattr(fd, &foo) != -1) { + foo.c_cc[VERASE] = '\010'; + if (tcsetattr(fd, TCSANOW, &foo) == -1) + msgDebug("Doctor: I'm unable to set the erase character.\n"); + } + else + msgDebug("Doctor: I'm unable to get the terminal attributes!\n"); } execlp("sh", "-sh", 0); msgDebug("Was unable to execute sh for Holographic shell!\n"); - exit(1); + _exit(1); } else { if (strcmp(variable_get(VAR_FIXIT_TTY), "standard") == 0) { @@ -535,8 +535,10 @@ it serial mode since there is no virtual console */ + tcsetpgrp(0, getpgrp()); /* go back to foreground group */ systemResumeDialog(); } + (void)signal(SIGTTOU, sigttou); } } } --=_4vgnvhj5bjc-- >Release-Note: >Audit-Trail: >Unformatted: This message is in MIME format. --=_4vgnvhj5bjc Content-Type: text/plain; charset="ISO-8859-1" Content-Disposition: inline Content-Transfer-Encoding: 7bit --=_4vgnvhj5bjc Content-Type: text/plain; charset="ISO-8859-1"; name="sysinstall.pr" Content-Disposition: inline; filename="sysinstall.pr" Content-Transfer-Encoding: 7bit