static void _log_flush(log_t *log) { if (!log->opt.buffered) return; if (log->opt.stderr_level) cbuf_read_to_fd(log->buf, fileno(stderr), -1); else if (log->logfp && (fileno(log->logfp) > 0)) cbuf_read_to_fd(log->fbuf, fileno(log->logfp), -1); }
void Cbuf_read_to_fd(cbuf_t buf, int fd) { assert(buf); if (cbuf_read_to_fd(buf, fd, -1) < 0) ierr_exit("Cbuf_read_to_fd(%d): %s", fd, strerror(errno)); }
static void _log_printf(log_t *log, cbuf_t cb, FILE *stream, const char *fmt, ...) { va_list ap; int fd = -1; /* If the fd is less than 0 just return since we can't do anything here. * This can happen if a calling program is the one that set up the io. */ if (stream) fd = fileno(stream); if (fd < 0) return; /* If the socket has gone away we just return like all is well. */ if (_fd_writeable(fd) != 1) return; va_start(ap, fmt); if (log->opt.buffered && (cb != NULL)) { char *buf = vxstrfmt(fmt, ap); int len = strlen(buf); int dropped; cbuf_write(cb, buf, len, &dropped); cbuf_read_to_fd(cb, fd, -1); xfree(buf); } else { vfprintf(stream, fmt, ap); } va_end(ap); }
static void _ipmipower_cleanup (void) { int i; cbuf_destroy (ttyin); /* Flush before destroying. */ cbuf_read_to_fd (ttyout, STDOUT_FILENO, -1); cbuf_destroy (ttyout); ipmipower_connection_array_destroy (ics, ics_len); for (i = 0; i < IPMIPOWER_MSG_TYPE_NUM_ENTRIES; i++) hostlist_destroy (output_hostrange[i]); }
/* * Callback when zio->dstfd is writeable. Write buffered data to * file descriptor. */ static int zio_writer_cb (zio_t *zio) { int rc = 0; if (cbuf_used (zio->buf)) rc = cbuf_read_to_fd (zio->buf, zio->dstfd, -1); if (rc < 0) { if (errno == EAGAIN) return (0); zio_debug (zio, "cbuf_read_to_fd: %s\n", strerror (errno)); return (-1); } if ((rc == 0) && zio_eof_pending (zio)) rc = zio_close (zio); return (rc); }
static int zio_writer_flush_all (zio_t *zio) { int n = 0; zio_debug (zio, "zio_writer_flush_all: used=%d\n", zio_buffer_used (zio)); while (zio_buffer_used (zio) > 0) { int rc = cbuf_read_to_fd (zio->buf, zio->dstfd, -1); zio_debug (zio, "zio_writer_flush_all: rc=%d\n", rc); if (rc < 0) return (rc); n += rc; } zio_debug (zio, "zio_writer_flush_all: n=%d\n", n); if (zio_buffer_used (zio) == 0 && zio_eof_pending (zio)) zio_close (zio); return (n); }
int main (int argc, char *argv[]) { int i; ipmi_disable_coredump (); ipmipower_argp_parse (argc, argv, &cmd_args); /* after ipmipower_argp_parse - IPMIPOWER_ERROR/IPMIPOWER_DEBUG * macros used */ if (cmd_args.powercmd == IPMIPOWER_POWER_CMD_NONE) ipmipower_error_setup (IPMIPOWER_ERROR_STDERR | IPMIPOWER_ERROR_SYSLOG); else ipmipower_error_setup (IPMIPOWER_ERROR_STDERR); _ipmipower_setup (); ipmipower_powercmd_setup (); if (cmd_args.common_args.hostname) { unsigned int len = 0; if (!(ics = ipmipower_connection_array_create (cmd_args.common_args.hostname, &len))) { /* dump error outputs here, most notably invalid hostname output */ cbuf_read_to_fd (ttyout, STDOUT_FILENO, -1); exit (EXIT_FAILURE); } ics_len = len; } /* If power command (i.e. --reset, --stat, etc.) is passed at * command line, put the power control commands in the pending * queue. */ if (cmd_args.powercmd != IPMIPOWER_POWER_CMD_NONE) { struct ipmipower_connection_extra_arg *eanode; char errbuf[IPMIPOWER_OUTPUT_BUFLEN + 1]; /* must be checked in args parsing */ assert (cmd_args.common_args.hostname); cmd_args.ping_interval = 0; memset (errbuf, '\0', IPMIPOWER_OUTPUT_BUFLEN + 1); if (cmd_args.oem_power_type == IPMIPOWER_OEM_POWER_TYPE_NONE) { if (ipmipower_power_cmd_check_privilege (cmd_args.powercmd, errbuf, IPMIPOWER_OUTPUT_BUFLEN) <= 0) { IPMIPOWER_ERROR (("%s", errbuf)); exit (EXIT_FAILURE); } } else { if (ipmipower_oem_power_cmd_check_support_and_privilege (cmd_args.powercmd, errbuf, IPMIPOWER_OUTPUT_BUFLEN) <= 0) { IPMIPOWER_ERROR (("%s", errbuf)); exit (EXIT_FAILURE); } } _eliminate_nodes (); /* Because can input multiple hosts, check all args before doing * powercmd queue so we don't do any if any single argument is * invalid */ if (cmd_args.oem_power_type != IPMIPOWER_OEM_POWER_TYPE_NONE) { for (i = 0; i < ics_len; i++) { assert (ics[i].extra_args); if (ics[i].skip) continue; eanode = ics[i].extra_args; while (eanode) { memset (errbuf, '\0', IPMIPOWER_OUTPUT_BUFLEN + 1); if (ipmipower_oem_power_cmd_check_extra_arg (eanode->extra_arg, errbuf, IPMIPOWER_OUTPUT_BUFLEN) <= 0) { IPMIPOWER_ERROR (("%s", errbuf)); exit (EXIT_FAILURE); } eanode = eanode->next; } } } for (i = 0; i < ics_len; i++) { if (ics[i].skip) continue; if (cmd_args.oem_power_type != IPMIPOWER_OEM_POWER_TYPE_NONE) { assert (ics[i].extra_args); eanode = ics[i].extra_args; while (eanode) { ipmipower_powercmd_queue (cmd_args.powercmd, &ics[i], eanode->extra_arg); eanode = eanode->next; } } else ipmipower_powercmd_queue (cmd_args.powercmd, &ics[i], NULL); } } /* immediately send out discovery messages upon startup */ ipmipower_ping_force_discovery_sweep (); _poll_loop ((cmd_args.powercmd != IPMIPOWER_POWER_CMD_NONE) ? 1 : 0); ipmipower_powercmd_cleanup (); _ipmipower_cleanup (); /* If any error messages other than "on", "off", or "ok", then an * error occurred */ for (i = IPMIPOWER_MSG_TYPE_ERROR_MIN; i < IPMIPOWER_MSG_TYPE_ERROR_MAX; i++) { if (output_counts[i]) return (EXIT_FAILURE); } return (EXIT_SUCCESS); }
/* _poll_loop * - poll on all descriptors */ static void _poll_loop (int non_interactive) { int nfds = 0; struct pollfd *pfds = NULL; int extra_fds; /* number of fds for stdin and stdout we'll need when polling * * Right now, always poll stdout. When non-interactive, * don't need stdin */ extra_fds = 1 + (non_interactive ? 0 : 1); while (non_interactive || ipmipower_prompt_process_cmdline ()) { int i, num, timeout; int powercmd_timeout = -1; int ping_timeout = -1; /* If there are no pending commands before this call, * powercmd_timeout will not be set, leaving it at -1 */ num = ipmipower_powercmd_process_pending (&powercmd_timeout); if (non_interactive && !num) break; /* ping timeout is always set if cmd_args.ping_interval > 0 */ ipmipower_ping_process_pings (&ping_timeout); if (cmd_args.ping_interval) { if (powercmd_timeout == -1) timeout = ping_timeout; else timeout = (ping_timeout < powercmd_timeout) ? ping_timeout : powercmd_timeout; } else timeout = powercmd_timeout; /* achu: I always wonder if this poll() loop could be done far * more elegantly and efficiently without all this crazy * indexing, perhaps through a callback/event mechanism. It'd * probably be more efficient, since most callback/event based * models have min-heap like structures inside for determining * what things timed out. Overall though, I don't think the O(n) * (n being hosts/fds) processing is really that inefficient for * this particular application and is not worth going back and * changing. By going to a callback/event mechanism, there will * still be some O(n) activities within the code, so I am only * going to create a more efficient O(n) poll loop. */ /* Has the number of hosts changed? */ if (nfds != (ics_len*2) + extra_fds) { /* The "*2" is for each host's two fds, one for ipmi * (ipmi_fd) and one for rmcp (ping_fd). */ nfds = (ics_len*2) + extra_fds; free (pfds); if (!(pfds = (struct pollfd *)malloc (nfds * sizeof (struct pollfd)))) { IPMIPOWER_ERROR (("malloc: %s", strerror (errno))); exit (EXIT_FAILURE); } } for (i = 0; i < ics_len; i++) { pfds[i*2].fd = ics[i].ipmi_fd; pfds[i*2+1].fd = ics[i].ping_fd; pfds[i*2].events = pfds[i*2+1].events = 0; pfds[i*2].revents = pfds[i*2+1].revents = 0; pfds[i*2].events |= POLLIN; if (!cbuf_is_empty (ics[i].ipmi_out)) pfds[i*2].events |= POLLOUT; if (!cmd_args.ping_interval) continue; pfds[i*2+1].events |= POLLIN; if (!cbuf_is_empty (ics[i].ping_out)) pfds[i*2+1].events |= POLLOUT; } if (!non_interactive) { pfds[nfds-2].fd = STDIN_FILENO; pfds[nfds-2].events = POLLIN; pfds[nfds-2].revents = 0; } pfds[nfds-1].fd = STDOUT_FILENO; if (!cbuf_is_empty (ttyout)) pfds[nfds-1].events = POLLOUT; else pfds[nfds-1].events = 0; pfds[nfds-1].revents = 0; ipmipower_poll (pfds, nfds, timeout); for (i = 0; i < ics_len; i++) { if (pfds[i*2].revents & POLLERR) { IPMIPOWER_DEBUG (("host = %s; IPMI POLLERR", ics[i].hostname)); /* See comments in _ipmi_recvfrom() regarding ECONNRESET/ECONNREFUSED */ _recvfrom (ics[i].ipmi_in, ics[i].ipmi_fd, &(ics[i].destaddr)); } else { if (pfds[i*2].revents & POLLIN) _recvfrom (ics[i].ipmi_in, ics[i].ipmi_fd, &(ics[i].destaddr)); if (pfds[i*2].revents & POLLOUT) _sendto (ics[i].ipmi_out, ics[i].ipmi_fd, &(ics[i].destaddr)); } if (!cmd_args.ping_interval) continue; if (pfds[i*2+1].revents & POLLERR) { IPMIPOWER_DEBUG (("host = %s; PING_POLLERR", ics[i].hostname)); _recvfrom (ics[i].ping_in, ics[i].ping_fd, &(ics[i].destaddr)); } else { if (pfds[i*2+1].revents & POLLIN) _recvfrom (ics[i].ping_in, ics[i].ping_fd, &(ics[i].destaddr)); if (pfds[i*2+1].revents & POLLOUT) _sendto (ics[i].ping_out, ics[i].ping_fd, &(ics[i].destaddr)); } } if (!non_interactive && (pfds[nfds-2].revents & POLLIN)) { int n, dropped = 0; if ((n = cbuf_write_from_fd (ttyin, STDIN_FILENO, -1, &dropped)) < 0) { IPMIPOWER_ERROR (("cbuf_write_from_fd: %s", strerror (errno))); exit (EXIT_FAILURE); } /* achu: If you are running ipmipower in co-process mode * with powerman, this error condition will probably be hit * with the file descriptor STDIN_FILENO. The powerman * daemon is usually closed by /etc/init.d/powerman stop, * which kills a process through a signal. Thus, powerman * closes stdin and stdout pipes to ipmipower and the call * to cbuf_write_from_fd will give us an EOF reading. We'll * consider this EOF an "ok" error. No need to output an * error message. */ if (!n) exit (EXIT_FAILURE); if (dropped) IPMIPOWER_DEBUG (("cbuf_write_from_fd: read dropped %d bytes", dropped)); } if (!cbuf_is_empty (ttyout) && (pfds[nfds-1].revents & POLLOUT)) { if (cbuf_read_to_fd (ttyout, STDOUT_FILENO, -1) < 0) { IPMIPOWER_ERROR (("cbuf_read_to_fd: %s", strerror (errno))); exit (EXIT_FAILURE); } } } free (pfds); }