luad

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

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:
Aluac.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 */ +}