new applet: script

Denys Vlasenko vda.linux at googlemail.com
Sun Feb 24 16:42:29 UTC 2008


On Sunday 24 February 2008 00:56, Pascal Bellard wrote:
> Hello,
> 
> Please find attached a patch to add script feature in busybox.
> May be usefull to log boot output, report bugs...

static FILE     *fscript;

You seem to ever use it only for fwrite(), not fprintf.
Just use low-level fd-based I/O then (open, not fopen).

Can you also do a "struct globals" trick and thus prevent
globals from eating data/bss? (See e.g. httpd.c for an example).


static void done(void)
{
        if (subchild) {
                fclose(fscript);
                close(pty);
        }
        else {
                tcsetattr(0, TCSAFLUSH, &tt);
                if (qflg == 0) printf("Script done, file is %s\n", fname);
        }
        exit(0);
}

exit() will close files. Don't bother doing it yourself.


static void finish(int sig)
{
        union wait status;
        int pid, die = 0;

        (void) sig;
        while ((pid = wait3((int *)&status, WNOHANG, 0)) > 0) {
                if (pid == child) {
                        die = 1;
                }
        }
        if (die) {
                done();
        }
}

How about less cryptic one like this?

static void sigchld_handler(int sig)
{
        pid_t pid;
        while ((pid = wait_any_nohang(&sig) > 0)
                if (pid == child)
                        done(); /* exits */
}


static void fail(const char *s)
{
        bb_perror_msg(s);
        kill(0, SIGTERM);
        done();
}

I do not understand why you send TERM to yourself.
Especially that you don't have a handler for it.
Comment?


int script_main(int argc, char *argv[]) MAIN_EXTERNALLY_VISIBLE;
int script_main(int argc, char *argv[])
{
        int count, ch;
        struct termios rtt;
        const char      *shell;
        struct  winsize win;
        char    line[32], buf[BUFSIZ];
BUFSIZ on stack is too big.
        static char *cflg, mode[] = "w", shell_arg[] = "-i";
        static int fflg;
None of these need to be static.


while ((ch = getopt(argc, argv, "ac:fq")) != -1)...

Please use getopt32 instead.


        if ((shell = getenv("SHELL")) == NULL) {
                shell = _PATH_BSHELL;
        }
        if ((pty = getpty(line,sizeof(line))) < 0) {
                fail("Out of pty's");
        }

For better readability, pull assignments out of if().


        if ((child = fork()) < 0) {
                fail("fork");
You can use bb_perror_msg_and_die("fork").
        }
        if (child) { /* parent */
                fclose(fscript);
                while ((count = read(0, buf, sizeof(buf))) > 0) {
                        write(pty, buf, count);
                }
Use bb_copyfd_eof(src_fd, dst_fd).
        }
        else { /* child */
                if ((subchild = child = fork()) < 0) {
                        fail("fork");
                }
                if (child) { /* parent */

Can you add a comment why two levels of forks are needed,
and how data is piped through pty fds?


                        pty = xopen(line, O_RDWR);
                        tcsetattr(pty, TCSAFLUSH, &tt);
                        ioctl(pty, TIOCSWINSZ, (char *)&win);
                        setsid();
                        ioctl(pty, TIOCSCTTY, 0);
                        dup2(pty, 0);
                        dup2(pty, 1);
                        dup2(pty, 2);
                        close(pty);

About this close() - are you sure pty is > 2? IOW: use
"xmove_fd(pty, 0); dup2(0, 1); dup2(0, 2);" instead.


                        execl(shell, strrchr(shell, '/') + 1, shell_arg, cflg, 0);

My gcc said "util-linux/script.c:147: warning: missing sentinel in function call"
(first time ever I see such a meesage. gcc is 4.2.1). s/0/NULL/ helped.
--
vda



More information about the busybox mailing list