Magellan Linux

Diff of /trunk/mkinitrd-magellan/busybox/libbb/xfuncs.c

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

revision 815 by niro, Sat Sep 1 22:45:15 2007 UTC revision 816 by niro, Fri Apr 24 18:33:46 2009 UTC
# Line 4  Line 4 
4   *   *
5   * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>   * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
6   * Copyright (C) 2006 Rob Landley   * Copyright (C) 2006 Rob Landley
7   * Copyright (C) 2006 Denis Vlasenko   * Copyright (C) 2006 Denys Vlasenko
8   *   *
9   * Licensed under GPL version 2, see file LICENSE in this tarball for details.   * Licensed under GPL version 2, see file LICENSE in this tarball for details.
10   */   */
11    
12  #include "busybox.h"  /* We need to have separate xfuncs.c and xfuncs_printf.c because
13     * with current linkers, even with section garbage collection,
14  /* All the functions starting with "x" call bb_error_msg_and_die() if they   * if *.o module references any of XXXprintf functions, you pull in
15   * fail, so callers never need to check for errors.  If it returned, it   * entire printf machinery. Even if you do not use the function
16   * succeeded. */   * which uses XXXprintf.
17     *
18  #ifndef DMALLOC   * xfuncs.c contains functions (not necessarily xfuncs)
19  /* dmalloc provides variants of these that do abort() on failure.   * which do not pull in printf, directly or indirectly.
20   * Since dmalloc's prototypes overwrite the impls here as they are   * xfunc_printf.c contains those which do.
21   * included after these prototypes in libbb.h, all is well.   *
22     * TODO: move xmalloc() and xatonum() here.
23   */   */
 // Die if we can't allocate size bytes of memory.  
 void *xmalloc(size_t size)  
 {  
  void *ptr = malloc(size);  
  if (ptr == NULL && size != 0)  
  bb_error_msg_and_die(bb_msg_memory_exhausted);  
  return ptr;  
 }  
   
 // Die if we can't resize previously allocated memory.  (This returns a pointer  
 // to the new memory, which may or may not be the same as the old memory.  
 // It'll copy the contents to a new chunk and free the old one if necessary.)  
 void *xrealloc(void *ptr, size_t size)  
 {  
  ptr = realloc(ptr, size);  
  if (ptr == NULL && size != 0)  
  bb_error_msg_and_die(bb_msg_memory_exhausted);  
  return ptr;  
 }  
 #endif /* DMALLOC */  
   
 // Die if we can't allocate and zero size bytes of memory.  
 void *xzalloc(size_t size)  
 {  
  void *ptr = xmalloc(size);  
  memset(ptr, 0, size);  
  return ptr;  
 }  
   
 // Die if we can't copy a string to freshly allocated memory.  
 char * xstrdup(const char *s)  
 {  
  char *t;  
   
  if (s == NULL)  
  return NULL;  
   
  t = strdup(s);  
   
  if (t == NULL)  
  bb_error_msg_and_die(bb_msg_memory_exhausted);  
   
  return t;  
 }  
   
 // Die if we can't allocate n+1 bytes (space for the null terminator) and copy  
 // the (possibly truncated to length n) string into it.  
 char * xstrndup(const char *s, int n)  
 {  
  int m;  
  char *t;  
   
  if (ENABLE_DEBUG && s == NULL)  
  bb_error_msg_and_die("xstrndup bug");  
   
  /* We can just xmalloc(n+1) and strncpy into it, */  
  /* but think about xstrndup("abc", 10000) wastage! */  
  m = n;  
  t = (char*) s;  
  while (m) {  
  if (!*t) break;  
  m--;  
  t++;  
  }  
  n -= m;  
  t = xmalloc(n + 1);  
  t[n] = '\0';  
   
  return memcpy(t, s, n);  
 }  
   
 // Die if we can't open a file and return a FILE * to it.  
 // Notice we haven't got xfread(), This is for use with fscanf() and friends.  
 FILE *xfopen(const char *path, const char *mode)  
 {  
  FILE *fp = fopen(path, mode);  
  if (fp == NULL)  
  bb_perror_msg_and_die("%s", path);  
  return fp;  
 }  
   
 // Die if we can't open an existing file and return an fd.  
 int xopen(const char *pathname, int flags)  
 {  
  //if (ENABLE_DEBUG && (flags & O_CREAT))  
  // bb_error_msg_and_die("xopen() with O_CREAT");  
   
  return xopen3(pathname, flags, 0666);  
 }  
   
 // Die if we can't open a new file and return an fd.  
 int xopen3(const char *pathname, int flags, int mode)  
 {  
  int ret;  
24    
25   ret = open(pathname, flags, mode);  #include "libbb.h"
  if (ret < 0) {  
  bb_perror_msg_and_die("%s", pathname);  
  }  
  return ret;  
 }  
