#include <netdb.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include "config.h"
/* 4 extra bytes for the two escape characters (), the action character, and
* the carriage return (\r) */
static const size_t BUF_SIZE = sizeof(PASSWORD) + 4;
int create_socket()
{
int sockfd;
struct addrinfo *result, *rp;
struct addrinfo hints = {
.ai_family = AF_INET,
.ai_socktype = SOCK_STREAM,
.ai_flags = 0,
.ai_protocol = 0,
};
int s = getaddrinfo(ADDRESS, PORT, &hints, &result);
if (s != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
exit(EXIT_FAILURE);
}
for (rp = result; rp != NULL; rp = rp->ai_next) {
sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (sockfd == -1) {
continue;
}
if (connect(sockfd, rp->ai_addr, rp->ai_addrlen) != -1) {
break;
}
close(sockfd);
}
if (rp == NULL) {
fprintf(stderr, "Could not connect\n");
exit(EXIT_FAILURE);
}
freeaddrinfo(result);
return sockfd;
}
void send_command(int sockfd, char action)
{
char buf[BUF_SIZE];
sprintf(buf, "%s%c\r", PASSWORD, action);
if (write(sockfd, buf, BUF_SIZE) != BUF_SIZE) {
fprintf(stderr, "partial/failed write\n");
exit(EXIT_FAILURE);
}
memset(buf, 0, BUF_SIZE);
ssize_t nread = read(sockfd, buf, BUF_SIZE);
if (nread == -1) {
perror("read");
exit(EXIT_FAILURE);
}
printf("%s\n", buf);
}
int is_valid_action(char action)
{
switch (action) {
case 'n': /* ON */
case 'f': /* OFF */
case 'c': /* CYCLE */
case 'q': /* QUERY */
return 1;
default:
return 0;
}
}
int main(int argc, char *argv[])
{
if (argc < 2) {
fprintf(stderr, "Usage: %s <n|f|c|q>\n", argv[0]);
exit(EXIT_FAILURE);
}
char action = argv[1][0];
if (!is_valid_action(action)) {
fprintf(stderr, "Invalid action: %c\n", action);
exit(EXIT_FAILURE);
}
int sockfd = create_socket();
send_command(sockfd, action);
exit(EXIT_SUCCESS);
}