int setup_log() { if ((rploglen =str_len(rplog)) < 7) { warn3x("log must have at least seven characters.", 0, 0); return(0); } if (pipe(logpipe) == -1) { warn3x("unable to create pipe for log.", 0, 0); return(-1); } coe(logpipe[1]); coe(logpipe[0]); ndelay_on(logpipe[0]); ndelay_on(logpipe[1]); if (fd_copy(2, logpipe[1]) == -1) { warn3x("unable to set filedescriptor for log.", 0, 0); return(-1); } io[0].fd =logpipe[0]; io[0].events =IOPAUSE_READ; taia_now(&stamplog); return(1); }
int main(int argc,char **argv) { struct stat st; dir = argv[1]; if (!dir || argv[2]) strerr_die1x(100,"supervise: usage: supervise dir"); if (pipe(selfpipe) == -1) strerr_die4sys(111,FATAL,"unable to create pipe for ",dir,": "); coe(selfpipe[0]); coe(selfpipe[1]); ndelay_on(selfpipe[0]); ndelay_on(selfpipe[1]); sig_block(sig_child); sig_catch(sig_child,trigger); if (chdir(dir) == -1) strerr_die4sys(111,FATAL,"unable to chdir to ",dir,": "); if (stat("down",&st) != -1) flagwantup = 0; else if (errno != error_noent) strerr_die4sys(111,FATAL,"unable to stat ",dir,"/down: "); mkdir("supervise",0700); fdlock = open_append("supervise/lock"); if ((fdlock == -1) || (lock_exnb(fdlock) == -1)) strerr_die4sys(111,FATAL,"unable to acquire ",dir,"/supervise/lock: "); coe(fdlock); fifo_make("supervise/control",0600); fdcontrol = open_read("supervise/control"); if (fdcontrol == -1) strerr_die4sys(111,FATAL,"unable to read ",dir,"/supervise/control: "); coe(fdcontrol); ndelay_on(fdcontrol); /* shouldn't be necessary */ fdcontrolwrite = open_write("supervise/control"); if (fdcontrolwrite == -1) strerr_die4sys(111,FATAL,"unable to write ",dir,"/supervise/control: "); coe(fdcontrolwrite); pidchange(); announce(); fifo_make("supervise/ok",0600); fdok = open_read("supervise/ok"); if (fdok == -1) strerr_die4sys(111,FATAL,"unable to read ",dir,"/supervise/ok: "); coe(fdok); if (!flagwant || flagwantup) trystart(); doit(); announce(); _exit(0); }
int selfpipe_init (void) { if (selfpipe[0] >= 0) return (errno = EBUSY, -1); if (pipe(selfpipe) == -1) return -1; if ((ndelay_on(selfpipe[1]) == -1) || (coe(selfpipe[1]) == -1) || (ndelay_on(selfpipe[0]) == -1) || (coe(selfpipe[0]) == -1)) selfpipe_close(); return selfpipe[0]; }
int ssl_timeoutconn(int t, int rfd, int wfd, SSL *ssl) { int r; /* if connection is established, keep NDELAY */ if (ndelay_on(rfd) == -1 || ndelay_on(wfd) == -1) return -1; r = ssl_timeoutio(SSL_connect, t, rfd, wfd, ssl, NULL, 0); if (r <= 0) { ndelay_off(rfd); ndelay_off(wfd); } else SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE); return r; }
/* Call this before doing anything else. Sets up the socket pair * and installs the signal handler */ void FAST_FUNC udhcp_sp_setup(void) { /* was socketpair, but it needs AF_UNIX in kernel */ xpiped_pair(signal_pipe); close_on_exec_on(signal_pipe.rd); close_on_exec_on(signal_pipe.wr); ndelay_on(signal_pipe.rd); ndelay_on(signal_pipe.wr); bb_signals(0 + (1 << SIGUSR1) + (1 << SIGUSR2) + (1 << SIGTERM) , signal_handler); }
int socket_udp6(void) { #ifdef LIBC_HAS_IP6 int s; if (noipv6) goto compat; s = socket(PF_INET6,SOCK_DGRAM,0); if (s == -1) { if (errno == EINVAL || errno == EAFNOSUPPORT) { compat: s=socket(AF_INET,SOCK_DGRAM,0); noipv6=1; if (s==-1) return -1; } else return -1; } if (ndelay_on(s) == -1) { close(s); return -1; } #ifdef IPV6_V6ONLY { int zero=0; setsockopt(s,IPPROTO_IPV6,IPV6_V6ONLY,(void*)&zero,sizeof(zero)); } #endif return s; #else return socket_udp(); #endif }
int less_main(int argc, char **argv) { int keypress; INIT_G(); /* TODO: -x: do not interpret backspace, -xx: tab also */ /* -xxx: newline also */ /* -w N: assume width N (-xxx -w 32: hex viewer of sorts) */ getopt32(argv, "EMmN~"); argc -= optind; argv += optind; num_files = argc; files = argv; /* Another popular pager, most, detects when stdout * is not a tty and turns into cat. This makes sense. */ if (!isatty(STDOUT_FILENO)) return bb_cat(argv); kbd_fd = open(CURRENT_TTY, O_RDONLY); if (kbd_fd < 0) return bb_cat(argv); ndelay_on(kbd_fd); if (!num_files) { if (isatty(STDIN_FILENO)) { /* Just "less"? No args and no redirection? */ bb_error_msg("missing filename"); bb_show_usage(); } } else filename = xstrdup(files[0]); get_terminal_width_height(kbd_fd, &width, &max_displayed_line); /* 20: two tabstops + 4 */ if (width < 20 || max_displayed_line < 3) return bb_cat(argv); max_displayed_line -= 2; buffer = xmalloc((max_displayed_line+1) * sizeof(char *)); if (option_mask32 & FLAG_TILDE) empty_line_marker = ""; tcgetattr(kbd_fd, &term_orig); term_less = term_orig; term_less.c_lflag &= ~(ICANON | ECHO); term_less.c_iflag &= ~(IXON | ICRNL); /*term_less.c_oflag &= ~ONLCR;*/ term_less.c_cc[VMIN] = 1; term_less.c_cc[VTIME] = 0; /* We want to restore term_orig on exit */ bb_signals(BB_FATAL_SIGS, sig_catcher); reinitialize(); while (1) { keypress = less_getch(-1); /* -1: do not position cursor */ keypress_process(keypress); } }
int conn_sock(struct conn_t *conn, struct in_addr *addr, int port) { struct sockaddr_in server; int sock; memset(&server, 0, sizeof(server)); server.sin_family = AF_INET; server.sin_port = htons(port); server.sin_addr.s_addr = addr->s_addr; if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) > 0) { #if(_debug_) /*log_dbg("SETTING non-blocking");*/ #endif if (ndelay_on(sock) < 0) { log_err(errno, "could not set non-blocking"); } if (safe_connect(sock, (struct sockaddr *) &server, sizeof(server)) < 0) { if (errno != EINPROGRESS) { log_err(errno, "could not connect to %s:%d", inet_ntoa(server.sin_addr), port); close(sock); return -1; } } } conn->sock = sock; return 0; }
int main (int argc, char const *const *argv, char const *const *envp) { unsigned int fd ; int block = 1 ; PROG = "fdblock" ; { subgetopt_t l = SUBGETOPT_ZERO ; for (;;) { register int opt = subgetopt_r(argc, argv, "n", &l) ; if (opt == -1) break ; switch (opt) { case 'n' : block = 0 ; break ; default : strerr_dieusage(100, USAGE) ; } } argc -= l.ind ; argv += l.ind ; } if ((argc < 2) || !uint0_scan(argv[0], &fd)) strerr_dieusage(100, USAGE) ; if ((block ? ndelay_off(fd) : ndelay_on(fd)) < 0) strerr_diefu1sys(111, block ? "ndelay_off" : "ndelay_on") ; pathexec_run(argv[1], argv+1, envp) ; strerr_dieexec(111, argv[1]) ; }
int socket_udp4(void) { int s; __winsock_init(); s = winsock2errno(socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP)); if (s == -1) return -1; if (ndelay_on(s) == -1) { close(s); return -1; } return s; }
int skaserver2_sync (bufalloc *b, char const *before, unsigned int beforelen, char const *after, unsigned int afterlen, struct taia const *deadline, struct taia *stamp) { char const *x = env_get("SKACLIENT_ADDITIONAL_FDS") ; if (x) { unsigned int fd ; if (!uint0_scan(x, &fd)) return (errno = EINVAL, 0) ; if (!bufalloc_put(bufalloc_1, before, beforelen)) return 0 ; if (!timed_bufalloc_flush(bufalloc_1, deadline, stamp)) return 0 ; if (ndelay_on(fd) < 0) return 0 ; bufalloc_init(b, &fd_write, (int)fd) ; if (!bufalloc_put(b, after, afterlen)) return 0 ; if (!timed_bufalloc_flush(b, deadline, stamp)) return 0 ; return 1 ; } else { int p[2] ; if (pipe(p) < 0) return 0 ; if (ndelay_on(p[1]) < 0) goto fail ; if (!bufalloc_put(bufalloc_1, before, beforelen)) goto fail ; { char pack[4] ; uint32_pack_big(pack, 1) ; if (!bufalloc_put(bufalloc_1, pack, 4)) goto fail ; } if (!timed_bufalloc_flush(bufalloc_1, deadline, stamp)) goto fail ; if (!timed_ancil_fd_send(1, p[0], deadline, stamp)) goto fail ; if (!bufalloc_put(bufalloc_1, after, afterlen)) goto fail ; if (!timed_bufalloc_flush(bufalloc_1, deadline, stamp)) goto fail ; #ifndef HASANCILAUTOCLOSE fd_close(p[0]) ; #endif bufalloc_init(b, &fd_write, p[1]) ; return 1 ; fail: { register int e = errno ; fd_close(p[1]) ; fd_close(p[0]) ; errno = e ; } return 0 ; } }
int socket_udp(void) { int s; s = socket(AF_INET,SOCK_DGRAM,0); if (s == -1) return -1; if (ndelay_on(s) == -1) { close(s); return -1; } return s; }
int main (int argc, char const *const *argv, char const *const *envp) { int fd, fd2 ; unsigned int flags = 0 ; int what = -1 ; int changemode = 0 ; PROG = "redirfd" ; { subgetopt_t l = SUBGETOPT_ZERO ; for (;;) { register int opt = subgetopt_r(argc, argv, "rwuacxnb", &l) ; if (opt == -1) break ; switch (opt) { case 'r' : what = O_RDONLY ; flags &= ~(O_APPEND|O_CREAT|O_TRUNC|O_EXCL) ; break ; case 'w' : what = O_WRONLY ; flags |= O_CREAT|O_TRUNC ; flags &= ~(O_APPEND|O_EXCL) ; break ; case 'u' : what = O_RDWR ; flags &= ~(O_APPEND|O_CREAT|O_TRUNC|O_EXCL) ; break ; case 'a' : what = O_WRONLY ; flags |= O_CREAT|O_APPEND ; flags &= ~(O_TRUNC|O_EXCL) ; break ; case 'c' : what = O_WRONLY ; flags |= O_APPEND ; flags &= ~(O_CREAT|O_TRUNC|O_EXCL) ; break ; case 'x' : what = O_WRONLY ; flags |= O_CREAT|O_EXCL ; flags &= ~(O_APPEND|O_TRUNC) ; break ; case 'n' : flags |= O_NONBLOCK ; break ; case 'b' : changemode = 1 ; break ; default : dieusage() ; } } argc -= l.ind ; argv += l.ind ; } if ((argc < 3) || (what == -1)) dieusage() ; if (!uint0_scan(argv[0], (unsigned int *)&fd)) dieusage() ; flags |= what ; fd2 = open3(argv[1], flags, 0666) ; if ((fd2 == -1) && (what == O_WRONLY) && (errno == ENXIO)) { register int e ; int fdr = open_read(argv[1]) ; if (fdr == -1) strerr_diefu2sys(111, "open_read ", argv[1]) ; fd2 = open3(argv[1], flags, 0666) ; e = errno ; fd_close(fdr) ; errno = e ; } if (fd2 == -1) strerr_diefu2sys(111, "open ", argv[1]) ; if (fd_move(fd, fd2) == -1) { char fmt[UINT_FMT] ; fmt[uint_fmt(fmt, fd2)] = 0 ; strerr_diefu4sys(111, "move fd ", fmt, " to fd ", argv[0]) ; } if (changemode) { if (((flags & O_NONBLOCK) ? ndelay_off(fd) : ndelay_on(fd)) < 0) strerr_diefu1sys(111, "change blocking mode") ; } pathexec_run(argv[2], argv+2, envp) ; strerr_dieexec(111, argv[2]) ; }
int socket_tcp() { int s; s = socket(AF_INET,SOCK_STREAM,0); if (s == -1) return -1; if (ndelay_on(s) == -1) { close(s); return -1; } return s; }
int socket_tcp(int domain, int proto) { int s; s = socket(domain,SOCK_STREAM,proto); if (s == -1) return -1; if (ndelay_on(s) == -1) { close(s); return -1; } return s; }
int socket_tcp6(void) { int s; #if defined(LIBC_HAS_IP6) && defined(SOCK_NONBLOCK) if ((s=socket(noipv6?PF_INET:PF_INET6,SOCK_STREAM|SOCK_NONBLOCK,IPPROTO_TCP))>-1 || (errno!=EINVAL && errno!=EAFNOSUPPORT && errno!=EPFNOSUPPORT && errno!=EPROTONOSUPPORT)) return s; #endif s=socket_tcp6b(); if (s==-1) return -1; if (ndelay_on(s) == -1) { close(s); return -1; } return s; }
/* Call this before doing anything else. Sets up the socket pair * and installs the signal handler */ void udhcp_sp_setup(void) { /* was socketpair, but it needs AF_UNIX in kernel */ xpipe(signal_pipe); close_on_exec_on(signal_pipe[0]); close_on_exec_on(signal_pipe[1]); ndelay_on(signal_pipe[1]); signal(SIGUSR1, signal_handler); signal(SIGUSR2, signal_handler); signal(SIGTERM, signal_handler); }
void t_new (void) { int i = 0, j = 0; struct tcpclient *x = NULL; for (j = 0; j < MAXTCP; ++j) if (!t[j].active) break; if (j >= MAXTCP) { j = 0; for (i = 1; i < MAXTCP; ++i) if (taia_less (&t[i].start, &t[j].start)) j = i; errno = error_timeout; if (t[j].state == 0) t_drop (j); else t_close (j); } x = t + j; taia_now (&x->start); x->tcp = socket_accept4 (tcp53, x->ip, &x->port); if (x->tcp == -1) return; if (x->port < 1024 && x->port != 53) { close (x->tcp); return; } if (!okclient (x->ip)) { close (x->tcp); return; } if (ndelay_on (x->tcp) == -1) { close(x->tcp); return; } /* Linux bug */ x->active = 1; ++tactive; x->state = 1; t_timeout (j); if (debug_level > 2) log_tcpopen (x->ip, x->port); }
static void alarm_handler(int sig UNUSED_PARAM) { /* This is the escape hatch! Poor serial line users and the like * arrive here when their connection is broken. * We don't want to block here */ ndelay_on(1); printf("\r\nLogin timed out after %d seconds\r\n", TIMEOUT); fflush_all(); /* unix API is brain damaged regarding O_NONBLOCK, * we should undo it, or else we can affect other processes */ ndelay_off(1); _exit(EXIT_SUCCESS); }
int pipe_internal (int *p, unsigned int flags) { #ifdef HASPIPE2 return pipe2(p, ((flags & DJBUNIX_FLAG_COE) ? O_CLOEXEC : 0) | ((flags & DJBUNIX_FLAG_NB) ? O_NONBLOCK : 0)) ; #else int pi[2] ; if (pipe(pi) < 0) return -1 ; if (flags & DJBUNIX_FLAG_COE) if ((coe(pi[0]) < 0) || (coe(pi[1]) < 0)) goto err ; if (flags & DJBUNIX_FLAG_NB) if ((ndelay_on(pi[0]) < 0) || (ndelay_on(pi[1]) < 0)) goto err ; p[0] = pi[0] ; p[1] = pi[1] ; return 0 ; err: { register int e = errno ; fd_close(pi[1]) ; fd_close(pi[0]) ; errno = e ; } return -1 ; #endif }
int socket_internal (int domain, int type, int protocol, unsigned int flags) { int s = socket(domain, type, protocol) ; if (s == -1) return -1 ; if ((((flags & DJBUNIX_FLAG_NB) ? ndelay_on(s) : ndelay_off(s)) < 0) || (((flags & DJBUNIX_FLAG_COE) ? coe(s) : uncoe(s)) < 0)) { register int e = errno ; fd_close(s) ; errno = e ; return -1 ; } return s ; }
int socketpair_internal (int domain, int type, int protocol, unsigned int flags, int *sv) { int fd[2] ; if (socketpair(domain, type, protocol, fd) < 0) return -1 ; if (flags & DJBUNIX_FLAG_NB) { if (ndelay_on(fd[0]) < 0) goto err ; if (ndelay_on(fd[1]) < 0) goto err ; } else { if (ndelay_off(fd[0]) < 0) goto err ; if (ndelay_off(fd[1]) < 0) goto err ; } if (flags & DJBUNIX_FLAG_COE) { if (coe(fd[0]) < 0) goto err ; if (coe(fd[1]) < 0) goto err ; } else { if (uncoe(fd[0]) < 0) goto err ; if (uncoe(fd[1]) < 0) goto err ; } sv[0] = fd[0] ; sv[1] = fd[1] ; return 0 ; err: { register int e = errno ; fd_close(fd[1]) ; fd_close(fd[0]) ; errno = e ; } return -1 ; }
static int setup_log(void) { rploglen = strlen(rplog); if (rploglen < 7) { warnx("log must have at least seven characters"); return 0; } if (pipe(logpipe)) { warnx("cannot create pipe for log"); return -1; } coe(logpipe[1]); coe(logpipe[0]); ndelay_on(logpipe[0]); ndelay_on(logpipe[1]); if (dup2(logpipe[1], 2) == -1) { warnx("cannot set filedescriptor for log"); return -1; } pfd[0].fd = logpipe[0]; pfd[0].events = POLLIN; stamplog = monotonic_sec(); return 1; }
static int setup_log(void) { rploglen = strlen(rplog); if (rploglen < 7) { warnx("log must have at least seven characters"); return 0; } if (pipe(logpipe)) { warnx("cannot create pipe for log"); return -1; } coe(logpipe[1]); coe(logpipe[0]); ndelay_on(logpipe[0]); ndelay_on(logpipe[1]); if (dup2(logpipe[1], 2) == -1) { warnx("cannot set filedescriptor for log"); return -1; } io[0].fd = logpipe[0]; io[0].events = IOPAUSE_READ; taia_now(&stamplog); return 1; }
int timeoutconn6(int s,struct ip6_address *ip,unsigned int port,int timeout) //int s; //struct ip6_address *ip; //unsigned int port; //int timeout; { char ch; struct sockaddr_in6 sin; // char *x; fd_set wfds; struct timeval tv; byte_zero(&sin,sizeof(sin)); byte_copy(&sin.sin6_addr,16,ip); sin.sin6_port = htons(port);; sin.sin6_family = AF_INET6; if (ndelay_on(s) == -1) return -1; /* XXX: could bind s */ if (connect(s,(struct sockaddr *) &sin,sizeof(sin)) == 0) { ndelay_off(s); return 0; } if ((errno != error_inprogress) && (errno != error_wouldblock)) return -1; FD_ZERO(&wfds); FD_SET(s,&wfds); tv.tv_sec = timeout; tv.tv_usec = 0; if (select(s + 1,(fd_set *) 0,&wfds,(fd_set *) 0,&tv) == -1) return -1; if (FD_ISSET(s,&wfds)) { int dummy; dummy = sizeof(sin); if (getpeername(s,(struct sockaddr *) &sin,(socklen_t *)&dummy) == -1) { /* get return value of read to prevent warn_unused_result */ //int x = read(s,&ch,1); return -1; } ndelay_off(s); return 0; } errno = error_timeout; /* note that connect attempt is continuing */ return -1; }
static void init_notify(void) { VERB1 log("Initializing inotify"); errno = 0; inotify_fd = inotify_init(); if (inotify_fd < 0) perror_msg("inotify_init failed"); else { close_on_exec_on(inotify_fd); ndelay_on(inotify_fd); VERB1 log("Adding inotify watch to glib main loop"); channel_inotify = g_io_channel_unix_new(inotify_fd); channel_inotify_event_id = g_io_add_watch(channel_inotify, G_IO_IN, handle_inotify_cb, NULL); } }
int main(int argc,char * const *argv) { int r; int fd; const char *file; file = *++argv; if (!file) usage(); fd = open_append(file); if (fd == -1) strerr_die4sys(111,FATAL,"cannot open ",file,": "); if (ndelay_on(fd) == -1) strerr_die4sys(111,FATAL,"cannot control ",file,": "); sig_ignore(sig_pipe); r = write(fd,"",1); if (r != -1) _exit(0); if (errno == error_again) _exit(0); if (errno == error_pipe) _exit(0); strerr_die4sys(111,FATAL,"cannot write ",file,": "); }
int ipc_accept_internal (int s, char *p, unsigned int l, int *trunc, unsigned int options) { struct sockaddr_un sa ; socklen_t dummy = sizeof sa ; register int fd ; byte_zero((char*)&sa, (unsigned int)dummy) ; do #ifdef SKALIBS_HASACCEPT4 fd = accept4(s, (struct sockaddr *)&sa, &dummy, ((options & DJBUNIX_FLAG_NB) ? SOCK_NONBLOCK : 0) | ((options & DJBUNIX_FLAG_COE) ? SOCK_CLOEXEC : 0)) ; #else fd = accept(s, (struct sockaddr *)&sa, &dummy) ; #endif while ((fd == -1) && (errno == EINTR)) ; if (fd == -1) return -1 ; #ifndef SKALIBS_HASACCEPT4 if ((((options & DJBUNIX_FLAG_NB) ? ndelay_on(fd) : ndelay_off(fd)) < 0) || (((options & DJBUNIX_FLAG_COE) ? coe(fd) : uncoe(fd)) < 0)) { register int e = errno ; fd_close(fd) ; errno = e ; return -1 ; } #endif if (p) { dummy = byte_chr(sa.sun_path, dummy, 0) ; *trunc = 1 ; if (!l) return fd ; if (l < (dummy + 1)) dummy = l - 1 ; else *trunc = 0 ; byte_copy(p, dummy, sa.sun_path) ; p[dummy] = 0 ; } return fd ; }
int timed_ancil_fd_sandwiched_recv (int fdsock, char const *before, unsigned int beforelen, char const *after, unsigned int afterlen, struct taia const *deadline, struct taia *stamp) { unsigned int maxlen = beforelen > afterlen ? beforelen : afterlen ; char buf[maxlen] ; buffer b = BUFFER_INIT(&fd_read, fdsock, buf, maxlen) ; int p ; { char gotbefore[beforelen] ; if (timed_buffer_get(&b, gotbefore, beforelen, deadline, stamp) < beforelen) return -1 ; if (byte_diff(gotbefore, beforelen, before)) return (errno = EPROTO, -1) ; } if (!timed_ancil_fd_recv(fdsock, &p, deadline, stamp)) return -1 ; if (ndelay_on(p) < 0) { register int e = errno ; fd_close(p) ; errno = e ; return -1 ; } { char gotafter[afterlen] ; if (timed_buffer_get(&b, gotafter, afterlen, deadline, stamp) < afterlen) { register int e = errno ; fd_close(p) ; errno = e ; return -1 ; } if (byte_diff(gotafter, afterlen, after)) { fd_close(p) ; return (errno = EPROTO, -1) ; } } return p ; }
int main (int argc, const char * const *argv, char * const *envp) { const char * prog[2]; int pid, pid2; int wstat; int st; iopause_fd x; #ifndef IOPAUSE_POLL fd_set rfds; struct timeval t; #endif char ch; int ttyfd; struct stat s; if (getpid() != 1) strerr_die2x(111, FATAL, "must be run as process no 1."); setsid(); sig_block(sig_alarm); sig_block(sig_child); sig_catch(sig_child, sig_child_handler); sig_block(sig_cont); sig_catch(sig_cont, sig_cont_handler); sig_block(sig_hangup); sig_block(sig_int); sig_catch(sig_int, sig_int_handler); sig_block(sig_pipe); sig_block(sig_term); /* console */ if ((ttyfd =open_write("/dev/console")) != -1) { dup2(ttyfd, 0); dup2(ttyfd, 1); dup2(ttyfd, 2); if (ttyfd > 2) close(ttyfd); } /* create selfpipe */ while (pipe(selfpipe) == -1) { strerr_warn2(FATAL, "unable to create selfpipe, pausing: ", &strerr_sys); sleep(5); } coe(selfpipe[0]); coe(selfpipe[1]); ndelay_on(selfpipe[0]); ndelay_on(selfpipe[1]); #ifdef RB_DISABLE_CAD /* activate ctrlaltdel handling, glibc, dietlibc */ if (RB_DISABLE_CAD == 0) reboot_system(0); #endif strerr_warn3(INFO, "$Id: 25da3b86f7bed4038b8a039d2f8e8c9bbcf0822b $", ": booting.", 0); /* runit */ for (st =0; st < 3; st++) { /* if (st == 2) logwtmp("~", "reboot", ""); */ while ((pid =fork()) == -1) { strerr_warn4(FATAL, "unable to fork for \"", stage[st], "\" pausing: ", &strerr_sys); sleep(5); } if (!pid) { /* child */ prog[0] =stage[st]; prog[1] =0; /* stage 1 gets full control of console */ if (st == 0) { if ((ttyfd =open("/dev/console", O_RDWR)) != -1) { #ifdef TIOCSCTTY ioctl(ttyfd, TIOCSCTTY, (char *)0); #endif dup2(ttyfd, 0); if (ttyfd > 2) close(ttyfd); } else strerr_warn2(WARNING, "unable to open /dev/console: ", &strerr_sys); } else setsid(); sig_unblock(sig_alarm); sig_unblock(sig_child); sig_uncatch(sig_child); sig_unblock(sig_cont); sig_ignore(sig_cont); sig_unblock(sig_hangup); sig_unblock(sig_int); sig_uncatch(sig_int); sig_unblock(sig_pipe); sig_unblock(sig_term); strerr_warn3(INFO, "enter stage: ", stage[st], 0); execve(*prog, (char *const *)prog, envp); strerr_die4sys(0, FATAL, "unable to start child: ", stage[st], ": "); } x.fd =selfpipe[0]; x.events =IOPAUSE_READ; for (;;) { int child; sig_unblock(sig_child); sig_unblock(sig_cont); sig_unblock(sig_int); #ifdef IOPAUSE_POLL poll(&x, 1, 14000); #else t.tv_sec =14; t.tv_usec =0; FD_ZERO(&rfds); FD_SET(x.fd, &rfds); select(x.fd +1, &rfds, (fd_set*)0, (fd_set*)0, &t); #endif sig_block(sig_cont); sig_block(sig_child); sig_block(sig_int); while (read(selfpipe[0], &ch, 1) == 1) {} while ((child =wait_nohang(&wstat)) > 0) if (child == pid) break; if (child == -1) { strerr_warn2(WARNING, "wait_nohang, pausing: ", &strerr_sys); sleep(5); } /* reget stderr */ if ((ttyfd =open_write("/dev/console")) != -1) { dup2(ttyfd, 2); if (ttyfd > 2) close(ttyfd); } if (child == pid) { if (wait_exitcode(wstat) != 0) { if (wait_crashed(wstat)) strerr_warn3(WARNING, "child crashed: ", stage[st], 0); else strerr_warn3(WARNING, "child failed: ", stage[st], 0); if (st == 0) /* this is stage 1 */ if (wait_crashed(wstat) || (wait_exitcode(wstat) == 100)) { strerr_warn3(INFO, "leave stage: ", stage[st], 0); strerr_warn2(WARNING, "skipping stage 2...", 0); st++; break; } if (st == 1) /* this is stage 2 */ if (wait_crashed(wstat) || (wait_exitcode(wstat) == 111)) { strerr_warn2(WARNING, "killing all processes in stage 2...", 0); kill(-pid, 9); sleep(5); strerr_warn2(WARNING, "restarting.", 0); st--; break; } } strerr_warn3(INFO, "leave stage: ", stage[st], 0); break; } if (child != 0) { /* collect terminated children */ write(selfpipe[1], "", 1); continue; } /* sig? */ if (!sigc && !sigi) { #ifdef DEBUG strerr_warn2(WARNING, "poll: ", &strerr_sys); #endif continue; } if (st != 1) { strerr_warn2(WARNING, "signals only work in stage 2.", 0); sigc =sigi =0; continue; } if (sigi && (stat(CTRLALTDEL, &s) != -1) && (s.st_mode & S_IXUSR)) { strerr_warn2(INFO, "ctrl-alt-del request...", 0); prog[0] =CTRLALTDEL; prog[1] =0; while ((pid2 =fork()) == -1) { strerr_warn4(FATAL, "unable to fork for \"", CTRLALTDEL, "\" pausing: ", &strerr_sys); sleep(5); } if (!pid2) { /* child */ strerr_warn3(INFO, "enter stage: ", prog[0], 0); execve(*prog, (char *const *) prog, envp); strerr_die4sys(0, FATAL, "unable to start child: ", prog[0], ": "); } if (wait_pid(&wstat, pid2) == -1) strerr_warn2(FATAL, "wait_pid: ", &strerr_sys); if (wait_crashed(wstat)) strerr_warn3(WARNING, "child crashed: ", CTRLALTDEL, 0); strerr_warn3(INFO, "leave stage: ", prog[0], 0); sigi =0; sigc++; } if (sigc && (stat(STOPIT, &s) != -1) && (s.st_mode & S_IXUSR)) { int i; /* unlink(STOPIT); */ chmod(STOPIT, 0); /* kill stage 2 */ #ifdef DEBUG strerr_warn2(WARNING, "sending sigterm...", 0); #endif kill(pid, sig_term); i =0; while (i < 5) { if ((child =wait_nohang(&wstat)) == pid) { #ifdef DEBUG strerr_warn2(WARNING, "stage 2 terminated.", 0); #endif pid =0; break; } if (child) continue; if (child == -1) strerr_warn2(WARNING, "wait_nohang: ", &strerr_sys); #ifdef DEBUG strerr_warn2(WARNING, "waiting...", 0); #endif sleep(1); i++; } if (pid) { /* still there */ strerr_warn2(WARNING, "stage 2 not terminated, sending sigkill...", 0); kill(pid, 9); if (wait_pid(&wstat, pid) == -1) strerr_warn2(WARNING, "wait_pid: ", &strerr_sys); } sigc =0; strerr_warn3(INFO, "leave stage: ", stage[st], 0); /* enter stage 3 */ break; } sigc =sigi =0; #ifdef DEBUG strerr_warn2(WARNING, "no request.", 0); #endif } } /* reget stderr */ if ((ttyfd =open_write("/dev/console")) != -1) { dup2(ttyfd, 2); if (ttyfd > 2) close(ttyfd); } #ifdef RB_AUTOBOOT /* fallthrough stage 3 */ strerr_warn2(INFO, "sending KILL signal to all processes...", 0); kill(-1, SIGKILL); pid =fork(); switch (pid) { case 0: case -1: if ((stat(REBOOT, &s) != -1) && (s.st_mode & S_IXUSR)) { strerr_warn2(INFO, "system reboot.", 0); sync(); reboot_system(RB_AUTOBOOT); } else { #ifdef RB_POWER_OFF strerr_warn2(INFO, "power off...", 0); sync(); reboot_system(RB_POWER_OFF); sleep(2); #endif #ifdef RB_HALT_SYSTEM strerr_warn2(INFO, "system halt.", 0); sync(); reboot_system(RB_HALT_SYSTEM); #else #ifdef RB_HALT strerr_warn2(INFO, "system halt.", 0); sync(); reboot_system(RB_HALT); #else strerr_warn2(INFO, "system reboot.", 0); sync(); reboot_system(RB_AUTOBOOT); #endif #endif } if (pid == 0) _exit(0); break; default: sig_unblock(sig_child); while (wait_pid(0, pid) == -1); } #endif for (;;) sig_pause(); /* not reached */ strerr_die2x(0, INFO, "exit."); return(0); }