-extern void complain_copyfd_and_die(off_t sz) ATTRIBUTE_NORETURN;
-extern char bb_process_escape_sequence(const char **ptr);
-/* TODO: sometimes modifies its parameter, which
- * makes it rather inconvenient at times: */
-extern char *bb_get_last_path_component(char *path);
-
-int ndelay_on(int fd);
-int ndelay_off(int fd);
-void xdup2(int, int);
-void xmove_fd(int, int);
-
-
-DIR *xopendir(const char *path);
-DIR *warn_opendir(const char *path);
-
-char *xrealloc_getcwd_or_warn(char *cwd);
-char *xmalloc_readlink_or_warn(const char *path);
-char *xmalloc_realpath(const char *path);
-
-
-//TODO: signal(sid, f) is the same? then why?
-extern void sig_catch(int,void (*)(int));
-//#define sig_ignore(s) (sig_catch((s), SIG_IGN))
-//#define sig_uncatch(s) (sig_catch((s), SIG_DFL))
-extern void sig_block(int);
-extern void sig_unblock(int);
-/* UNUSED: extern void sig_blocknone(void); */
-extern void sig_pause(void);
-
-
-void xsetgid(gid_t gid);
-void xsetuid(uid_t uid);
-void xchdir(const char *path);
-void xsetenv(const char *key, const char *value);
-void xunlink(const char *pathname);
-void xstat(const char *pathname, struct stat *buf);
-int xopen(const char *pathname, int flags);
-int xopen3(const char *pathname, int flags, int mode);
-int open_or_warn(const char *pathname, int flags);
-int open3_or_warn(const char *pathname, int flags, int mode);
-void xpipe(int filedes[2]);
-off_t xlseek(int fd, off_t offset, int whence);
-off_t fdlength(int fd);
-
-int xsocket(int domain, int type, int protocol);
-void xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);
-void xlisten(int s, int backlog);
-void xconnect(int s, const struct sockaddr *s_addr, socklen_t addrlen);
+extern void complain_copyfd_and_die(off_t sz) NORETURN FAST_FUNC;
+extern char bb_process_escape_sequence(const char **ptr) FAST_FUNC;
+/* xxxx_strip version can modify its parameter:
+ * "/" -> "/"
+ * "abc" -> "abc"
+ * "abc/def" -> "def"
+ * "abc/def/" -> "def" !!
+ */
+extern char *bb_get_last_path_component_strip(char *path) FAST_FUNC;
+/* "abc/def/" -> "" and it never modifies 'path' */
+extern char *bb_get_last_path_component_nostrip(const char *path) FAST_FUNC;
+
+int ndelay_on(int fd) FAST_FUNC;
+int ndelay_off(int fd) FAST_FUNC;
+int close_on_exec_on(int fd) FAST_FUNC;
+void xdup2(int, int) FAST_FUNC;
+void xmove_fd(int, int) FAST_FUNC;
+
+
+DIR *xopendir(const char *path) FAST_FUNC;
+DIR *warn_opendir(const char *path) FAST_FUNC;
+
+/* UNUSED: char *xmalloc_realpath(const char *path) FAST_FUNC; */
+char *xmalloc_readlink(const char *path) FAST_FUNC;
+char *xmalloc_readlink_or_warn(const char *path) FAST_FUNC;
+char *xrealloc_getcwd_or_warn(char *cwd) FAST_FUNC;
+
+char *xmalloc_follow_symlinks(const char *path) FAST_FUNC;
+
+
+enum {
+ /* bb_signals(BB_FATAL_SIGS, handler) catches all signals which
+ * otherwise would kill us, except for those resulting from bugs:
+ * SIGSEGV, SIGILL, SIGFPE.
+ * Other fatal signals not included (TODO?):
+ * SIGBUS Bus error (bad memory access)
+ * SIGPOLL Pollable event. Synonym of SIGIO
+ * SIGPROF Profiling timer expired
+ * SIGSYS Bad argument to routine
+ * SIGTRAP Trace/breakpoint trap
+ *
+ * The only known arch with some of these sigs not fitting
+ * into 32 bits is parisc (SIGXCPU=33, SIGXFSZ=34, SIGSTKFLT=36).
+ * Dance around with long long to guard against that...
+ */
+ BB_FATAL_SIGS = (int)(0
+ + (1LL << SIGHUP)
+ + (1LL << SIGINT)
+ + (1LL << SIGTERM)
+ + (1LL << SIGPIPE) // Write to pipe with no readers
+ + (1LL << SIGQUIT) // Quit from keyboard
+ + (1LL << SIGABRT) // Abort signal from abort(3)
+ + (1LL << SIGALRM) // Timer signal from alarm(2)
+ + (1LL << SIGVTALRM) // Virtual alarm clock
+ + (1LL << SIGXCPU) // CPU time limit exceeded
+ + (1LL << SIGXFSZ) // File size limit exceeded
+ + (1LL << SIGUSR1) // Yes kids, these are also fatal!
+ + (1LL << SIGUSR2)
+ + 0),
+};
+void bb_signals(int sigs, void (*f)(int)) FAST_FUNC;
+/* Unlike signal() and bb_signals, sets handler with sigaction()
+ * and in a way that while signal handler is run, no other signals
+ * will be blocked; syscalls will not be restarted: */
+void bb_signals_recursive_norestart(int sigs, void (*f)(int)) FAST_FUNC;
+/* syscalls like read() will be interrupted with EINTR: */
+void signal_no_SA_RESTART_empty_mask(int sig, void (*handler)(int)) FAST_FUNC;
+/* syscalls like read() won't be interrupted (though select/poll will be): */
+void signal_SA_RESTART_empty_mask(int sig, void (*handler)(int)) FAST_FUNC;
+void wait_for_any_sig(void) FAST_FUNC;
+void kill_myself_with_sig(int sig) NORETURN FAST_FUNC;
+void sig_block(int sig) FAST_FUNC;
+void sig_unblock(int sig) FAST_FUNC;
+/* Will do sigaction(signum, act, NULL): */
+int sigaction_set(int sig, const struct sigaction *act) FAST_FUNC;
+/* SIG_BLOCK/SIG_UNBLOCK all signals: */
+int sigprocmask_allsigs(int how) FAST_FUNC;
+/* Standard handler which just records signo */
+extern smallint bb_got_signal;
+void record_signo(int signo); /* not FAST_FUNC! */
+
+
+void xsetgid(gid_t gid) FAST_FUNC;
+void xsetuid(uid_t uid) FAST_FUNC;
+void xchdir(const char *path) FAST_FUNC;
+void xchroot(const char *path) FAST_FUNC;
+void xsetenv(const char *key, const char *value) FAST_FUNC;
+void bb_unsetenv(const char *key) FAST_FUNC;
+void xunlink(const char *pathname) FAST_FUNC;
+void xstat(const char *pathname, struct stat *buf) FAST_FUNC;
+int xopen(const char *pathname, int flags) FAST_FUNC FAST_FUNC;
+int xopen3(const char *pathname, int flags, int mode) FAST_FUNC;
+int open_or_warn(const char *pathname, int flags) FAST_FUNC;
+int open3_or_warn(const char *pathname, int flags, int mode) FAST_FUNC;
+int open_or_warn_stdin(const char *pathname) FAST_FUNC;
+void xrename(const char *oldpath, const char *newpath) FAST_FUNC;
+int rename_or_warn(const char *oldpath, const char *newpath) FAST_FUNC;
+off_t xlseek(int fd, off_t offset, int whence) FAST_FUNC;
+off_t fdlength(int fd) FAST_FUNC;
+
+void xpipe(int filedes[2]) FAST_FUNC;
+/* In this form code with pipes is much more readable */
+struct fd_pair { int rd; int wr; };
+#define piped_pair(pair) pipe(&((pair).rd))
+#define xpiped_pair(pair) xpipe(&((pair).rd))
+
+/* Useful for having small structure members/global variables */
+typedef int8_t socktype_t;
+typedef int8_t family_t;
+struct BUG_too_small {
+ char BUG_socktype_t_too_small[(0
+ | SOCK_STREAM
+ | SOCK_DGRAM
+ | SOCK_RDM
+ | SOCK_SEQPACKET
+ | SOCK_RAW
+ ) <= 127 ? 1 : -1];
+ char BUG_family_t_too_small[(0
+ | AF_UNSPEC
+ | AF_INET
+ | AF_INET6
+ | AF_UNIX
+#ifdef AF_PACKET
+ | AF_PACKET
+#endif
+#ifdef AF_NETLINK
+ | AF_NETLINK
+#endif
+ /* | AF_DECnet */
+ /* | AF_IPX */
+ ) <= 127 ? 1 : -1];
+};
+
+
+int xsocket(int domain, int type, int protocol) FAST_FUNC;
+void xbind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen) FAST_FUNC;
+void xlisten(int s, int backlog) FAST_FUNC;
+void xconnect(int s, const struct sockaddr *s_addr, socklen_t addrlen) FAST_FUNC;