commit 7fdcc89ec178dd27d33629e301189d5d2d353e6f
parent e3bf89dcdf6588076e04a66bbb150671c84b0854
Author: Daniel Barlow <dan@telent.net>
Date: Sun, 17 May 2026 23:57:42 +0100
WIP luac C translation
TODO wait for server to send script exit value
Diffstat:
| A | luac.c | | | 144 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 144 insertions(+), 0 deletions(-)
diff --git a/luac.c b/luac.c
@@ -0,0 +1,144 @@
+#include <unistd.h>
+
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+
+#include <sys/socket.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/un.h>
+
+#include <arpa/inet.h>
+
+// copied from OpenBSD
+// https://github.com/openbsd/src/blob/master/lib/libc/string/strlcpy.c
+
+/*
+ * Copy string src to buffer dst of size dsize. At most dsize-1
+ * chars will be copied. Always NUL terminates (unless dsize == 0).
+ * Returns strlen(src); if retval >= dsize, truncation occurred.
+ */
+size_t strlcpy(char *dst, const char *src, size_t dsize)
+{
+ const char *osrc = src;
+ size_t nleft = dsize;
+
+ /* Copy as many bytes as will fit. */
+ if (nleft != 0) {
+ while (--nleft != 0) {
+ if ((*dst++ = *src++) == '\0')
+ break;
+ }
+ }
+
+ /* Not enough room in dst, add NUL and traverse rest of src. */
+ if (nleft == 0) {
+ if (dsize != 0)
+ *dst = '\0'; /* NUL-terminate dst */
+ while (*src++)
+ ;
+ }
+
+ return(src - osrc - 1); /* count does not include NUL */
+}
+
+int open_socket(char * pathname){
+
+ struct sockaddr_un addr;
+ addr.sun_family = AF_UNIX;
+ addr.sun_path[0] = '\0'; /* abstract path */
+ strncpy(&addr.sun_path[1], pathname, sizeof(addr.sun_path) - 2);
+
+ int fd = socket(AF_LOCAL, SOCK_DGRAM, PF_LOCAL);
+ if(fd < 0) {
+ perror("socket");
+ exit(EXIT_FAILURE);
+ }
+
+ if((bind(fd, (struct sockaddr *) &addr, sizeof addr)) < 0) {
+ perror("bind");
+ exit(EXIT_FAILURE);
+ }
+ return fd;
+}
+
+int encode_args(char * buf, int len, int argc, char ** argv) {
+
+ char * buf_end = buf + len;
+ char * p = buf;
+ for (int i = 1; i < argc; i++) {
+ p += strlcpy(p, argv[i], buf_end - p);
+ if(p >= buf_end) {
+ fprintf(stderr, "comand line too long\n");
+ exit(1);
+ }
+ p++;
+ }
+ return p - buf;
+}
+
+int main(int argc, char **argv)
+{
+#ifdef TEST
+ char *test_args[] = // { "luac", "john", "paul is dead", "ringo" };
+ { "luac", "hello.lua" };
+ write(1, encode_args(25, 2, test_args), 25);
+ char *test2_args[] = { // this is too long
+ "luac", "0123456789", "0123456789", "012"
+ };
+ write(1, encode_args(25, 4, test2_args), 25);
+ exit(0);
+#endif
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s pathname.lua\n", argv[0]);
+ exit(1);
+ }
+
+ char * iobuf = (char *) calloc(1024, sizeof(char));
+ if(!iobuf) return 1;
+ int iobuf_len = encode_args(iobuf, 1024, argc, argv);
+
+ int maxnamelen=sizeof (((struct sockaddr_un *) 0)->sun_path);
+ char *sockname = calloc(maxnamelen, 1);
+ pid_t mypid = getpid();
+ memcpy(sockname, (void *) &mypid, sizeof mypid);
+ memcpy(sockname + sizeof mypid, iobuf, maxnamelen - sizeof mypid);
+
+ struct sockaddr_un peer_addr = { AF_UNIX, "/tmp/mysock" };
+ int socket = open_socket(sockname);
+ connect(socket, (struct sockaddr *) &peer_addr, sizeof peer_addr);
+
+ struct msghdr msg = { 0 };
+ struct cmsghdr *cmsg;
+ int myfds[] = {0,1,2};
+ struct iovec iov = {
+ .iov_base = iobuf,
+ .iov_len = iobuf_len
+ };
+ union { /* Ancillary data buffer, wrapped in a union
+ in order to ensure it is suitably aligned */
+ char buf[CMSG_SPACE(sizeof(myfds))];
+ struct cmsghdr align;
+ } u;
+
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = u.buf;
+ msg.msg_controllen = sizeof(u.buf);
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(myfds));
+ memcpy(CMSG_DATA(cmsg), myfds, sizeof(myfds));
+
+ int bytes = sendmsg(socket, &msg, 0);
+ if(bytes <= 0) {
+ perror("sendmsg");
+ exit(1);
+ }
+
+ /* FIXME: wait for bytes on socket signifying return value */
+}