146 lines
3.5 KiB
C
146 lines
3.5 KiB
C
/*
|
|
* prezzyc
|
|
* Copyright (c) 2024 Jeremy Baxter.
|
|
*/
|
|
|
|
#define _PREZZYC_C_
|
|
#define _DEFAULT_SOURCE
|
|
|
|
#ifndef BUILD_DATE
|
|
#define BUILD_DATE "1970-01-01"
|
|
#endif
|
|
|
|
#include <err.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
|
|
#include "prezzyipc.h"
|
|
#include "discord_rpc.h"
|
|
|
|
static PrezzyIpcPacket **packets;
|
|
static int packetCount;
|
|
|
|
void
|
|
addPacket(PrezzyProperty property, PrezzyPayloadType type,
|
|
char *pString, int64_t pInteger)
|
|
{
|
|
PrezzyIpcPacket *p;
|
|
size_t len;
|
|
|
|
p = malloc(sizeof(PrezzyIpcPacket));
|
|
p->property = property;
|
|
p->type = type;
|
|
if (type == PLT_STRING) {
|
|
len = strlen(pString) + 1;
|
|
p->pString = malloc(len * sizeof(char));
|
|
strbcpy(p->pString, pString, len);
|
|
} else
|
|
p->pInteger = pInteger;
|
|
|
|
packetCount++;
|
|
packets = realloc(packets,
|
|
packetCount * sizeof(PrezzyIpcPacket *));
|
|
packets[packetCount - 1] = p;
|
|
}
|
|
|
|
int
|
|
getServer(const char *socketPath)
|
|
{
|
|
struct sockaddr_un addr;
|
|
int fd;
|
|
|
|
memset(&addr, 0, sizeof(struct sockaddr_un));
|
|
addr.sun_family = AF_UNIX;
|
|
strbcpy(addr.sun_path, socketPath, sizeof(addr.sun_path) - 1);
|
|
|
|
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
|
|
err(1, "failed to create IPC client socket");
|
|
if (connect(fd, (struct sockaddr *)&addr,
|
|
sizeof(struct sockaddr_un)) == -1)
|
|
err(1, "failed to establish connection to IPC daemon");
|
|
|
|
return fd;
|
|
}
|
|
|
|
void
|
|
usage(void)
|
|
{
|
|
fputs(
|
|
"usage: prezzyc [-aV] [-d details] [-I icon] [-i tooltip]\n"
|
|
" [-L large-image] [-l tooltip] [-s state]\n"
|
|
" [-P limit] [-p size] [-T end] [-t start]\n",
|
|
stderr);
|
|
}
|
|
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
char *buffer;
|
|
ssize_t sz;
|
|
int ch, i;
|
|
int server;
|
|
|
|
if (argc < 2) { /* no options? */
|
|
usage();
|
|
return 1;
|
|
}
|
|
|
|
while ((ch = getopt(argc, argv, "ad:I:i:L:l:P:p:s:T:t:V")) != -1) {
|
|
switch (ch) {
|
|
case 'a': addPacket(PREZZY_TIMESTAMP_START, PLT_INT64, NULL, time(NULL)); break;
|
|
case 'd': addPacket(PREZZY_DETAILS, PLT_STRING, optarg, 0); break;
|
|
case 'I': addPacket(PREZZY_ICON, PLT_STRING, optarg, 0); break;
|
|
case 'i': addPacket(PREZZY_ICON_TOOLTIP, PLT_STRING, optarg, 0); break;
|
|
case 'L': addPacket(PREZZY_LARGE_IMAGE, PLT_STRING, optarg, 0); break;
|
|
case 'l': addPacket(PREZZY_LARGE_TOOLTIP, PLT_STRING, optarg, 0); break;
|
|
case 's': addPacket(PREZZY_STATE, PLT_STRING, optarg, 0); break;
|
|
case 'P': addPacket(PREZZY_PARTY_LIMIT, PLT_INT, NULL,
|
|
squashLong(strtol(optarg, NULL, 10))); break;
|
|
case 'p': addPacket(PREZZY_PARTY_SIZE, PLT_INT, NULL,
|
|
squashLong(strtol(optarg, NULL, 10))); break;
|
|
case 'T': addPacket(PREZZY_TIMESTAMP_END, PLT_INT64, NULL,
|
|
strtol(optarg, NULL, 10)); break;
|
|
case 't': addPacket(PREZZY_TIMESTAMP_START, PLT_INT64, NULL,
|
|
strtol(optarg, NULL, 10)); break;
|
|
case 'V':
|
|
printf("prezzyc version 0.1 built on " BUILD_DATE "\n");
|
|
return 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (argc - optind > 0) { /* extra arguments? */
|
|
usage();
|
|
return 1;
|
|
}
|
|
|
|
server = getServer(PREZZY_SOCK);
|
|
|
|
for (i = 0; i < packetCount; i++) {
|
|
buffer = fromIpcPacket(*packets[i]);
|
|
write(server, buffer, strlen(buffer));
|
|
free(buffer);
|
|
}
|
|
write(server, "\0", 1);
|
|
|
|
buffer = malloc(PREZZY_PACKET_MAX * sizeof(char));
|
|
memset(buffer, 0, PREZZY_PACKET_MAX);
|
|
while ((sz = read(server, buffer, PREZZY_PACKET_MAX - 1)) > 0) {
|
|
if (buffer[0] != 0)
|
|
errx(1, "IPC error %d: %s", buffer[0], buffer + 1);
|
|
}
|
|
|
|
if (sz == -1)
|
|
err(1, "failed to read from IPC server");
|
|
|
|
for (i = 0; i < packetCount; i++) {
|
|
if (packets[i]->type == PLT_STRING)
|
|
free(packets[i]->pString);
|
|
free(packets[i]);
|
|
}
|
|
free(packets);
|
|
|
|
return 0;
|
|
}
|