Ignore:
Timestamp:
Feb 25, 2011, 9:26:54 PM (13 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.18.3 to avoid problems with the tar command which is now failing on recent versions with busybox 1.7.3
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.9/mindi-busybox/console-tools/openvt.c

    r1765 r2725  
    66 *  hacked by Tito <farmatito@tiscali.it>
    77 *
    8  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    99 */
    1010
    11 /* getopt not needed */
    12 
     11#include <linux/vt.h>
    1312#include "libbb.h"
    1413
    15 int openvt_main(int argc, char **argv);
    16 int openvt_main(int argc, char **argv)
     14/* "Standard" openvt's man page (we do not support all of this):
     15
     16openvt [-c NUM] [-fsulv] [--] [command [args]]
     17
     18Find the first available VT, and run command on it. Stdio is directed
     19to that VT. If no command is specified then $SHELL is used.
     20
     21-c NUM
     22    Use the given VT number, not the first free one.
     23-f
     24    Force opening a VT: don't try to check if VT is already in use.
     25-s
     26    Switch to the new VT when starting the command.
     27    The VT of the new command will be made the new current VT.
     28-u
     29    Figure out the owner of the current VT, and run login as that user.
     30    Suitable to be called by init. Shouldn't be used with -c or -l.
     31-l
     32    Make the command a login shell: a "-" is prepended to the argv[0]
     33    when command is executed.
     34-v
     35    Verbose.
     36-w
     37    Wait for command to complete. If -w and -s are used together,
     38    switch back to the controlling terminal when the command completes.
     39
     40bbox:
     41-u: not implemented
     42-f: always in effect
     43-l: not implemented, ignored
     44-v: ignored
     45-ws: does NOT switch back
     46*/
     47
     48/* Helper: does this fd understand VT_xxx? */
     49static int not_vt_fd(int fd)
    1750{
    18     char vtname[sizeof(VC_FORMAT) + 2];
     51    struct vt_stat vtstat;
     52    return ioctl(fd, VT_GETSTATE, &vtstat); /* !0: error, it's not VT fd */
     53}
    1954
    20     if (argc < 3)
    21         bb_show_usage();
     55/* Helper: get a fd suitable for VT_xxx */
     56static int get_vt_fd(void)
     57{
     58    int fd;
    2259
    23     /* check for illegal vt number: < 1 or > 63 */
    24     sprintf(vtname, VC_FORMAT, (int)xatou_range(argv[1], 1, 63));
     60    /* Do we, by chance, already have it? */
     61    for (fd = 0; fd < 3; fd++)
     62        if (!not_vt_fd(fd))
     63            return fd;
     64    fd = open(DEV_CONSOLE, O_RDONLY | O_NONBLOCK);
     65    if (fd >= 0 && !not_vt_fd(fd))
     66        return fd;
     67    bb_error_msg_and_die("can't find open VT");
     68}
    2569
    26     bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS, argv);
    27     /* grab new one */
    28     close(0);
     70static int find_free_vtno(void)
     71{
     72    int vtno;
     73    int fd = get_vt_fd();
     74
     75    errno = 0;
     76    /*xfunc_error_retval = 3; - do we need compat? */
     77    if (ioctl(fd, VT_OPENQRY, &vtno) != 0 || vtno <= 0)
     78        bb_perror_msg_and_die("can't find open VT");
     79// Not really needed, grep for DAEMON_ONLY_SANITIZE
     80//  if (fd > 2)
     81//      close(fd);
     82    return vtno;
     83}
     84
     85/* vfork scares gcc, it generates bigger code.
     86 * Keep it away from main program.
     87 * TODO: move to libbb; or adapt existing libbb's spawn().
     88 */
     89static NOINLINE void vfork_child(char **argv)
     90{
     91    if (vfork() == 0) {
     92        /* CHILD */
     93        /* Try to make this VT our controlling tty */
     94        setsid(); /* lose old ctty */
     95        ioctl(STDIN_FILENO, TIOCSCTTY, 0 /* 0: don't forcibly steal */);
     96        //bb_error_msg("our sid %d", getsid(0));
     97        //bb_error_msg("our pgrp %d", getpgrp());
     98        //bb_error_msg("VT's sid %d", tcgetsid(0));
     99        //bb_error_msg("VT's pgrp %d", tcgetpgrp(0));
     100        BB_EXECVP_or_die(argv);
     101    }
     102}
     103
     104int openvt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     105int openvt_main(int argc UNUSED_PARAM, char **argv)
     106{
     107    char vtname[sizeof(VC_FORMAT) + sizeof(int)*3];
     108    struct vt_stat vtstat;
     109    char *str_c;
     110    int vtno;
     111    int flags;
     112    enum {
     113        OPT_c = (1 << 0),
     114        OPT_w = (1 << 1),
     115        OPT_s = (1 << 2),
     116        OPT_l = (1 << 3),
     117        OPT_f = (1 << 4),
     118        OPT_v = (1 << 5),
     119    };
     120
     121    /* "+" - stop on first non-option */
     122    flags = getopt32(argv, "+c:wslfv", &str_c);
     123    argv += optind;
     124
     125    if (flags & OPT_c) {
     126        /* Check for illegal vt number: < 1 or > 63 */
     127        vtno = xatou_range(str_c, 1, 63);
     128    } else {
     129        vtno = find_free_vtno();
     130    }
     131
     132    /* Grab new VT */
     133    sprintf(vtname, VC_FORMAT, vtno);
     134    /* (Try to) clean up stray open fds above fd 2 */
     135    bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS | DAEMON_ONLY_SANITIZE, NULL);
     136    close(STDIN_FILENO);
     137    /*setsid(); - BAD IDEA: after we exit, child is SIGHUPed... */
    29138    xopen(vtname, O_RDWR);
    30     dup2(0, STDOUT_FILENO);
    31     dup2(0, STDERR_FILENO);
     139    xioctl(STDIN_FILENO, VT_GETSTATE, &vtstat);
    32140
    33     BB_EXECVP(argv[2], &argv[2]);
    34     _exit(1);
     141    if (flags & OPT_s) {
     142        console_make_active(STDIN_FILENO, vtno);
     143    }
     144
     145    if (!argv[0]) {
     146        argv--;
     147        argv[0] = getenv("SHELL");
     148        if (!argv[0])
     149            argv[0] = (char *) DEFAULT_SHELL;
     150        /*argv[1] = NULL; - already is */
     151    }
     152
     153    xdup2(STDIN_FILENO, STDOUT_FILENO);
     154    xdup2(STDIN_FILENO, STDERR_FILENO);
     155
     156#ifdef BLOAT
     157    {
     158    /* Handle -l (login shell) option */
     159    const char *prog = argv[0];
     160    if (flags & OPT_l)
     161        argv[0] = xasprintf("-%s", argv[0]);
     162    }
     163#endif
     164
     165    vfork_child(argv);
     166    if (flags & OPT_w) {
     167        /* We have only one child, wait for it */
     168        safe_waitpid(-1, NULL, 0); /* loops on EINTR */
     169        if (flags & OPT_s) {
     170            console_make_active(STDIN_FILENO, vtstat.v_active);
     171            // Compat: even with -c N (try to) disallocate:
     172            // # /usr/app/kbd-1.12/bin/openvt -f -c 9 -ws sleep 5
     173            // openvt: could not deallocate console 9
     174            xioctl(STDIN_FILENO, VT_DISALLOCATE, (void*)(ptrdiff_t)vtno);
     175        }
     176    }
     177    return EXIT_SUCCESS;
    35178}
Note: See TracChangeset for help on using the changeset viewer.