Magellan Linux

Diff of /trunk/mkinitrd-magellan/busybox/miscutils/chat.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 9  Line 9 
9   */   */
10  #include "libbb.h"  #include "libbb.h"
11    
 /*  
 #define ENABLE_FEATURE_CHAT_NOFAIL              1 // +126 bytes  
 #define ENABLE_FEATURE_CHAT_TTY_HIFI            0 // + 70 bytes  
 #define ENABLE_FEATURE_CHAT_IMPLICIT_CR         1 // + 44 bytes  
 #define ENABLE_FEATURE_CHAT_SEND_ESCAPES        0 // +103 bytes  
 #define ENABLE_FEATURE_CHAT_VAR_ABORT_LEN       0 // + 70 bytes  
 #define ENABLE_FEATURE_CHAT_CLR_ABORT           0 // +113 bytes  
 #define ENABLE_FEATURE_CHAT_SWALLOW_OPTS        0 // + 23 bytes  
 */  
   
12  // default timeout: 45 sec  // default timeout: 45 sec
13  #define DEFAULT_CHAT_TIMEOUT 45*1000  #define DEFAULT_CHAT_TIMEOUT 45*1000
14  // max length of "abort string",  // max length of "abort string",
# Line 37  enum { Line 27  enum {
27  };  };
28    
29  // exit code  // exit code
30  // N.B> 10 bytes for volatile. Why all these signals?!  #define exitcode bb_got_signal
 static /*volatile*/ smallint exitcode;  
31    
32  // trap for critical signals  // trap for critical signals
33  static void signal_handler(UNUSED_PARAM int signo)  static void signal_handler(UNUSED_PARAM int signo)
# Line 101  static size_t unescape(char *s, int *noc Line 90  static size_t unescape(char *s, int *noc
90   return p - start;   return p - start;
91  }  }
92    
   
