int main(int argc, char *argv[]) { struct pollfd pfd[1]; char *ep, *cp; int on = 1; int send_time = 180; /* Default time, 180 seconds (3 minutes) */ struct sockaddr_in m_sin; uid_t unpriv_uid; gid_t unpriv_gid; long tmp; time_t delta = 0; struct timeval next, now; if (getuid()) errx(1, "not super user"); run_as(&unpriv_uid, &unpriv_gid); argv++; argc--; while (argc > 0 && *argv[0] == '-') { if (strcmp(*argv, "-m") == 0) { if (argc > 1 && *(argv + 1)[0] != '-') { /* Argument has been given */ argv++, argc--; multicast_mode = SCOPED_MULTICAST; tmp = strtol(*argv, &ep, 10); if (*ep != '\0' || tmp < INT_MIN || tmp > INT_MAX) errx(1, "invalid ttl: %s", *argv); multicast_scope = (int)tmp; if (multicast_scope > MAX_MULTICAST_SCOPE) errx(1, "ttl must not exceed %u", MAX_MULTICAST_SCOPE); } else multicast_mode = PER_INTERFACE_MULTICAST; } else if (strcmp(*argv, "-g") == 0) { if (argc > 1 && *(argv + 1)[0] != '-') { argv++, argc--; send_time = (int)strtol(*argv, &ep, 10); if (send_time <= 0) errx(1, "time must be greater than 0"); if (ep[0] != '\0') { if (ep[1] != '\0') errx(1, "invalid argument: %s", *argv); if (*ep == 'M' || *ep == 'm') { /* Time in minutes. */ send_time *= 60; } else errx(1, "invalid argument: %s", *argv); } if (send_time > 180) errx(1, "cannot be greater than 180 seconds (3 minutes)"); } else errx(1, "missing argument"); } else if (strcmp(*argv, "-i") == 0) insecure_mode = 1; else if (strcmp(*argv, "-l") == 0) quiet_mode = 1; else if (strcmp(*argv, "-p") == 0) iff_flag = 0; else usage(); argv++, argc--; } if (argc > 0) usage(); #ifndef DEBUG struct pidfh *pfh = NULL; pfh = pidfile_open(NULL, 600, NULL); daemon(1, 0); pidfile_write(pfh); #endif signal(SIGHUP, hup); openlog("rwhod", LOG_PID, LOG_DAEMON); sp = getservbyname("who", "udp"); if (sp == NULL) quit("udp/who: unknown service", WITHOUT_ERRNO); if (chdir(_PATH_RWHODIR) < 0) quit(_PATH_RWHODIR, WITH_ERRNO); /* * Establish host name as returned by system. */ if (gethostname(myname, sizeof(myname)) < 0) quit("gethostname", WITH_ERRNO); if ((cp = strchr(myname, '.')) != NULL) *cp = '\0'; strlcpy(mywd.wd_hostname, myname, sizeof(mywd.wd_hostname)); utmpf = open(_PATH_UTMP, O_RDONLY|O_CREAT, 0644); if (utmpf < 0) quit(_PATH_UTMP, WITH_ERRNO); getboottime(); if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) quit("socket", WITH_ERRNO); if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0) quit("setsockopt SO_BROADCAST", WITH_ERRNO); memset(&m_sin, 0, sizeof(m_sin)); m_sin.sin_len = sizeof(m_sin); m_sin.sin_family = AF_INET; m_sin.sin_port = sp->s_port; if (bind(s, (struct sockaddr *)&m_sin, sizeof(m_sin)) < 0) quit("bind", WITH_ERRNO); setgid(unpriv_gid); setgroups(1, &unpriv_gid); /* XXX BOGUS groups[0] = egid */ setuid(unpriv_uid); if (!configure(s)) exit(1); if (!quiet_mode) { send_host_information(); delta = send_time; gettimeofday(&now, NULL); timeadd(&now, delta, &next); } pfd[0].fd = s; pfd[0].events = POLLIN; for (;;) { int n; n = poll(pfd, 1, 1000); if (onsighup) { onsighup = 0; getboottime(); } if (n == 1) handleread(s); if (!quiet_mode) { gettimeofday(&now, NULL); if (now.tv_sec > next.tv_sec) { send_host_information(); timeadd(&now, delta, &next); } } } }
void sender_process(void) { int sendcount; double avenrun[3]; time_t now; int i, cc, status; struct utmpx *ut; struct stat stb; struct neighbor *np; struct whoent *we, *wend; sendcount = 0; for (;;) { we = mywd.wd_we; now = time(NULL); if (sendcount % 10 == 0) getboottime(0); sendcount++; wend = &mywd.wd_we[1024 / sizeof(struct whoent)]; setutxent(); while ((ut = getutxent()) != NULL && we < wend) { if (ut->ut_type != USER_PROCESS) continue; strncpy(we->we_utmp.out_line, ut->ut_line, sizeof(we->we_utmp.out_line)); strncpy(we->we_utmp.out_name, ut->ut_user, sizeof(we->we_utmp.out_name)); we->we_utmp.out_time = htonl(_time_to_time32(ut->ut_tv.tv_sec)); we++; } endutxent(); if (chdir(_PATH_DEV) < 0) { syslog(LOG_ERR, "chdir(%s): %m", _PATH_DEV); exit(1); } wend = we; for (we = mywd.wd_we; we < wend; we++) { if (stat(we->we_utmp.out_line, &stb) >= 0) we->we_idle = htonl(now - stb.st_atime); we++; } (void) getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])); for (i = 0; i < 3; i++) mywd.wd_loadav[i] = htonl((u_long)(avenrun[i] * 100)); cc = (char *)wend - (char *)&mywd; mywd.wd_sendtime = htonl(_time_to_time32(time(NULL))); mywd.wd_vers = WHODVERSION; mywd.wd_type = WHODTYPE_STATUS; if (multicast_mode == SCOPED_MULTICAST) { (void) sendto(s, (char *)&mywd, cc, 0, (struct sockaddr *)&multicast_addr, sizeof(multicast_addr)); } else { for (np = neighbors; np != NULL; np = np->n_next) { if (multicast_mode == PER_INTERFACE_MULTICAST && (np->n_flags & IFF_MULTICAST) != 0) { /* * Select the outgoing interface for the * multicast. */ if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &(((struct sockaddr_in *)np->n_addr)->sin_addr), sizeof(struct in_addr)) < 0) { syslog(LOG_ERR, "setsockopt IP_MULTICAST_IF: %m"); exit(1); } (void) sendto(s, (char *)&mywd, cc, 0, (struct sockaddr *)&multicast_addr, sizeof(multicast_addr)); } else { (void) sendto(s, (char *)&mywd, cc, 0, np->n_addr, np->n_addrlen); } } } if (chdir(_PATH_RWHODIR) < 0) { syslog(LOG_ERR, "chdir(%s): %m", _PATH_RWHODIR); exit(1); } if (waitpid(pid_child_receiver, &status, WNOHANG) == pid_child_receiver) { break; } sleep(SL_INTERVAL); } }
static int show_stat(struct seq_file *p, void *v) { int i, j; unsigned long jif; cputime64_t user, nice, system, idle, iowait, irq, softirq, steal; cputime64_t guest, guest_nice; u64 sum = 0; u64 sum_softirq = 0; unsigned int per_softirq_sums[NR_SOFTIRQS] = {0}; struct timespec boottime; user = nice = system = idle = iowait = irq = softirq = steal = cputime64_zero; guest = guest_nice = cputime64_zero; getboottime(&boottime); jif = boottime.tv_sec; for_each_possible_cpu(i) { user = cputime64_add(user, kstat_cpu(i).cpustat.user); nice = cputime64_add(nice, kstat_cpu(i).cpustat.nice); system = cputime64_add(system, kstat_cpu(i).cpustat.system); idle = cputime64_add(idle, get_idle_time(i)); iowait = cputime64_add(iowait, get_iowait_time(i)); irq = cputime64_add(irq, kstat_cpu(i).cpustat.irq); softirq = cputime64_add(softirq, kstat_cpu(i).cpustat.softirq); steal = cputime64_add(steal, kstat_cpu(i).cpustat.steal); guest = cputime64_add(guest, kstat_cpu(i).cpustat.guest); guest_nice = cputime64_add(guest_nice, kstat_cpu(i).cpustat.guest_nice); sum += kstat_cpu_irqs_sum(i); sum += arch_irq_stat_cpu(i); for (j = 0; j < NR_SOFTIRQS; j++) { unsigned int softirq_stat = kstat_softirqs_cpu(j, i); per_softirq_sums[j] += softirq_stat; sum_softirq += softirq_stat; } } sum += arch_irq_stat(); seq_printf(p, "cpu %llu %llu %llu %llu %llu %llu %llu %llu %llu " "%llu\n", (unsigned long long)cputime64_to_clock_t(user), (unsigned long long)cputime64_to_clock_t(nice), (unsigned long long)cputime64_to_clock_t(system), (unsigned long long)cputime64_to_clock_t(idle), (unsigned long long)cputime64_to_clock_t(iowait), (unsigned long long)cputime64_to_clock_t(irq), (unsigned long long)cputime64_to_clock_t(softirq), (unsigned long long)cputime64_to_clock_t(steal), (unsigned long long)cputime64_to_clock_t(guest), (unsigned long long)cputime64_to_clock_t(guest_nice)); for_each_online_cpu(i) { /* Copy values here to work around gcc-2.95.3, gcc-2.96 */ user = kstat_cpu(i).cpustat.user; nice = kstat_cpu(i).cpustat.nice; system = kstat_cpu(i).cpustat.system; idle = get_idle_time(i); iowait = get_iowait_time(i); irq = kstat_cpu(i).cpustat.irq; softirq = kstat_cpu(i).cpustat.softirq; steal = kstat_cpu(i).cpustat.steal; guest = kstat_cpu(i).cpustat.guest; guest_nice = kstat_cpu(i).cpustat.guest_nice; seq_printf(p, "cpu%d %llu %llu %llu %llu %llu %llu %llu %llu %llu " "%llu\n", i, (unsigned long long)cputime64_to_clock_t(user), (unsigned long long)cputime64_to_clock_t(nice), (unsigned long long)cputime64_to_clock_t(system), (unsigned long long)cputime64_to_clock_t(idle), (unsigned long long)cputime64_to_clock_t(iowait), (unsigned long long)cputime64_to_clock_t(irq), (unsigned long long)cputime64_to_clock_t(softirq), (unsigned long long)cputime64_to_clock_t(steal), (unsigned long long)cputime64_to_clock_t(guest), (unsigned long long)cputime64_to_clock_t(guest_nice)); } seq_printf(p, "intr %llu", (unsigned long long)sum); /* sum again ? it could be updated? */ for_each_irq_nr(j) seq_printf(p, " %u", kstat_irqs(j)); seq_printf(p, "\nctxt %llu\n" "btime %lu\n" "processes %lu\n" "procs_running %lu\n" "procs_blocked %lu\n", nr_context_switches(), (unsigned long)jif, total_forks, nr_running(), nr_iowait()); seq_printf(p, "softirq %llu", (unsigned long long)sum_softirq); for (i = 0; i < NR_SOFTIRQS; i++) seq_printf(p, " %u", per_softirq_sums[i]); seq_putc(p, '\n'); return 0; }
/* * This version of Berkeley's rwhod has been modified to use IP multicast * datagrams, under control of a new command-line option: * * rwhod -m causes rwhod to use IP multicast (instead of * broadcast or unicast) on all interfaces that have * the IFF_MULTICAST flag set in their "ifnet" structs * (excluding the loopback interface). The multicast * reports are sent with a time-to-live of 1, to prevent * forwarding beyond the directly-connected subnet(s). * * rwhod -m <ttl> causes rwhod to send IP multicast datagrams with a * time-to-live of <ttl>, via a SINGLE interface rather * than all interfaces. <ttl> must be between 0 and * MAX_MULTICAST_SCOPE, defined below. Note that "-m 1" * is different than "-m", in that "-m 1" specifies * transmission on one interface only. * * When "-m" is used without a <ttl> argument, the program accepts multicast * rwhod reports from all multicast-capable interfaces. If a <ttl> argument * is given, it accepts multicast reports from only one interface, the one * on which reports are sent (which may be controlled via the host's routing * table). Regardless of the "-m" option, the program accepts broadcast or * unicast reports from all interfaces. Thus, this program will hear the * reports of old, non-multicasting rwhods, but, if multicasting is used, * those old rwhods won't hear the reports generated by this program. * * -- Steve Deering, Stanford University, February 1989 */ int main(int argc, char *argv[]) { int on; char *cp; struct sockaddr_in soin; uid_t unpriv_uid; gid_t unpriv_gid; on = 1; if (getuid()) errx(1, "not super user"); run_as(&unpriv_uid, &unpriv_gid); argv++; argc--; while (argc > 0 && *argv[0] == '-') { if (strcmp(*argv, "-m") == 0) { if (argc > 1 && isdigit(*(argv + 1)[0])) { argv++; argc--; multicast_mode = SCOPED_MULTICAST; multicast_scope = atoi(*argv); if (multicast_scope > MAX_MULTICAST_SCOPE) { errx(1, "ttl must not exceed %u", MAX_MULTICAST_SCOPE); } } else { multicast_mode = PER_INTERFACE_MULTICAST; } } else if (strcmp(*argv, "-i") == 0) { insecure_mode = 1; } else if (strcmp(*argv, "-l") == 0) { quiet_mode = 1; } else if (strcmp(*argv, "-p") == 0) { iff_flag = 0; } else { usage(); } argv++; argc--; } if (argc > 0) usage(); #ifndef DEBUG daemon(1, 0); #endif (void) signal(SIGHUP, getboottime); openlog("rwhod", LOG_PID | LOG_NDELAY, LOG_DAEMON); sp = getservbyname("who", "udp"); if (sp == NULL) { syslog(LOG_ERR, "who/udp: unknown service"); exit(1); } if (chdir(_PATH_RWHODIR) < 0) { syslog(LOG_ERR, "%s: %m", _PATH_RWHODIR); exit(1); } /* * Establish host name as returned by system. */ if (gethostname(myname, sizeof(myname) - 1) < 0) { syslog(LOG_ERR, "gethostname: %m"); exit(1); } if ((cp = strchr(myname, '.')) != NULL) *cp = '\0'; strlcpy(mywd.wd_hostname, myname, sizeof(mywd.wd_hostname)); getboottime(0); if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { syslog(LOG_ERR, "socket: %m"); exit(1); } if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0) { syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m"); exit(1); } memset(&soin, 0, sizeof(soin)); soin.sin_len = sizeof(soin); soin.sin_family = AF_INET; soin.sin_port = sp->s_port; if (bind(s, (struct sockaddr *)&soin, sizeof(soin)) < 0) { syslog(LOG_ERR, "bind: %m"); exit(1); } if (setgid(unpriv_gid) != 0) { syslog(LOG_ERR, "setgid: %m"); exit(1); } if (setgroups(1, &unpriv_gid) != 0) { /* XXX BOGUS groups[0] = egid */ syslog(LOG_ERR, "setgroups: %m"); exit(1); } if (setuid(unpriv_uid) != 0) { syslog(LOG_ERR, "setuid: %m"); exit(1); } if (!configure(s)) exit(1); if (!quiet_mode) { pid_child_receiver = pdfork(&fdp, 0); if (pid_child_receiver == 0) { receiver_process(); } else if (pid_child_receiver > 0) { sender_process(); } else if (pid_child_receiver == -1) { if (errno == ENOSYS) { syslog(LOG_ERR, "The pdfork(2) system call is not available; recompile the kernel with options PROCDESC"); } else { syslog(LOG_ERR, "pdfork: %m"); } exit(1); } } else { receiver_process(); } }
static int show_stat(struct seq_file *p, void *v) { int i, j; unsigned long jif; u64 user, nice, system, idle, iowait, irq, softirq, steal; u64 guest, guest_nice; u64 sum = 0; u64 sum_softirq = 0; unsigned int per_softirq_sums[NR_SOFTIRQS] = {0}; struct timespec boottime; user = nice = system = idle = iowait = irq = softirq = steal = 0; guest = guest_nice = 0; getboottime(&boottime); jif = boottime.tv_sec; for_each_possible_cpu(i) { user += kcpustat_cpu(i).cpustat[CPUTIME_USER]; nice += kcpustat_cpu(i).cpustat[CPUTIME_NICE]; system += kcpustat_cpu(i).cpustat[CPUTIME_SYSTEM]; idle += get_idle_time(i); iowait += get_iowait_time(i); irq += kcpustat_cpu(i).cpustat[CPUTIME_IRQ]; softirq += kcpustat_cpu(i).cpustat[CPUTIME_SOFTIRQ]; steal += kcpustat_cpu(i).cpustat[CPUTIME_STEAL]; guest += kcpustat_cpu(i).cpustat[CPUTIME_GUEST]; guest_nice += kcpustat_cpu(i).cpustat[CPUTIME_GUEST_NICE]; sum += kstat_cpu_irqs_sum(i); sum += arch_irq_stat_cpu(i); for (j = 0; j < NR_SOFTIRQS; j++) { unsigned int softirq_stat = kstat_softirqs_cpu(j, i); per_softirq_sums[j] += softirq_stat; sum_softirq += softirq_stat; } } sum += arch_irq_stat(); seq_puts(p, "cpu "); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(user)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(nice)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(system)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(idle)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(iowait)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(irq)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(softirq)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(steal)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(guest)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(guest_nice)); seq_putc(p, '\n'); for_each_online_cpu(i) { /* Copy values here to work around gcc-2.95.3, gcc-2.96 */ user = kcpustat_cpu(i).cpustat[CPUTIME_USER]; nice = kcpustat_cpu(i).cpustat[CPUTIME_NICE]; system = kcpustat_cpu(i).cpustat[CPUTIME_SYSTEM]; idle = get_idle_time(i); iowait = get_iowait_time(i); irq = kcpustat_cpu(i).cpustat[CPUTIME_IRQ]; softirq = kcpustat_cpu(i).cpustat[CPUTIME_SOFTIRQ]; steal = kcpustat_cpu(i).cpustat[CPUTIME_STEAL]; guest = kcpustat_cpu(i).cpustat[CPUTIME_GUEST]; guest_nice = kcpustat_cpu(i).cpustat[CPUTIME_GUEST_NICE]; seq_printf(p, "cpu%d", i); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(user)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(nice)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(system)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(idle)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(iowait)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(irq)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(softirq)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(steal)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(guest)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(guest_nice)); seq_putc(p, '\n'); } seq_printf(p, "intr %llu", (unsigned long long)sum); /* sum again ? it could be updated? */ for_each_irq_nr(j) seq_put_decimal_ull(p, ' ', kstat_irqs_usr(j)); seq_printf(p, "\nctxt %llu\n" "btime %lu\n" "processes %lu\n" "procs_running %lu\n" "procs_blocked %lu\n", nr_context_switches(), (unsigned long)jif, total_forks, nr_running(), nr_iowait()); seq_printf(p, "softirq %llu", (unsigned long long)sum_softirq); for (i = 0; i < NR_SOFTIRQS; i++) seq_put_decimal_ull(p, ' ', per_softirq_sums[i]); seq_putc(p, '\n'); return 0; }