Magellan Linux

Diff of /trunk/mkinitrd-magellan/busybox/util-linux/script.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 983 by niro, Fri Apr 24 18:33:46 2009 UTC revision 984 by niro, Sun May 30 11:32:42 2010 UTC
# Line 10  Line 10 
10   *   *
11   * Licensed under GPLv2 or later, see file License in this tarball for details.   * Licensed under GPLv2 or later, see file License in this tarball for details.
12   */   */
   
13  #include "libbb.h"  #include "libbb.h"
14    
 static smallint fd_count = 2;  
   
 static void handle_sigchld(int sig UNUSED_PARAM)  
 {  
  fd_count = 0;  
 }  
   
15  int script_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;  int script_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
16  int script_main(int argc UNUSED_PARAM, char **argv)  int script_main(int argc UNUSED_PARAM, char **argv)
17  {  {
# Line 36  int script_main(int argc UNUSED_PARAM, c Line 28  int script_main(int argc UNUSED_PARAM, c
28   const char *shell;   const char *shell;
29   char shell_opt[] = "-i";   char shell_opt[] = "-i";
30   char *shell_arg = NULL;   char *shell_arg = NULL;
31     enum {
32     OPT_a = (1 << 0),
33     OPT_c = (1 << 1),
34     OPT_f = (1 << 2),
35     OPT_q = (1 << 3),
36     OPT_t = (1 << 4),
37     };
38    
39  #if ENABLE_GETOPT_LONG  #if ENABLE_LONG_OPTS
40   static const char getopt_longopts[] ALIGN1 =   static const char getopt_longopts[] ALIGN1 =
41   "append\0"  No_argument       "a"   "append\0"  No_argument       "a"
42   "command\0" Required_argument "c"   "command\0" Required_argument "c"
43   "flush\0"   No_argument       "f"   "flush\0"   No_argument       "f"
44   "quiet\0"   No_argument       "q"   "quiet\0"   No_argument       "q"
45     IF_SCRIPTREPLAY("timing\0" No_argument "t")
46   ;   ;
47    
48   applet_long_options = getopt_longopts;   applet_long_options = getopt_longopts;
49  #endif  #endif
50    
51   opt_complementary = "?1"; /* max one arg */   opt_complementary = "?1"; /* max one arg */
52   opt = getopt32(argv, "ac:fq", &shell_arg);   opt = getopt32(argv, "ac:fq" IF_SCRIPTREPLAY("t") , &shell_arg);
53   //argc -= optind;   //argc -= optind;
54   argv += optind;   argv += optind;
55   if (argv[0]) {   if (argv[0]) {
56   fname = argv[0];   fname = argv[0];
57   }   }
58   mode = O_CREAT|O_TRUNC|O_WRONLY;   mode = O_CREAT|O_TRUNC|O_WRONLY;
59   if (opt & 1) {   if (opt & OPT_a) {
60   mode = O_CREAT|O_APPEND|O_WRONLY;   mode = O_CREAT|O_APPEND|O_WRONLY;
61   }   }
62   if (opt & 2) {   if (opt & OPT_c) {
63   shell_opt[1] = 'c';   shell_opt[1] = 'c';
64   }   }
65   if (!(opt & 8)) { /* not -q */   if (!(opt & OPT_q)) {
66   printf("Script started, file is %s\n", fname);   printf("Script started, file is %s\n", fname);
67   }   }
68   shell = getenv("SHELL");   shell = getenv("SHELL");
# Line 83  int script_main(int argc UNUSED_PARAM, c Line 84  int script_main(int argc UNUSED_PARAM, c
84   /* "script" from util-linux exits when child exits,   /* "script" from util-linux exits when child exits,
85   * we wouldn't wait for EOF from slave pty   * we wouldn't wait for EOF from slave pty
86   * (output may be produced by grandchildren of child) */   * (output may be produced by grandchildren of child) */
87   signal(SIGCHLD, handle_sigchld);   signal(SIGCHLD, record_signo);
88    
89   /* TODO: SIGWINCH? pass window size changes down to slave? */   /* TODO: SIGWINCH? pass window size changes down to slave? */
90    
# Line 97  int script_main(int argc UNUSED_PARAM, c Line 98  int script_main(int argc UNUSED_PARAM, c
98  #define buf bb_common_bufsiz1  #define buf bb_common_bufsiz1
99   struct pollfd pfd[2];   struct pollfd pfd[2];
100   int outfd, count, loop;   int outfd, count, loop;
101     double oldtime = ENABLE_SCRIPTREPLAY ? time(NULL) : 0;
102     smallint fd_count = 2;
103    
104   outfd = xopen(fname, mode);   outfd = xopen(fname, mode);
105   pfd[0].fd = pty;   pfd[0].fd = pty;
106   pfd[0].events = POLLIN;   pfd[0].events = POLLIN;
107   pfd[1].fd = 0;   pfd[1].fd = STDIN_FILENO;
108   pfd[1].events = POLLIN;   pfd[1].events = POLLIN;
109   ndelay_on(pty); /* this descriptor is not shared, can do this */   ndelay_on(pty); /* this descriptor is not shared, can do this */
110   /* ndelay_on(0); - NO, stdin can be shared! Pity :( */   /* ndelay_on(STDIN_FILENO); - NO, stdin can be shared! Pity :( */
111    
112   /* copy stdin to pty master input,   /* copy stdin to pty master input,
113   * copy pty master output to stdout and file */   * copy pty master output to stdout and file */
114   /* TODO: don't use full_write's, use proper write buffering */   /* TODO: don't use full_write's, use proper write buffering */
115   while (fd_count) {   while (fd_count && !bb_got_signal) {
116   /* not safe_poll! we want SIGCHLD to EINTR poll */   /* not safe_poll! we want SIGCHLD to EINTR poll */
117   if (poll(pfd, fd_count, -1) < 0 && errno != EINTR) {   if (poll(pfd, fd_count, -1) < 0 && errno != EINTR) {
118   /* If child exits too quickly, we may get EIO:   /* If child exits too quickly, we may get EIO:
# Line 124  int script_main(int argc UNUSED_PARAM, c Line 127  int script_main(int argc UNUSED_PARAM, c
127   goto restore;   goto restore;
128   }   }
129   if (count > 0) {   if (count > 0) {
130     if (ENABLE_SCRIPTREPLAY && (opt & OPT_t)) {
131     struct timeval tv;
132     double newtime;
133    
134     gettimeofday(&tv, NULL);
135     newtime = tv.tv_sec + (double) tv.tv_usec / 1000000;
136     fprintf(stderr, "%f %u\n", newtime - oldtime, count);
137     oldtime = newtime;
138     }
139   full_write(STDOUT_FILENO, buf, count);   full_write(STDOUT_FILENO, buf, count);
140   full_write(outfd, buf, count);   full_write(outfd, buf, count);
141   if (opt & 4) { /* -f */   if (opt & OPT_f) {
142   fsync(outfd);   fsync(outfd);
143   }   }
144   }   }
# Line 142  int script_main(int argc UNUSED_PARAM, c Line 154  int script_main(int argc UNUSED_PARAM, c
154   }   }
155   }   }
156   }   }
157   /* If loop was exited because SIGCHLD handler set fd_count to 0,   /* If loop was exited because SIGCHLD handler set bb_got_signal,
158   * there still can be some buffered output. But not loop forever:   * there still can be some buffered output. But dont loop forever:
159   * we won't pump orphaned grandchildren's output indefinitely.   * we won't pump orphaned grandchildren's output indefinitely.
160   * Testcase: running this in script:   * Testcase: running this in script:
161   *      exec dd if=/dev/zero bs=1M count=1   *      exec dd if=/dev/zero bs=1M count=1
# Line 158  int script_main(int argc UNUSED_PARAM, c Line 170  int script_main(int argc UNUSED_PARAM, c
170   restore:   restore:
171   if (attr_ok == 0)   if (attr_ok == 0)
172   tcsetattr(0, TCSAFLUSH, &tt);   tcsetattr(0, TCSAFLUSH, &tt);
173   if (!(opt & 8)) /* not -q */   if (!(opt & OPT_q))
174   printf("Script done, file is %s\n", fname);   printf("Script done, file is %s\n", fname);
175   return EXIT_SUCCESS;   return EXIT_SUCCESS;
176   }   }
# Line 181  int script_main(int argc UNUSED_PARAM, c Line 193  int script_main(int argc UNUSED_PARAM, c
193    
194   /* Non-ignored signals revert to SIG_DFL on exec anyway */   /* Non-ignored signals revert to SIG_DFL on exec anyway */
195   /*signal(SIGCHLD, SIG_DFL);*/   /*signal(SIGCHLD, SIG_DFL);*/
196   execl(shell, shell, shell_opt, shell_arg, NULL);   execl(shell, shell, shell_opt, shell_arg, (char *) NULL);
197   bb_simple_perror_msg_and_die(shell);   bb_simple_perror_msg_and_die(shell);
198  }  }

Legend:
Removed from v.983  
changed lines
  Added in v.984