26    
27  // Turn on nonblocking I/O on a fd  /* Turn on nonblocking I/O on a fd */
28  int ndelay_on(int fd)  int FAST_FUNC ndelay_on(int fd)
29  {  {
30   return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) | O_NONBLOCK);   return fcntl(fd, F_SETFL, fcntl(fd,F_GETFL) | O_NONBLOCK);
31  }  }
32    
33  int ndelay_off(int fd)  int FAST_FUNC ndelay_off(int fd)
34  {  {
35   return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) & ~O_NONBLOCK);   return fcntl(fd, F_SETFL, fcntl(fd,F_GETFL) & ~O_NONBLOCK);
36  }  }
37    
38  // Die with an error message if we can't write the entire buffer.  int FAST_FUNC close_on_exec_on(int fd)
 void xwrite(int fd, const void *buf, size_t count)  
39  {  {
40   if (count) {   return fcntl(fd, F_SETFD, FD_CLOEXEC);
  ssize_t size = full_write(fd, buf, count);  
  if (size != count)  
  bb_error_msg_and_die("short write");  
  }  
41  }  }
42    
43  // Die with an error message if we can't lseek to the right spot.  /* Convert unsigned long long value into compact 4-char
44  off_t xlseek(int fd, off_t offset, int whence)   * representation. Examples: "1234", "1.2k", " 27M", "123T"
45     * String is not terminated (buf[4] is untouched) */
46    void FAST_FUNC smart_ulltoa4(unsigned long long ul, char buf[5], const char *scale)
47  {  {
48   off_t off = lseek(fd, offset, whence);   const char *fmt;
49   if (off == (off_t)-1) {   char c;
50   if (whence == SEEK_SET)   unsigned v, u, idx = 0;
  bb_perror_msg_and_die("lseek(%"OFF_FMT"u)", offset);  
  bb_perror_msg_and_die("lseek");  
  }  
  return off;  
 }  
   
 // Die with supplied filename if this FILE * has ferror set.  
 void die_if_ferror(FILE *fp, const char *fn)  
 {  
  if (ferror(fp)) {  
  bb_error_msg_and_die("%s: I/O error", fn);  
  }  
 }  
   
 // Die with an error message if stdout has ferror set.  
 void die_if_ferror_stdout(void)  
 {  
  die_if_ferror(stdout, bb_msg_standard_output);  
 }  
51    
52  // Die with an error message if we have trouble flushing stdout.   if (ul > 9999) { // do not scale if 9999 or less
53  void xfflush_stdout(void)   ul *= 10;
54  {   do {
55   if (fflush(stdout)) {   ul /= 1024;
56   bb_perror_msg_and_die(bb_msg_standard_output);   idx++;
57     } while (ul >= 10000);
58   }   }
59  }   v = ul; // ullong divisions are expensive, avoid them
   
 // This does a fork/exec in one call, using vfork().  Return PID of new child,  
 // -1 for failure.  Runs argv[0], searching path if that has no / in it.  
 pid_t spawn(char **argv)  
 {  
  /* Why static? */  
  static int failed;  
  pid_t pid;  
  void *app = ENABLE_FEATURE_SH_STANDALONE_SHELL ? find_applet_by_name(argv[0]) : 0;  
   
  // Be nice to nommu machines.  
  failed = 0;  
  pid = vfork();  
  if (pid < 0) return pid;  
  if (!pid) {  
  execvp(app ? CONFIG_BUSYBOX_EXEC_PATH : *argv, argv);  
   
  // We're sharing a stack with blocked parent, let parent know we failed  
  // and then exit to unblock parent (but don't run atexit() stuff, which  
  // would screw up parent.)  
60    
61   failed = errno;   fmt = " 123456789";
62   _exit(0);   u = v / 10;
63   }   v = v % 10;
64   if (failed) {   if (!idx) {
65   errno = failed;   // 9999 or less: use "1234" format
66   return -1;   // u is value/10, v is last digit
67     c = buf[0] = " 123456789"[u/100];
68     if (c != ' ') fmt = "0123456789";
69     c = buf[1] = fmt[u/10%10];
70     if (c != ' ') fmt = "0123456789";
71     buf[2] = fmt[u%10];
72     buf[3] = "0123456789"[v];
73     } else {
74     // u is value, v is 1/10ths (allows for 9.2M format)
75     if (u >= 10) {
76     // value is >= 10: use "123M', " 12M" formats
77     c = buf[0] = " 123456789"[u/100];
78     if (c != ' ') fmt = "0123456789";
79     v = u % 10;
80     u = u / 10;
81     buf[1] = fmt[u%10];
82     } else {
83     // value is < 10: use "9.2M" format
84     buf[0] = "0123456789"[u];
85     buf[1] = '.';
86     }
87     buf[2] = "0123456789"[v];
88     buf[3] = scale[idx]; /* typically scale = " kmgt..." */
89   }   }
  return pid;  
 }  
   
 // Die with an error message if we can't spawn a child process.  
 pid_t xspawn(char **argv)  
 {  
  pid_t pid = spawn(argv);  
  if (pid < 0) bb_perror_msg_and_die("%s", *argv);  
  return pid;  
 }  
   
 // Wait for the specified child PID to exit, returning child's error return.  
 int wait4pid(int pid)  
 {  
  int status;  
   
  if (pid == -1 || waitpid(pid, &status, 0) == -1) return -1;  
  if (WIFEXITED(status)) return WEXITSTATUS(status);  
  if (WIFSIGNALED(status)) return WTERMSIG(status);  
  return 0;  
 }  
   
 void xsetenv(const char *key, const char *value)  
 {  
  if (setenv(key, value, 1))  
  bb_error_msg_and_die(bb_msg_memory_exhausted);  
90  }  }
91    
92  // Converts unsigned long long value into compact 4-char  /* Convert unsigned long long value into compact 5-char representation.
93  // representation. Examples: "1234", "1.2k", " 27M", "123T"   * String is not terminated (buf[5] is untouched) */
94  // Fifth char is always '\0'  void FAST_FUNC smart_ulltoa5(unsigned long long ul, char buf[6], const char *scale)
 void smart_ulltoa5(unsigned long long ul, char buf[5])  
