int upscli_sendline(UPSCONN_t *ups, const char *buf, size_t buflen) { int ret; if (!ups) { return -1; } if (ups->fd < 0) { ups->upserror = UPSCLI_ERR_DRVNOTCONN; return -1; } if ((!buf) || (buflen < 1)) { ups->upserror = UPSCLI_ERR_INVALIDARG; return -1; } if (ups->upsclient_magic != UPSCLIENT_MAGIC) { ups->upserror = UPSCLI_ERR_INVALIDARG; return -1; } ret = net_write(ups, buf, buflen); if (ret < 1) { upscli_disconnect(ups); return -1; } return 0; }
static void clean_exit(void) { if (ups) { upscli_disconnect(ups); } free(upsname); free(hostname); free(ups); }
static void free_nut_ups_t (nut_ups_t *ups) { if (ups->conn != NULL) { upscli_disconnect (ups->conn); sfree (ups->conn); } sfree (ups->hostname); sfree (ups->upsname); sfree (ups); } /* void free_nut_ups_t */
/* cleanly close the connection to a given UPS */ static void drop_connection(utype_t *ups) { upsdebugx(2, "Dropping connection to UPS [%s]", ups->sys); ups->commstate = 0; ups->linestate = 0; clearflag(&ups->status, ST_LOGIN); clearflag(&ups->status, ST_CONNECTED); upscli_disconnect(&ups->conn); }
int upscli_readline(UPSCONN_t *ups, char *buf, size_t buflen) { int ret; size_t recv; if (!ups) { return -1; } if (ups->fd < 0) { ups->upserror = UPSCLI_ERR_DRVNOTCONN; return -1; } if ((!buf) || (buflen < 1)) { ups->upserror = UPSCLI_ERR_INVALIDARG; return -1; } if (ups->upsclient_magic != UPSCLIENT_MAGIC) { ups->upserror = UPSCLI_ERR_INVALIDARG; return -1; } for (recv = 0; recv < (buflen-1); recv++) { if (ups->readidx == ups->readlen) { ret = net_read(ups, ups->readbuf, sizeof(ups->readbuf)); if (ret < 1) { upscli_disconnect(ups); return -1; } ups->readlen = ret; ups->readidx = 0; } buf[recv] = ups->readbuf[ups->readidx++]; if (buf[recv] == '\n') { break; } } buf[recv] = '\0'; return 0; }
void upsdrv_cleanup(void) { if ( (mode == MODE_META) || (mode == MODE_REPEATER) ) { if (ups) { upscli_disconnect(ups); } if (ctx) { pconf_finish(ctx); free(ctx); } free(client_upsname); free(hostname); free(ups); } }
void upsdrv_updateinfo(void) { upsdebugx(1, "upsdrv_updateinfo..."); sleep(1); switch (mode) { case MODE_DUMMY: /* Now get user's defined variables */ if (parse_data_file(upsfd) >= 0) dstate_dataok(); break; case MODE_META: case MODE_REPEATER: if (upsclient_update_vars() > 0) { dstate_dataok(); } else { /* try to reconnect */ upscli_disconnect(ups); if (upscli_connect(ups, hostname, port, UPSCLI_CONN_TRYSSL) < 0) { upsdebugx(1, "Error reconnecting: %s", upscli_strerror(ups)); } else { upsdebugx(1, "Reconnected"); } } break; case MODE_NONE: default: break; } }
static int nut_read_one (nut_ups_t *ups) { const char *query[3] = {"VAR", ups->upsname, NULL}; unsigned int query_num = 2; char **answer; unsigned int answer_num; int status; /* (Re-)Connect if we have no connection */ if (ups->conn == NULL) { ups->conn = (collectd_upsconn_t *) malloc (sizeof (collectd_upsconn_t)); if (ups->conn == NULL) { ERROR ("nut plugin: malloc failed."); return (-1); } status = upscli_connect (ups->conn, ups->hostname, ups->port, UPSCLI_CONN_TRYSSL); if (status != 0) { ERROR ("nut plugin: nut_read_one: upscli_connect (%s, %i) failed: %s", ups->hostname, ups->port, upscli_strerror (ups->conn)); sfree (ups->conn); return (-1); } INFO ("nut plugin: Connection to (%s, %i) established.", ups->hostname, ups->port); } /* if (ups->conn == NULL) */ /* nut plugin: nut_read_one: upscli_list_start (adpos) failed: Protocol * error */ status = upscli_list_start (ups->conn, query_num, query); if (status != 0) { ERROR ("nut plugin: nut_read_one: upscli_list_start (%s) failed: %s", ups->upsname, upscli_strerror (ups->conn)); upscli_disconnect (ups->conn); sfree (ups->conn); return (-1); } while ((status = upscli_list_next (ups->conn, query_num, query, &answer_num, &answer)) == 1) { char *key; double value; if (answer_num < 4) continue; key = answer[2]; value = atof (answer[3]); if (strncmp ("ambient.", key, 8) == 0) { if (strcmp ("ambient.humidity", key) == 0) nut_submit (ups, "humidity", "ambient", value); else if (strcmp ("ambient.temperature", key) == 0) nut_submit (ups, "temperature", "ambient", value); } else if (strncmp ("battery.", key, 8) == 0) { if (strcmp ("battery.charge", key) == 0) nut_submit (ups, "percent", "charge", value); else if (strcmp ("battery.current", key) == 0) nut_submit (ups, "current", "battery", value); else if (strcmp ("battery.runtime", key) == 0) nut_submit (ups, "timeleft", "battery", value); else if (strcmp ("battery.temperature", key) == 0) nut_submit (ups, "temperature", "battery", value); else if (strcmp ("battery.voltage", key) == 0) nut_submit (ups, "voltage", "battery", value); } else if (strncmp ("input.", key, 6) == 0) { if (strcmp ("input.frequency", key) == 0) nut_submit (ups, "frequency", "input", value); else if (strcmp ("input.voltage", key) == 0) nut_submit (ups, "voltage", "input", value); } else if (strncmp ("output.", key, 7) == 0) { if (strcmp ("output.current", key) == 0) nut_submit (ups, "current", "output", value); else if (strcmp ("output.frequency", key) == 0) nut_submit (ups, "frequency", "output", value); else if (strcmp ("output.voltage", key) == 0) nut_submit (ups, "voltage", "output", value); } else if (strncmp ("ups.", key, 4) == 0) { if (strcmp ("ups.load", key) == 0) nut_submit (ups, "percent", "load", value); else if (strcmp ("ups.power", key) == 0) nut_submit (ups, "power", "ups", value); else if (strcmp ("ups.temperature", key) == 0) nut_submit (ups, "temperature", "ups", value); } } /* while (upscli_list_next) */ return (0); } /* int nut_read_one */
int main(int argc, char **argv) { int interval = 30, i; const char *prog = xbasename(argv[0]); time_t now, nextpoll = 0; const char *user = NULL; struct passwd *new_uid = NULL; const char *pidfilebase = prog; logformat = DEFAULT_LOGFORMAT; user = RUN_AS_USER; printf("Network UPS Tools %s %s\n", prog, UPS_VERSION); while ((i = getopt(argc, argv, "+hs:l:i:f:u:Vp:")) != -1) { switch(i) { case 'h': help(prog); break; case 's': monhost = optarg; break; case 'l': logfn = optarg; break; case 'i': interval = atoi(optarg); break; case 'f': logformat = optarg; break; case 'u': user = optarg; break; case 'V': exit(EXIT_SUCCESS); case 'p': pidfilebase = optarg; break; } } argc -= optind; argv += optind; /* not enough args for the old way? */ if ((argc == 1) || (argc == 2)) help(prog); /* see if it's being called in the old style - 3 or 4 args */ /* <system> <logfn> <interval> [<format>] */ if (argc >= 3) { monhost = argv[0]; logfn = argv[1]; interval = atoi(argv[2]); } if (argc >= 4) { /* read out the remaining argv entries to the format string */ logformat = xmalloc(LARGEBUF); memset(logformat, '\0', LARGEBUF); for (i = 3; i < argc; i++) snprintfcat(logformat, LARGEBUF, "%s ", argv[i]); } if (!monhost) fatalx(EXIT_FAILURE, "No UPS defined for monitoring - use -s <system>"); if (!logfn) fatalx(EXIT_FAILURE, "No filename defined for logging - use -l <file>"); /* shouldn't happen */ if (!logformat) fatalx(EXIT_FAILURE, "No format defined - but this should be impossible"); printf("logging status of %s to %s (%is intervals)\n", monhost, logfn, interval); if (upscli_splitname(monhost, &upsname, &hostname, &port) != 0) { fatalx(EXIT_FAILURE, "Error: invalid UPS definition. Required format: upsname[@hostname[:port]]\n"); } if (upscli_connect(&ups, hostname, port, UPSCLI_CONN_TRYSSL) < 0) fprintf(stderr, "Warning: initial connect failed: %s\n", upscli_strerror(&ups)); if (strcmp(logfn, "-") == 0) logfile = stdout; else logfile = fopen(logfn, "a"); if (logfile == NULL) fatal_with_errno(EXIT_FAILURE, "could not open logfile %s", logfn); /* now drop root if we have it */ new_uid = get_user_pwent(user); open_syslog(prog); if (logfile != stdout) background(); setup_signals(); writepid(pidfilebase); become_user(new_uid); compile_format(); while (exit_flag == 0) { time(&now); if (nextpoll > now) { /* there is still time left, so sleep it off */ sleep(difftime(nextpoll, now)); nextpoll += interval; } else { /* we spent more time in polling than the interval allows */ nextpoll = now + interval; } if (reopen_flag) { upslogx(LOG_INFO, "Signal %d: reopening log file", reopen_flag); reopen_log(); reopen_flag = 0; } /* reconnect if necessary */ if (upscli_fd(&ups) < 0) { upscli_connect(&ups, hostname, port, 0); } run_flist(); /* don't keep connection open if we don't intend to use it shortly */ if (interval > 30) { upscli_disconnect(&ups); } } upslogx(LOG_INFO, "Signal %d: exiting", exit_flag); if (logfile != stdout) fclose(logfile); upscli_disconnect(&ups); exit(EXIT_SUCCESS); }
int upscli_tryconnect(UPSCONN_t *ups, const char *host, int port, int flags,struct timeval * timeout) { int sock_fd; struct addrinfo hints, *res, *ai; char sport[NI_MAXSERV]; int v; fd_set wfds; int error; socklen_t error_size; long fd_flags; if (!ups) { return -1; } /* clear out any lingering junk */ memset(ups, 0, sizeof(*ups)); ups->upsclient_magic = UPSCLIENT_MAGIC; ups->fd = -1; if (!host) { ups->upserror = UPSCLI_ERR_NOSUCHHOST; return -1; } snprintf(sport, sizeof(sport), "%hu", (unsigned short int)port); memset(&hints, 0, sizeof(hints)); if (flags & UPSCLI_CONN_INET6) { hints.ai_family = AF_INET6; } else if (flags & UPSCLI_CONN_INET) { hints.ai_family = AF_INET; } else { hints.ai_family = AF_UNSPEC; } hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; while ((v = getaddrinfo(host, sport, &hints, &res)) != 0) { switch (v) { case EAI_AGAIN: continue; case EAI_NONAME: ups->upserror = UPSCLI_ERR_NOSUCHHOST; return -1; case EAI_MEMORY: ups->upserror = UPSCLI_ERR_NOMEM; return -1; case EAI_SYSTEM: ups->syserrno = errno; break; } ups->upserror = UPSCLI_ERR_UNKNOWN; return -1; } for (ai = res; ai != NULL; ai = ai->ai_next) { sock_fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sock_fd < 0) { switch (errno) { case EAFNOSUPPORT: case EINVAL: break; default: ups->upserror = UPSCLI_ERR_SOCKFAILURE; ups->syserrno = errno; } continue; } /* non blocking connect */ if(timeout != NULL) { fd_flags = fcntl(sock_fd, F_GETFL); fd_flags |= O_NONBLOCK; fcntl(sock_fd, F_SETFL, fd_flags); } while ((v = connect(sock_fd, ai->ai_addr, ai->ai_addrlen)) < 0) { if(errno == EINPROGRESS) { FD_ZERO(&wfds); FD_SET(sock_fd, &wfds); select(sock_fd+1,NULL,&wfds,NULL, timeout); if (FD_ISSET(sock_fd, &wfds)) { error_size = sizeof(error); getsockopt(sock_fd,SOL_SOCKET,SO_ERROR, &error,&error_size); if( error == 0) { /* connect successful */ v = 0; break; } errno = error; } else { /* Timeout */ v = -1; break; } } switch (errno) { case EAFNOSUPPORT: break; case EINTR: case EAGAIN: continue; default: ups->upserror = UPSCLI_ERR_CONNFAILURE; ups->syserrno = errno; } break; } if (v < 0) { close(sock_fd); continue; } /* switch back to blocking operation */ if(timeout != NULL) { fd_flags = fcntl(sock_fd, F_GETFL); fd_flags &= ~O_NONBLOCK; fcntl(sock_fd, F_SETFL, fd_flags); } ups->fd = sock_fd; ups->upserror = 0; ups->syserrno = 0; break; } freeaddrinfo(res); if (ups->fd < 0) { return -1; } pconf_init(&ups->pc_ctx, NULL); ups->host = strdup(host); if (!ups->host) { ups->upserror = UPSCLI_ERR_NOMEM; upscli_disconnect(ups); return -1; } ups->port = port; if (flags & UPSCLI_CONN_TRYSSL) { upscli_sslinit(ups); /* see if something made us die inside sslinit */ if (ups->upserror != 0) { upscli_disconnect(ups); return -1; } } if ((flags & UPSCLI_CONN_REQSSL) && (upscli_sslinit(ups) != 1)) { ups->upserror = UPSCLI_ERR_SSLFAIL; upscli_disconnect(ups); return -1; } return 0; }