static cv::Mat generateRadianceMap(const cv::Mat& rc) { cv::Size size = getImage(0).size(); cv::Mat_<cv::Vec3f> radiance(size); for (int y = 0; y < size.height; ++y) { for (int x = 0; x < size.width; ++x) { cv::Vec3f sum(0,0,0), wsum(0,0,0); for (int p = 0, n = numImages(); p < n; ++p) { const cv::Mat& img = getImage(p); cv::Vec3b c = img.at<cv::Vec3b>(y, x); float exptime = getExposureTime(p); cv::Vec3f tmp, wtmp(weight(c[0]), weight(c[1]), weight(c[2])); tmp[0] = (rc.at<float>(c[0], 0) - std::log(exptime)) * wtmp[0]; tmp[1] = (rc.at<float>(c[1], 1) - std::log(exptime)) * wtmp[1]; tmp[2] = (rc.at<float>(c[2], 2) - std::log(exptime)) * wtmp[2]; sum += tmp; wsum += wtmp; } cv::Vec3f tmp; tmp[0] = std::exp( sum[0] / wsum[0] ); tmp[1] = std::exp( sum[1] / wsum[1] ); tmp[2] = std::exp( sum[2] / wsum[2] ); radiance.at<cv::Vec3f>(y, x) = tmp; } } return radiance; }
int main(int argc, char **argv) { extern int optind; extern char *optarg; int ch; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); while ((ch = getopt(argc, argv, "0123456789yli:f:h:t:")) != -1) switch((char)ch) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* * kludge: last was originally designed to take * a number after a dash. */ if (!maxrec) maxrec = atol(argv[optind - 1] + 1); break; case 'f': file = optarg; break; case 'h': hostconv(optarg); addarg(HOST_TYPE, optarg); break; case 't': addarg(TTY_TYPE, ttyconv(optarg)); break; case 'y': doyear = 1; break; case 'l': dolong = 1; break; case 'i': addarg(INET_TYPE, optarg); break; case '?': default: fputs(_("usage: last [-#] [-f file] [-t tty] [-h hostname] [user ...]\n"), stderr); exit(1); } for (argv += optind; *argv; ++argv) { #define COMPATIBILITY #ifdef COMPATIBILITY /* code to allow "last p5" to work */ addarg(TTY_TYPE, ttyconv(*argv)); #endif addarg(USER_TYPE, *argv); } wtmp(); exit(0); }
Topology::Topology(const RuntimeEnvironment *renv) : RR(renv), _amRoot(false) { std::string alls(RR->node->dataStoreGet("peers.save")); const uint8_t *all = reinterpret_cast<const uint8_t *>(alls.data()); RR->node->dataStoreDelete("peers.save"); Buffer<ZT_PEER_SUGGESTED_SERIALIZATION_BUFFER_SIZE> *deserializeBuf = new Buffer<ZT_PEER_SUGGESTED_SERIALIZATION_BUFFER_SIZE>(); unsigned int ptr = 0; while ((ptr + 4) < alls.size()) { try { const unsigned int reclen = ( // each Peer serialized record is prefixed by a record length ((((unsigned int)all[ptr]) & 0xff) << 24) | ((((unsigned int)all[ptr + 1]) & 0xff) << 16) | ((((unsigned int)all[ptr + 2]) & 0xff) << 8) | (((unsigned int)all[ptr + 3]) & 0xff) ); unsigned int pos = 0; deserializeBuf->copyFrom(all + ptr,reclen + 4); SharedPtr<Peer> p(Peer::deserializeNew(RR,RR->identity,*deserializeBuf,pos)); ptr += pos; if (!p) break; // stop if invalid records if (p->address() != RR->identity.address()) _peers.set(p->address(),p); } catch ( ... ) { break; // stop if invalid records } } delete deserializeBuf; clean(RR->node->now()); std::string dsWorld(RR->node->dataStoreGet("world")); World cachedWorld; if (dsWorld.length() > 0) { try { Buffer<ZT_WORLD_MAX_SERIALIZED_LENGTH> dswtmp(dsWorld.data(),(unsigned int)dsWorld.length()); cachedWorld.deserialize(dswtmp,0); } catch ( ... ) { cachedWorld = World(); // clear if cached world is invalid } } World defaultWorld; { Buffer<ZT_DEFAULT_WORLD_LENGTH> wtmp(ZT_DEFAULT_WORLD,ZT_DEFAULT_WORLD_LENGTH); defaultWorld.deserialize(wtmp,0); // throws on error, which would indicate a bad static variable up top } if (cachedWorld.shouldBeReplacedBy(defaultWorld,false)) { _setWorld(defaultWorld); if (dsWorld.length() > 0) RR->node->dataStoreDelete("world"); } else _setWorld(cachedWorld); }
int main(int argc, char *argv[]) { const char *errstr; int ch, lastch = '\0', newarg = 1, prevoptind = 1; while ((ch = getopt(argc, argv, "0123456789cf:h:n:st:d:T")) != -1) { switch (ch) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* * kludge: last was originally designed to take * a number after a dash. */ if (newarg || !isdigit(lastch)) maxrec = 0; else if (maxrec > INT_MAX / 10) usage(); maxrec = (maxrec * 10) + (ch - '0'); break; case 'c': calculate++; break; case 'f': file = optarg; break; case 'h': hostconv(optarg); addarg(HOST_TYPE, optarg); break; case 'n': maxrec = strtonum(optarg, 0, LONG_MAX, &errstr); if (errstr != NULL) errx(1, "number of lines is %s: %s", errstr, optarg); if (maxrec == 0) exit(0); break; case 's': seconds++; break; case 't': addarg(TTY_TYPE, ttyconv(optarg)); break; case 'd': snaptime = dateconv(optarg); break; case 'T': fulltime = 1; break; default: usage(); } lastch = ch; newarg = optind != prevoptind; prevoptind = optind; } if (maxrec == 0) exit(0); if (argc) { setlinebuf(stdout); for (argv += optind; *argv; ++argv) { #define COMPATIBILITY #ifdef COMPATIBILITY /* code to allow "last p5" to work */ addarg(TTY_TYPE, ttyconv(*argv)); #endif addarg(USER_TYPE, *argv); } } checkargs(); wtmp(); exit(0); }
int main(int argc, char *argv[]) { int ch; char *p; const char *file = NULL; int namesize = UT_NAMESIZE; int linesize = UT_LINESIZE; int hostsize = UT_HOSTSIZE; int numeric = 0; maxrec = -1; while ((ch = getopt(argc, argv, "0123456789f:H:h:L:nN:Tt:x")) != -1) switch (ch) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* * kludge: last was originally designed to take * a number after a dash. */ if (maxrec == -1) { p = argv[optind - 1]; if (p[0] == '-' && p[1] == ch && !p[2]) maxrec = atol(++p); else if (optind < argc) maxrec = atol(argv[optind] + 1); else usage(); if (!maxrec) return 0; } break; case 'f': file = optarg; if ('\0' == file[0]) usage(); break; case 'H': hostsize = atoi(optarg); if (hostsize < 1) usage(); break; case 'h': hostconv(optarg); addarg(HOST_TYPE, optarg); break; case 'L': linesize = atoi(optarg); if (linesize < 1) usage(); break; case 'N': namesize = atoi(optarg); if (namesize < 1) usage(); break; case 'n': numeric = 1; break; case 'T': fulltime = 1; break; case 't': addarg(TTY_TYPE, ttyconv(optarg)); break; case 'x': xflag = 1; break; case '?': default: usage(); } if (argc) { setlinebuf(stdout); for (argv += optind; *argv; ++argv) { #define COMPATIBILITY #ifdef COMPATIBILITY /* code to allow "last p5" to work */ addarg(TTY_TYPE, ttyconv(*argv)); #endif addarg(USER_TYPE, *argv); } } if (file == NULL) { #ifdef SUPPORT_UTMPX if (access(_PATH_WTMPX, R_OK) == 0) file = _PATH_WTMPX; else #endif #ifdef SUPPORT_UTMP if (access(_PATH_WTMP, R_OK) == 0) file = _PATH_WTMP; #endif if (file == NULL) #if defined(SUPPORT_UTMPX) && defined(SUPPORT_UTMP) errx(EXIT_FAILURE, "Cannot access `%s' or `%s'", _PATH_WTMPX, _PATH_WTMP); #elif defined(SUPPORT_UTMPX) errx(EXIT_FAILURE, "Cannot access `%s'", _PATH_WTMPX); #elif defined(SUPPORT_UTMP) errx(EXIT_FAILURE, "Cannot access `%s'", _PATH_WTMP); #else errx(EXIT_FAILURE, "No utmp or utmpx support compiled in."); #endif } #if defined(SUPPORT_UTMPX) && defined(SUPPORT_UTMP) if (file[strlen(file) - 1] == 'x' || xflag) wtmpx(file, namesize, linesize, hostsize, numeric); else wtmp(file, namesize, linesize, hostsize, numeric); #elif defined(SUPPORT_UTMPX) wtmpx(file, namesize, linesize, hostsize, numeric); #elif defined(SUPPORT_UTMP) wtmp(file, namesize, linesize, hostsize, numeric); #else errx(EXIT_FAILURE, "No utmp or utmpx support compiled in."); #endif exit(EXIT_SUCCESS); }
void nmf(viennacl::matrix_base<NumericT> const & V, viennacl::matrix_base<NumericT> & W, viennacl::matrix_base<NumericT> & H, viennacl::linalg::nmf_config const & conf) { viennacl::hsa::context & ctx = const_cast<viennacl::hsa::context &>(viennacl::traits::hsa_context(V)); const std::string NMF_MUL_DIV_KERNEL = "el_wise_mul_div"; viennacl::linalg::opencl::kernels::nmf<NumericT, viennacl::hsa::context>::init(ctx); vcl_size_t k = W.size2(); conf.iters_ = 0; if (viennacl::linalg::norm_frobenius(W) <= 0) W = viennacl::scalar_matrix<NumericT>(W.size1(), W.size2(), NumericT(1), ctx); if (viennacl::linalg::norm_frobenius(H) <= 0) H = viennacl::scalar_matrix<NumericT>(H.size1(), H.size2(), NumericT(1), ctx); viennacl::matrix_base<NumericT> wn(V.size1(), k, W.row_major(), ctx); viennacl::matrix_base<NumericT> wd(V.size1(), k, W.row_major(), ctx); viennacl::matrix_base<NumericT> wtmp(V.size1(), V.size2(), W.row_major(), ctx); viennacl::matrix_base<NumericT> hn(k, V.size2(), H.row_major(), ctx); viennacl::matrix_base<NumericT> hd(k, V.size2(), H.row_major(), ctx); viennacl::matrix_base<NumericT> htmp(k, k, H.row_major(), ctx); viennacl::matrix_base<NumericT> appr(V.size1(), V.size2(), V.row_major(), ctx); NumericT last_diff = 0; NumericT diff_init = 0; bool stagnation_flag = false; for (vcl_size_t i = 0; i < conf.max_iterations(); i++) { conf.iters_ = i + 1; { hn = viennacl::linalg::prod(trans(W), V); htmp = viennacl::linalg::prod(trans(W), W); hd = viennacl::linalg::prod(htmp, H); viennacl::hsa::kernel & mul_div_kernel = ctx.get_kernel(viennacl::linalg::opencl::kernels::nmf<NumericT>::program_name(), NMF_MUL_DIV_KERNEL); viennacl::hsa::enqueue(mul_div_kernel(H, hn, hd, cl_uint(H.internal_size1() * H.internal_size2()))); } { wn = viennacl::linalg::prod(V, trans(H)); wtmp = viennacl::linalg::prod(W, H); wd = viennacl::linalg::prod(wtmp, trans(H)); viennacl::hsa::kernel & mul_div_kernel = ctx.get_kernel(viennacl::linalg::opencl::kernels::nmf<NumericT>::program_name(), NMF_MUL_DIV_KERNEL); viennacl::hsa::enqueue(mul_div_kernel(W, wn, wd, cl_uint(W.internal_size1() * W.internal_size2()))); } if (i % conf.check_after_steps() == 0) //check for convergence { appr = viennacl::linalg::prod(W, H); appr -= V; NumericT diff_val = viennacl::linalg::norm_frobenius(appr); if (i == 0) diff_init = diff_val; if (conf.print_relative_error()) std::cout << diff_val / diff_init << std::endl; // Approximation check if (diff_val / diff_init < conf.tolerance()) break; // Stagnation check if (std::fabs(diff_val - last_diff) / (diff_val * NumericT(conf.check_after_steps())) < conf.stagnation_tolerance()) //avoid situations where convergence stagnates { if (stagnation_flag) // iteration stagnates (two iterates with no notable progress) break; else // record stagnation in this iteration stagnation_flag = true; } else // good progress in this iteration, so unset stagnation flag stagnation_flag = false; // prepare for next iterate: last_diff = diff_val; } } }
void nmf(viennacl::matrix<ScalarType> const & v, viennacl::matrix<ScalarType> & w, viennacl::matrix<ScalarType> & h, std::size_t k, ScalarType eps = 0.000001, std::size_t max_iter = 10000, std::size_t check_diff_every_step = 100) { viennacl::linalg::kernels::nmf<ScalarType, 1>::init(); w.resize(v.size1(), k); h.resize(k, v.size2()); std::vector<ScalarType> stl_w(w.internal_size1() * w.internal_size2()); std::vector<ScalarType> stl_h(h.internal_size1() * h.internal_size2()); for (std::size_t j = 0; j < stl_w.size(); j++) stl_w[j] = static_cast<ScalarType>(rand()) / RAND_MAX; for (std::size_t j = 0; j < stl_h.size(); j++) stl_h[j] = static_cast<ScalarType>(rand()) / RAND_MAX; viennacl::matrix<ScalarType> wn(v.size1(), k); viennacl::matrix<ScalarType> wd(v.size1(), k); viennacl::matrix<ScalarType> wtmp(v.size1(), v.size2()); viennacl::matrix<ScalarType> hn(k, v.size2()); viennacl::matrix<ScalarType> hd(k, v.size2()); viennacl::matrix<ScalarType> htmp(k, k); viennacl::matrix<ScalarType> appr(v.size1(), v.size2()); viennacl::vector<ScalarType> diff(v.size1() * v.size2()); viennacl::fast_copy(&stl_w[0], &stl_w[0] + stl_w.size(), w); viennacl::fast_copy(&stl_h[0], &stl_h[0] + stl_h.size(), h); ScalarType last_diff = 0.0f; for (std::size_t i = 0; i < max_iter; i++) { { hn = viennacl::linalg::prod(trans(w), v); htmp = viennacl::linalg::prod(trans(w), w); hd = viennacl::linalg::prod(htmp, h); viennacl::ocl::kernel & mul_div_kernel = viennacl::ocl::get_kernel(viennacl::linalg::kernels::nmf<ScalarType, 1>::program_name(), NMF_MUL_DIV_KERNEL); viennacl::ocl::enqueue(mul_div_kernel(h, hn, hd, cl_uint(stl_h.size()))); } { wn = viennacl::linalg::prod(v, trans(h)); wtmp = viennacl::linalg::prod(w, h); wd = viennacl::linalg::prod(wtmp, trans(h)); viennacl::ocl::kernel & mul_div_kernel = viennacl::ocl::get_kernel(viennacl::linalg::kernels::nmf<ScalarType, 1>::program_name(), NMF_MUL_DIV_KERNEL); viennacl::ocl::enqueue(mul_div_kernel(w, wn, wd, cl_uint(stl_w.size()))); } if (i % check_diff_every_step == 0) { appr = viennacl::linalg::prod(w, h); viennacl::ocl::kernel & sub_kernel = viennacl::ocl::get_kernel(viennacl::linalg::kernels::nmf<ScalarType, 1>::program_name(), NMF_SUB_KERNEL); //this is a cheat. i.e save difference of two matrix into vector to get norm_2 viennacl::ocl::enqueue(sub_kernel(appr, v, diff, cl_uint(v.size1() * v.size2()))); ScalarType diff_val = viennacl::linalg::norm_2(diff); if((diff_val < eps) || (fabs(diff_val - last_diff) < eps)) { //std::cout << "Breaked at diff - " << diff_val << "\n"; break; } last_diff = diff_val; //printf("Iteration #%lu - %.5f \n", i, diff_val); } } }
int main(void) { pid_t pid; /* pid of child process */ int fd; /* generally useful */ int linenr; /* loop variable */ int check; /* check if a new process must be spawned */ int sn; /* signal number */ struct slotent *slotp; /* slots[] pointer */ struct ttyent *ttyp; /* ttytab entry */ struct sigaction sa; struct stat stb; #define OPENFDS \ if (fstat(0, &stb) < 0) { \ /* Open standard input, output & error. */ \ (void) open("/dev/null", O_RDONLY); \ (void) open("/dev/log", O_WRONLY); \ dup(1); \ } sigemptyset(&sa.sa_mask); sa.sa_flags = 0; /* Default: Ignore every signal (except those that follow). */ sa.sa_handler = SIG_IGN; for (sn = 1; sn < _NSIG; sn++) { sigaction(sn, &sa, NULL); } /* Hangup: Reexamine /etc/ttytab for newly enabled terminal lines. */ sa.sa_handler = onhup; sigaction(SIGHUP, &sa, NULL); /* Terminate: Stop spawning login processes, shutdown is near. */ sa.sa_handler = onterm; sigaction(SIGTERM, &sa, NULL); /* Abort: Sent by the kernel on CTRL-ALT-DEL; shut the system down. */ sa.sa_handler = onabrt; sigaction(SIGABRT, &sa, NULL); /* Execute the /etc/rc file. */ if ((pid = fork()) != 0) { /* Parent just waits. */ while (wait(NULL) != pid) { if (gotabrt) reboot(RBT_HALT); } } else { #if ! SYS_GETKENV struct sysgetenv sysgetenv; #endif char bootopts[16]; static char *rc_command[] = { "sh", "/etc/rc", NULL, NULL, NULL }; char **rcp = rc_command + 2; /* Get the boot options from the boot environment. */ sysgetenv.key = "bootopts"; sysgetenv.keylen = 8+1; sysgetenv.val = bootopts; sysgetenv.vallen = sizeof(bootopts); if (svrctl(PMGETPARAM, &sysgetenv) == 0) *rcp++ = bootopts; *rcp = "start"; execute(rc_command); report(2, "sh /etc/rc"); _exit(1); /* impossible, we hope */ } OPENFDS; /* Clear /etc/utmp if it exists. */ if ((fd = open(PATH_UTMP, O_WRONLY | O_TRUNC)) >= 0) close(fd); /* Log system reboot. */ wtmp(BOOT_TIME, 0, NULL, 0); /* Main loop. If login processes have already been started up, wait for one * to terminate, or for a HUP signal to arrive. Start up new login processes * for all ttys which don't have them. Note that wait() also returns when * somebody's orphan dies, in which case ignore it. If the TERM signal is * sent then stop spawning processes, shutdown time is near. */ check = 1; while (1) { while ((pid = waitpid(-1, NULL, check ? WNOHANG : 0)) > 0) { /* Search to see which line terminated. */ for (linenr = 0; linenr < PIDSLOTS; linenr++) { slotp = &slots[linenr]; if (slotp->pid == pid) { /* Record process exiting. */ wtmp(DEAD_PROCESS, linenr, NULL, pid); slotp->pid = NO_PID; check = 1; } } } /* If a signal 1 (SIGHUP) is received, simply reset error counts. */ if (gothup) { gothup = 0; for (linenr = 0; linenr < PIDSLOTS; linenr++) { slots[linenr].errct = 0; } check = 1; } /* Shut down on signal 6 (SIGABRT). */ if (gotabrt) { gotabrt = 0; startup(0, &TT_REBOOT); } if (spawn && check) { /* See which lines need a login process started up. */ for (linenr = 0; linenr < PIDSLOTS; linenr++) { slotp = &slots[linenr]; if ((ttyp = getttyent()) == NULL) break; if (ttyp->ty_getty != NULL /* ty_getty is a string, and TTY_ON is * the way to check for enabled ternimanls. */ && (ttyp->ty_status & TTY_ON) && slotp->pid == NO_PID && slotp->errct < ERRCT_DISABLE) { startup(linenr, ttyp); } } endttyent(); } check = 0; } }
void startup(int linenr, struct ttyent *ttyp) { /* Fork off a process for the indicated line. */ struct slotent *slotp; /* pointer to ttyslot */ pid_t pid; /* new pid */ int err[2]; /* error reporting pipe */ char line[32]; /* tty device name */ int status; char **ty_getty_argv; slotp = &slots[linenr]; /* Error channel for between fork and exec. */ if (pipe(err) < 0) err[0] = err[1] = -1; if ((pid = fork()) == -1 ) { report(2, "fork()"); sleep(10); return; } if (pid == 0) { /* Child */ close(err[0]); fcntl(err[1], F_SETFD, fcntl(err[1], F_GETFD) | FD_CLOEXEC); /* A new session. */ setsid(); /* Construct device name. */ strcpy(line, "/dev/"); strncat(line, ttyp->ty_name, sizeof(line) - 6); /* Open the line for standard input and output. */ close(0); close(1); if (open(line, O_RDWR) < 0 || dup(0) < 0) { write(err[1], &errno, sizeof(errno)); _exit(1); } /* ty_init not present. */ /* Redirect standard error too. */ dup2(0, 2); /* Construct argv for execute() */ ty_getty_argv = construct_argv(ttyp->ty_getty); if (ty_getty_argv == NULL) report(2, "construct_argv"); /* Execute the getty process. */ execute(ty_getty_argv); /* Oops, disaster strikes. */ fcntl(2, F_SETFL, fcntl(2, F_GETFL) | O_NONBLOCK); if (linenr != 0) report(2, ty_getty_argv[0]); write(err[1], &errno, sizeof(errno)); _exit(1); } /* Parent */ if (ttyp != &TT_REBOOT) slotp->pid = pid; close(err[1]); if (read(err[0], &errno, sizeof(errno)) != 0) { /* If an errno value goes down the error pipe: Problems. */ switch (errno) { case ENOENT: case ENODEV: case ENXIO: /* Device nonexistent, no driver, or no minor device. */ slotp->errct = ERRCT_DISABLE; close(err[0]); return; case 0: /* Error already reported. */ break; default: /* Any other error on the line. */ report(2, ttyp->ty_name); } close(err[0]); if (++slotp->errct >= ERRCT_DISABLE) { tell(2, "init: "); tell(2, ttyp->ty_name); tell(2, ": excessive errors, shutting down\n"); } else { sleep(5); } return; } close(err[0]); if (ttyp != &TT_REBOOT) wtmp(LOGIN_PROCESS, linenr, ttyp->ty_name, pid); slotp->errct = 0; }
int main(void) { pid_t pid; /* pid of child process */ int fd; /* generally useful */ int linenr; /* loop variable */ int check; /* check if a new process must be spawned */ struct slotent *slotp; /* slots[] pointer */ struct ttyent *ttyp; /* ttytab entry */ struct sigaction sa; struct stat stb; if (fstat(0, &stb) < 0) { /* Open standard input, output & error. */ (void) open("/dev/null", O_RDONLY); (void) open("/dev/log", O_WRONLY); dup(1); } sigemptyset(&sa.sa_mask); sa.sa_flags = 0; /* Hangup: Reexamine /etc/ttytab for newly enabled terminal lines. */ sa.sa_handler = onhup; sigaction(SIGHUP, &sa, NULL); /* Terminate: Stop spawning login processes, shutdown is near. */ sa.sa_handler = onterm; sigaction(SIGTERM, &sa, NULL); /* Abort: Sent by the kernel on CTRL-ALT-DEL; shut the system down. */ sa.sa_handler = onabrt; sigaction(SIGABRT, &sa, NULL); /* Execute the /etc/rc file. */ if ((pid = fork()) != 0) { /* Parent just waits. */ while (wait(NULL) != pid) { if (gotabrt) reboot(RBT_HALT); } } else { static char *rc_command[] = { "sh", "/etc/rc", NULL, NULL }; #if __minix_vmd /* Minix-vmd: Get the boot options from the boot environment. */ rc_command[2] = getenv("bootopts"); #else /* Minix: Input from the console. */ close(0); (void) open("/dev/console", O_RDONLY); #endif execute(rc_command); report(2, "sh /etc/rc"); _exit(1); /* impossible, we hope */ } /* Clear /etc/utmp if it exists. */ if ((fd = open(PATH_UTMP, O_WRONLY | O_TRUNC)) >= 0) close(fd); /* Log system reboot. */ wtmp(BOOT_TIME, 0, NULL, 0); /* Main loop. If login processes have already been started up, wait for one * to terminate, or for a HUP signal to arrive. Start up new login processes * for all ttys which don't have them. Note that wait() also returns when * somebody's orphan dies, in which case ignore it. If the TERM signal is * sent then stop spawning processes, shutdown time is near. */ check = 1; while (1) { while ((pid = waitpid(-1, NULL, check ? WNOHANG : 0)) > 0) { /* Search to see which line terminated. */ for (linenr = 0; linenr < PIDSLOTS; linenr++) { slotp = &slots[linenr]; if (slotp->pid == pid) { /* Record process exiting. */ wtmp(DEAD_PROCESS, linenr, NULL, pid); slotp->pid = NO_PID; check = 1; } } } /* If a signal 1 (SIGHUP) is received, simply reset error counts. */ if (gothup) { gothup = 0; for (linenr = 0; linenr < PIDSLOTS; linenr++) { slots[linenr].errct = 0; } check = 1; } /* Shut down on signal 6 (SIGABRT). */ if (gotabrt) { gotabrt = 0; startup(0, &TT_REBOOT); } if (spawn && check) { /* See which lines need a login process started up. */ for (linenr = 0; linenr < PIDSLOTS; linenr++) { slotp = &slots[linenr]; if ((ttyp = getttyent()) == NULL) break; if (ttyp->ty_getty != NULL && ttyp->ty_getty[0] != NULL && slotp->pid == NO_PID && slotp->errct < ERRCT_DISABLE) { startup(linenr, ttyp); } } endttyent(); } check = 0; } }
main() { int pid; /* pid of child process */ int fd; /* fd of console for error messages */ int i; /* loop variable */ int status; /* return status from child process */ struct slotent *slotp; /* slots[] pointer */ void onhup(); /* SIGHUP interrupt catch routine */ sync(); /* force buffers out onto disk */ /* Execute the /etc/rc file. */ if(fork()) { /* Parent just waits. */ wait(&status); } else { /* Child exec's the shell to do the work. */ if(open("/etc/rc", 0) < 0) exit(EXIT_OPENFAIL); dup(open(CONSOLE, 1)); /* std output, error */ execle(SHELL1, SHELL1, (char *)0, env); execle(SHELL2, SHELL2, (char *)0, env); exit(EXIT_EXECFAIL); /* impossible, we hope */ } /* Log system reboot. */ wtmp("reboot", "~~", "~", 0, BOOT_TIME, -1); /* Read the /etc/ttys file. */ readttys(); /* Main loop. If login processes have already been started up, wait for one * to terminate, or for a HUP signal to arrive. Start up new login processes * for all ttys which don't have them. Note that wait() also returns when * somebody's orphan dies, in which case ignore it. * First set up the signals. */ for (i = 1; i <= _NSIG; i++) signal(i, SIG_IGN); signal(SIGHUP, onhup); while(1) { sync(); if( pidct && (pid = wait(&status)) > 0 ) { /* Search to see which line terminated. */ for(slotp = slots; slotp < &slots[PIDSLOTS]; ++slotp) { if(slotp->pid == pid) { pidct--; slotp->pid = 0; /* now no login process */ slotp->exit = status; if(((status >> 8) & 0xFF) == EXIT_TTYFAIL) { fd = open(CONSOLE, 1); write(fd, "init: tty problems, shutting down ", 39); write(fd, slotp->name, sizeof slotp->name); write(fd, "\n", 1); close(fd); slotp->onflag = 0; } break; } } } /* If a signal 1 (SIGHUP) is received, reread /etc/ttys. */ if(gothup) { readttys(); gothup = 0; } /* See which lines need a login process started up. */ for(slotp = slots; slotp < &slots[PIDSLOTS]; ++slotp) { if(slotp->onflag && slotp->pid <= 0) startup(slotp - slots, DEAD_PROCESS, LOGIN_PROCESS); } }