95  {  {
96   char *fmt;   const char *fmt;
97   char c;   char c;
98   unsigned v,idx = 0;   unsigned v, u, idx = 0;
99   ul *= 10;  
100   if (ul > 9999*10) { // do not scale if 9999 or less   if (ul > 99999) { // do not scale if 99999 or less
101   while (ul >= 10000) {   ul *= 10;
102     do {
103   ul /= 1024;   ul /= 1024;
104   idx++;   idx++;
105   }   } while (ul >= 100000);
106   }   }
107   v = ul; // ullong divisions are expensive, avoid them   v = ul; // ullong divisions are expensive, avoid them
108    
109   fmt = " 123456789";   fmt = " 123456789";
110   if (!idx) { // 9999 or less: use 1234 format   u = v / 10;
111   c = buf[0] = " 123456789"[v/10000];   v = v % 10;
112   if (c!=' ') fmt = "0123456789";   if (!idx) {
113   c = buf[1] = fmt[v/1000%10];   // 99999 or less: use "12345" format
114   if (c!=' ') fmt = "0123456789";   // u is value/10, v is last digit
115   buf[2] = fmt[v/100%10];   c = buf[0] = " 123456789"[u/1000];
116   buf[3] = "0123456789"[v/10%10];   if (c != ' ') fmt = "0123456789";
117     c = buf[1] = fmt[u/100%10];
118     if (c != ' ') fmt = "0123456789";
119     c = buf[2] = fmt[u/10%10];
120     if (c != ' ') fmt = "0123456789";
121     buf[3] = fmt[u%10];
122     buf[4] = "0123456789"[v];
123   } else {   } else {
124   if (v>=10*10) { // scaled value is >=10: use 123M format   // value has been scaled into 0..9999.9 range
125   c = buf[0] = " 123456789"[v/1000];   // u is value, v is 1/10ths (allows for 92.1M format)
126   if (c!=' ') fmt = "0123456789";   if (u >= 100) {
127   buf[1] = fmt[v/100%10];   // value is >= 100: use "1234M', " 123M" formats
128   buf[2] = "0123456789"[v/10%10];   c = buf[0] = " 123456789"[u/1000];
129   } else { // scaled value is <10: use 1.2M format   if (c != ' ') fmt = "0123456789";
130   buf[0] = "0123456789"[v/10];   c = buf[1] = fmt[u/100%10];
131   buf[1] = '.';   if (c != ' ') fmt = "0123456789";
132   buf[2] = "0123456789"[v%10];   v = u % 10;
133     u = u / 10;
134     buf[2] = fmt[u%10];
135     } else {
136     // value is < 100: use "92.1M" format
137     c = buf[0] = " 123456789"[u/10];
138     if (c != ' ') fmt = "0123456789";
139     buf[1] = fmt[u%10];
140     buf[2] = '.';
141   }   }
142   // see http://en.wikipedia.org/wiki/Tera   buf[3] = "0123456789"[v];
143   buf[3] = " kMGTPEZY"[idx];   buf[4] = scale[idx]; /* typically scale = " kmgt..." */
144   }   }
  buf[4] = '\0';  
145  }  }
146    
147  // Convert unsigned integer to ascii, writing into supplied buffer.  A  
148  // truncated result is always null terminated (unless buflen is 0), and  // Convert unsigned integer to ascii, writing into supplied buffer.
149  // contains the first few digits of the result ala strncpy.  // A truncated result contains the first few digits of the result ala strncpy.
150    // Returns a pointer past last generated digit, does _not_ store NUL.
151  void BUG_sizeof_unsigned_not_4(void);  void BUG_sizeof_unsigned_not_4(void);
152  void utoa_to_buf(unsigned n, char *buf, unsigned buflen)  char* FAST_FUNC utoa_to_buf(unsigned n, char *buf, unsigned buflen)
153  {  {
154   unsigned i, out, res;   unsigned i, out, res;
155   if (sizeof(unsigned) != 4)   if (sizeof(unsigned) != 4)
# Line 294  void utoa_to_buf(unsigned n, char *buf, Line 165  void utoa_to_buf(unsigned n, char *buf,
165   *buf++ = '0' + res;   *buf++ = '0' + res;
166   }   }
167   }   }
  *buf = '\0';  