93  int chat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;  int chat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
94  int chat_main(int argc UNUSED_PARAM, char **argv)  int chat_main(int argc UNUSED_PARAM, char **argv)
95  {  {
96  // should we dump device output? to what fd? by default no.   int record_fd = -1;
 // this can be controlled later via ECHO {ON|OFF} chat directive  
 // int echo_fd;  
97   bool echo = 0;   bool echo = 0;
98   // collection of device replies which cause unconditional termination   // collection of device replies which cause unconditional termination
99   llist_t *aborts = NULL;   llist_t *aborts = NULL;
# Line 132  int chat_main(int argc UNUSED_PARAM, cha Line 118  int chat_main(int argc UNUSED_PARAM, cha
118   DIR_TIMEOUT,   DIR_TIMEOUT,
119   DIR_ECHO,   DIR_ECHO,
120   DIR_SAY,   DIR_SAY,
121     DIR_RECORD,
122   };   };
123    
124   // make x* functions fail with correct exitcode   // make x* functions fail with correct exitcode
# Line 166  int chat_main(int argc UNUSED_PARAM, cha Line 153  int chat_main(int argc UNUSED_PARAM, cha
153  #if ENABLE_FEATURE_CHAT_CLR_ABORT  #if ENABLE_FEATURE_CHAT_CLR_ABORT
154   "CLR_ABORT\0"   "CLR_ABORT\0"
155  #endif  #endif
156   "TIMEOUT\0" "ECHO\0" "SAY\0"   "TIMEOUT\0" "ECHO\0" "SAY\0" "RECORD\0"
157   , *argv   , *argv
158   );   );
159   if (key >= 0) {   if (key >= 0) {
160   // cache directive value   // cache directive value
161   char *arg = *++argv;   char *arg = *++argv;
162   // ON -> 1, anything else -> 0   // OFF -> 0, anything else -> 1
163   bool onoff = !strcmp("ON", arg);   bool onoff = (0 != strcmp("OFF", arg));
164   // process directive   // process directive
165   if (DIR_HANGUP == key) {   if (DIR_HANGUP == key) {
166   // turn SIGHUP on/off   // turn SIGHUP on/off
# Line 217  int chat_main(int argc UNUSED_PARAM, cha Line 204  int chat_main(int argc UNUSED_PARAM, cha
204   timeout = DEFAULT_CHAT_TIMEOUT;   timeout = DEFAULT_CHAT_TIMEOUT;
205   } else if (DIR_ECHO == key) {   } else if (DIR_ECHO == key) {
206   // turn echo on/off   // turn echo on/off
207   // N.B. echo means dumping output   // N.B. echo means dumping device input/output to stderr
  // from stdin (device) to stderr  
208   echo = onoff;   echo = onoff;
209  //TODO? echo_fd = onoff * STDERR_FILENO;   } else if (DIR_RECORD == key) {
210  //TODO? echo_fd = xopen(arg, O_WRONLY|O_CREAT|O_TRUNC);   // turn record on/off
211     // N.B. record means dumping device input to a file
212     // close previous record_fd
213     if (record_fd > 0)
214     close(record_fd);
215     // N.B. do we have to die here on open error?
216     record_fd = (onoff) ? xopen(arg, O_WRONLY|O_CREAT|O_TRUNC) : -1;
217   } else if (DIR_SAY == key) {   } else if (DIR_SAY == key) {
218   // just print argument verbatim   // just print argument verbatim
219   fprintf(stderr, arg);   // TODO: should we use full_write() to avoid unistd/stdio conflict?
220     bb_error_msg("%s", arg);
221   }   }
222   // next, please!   // next, please!
223   argv++;   argv++;
# Line 288  int chat_main(int argc UNUSED_PARAM, cha Line 281  int chat_main(int argc UNUSED_PARAM, cha
281    
282   // read next char from device   // read next char from device
283   if (safe_read(STDIN_FILENO, buf+buf_len, 1) > 0) {   if (safe_read(STDIN_FILENO, buf+buf_len, 1) > 0) {
284   // dump device output if ECHO ON or RECORD fname   // dump device input if RECORD fname
285  //TODO? if (echo_fd > 0) {   if (record_fd > 0) {
286  //TODO? full_write(echo_fd, buf+buf_len, 1);   full_write(record_fd, buf+buf_len, 1);
287  //TODO? }   }
288   if (echo > 0)   // dump device input if ECHO ON
289     if (echo > 0) {
290    // if (buf[buf_len] < ' ') {
291    // full_write(STDERR_FILENO, "^", 1);
292    // buf[buf_len] += '@';
293    // }
294   full_write(STDERR_FILENO, buf+buf_len, 1);   full_write(STDERR_FILENO, buf+buf_len, 1);
295     }
296   buf_len++;   buf_len++;
297   // move input frame if we've reached higher bound   // move input frame if we've reached higher bound
298   if (buf_len > COMMON_BUFSIZE) {   if (buf_len > COMMON_BUFSIZE) {
# Line 320  int chat_main(int argc UNUSED_PARAM, cha Line 319  int chat_main(int argc UNUSED_PARAM, cha
319   if (delta >= 0 && !memcmp(buf+delta, expect, expect_len))   if (delta >= 0 && !memcmp(buf+delta, expect, expect_len))
320   goto expect_done;   goto expect_done;
321  #undef buf  #undef buf
322   }   } /* while (have data) */
323    
324   // device timed out or unexpected reply received   // device timed out or unexpected reply received
325   exitcode = ERR_TIMEOUT;   exitcode = ERR_TIMEOUT;
# Line 365  int chat_main(int argc UNUSED_PARAM, cha Line 364  int chat_main(int argc UNUSED_PARAM, cha
364   trim(++buf);   trim(++buf);
365   buf = loaded = xmalloc_xopen_read_close(buf, NULL);   buf = loaded = xmalloc_xopen_read_close(buf, NULL);
366   }   }
   
367   // expand escape sequences in command   // expand escape sequences in command
368   len = unescape(buf, &nocr);   len = unescape(buf, &nocr);
369    
370   // send command   // send command
371  #if ENABLE_FEATURE_CHAT_SEND_ESCAPES   alarm(timeout);
372   pfd.fd = STDOUT_FILENO;   pfd.fd = STDOUT_FILENO;
373   pfd.events = POLLOUT;   pfd.events = POLLOUT;
374   while (len && !exitcode   while (len && !exitcode
375      && poll(&pfd, 1, timeout) > 0      && poll(&pfd, 1, -1) > 0
376      && (pfd.revents & POLLOUT)      && (pfd.revents & POLLOUT)
377   ) {   ) {
378   // ugly! ugly! ugly!  #if ENABLE_FEATURE_CHAT_SEND_ESCAPES
  // gotta send char by char to achieve this!  
  // Brrr...  
379   // "\\d" means 1 sec delay, "\\p" means 0.01 sec delay   // "\\d" means 1 sec delay, "\\p" means 0.01 sec delay
380   // "\\K" means send BREAK   // "\\K" means send BREAK
381   char c = *buf;   char c = *buf;
# Line 389  int chat_main(int argc UNUSED_PARAM, cha Line 385  int chat_main(int argc UNUSED_PARAM, cha
385   sleep(1);   sleep(1);
386   len--;   len--;
387   continue;   continue;
388   } else if ('p' == c) {   }
389     if ('p' == c) {
390   usleep(10000);   usleep(10000);
391   len--;   len--;
392   continue;   continue;
393   } else if ('K' == c) {   }
394     if ('K' == c) {
395   tcsendbreak(STDOUT_FILENO, 0);   tcsendbreak(STDOUT_FILENO, 0);
396   len--;   len--;
397   continue;   continue;
  } else {  
  buf--;  
398   }   }
399     buf--;
400   }   }
401   if (safe_write(STDOUT_FILENO, buf, 1) > 0) {   if (safe_write(STDOUT_FILENO, buf, 1) != 1)
  len--;  
  buf++;  
  } else  
402   break;   break;
403   }   len--;
404     buf++;
405  #else  #else
 // if (len) {  
  alarm(timeout);  
406   len -= full_write(STDOUT_FILENO, buf, len);   len -= full_write(STDOUT_FILENO, buf, len);
  alarm(0);  
 // }  
407  #endif  #endif
408     } /* while (can write) */
409     alarm(0);
410    
411   // report I/O error if there still exists at least one non-sent char   // report I/O error if there still exists at least one non-sent char
412   if (len)   if (len)
# Line 427  int chat_main(int argc UNUSED_PARAM, cha Line 420  int chat_main(int argc UNUSED_PARAM, cha
420   else if (!nocr)   else if (!nocr)
421   xwrite(STDOUT_FILENO, "\r", 1);   xwrite(STDOUT_FILENO, "\r", 1);
422  #endif  #endif
   
423   // bail out unless we sent command successfully   // bail out unless we sent command successfully
424   if (exitcode)   if (exitcode)
425   break;   break;
426     } /* if (*argv) */
  }  
427   }   }
428   }   } /* while (*argv) */
429    
430  #if ENABLE_FEATURE_CHAT_TTY_HIFI  #if ENABLE_FEATURE_CHAT_TTY_HIFI
431   tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio0);   tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio0);

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