diff --git a/lit/seed.lit b/lit/seed.lit deleted file mode 100644 index 27ceb2a..0000000 --- a/lit/seed.lit +++ /dev/null @@ -1,222 +0,0 @@ -@code_type c .c -@comment_type /* %s */ - -@title seed - -@s Introduction -Using seed is rather straight forward. The syntax is as follows: `seed COMMAND`. - -The program is also simple. Here is an outline. - ---- seed.c -@{copyright notice} -@{c headers} -@{posix headers} - -@{helper function} - -int -main(int argc, char *argv[]) -{ - @{variables local to main} - - if (argc < 2) { - die("%s: not enough arguments\n", argv[0]); - } - - @{open socket} - @{send message} - @{receive and print reply} - @{cleanup} -} ---- - -As we can already see we will need to include `stdio.h` and `stdlib.h`. - ---- c headers -#include -#include ---- - -@s Copyright - -This project is licensed under the Mozilla Public License Version 2.0. Please read LICENSE for more details. - ---- copyright notice -/* Copyright (c), Niclas Meyer - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at https://mozilla.org/MPL/2.0/. - */ ---- - -@s Creating the socket object - -This is rather straight forward. We setup all the things in our socket object and then connect. - -We're going to store the file descriptor and the `sockaddr` local to main. - ---- variables local to main -int sock_fd; -struct sockaddr_un sock_addr; ---- - -This requires including the following headers. - ---- posix headers -#include -#include ---- - -Now it's finally time to fill stuff into our `sockaddr`. - ---- open socket -if ((sock_fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { - die("%s: failed to open socket\n", argv[0]); -} - -sock_addr.sun_family = AF_UNIX; - -@{get socket path} - -if (connect(sock_fd, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) < 0) { - die("%s: failed to connect to socket\n", argv[0]); -} ---- - -@s Get the socket path - -It's important that we open the correct socket. -This might be set via an environment variable to allow maximum flexibility, while still keeping a trivial interface. - -We're going to store the path in `sock_path`, local to main. - ---- variables local to main += -const char *sock_path; ---- - -We check if `KIWMI_SOCKET` is set, and use it, or default to `/tmp/kiwmi.sock`. - ---- get socket path -sock_path = getenv("KIWMI_SOCKET"); - -if (sock_path) { - strncpy(sock_addr.sun_path, sock_path, sizeof(sock_addr.sun_path)); -} else { - strncpy(sock_addr.sun_path, "/tmp/kiwmi.sock", sizeof(sock_addr.sun_path)); -} ---- - -For this we need `string.h`. - ---- c headers += -#include ---- - -@s Send our message - -This actually consists of two steps. - ---- send message -@{generate message from argv} -@{send generated message} ---- - -@s Generate message - -Pretty straight forward. We need a buffer and then we just append all arguments, beginning with `argv[1]`, separated by spaces. - ---- variables local to main += -char msg[BUFSIZ]; -size_t msg_len; ---- - ---- generate message from argv -msg_len = 0; - -for (int i = 1; i < argc; i++) { - msg_len += (size_t)snprintf(msg + msg_len, sizeof(msg), "%s ", argv[i]); -} - -msg_len -= 1; // Remove trailing space ---- - -@s Actually send the message - -This is straight forward enough. We just `send` the message. - ---- send generated message -if (send(sock_fd, msg, msg_len, 0) < 0) { - die("%s: failed to send message\n", argv[0]); -} ---- - -@s Handling the reply - -Some commands return a string to print. If there's none, we'll just receive a `\0`. -This is pretty much stolen from baskerville. - ---- receive and print reply -struct pollfd fds[] = { - { sock_fd, POLLIN, 0 }, - { STDOUT_FILENO, POLLHUP, 0 }, -}; - -while (poll(fds, 2, -1) > 0) { - if (fds[1].revents & (POLLERR | POLLHUP)) { - break; - } - - if (fds[0].revents & POLLIN) { - if ((msg_len = recv(sock_fd, msg, sizeof(msg) - 1, 0)) > 0) { - msg[msg_len] = '\0'; - if (msg_len == 1) { - break; - } - - printf("%s", msg); - fflush(stdout); - } else { - break; - } - } -} ---- - -This requires us to include `poll.h` and `unistd.h`. - ---- posix headers += -#include -#include ---- - -@s Cleanup - -Not much to do here. Just close the socket. - ---- cleanup -close(sock_fd); ---- - -@s Helper function - -We used `die` the whole time. Time to make it a thing already. - ---- helper function -static void -die(char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - exit(EXIT_FAILURE); -} ---- - -Note that this requires the `stdarg.h` header. - ---- c headers += -#include ----