Package: apcupsd
Version: 3.10.17-2
Severity: normal
Tags: patch
Hi,
Example client.c cannot be compiled as supplied in the examples dir.
I downloaded the source and added the code necessary to compile it.
BTW thanks for maintaining apcupsd: it's the reason I picked an APC product.
Regards,
Hugo
===========================================================================================================
--- client.c 2003-11-26 09:54:46.000000000 -0600
+++ do_apcups_client.cpp 2005-12-25 07:33:12.000000000 -0600
@@ -17,15 +17,34 @@
* For additional examples of code, see cgi/upsfetch.c
*/
-#include "apc.h"
+// 12/25/2005 - Changed by Hugo Vanwoerkom to compile + run on Debian
Sarge.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <unistd.h>
-#ifdef HAVE_NISLIB
/* Default values, can be changed on command line */
#define SERV_TCP_PORT 3551
#define SERV_HOST_ADDR "127.0.0.1"
-void handle_client();
+//Only working parms:
+//127.0.0.1:3551 status
+//127.0.0.1:3551 events
+
+
+void handle_client(FILE *fp, int sockfd, char *cmd);
+int net_open(char *host, char *service, int port);
+int net_recv(int sockfd, char *buff, int maxlen);
+int net_send(int sockfd, char *buff, int len);
+void net_close(int sockfd);
+int asnprintf(char *str, size_t size, const char *fmt, ...);
+void (*error_out)(const char *file, int line, const char *fmt,...);
extern int net_errno;
@@ -66,6 +85,7 @@
error_abort(msg);
}
+//printf("%d %s\n",__LINE__,__FILE__);
handle_client(stdin, sockfd, cmd); /* do it all */
net_close(sockfd);
exit(0);
@@ -83,39 +103,265 @@
void handle_client(FILE *fp, int sockfd, char *cmd)
{
- int n;
- char sendline[MAXLINE];
- char recvline[MAXLINE+1];
- int quit = 0;
-
- while (!quit) {
- if (cmd) {
- strcpy(sendline, cmd); /* one shot command */
- quit = 1;
- } else if (fgets(sendline, MAXLINE, fp) == NULL) {
- break;
- }
- n = strlen(sendline);
- if (net_send(sockfd, sendline, n) != n)
- error_abort("handle_client: write error on socket");
-
- while ((n = net_recv(sockfd, recvline, sizeof(recvline))) > 0) {
- recvline[n] = 0;
- fputs(recvline, stdout);
- }
- if (n < 0) {
- char msg[200];
- sprintf(msg, "handle_client: net_recv error: %s\n",
strerror(net_errno));
- error_abort(msg);
- }
- }
+ int n;
+ char sendline[MAXLINE];
+ char recvline[MAXLINE+1];
+ int quit = 0;
+
+ while (!quit) {
+ if (cmd) {
+ strcpy(sendline, cmd); /* one shot command */
+ quit = 1;
+// It's never NULL:
+// } else if (fgets(sendline, MAXLINE, fp) == NULL) {
+// break;
+// }
+ }
+ else {
+ fgets(sendline, MAXLINE, fp);
+ if (strlen (sendline) == 1) {
+ break;
+ }
+ }
+ n = strlen(sendline);
+ if (net_send(sockfd, sendline, n) != n)
+ error_abort("handle_client: write error on socket");
+
+ while ((n = net_recv(sockfd, recvline, sizeof(recvline))) > 0) {
+ recvline[n] = 0;
+ fputs(recvline, stdout);
+ }
+ if (n < 0) {
+ char msg[200];
+ sprintf(msg, "handle_client: net_recv error: %s\n",
strerror(net_errno));
+ error_abort(msg);
+ }
+ }
+}
+
+int net_errno = 0; /* error number -- not yet implemented */
+char *net_errmsg = NULL; /* pointer to error message */
+char net_errbuf[256]; /* error message buffer for messages */
+
+
+/*
+ * Read a nbytes from the network.
+ * It is possible that the total bytes require in several
+ * read requests
+ */
+
+static int read_nbytes(int fd, char *ptr, int nbytes)
+{
+ int nleft, nread;
+
+ nleft = nbytes;
+
+ while (nleft > 0) {
+
+ do {
+ nread = read(fd, ptr, nleft);
+ } while (nread == -1 && (errno == EINTR || errno == EAGAIN));
+ if (nread <= 0) {
+ net_errno = errno;
+ return(nread); /* error, or EOF */
+ }
+ nleft -= nread;
+ ptr += nread;
+ }
+ return(nbytes - nleft); /* return >= 0 */
}
-#else /* HAVE_NISLIB */
+/*
+ * Write nbytes to the network.
+ * It may require several writes.
+ */
+
+static int write_nbytes(int fd, char *ptr, int nbytes)
+{
+ int nleft, nwritten;
+
+ nleft = nbytes;
+ while (nleft > 0) {
+ nwritten = write(fd, ptr, nleft);
+ if (nwritten <= 0) {
+ net_errno = errno;
+ return (nwritten); /* error */
+ }
+
+ nleft -= nwritten;
+ ptr += nwritten;
+ }
+ return(nbytes-nleft);
+}
+
+/*
+ * Receive a message from the other end. Each message consists of
+ * two packets. The first is a header that contains the size
+ * of the data that follows in the second packet.
+ * Returns number of bytes read
+ * Returns 0 on end of file
+ * Returns -1 on hard end of file (i.e. network connection close)
+ * Returns -2 on error
+ */
+int net_recv(int sockfd, char *buff, int maxlen)
+{
+ int nbytes;
+ short pktsiz;
-int main(int argc, char *argv[]) {
- printf("Sorry, NIS code is not compiled in apcupsd.\n");
- return 1;
+ /* get data size -- in short */
+ if ((nbytes = read_nbytes(sockfd, (char *)&pktsiz, sizeof(short))) <= 0) {
+ /* probably pipe broken because client died */
+ return -1; /* assume hard EOF received */
+ }
+ if (nbytes != sizeof(short)) {
+ return -2;
+ }
+
+ pktsiz = ntohs(pktsiz); /* decode no. of bytes that follow */
+ if (pktsiz > maxlen) {
+ net_errmsg = "net_recv: record length too large\n";
+ return -2;
+ }
+ if (pktsiz == 0)
+ return 0; /* soft EOF */
+
+ /* now read the actual data */
+ if ((nbytes = read_nbytes(sockfd, buff, pktsiz)) <= 0) {
+ net_errmsg = "net_recv: read_nbytes error\n";
+ return -2;
+ }
+ if (nbytes != pktsiz) {
+ net_errmsg = "net_recv: error in read_nbytes\n";
+ return -2;
+ }
+ return(nbytes); /* return actual length of message */
}
-#endif /* HAVE_NISLIB */
+/*
+ * Send a message over the network. The send consists of
+ * two network packets. The first is sends a short containing
+ * the length of the data packet which follows.
+ * Returns number of bytes sent
+ * Returns -1 on error
+ */
+int net_send(int sockfd, char *buff, int len)
+{
+ int rc;
+ short pktsiz;
+
+ pktsiz = htons((short)len);
+ /* send short containing size of data packet */
+ rc = write_nbytes(sockfd, (char *)&pktsiz, sizeof(short));
+ if (rc != sizeof(short)) {
+ net_errmsg = "net_send: write_nbytes error of length prefix\n";
+ return -1;
+ }
+
+ /* send data packet */
+ rc = write_nbytes(sockfd, buff, len);
+ if (rc != len) {
+ net_errmsg = "net_send: write_nbytes error\n";
+ return -1;
+ }
+ return rc;
+}
+
+/*
+ * Open a TCP connection to the UPS network server
+ * Returns -1 on error
+ * Returns socket file descriptor otherwise
+ */
+int net_open(char *host, char *service, int port)
+{
+ int sockfd;
+ unsigned int inaddr; /* Careful here to use unsigned int for
*/
+ /* compatibility with Alpha */
+ struct hostent *hp;
+
+ /*
+ * Fill in the structure serv_addr with the address of
+ * the server that we want to connect with.
+ */
+ memset((char *) &tcp_serv_addr, 0, sizeof(tcp_serv_addr));
+ tcp_serv_addr.sin_family = AF_INET;
+ tcp_serv_addr.sin_port = htons(port);
+
+ if ((inaddr = inet_addr(host)) != INADDR_NONE) {
+ tcp_serv_addr.sin_addr.s_addr = inaddr;
+ } else {
+ if ((hp = gethostbyname(host)) == NULL) {
+ net_errmsg ="tcp_open: hostname error\n";
+ return -1;
+ }
+ if (hp->h_length != sizeof(inaddr) || hp->h_addrtype != AF_INET) {
+ net_errmsg ="tcp_open: funny gethostbyname value\n";
+ return -1;
+ }
+ tcp_serv_addr.sin_addr.s_addr = *(unsigned int *)hp->h_addr;
+ }
+
+
+ /* Open a TCP socket */
+ if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ net_errmsg = "tcp_open: cannot open stream socket\n";
+ return -1;
+ }
+ /* connect to server */
+ if (connect(sockfd, (struct sockaddr *) &tcp_serv_addr,
sizeof(tcp_serv_addr)) < 0) {
+// asnprintf(net_errbuf, sizeof(net_errbuf), _("tcp_open: cannot
connect to server %s on port %d.\n\
+ asnprintf(net_errbuf, sizeof(net_errbuf), ("tcp_open: cannot connect
to server %s on port %d.\n\
+ERR=%s\n"), host, port, strerror(errno));
+ net_errmsg = net_errbuf;
+ close (sockfd);
+ return -1;
+ }
+ return sockfd;
+}
+
+/* Close the network connection */
+void net_close(int sockfd)
+{
+ short pktsiz = 0;
+ /* send EOF sentinel */
+ write_nbytes(sockfd, (char *)&pktsiz, sizeof(short));
+ close(sockfd);
+}
+
+/*
+ * Accept a TCP connection.
+ * Returns -1 on error.
+ * Returns file descriptor of new connection otherwise.
+ */
+int net_accept(int fd, struct sockaddr_in *cli_addr)
+{
+ socklen_t clilen = sizeof(*cli_addr);
+ int newfd;
+
+ do {
+ newfd = accept(fd, (struct sockaddr*)cli_addr, &clilen);
+ } while (newfd == -1 && (errno == EINTR || errno == EAGAIN));
+
+ if (newfd < 0) {
+ net_errno = errno;
+ return(-1); /* error */
+ }
+
+ return newfd;
+}
+
+/*
+ * Implement snprintf
+ */
+int asnprintf(char *str, size_t size, const char *fmt, ...)
+{
+
+ va_list arg_ptr;
+ int len;
+
+ va_start(arg_ptr, fmt);
+ len = vsnprintf(str, size, fmt, arg_ptr);
+ va_end(arg_ptr);
+ str[size-1] = 0;
+ return len;
+
+}
--
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]