168   }   }
169     return buf;
170  }  }
171    
172  // Convert signed integer to ascii, like utoa_to_buf()  /* Convert signed integer to ascii, like utoa_to_buf() */
173  void itoa_to_buf(int n, char *buf, unsigned buflen)  char* FAST_FUNC itoa_to_buf(int n, char *buf, unsigned buflen)
174  {  {
175   if (buflen && n<0) {   if (buflen && n < 0) {
176   n = -n;   n = -n;
177   *buf++ = '-';   *buf++ = '-';
178   buflen--;   buflen--;
179   }   }
180   utoa_to_buf((unsigned)n, buf, buflen);   return utoa_to_buf((unsigned)n, buf, buflen);
181  }  }
182    
183  // The following two functions use a static buffer, so calling either one a  // The following two functions use a static buffer, so calling either one a
184  // second time will overwrite previous results.  // second time will overwrite previous results.
185  //  //
186  // The largest 32 bit integer is -2 billion plus null terminator, or 12 bytes.  // The largest 32 bit integer is -2 billion plus null terminator, or 12 bytes.
187  // Int should always be 32 bits on any remotely Unix-like system, see  // It so happens that sizeof(int) * 3 is enough for 32+ bits.
188  // http://www.unix.org/whitepapers/64bit.html for the reasons why.  // (sizeof(int) * 3 + 2 is correct for any width, even 8-bit)
189    
190  static char local_buf[12];  static char local_buf[sizeof(int) * 3];
191    
192  // Convert unsigned integer to ascii using a static buffer (returned).  // Convert unsigned integer to ascii using a static buffer (returned).
193  char *utoa(unsigned n)  char* FAST_FUNC utoa(unsigned n)
194  {  {
195   utoa_to_buf(n, local_buf, sizeof(local_buf));   *(utoa_to_buf(n, local_buf, sizeof(local_buf))) = '\0';
196    
197   return local_buf;   return local_buf;
198  }  }
199    
200  // Convert signed integer to ascii using a static buffer (returned).  /* Convert signed integer to ascii using a static buffer (returned). */
201  char *itoa(int n)  char* FAST_FUNC itoa(int n)
202  {  {
203   itoa_to_buf(n, local_buf, sizeof(local_buf));   *(itoa_to_buf(n, local_buf, sizeof(local_buf))) = '\0';
204    
205   return local_buf;   return local_buf;
206  }  }
207    
208  // Emit a string of hex representation of bytes  /* Emit a string of hex representation of bytes */
209  char *bin2hex(char *p, const char *cp, int count)  char* FAST_FUNC bin2hex(char *p, const char *cp, int count)
210  {  {
211   while (count) {   while (count) {
212   unsigned char c = *cp++;   unsigned char c = *cp++;
# Line 347  char *bin2hex(char *p, const char *cp, i Line 218  char *bin2hex(char *p, const char *cp, i
218   return p;   return p;
219  }  }
220    
221  // Die with an error message if we can't set gid.  (Because resource limits may  /* Return how long the file at fd is, if there's any way to determine it. */
222  // limit this user to a given number of processes, and if that fills up the  #ifdef UNUSED
223  // setgid() will fail and we'll _still_be_root_, which is bad.)  off_t FAST_FUNC fdlength(int fd)
 void xsetgid(gid_t gid)  
 {  
  if (setgid(gid)) bb_error_msg_and_die("setgid");  
 }  
   
 // Die with an error message if we can't set uid.  (See xsetgid() for why.)  
 void xsetuid(uid_t uid)  
 {  
  if (setuid(uid)) bb_error_msg_and_die("setuid");  
 }  
   
 // Return how long the file at fd is, if there's any way to determine it.  
 off_t fdlength(int fd)  
224  {  {
225   off_t bottom = 0, top = 0, pos;   off_t bottom = 0, top = 0, pos;
226   long size;   long size;
# Line 400  off_t fdlength(int fd) Line 258  off_t fdlength(int fd)
258    
259   return pos + 1;   return pos + 1;
260  }  }
   
 // Die with an error message if we can't malloc() enough space and do an  
 // sprintf() into that space.  
 char *xasprintf(const char *format, ...)  
 {  
  va_list p;  
  int r;  
  char *string_ptr;  
   
 #if 1  
  // GNU extension  
  va_start(p, format);  
  r = vasprintf(&string_ptr, format, p);  
  va_end(p);  
 #else  
  // Bloat for systems that haven't got the GNU extension.  
  va_start(p, format);  
  r = vsnprintf(NULL, 0, format, p);  
  va_end(p);  
  string_ptr = xmalloc(r+1);  
  va_start(p, format);  
  r = vsnprintf(string_ptr, r+1, format, p);  
  va_end(p);  
 #endif  
   
  if (r < 0) bb_error_msg_and_die(bb_msg_memory_exhausted);  
  return string_ptr;  
 }  
   
 #if 0 /* If we will ever meet a libc which hasn't [f]dprintf... */  
 int fdprintf(int fd, const char *format, ...)  
 {  
  va_list p;  
  int r;  
  char *string_ptr;  
   
 #if 1  
  // GNU extension  
  va_start(p, format);  
  r = vasprintf(&string_ptr, format, p);  
  va_end(p);  
 #else  
  // Bloat for systems that haven't got the GNU extension.  
  va_start(p, format);  
  r = vsnprintf(NULL, 0, format, p);  
  va_end(p);  
  string_ptr = xmalloc(r+1);  
  va_start(p, format);  
  r = vsnprintf(string_ptr, r+1, format, p);  
  va_end(p);  
 #endif  
   
  if (r >= 0) {  
  full_write(fd, string_ptr, r);  
  free(string_ptr);  
  }  
  return r;  
 }  
 #endif  
   
 // Die with an error message if we can't copy an entire FILE * to stdout, then  
 // close that file.  
 void xprint_and_close_file(FILE *file)  
 {  
  fflush(stdout);  
  // copyfd outputs error messages for us.  
  if (bb_copyfd_eof(fileno(file), 1) == -1)  
  exit(xfunc_error_retval);  
   
  fclose(file);  
 }  
   
 // Die if we can't chdir to a new path.  
 void xchdir(const char *path)  
 {  
  if (chdir(path))  
  bb_perror_msg_and_die("chdir(%s)", path);  
 }  
   
 // Print a warning message if opendir() fails, but don't die.  
 DIR *warn_opendir(const char *path)  
 {  
  DIR *dp;  
   
  if ((dp = opendir(path)) == NULL) {  
  bb_perror_msg("cannot open '%s'", path);  
  return NULL;  
  }  
  return dp;  
 }  
   
 // Die with an error message if opendir() fails.  
 DIR *xopendir(const char *path)  
 {  
  DIR *dp;  
   
  if ((dp = opendir(path)) == NULL)  
  bb_perror_msg_and_die("cannot open '%s'", path);  
  return dp;  
 }  
   
 #ifndef BB_NOMMU  
 // Die with an error message if we can't daemonize.  
 void xdaemon(int nochdir, int noclose)  
 {  
  if (daemon(nochdir, noclose))  
  bb_perror_msg_and_die("daemon");  
 }  
261  #endif  #endif
262    
 void bb_sanitize_stdio_maybe_daemonize(int daemonize)  
 {  
  int fd;  
  /* Mega-paranoid */  
  fd = xopen(bb_dev_null, O_RDWR);  
  while (fd < 2)  
  fd = dup(fd); /* have 0,1,2 open at least to /dev/null */  
  if (daemonize) {  
  pid_t pid = fork();  
  if (pid < 0) /* wtf? */  
  bb_perror_msg_and_die("fork");  
  if (pid) /* parent */  
  exit(0);  
      /* child */  
  /* if daemonizing, make sure we detach from stdio */  
  setsid();  
  dup2(fd, 0);  
  dup2(fd, 1);  
  dup2(fd, 2);  
  }  
  while (fd > 2)  
  close(fd--); /* close everything after fd#2 */  
 }  
 void bb_sanitize_stdio(void)  
 {  
  bb_sanitize_stdio_maybe_daemonize(0);  
 }  
 void bb_daemonize(void)  
 {  
  bb_sanitize_stdio_maybe_daemonize(1);  
 }  
   
 // Die with an error message if we can't open a new socket.  
 int xsocket(int domain, int type, int protocol)  
 {  
  int r = socket(domain, type, protocol);  
   
  if (r < 0) bb_perror_msg_and_die("socket");  
   
  return r;  
 }  
   
 // Die with an error message if we can't bind a socket to an address.  
 void xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen)  
 {  
  if (bind(sockfd, my_addr, addrlen)) bb_perror_msg_and_die("bind");  
 }  
   
 // Die with an error message if we can't listen for connections on a socket.  
 void xlisten(int s, int backlog)  
 {  
  if (listen(s, backlog)) bb_perror_msg_and_die("listen");  
 }  
   
 // xstat() - a stat() which dies on failure with meaningful error message  
 void xstat(char *name, struct stat *stat_buf)  
 {  
  if (stat(name, stat_buf))  
  bb_perror_msg_and_die("can't stat '%s'", name);  
 }  
   
263  /* It is perfectly ok to pass in a NULL for either width or for  /* It is perfectly ok to pass in a NULL for either width or for
264   * height, in which case that value will not be set.  */   * height, in which case that value will not be set.  */
265  int get_terminal_width_height(int fd, int *width, int *height)  int FAST_FUNC get_terminal_width_height(int fd, unsigned *width, unsigned *height)
266  {  {
267   struct winsize win = { 0, 0, 0, 0 };   struct winsize win = { 0, 0, 0, 0 };
268   int ret = ioctl(fd, TIOCGWINSZ, &win);   int ret = ioctl(fd, TIOCGWINSZ, &win);
# Line 600  int get_terminal_width_height(int fd, in Line 289  int get_terminal_width_height(int fd, in
289    
290   return ret;   return ret;
291  }  }
292    
293    int FAST_FUNC tcsetattr_stdin_TCSANOW(const struct termios *tp)
294    {
295     return tcsetattr(STDIN_FILENO, TCSANOW, tp);
296    }

Legend:
Removed from v.815  
changed lines
  Added in v.816