/* * prezzyc * Copyright (c) 2024 Jeremy Baxter. */ #define _PREZZYC_C_ #define _DEFAULT_SOURCE #ifndef BUILD_DATE #define BUILD_DATE "1970-01-01" #endif #include #include #include #include #include #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; }