#include <arpa/inet.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;
static const char ACTION_ON[] = "on";
static const char ACTION_OFF[] = "off";
static const char ACTION_CYCLE[] = "cycle";
static const char ACTION_QUERY[] = "query";
enum action {
ON = 'n',
OFF = 'f',
CYCLE = 'c',
QUERY = 'q',
};
int
create_socket()
{
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
fprintf(stderr, "Failed to create socket\n");
exit(EXIT_FAILURE);
}
struct sockaddr_in addr = {
.sin_family = AF_INET,
.sin_port = htons(PORT),
.sin_addr = { .s_addr = inet_addr(ADDRESS) },
};
if (connect(sockfd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
fprintf(stderr, "Failed to connect\n");
exit(EXIT_FAILURE);
}
return sockfd;
}
void
send_command(int sockfd, enum action action)
{
char buf[BUF_SIZE];
sprintf(buf, "\x1b%s\x1b%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);
}
enum action
get_action(const char *action)
{
if (!strcmp(action, ACTION_ON)) {
return ON;
}
if (!strcmp(action, ACTION_OFF)) {
return OFF;
}
if (!strcmp(action, ACTION_CYCLE)) {
return CYCLE;
}
if (!strcmp(action, ACTION_QUERY)) {
return QUERY;
}
return 0;
}
int
main(int argc, char *argv[])
{
if (argc < 2) {
fprintf(stderr, "Usage: %s <on|off|cycle|query>\n", argv[0]);
exit(EXIT_FAILURE);
}
char action = get_action(argv[1]);
if (!action) {
fprintf(stderr, "Invalid action: %s\n", argv[1]);
exit(EXIT_FAILURE);
}
int sockfd = create_socket();
send_command(sockfd, action);
return EXIT_SUCCESS;
}