all repos — nimisewi_c @ e7e4e22b69a0c9965c2d4f96903ae647165e99d3

simple random toki pona phrase generator

major refactoring

added options to compile cgi for http and gemini

FossilOrigin-Name: 393d793150423ffe6680f109ef6b0524fd8e2e3501766a6761aa63276e90d90e
la-ninpre leobrekalini@gmail.com
Wed, 02 Jun 2021 17:00:39 +0000
commit

e7e4e22b69a0c9965c2d4f96903ae647165e99d3

parent

44c234cfdf8588e5c53a9534cc2ee1c627682f7c

12 files changed, 355 insertions(+), 74 deletions(-)

jump to
M MakefileMakefile

@@ -1,6 +1,8 @@

+include conf.mk + PREFIX ?= /usr/local/ CFLAGS += -pedantic -Wall -Wextra -Wmissing-prototypes \ - -Wstrict-prototypes -Wwrite-strings + -Wstrict-prototypes -Wwrite-strings ${EXTRAFLAGS} NIMITOKI = nimitoki.c nimitoki.h

@@ -19,15 +21,25 @@

makenimitoki: makenimitoki.o ${CC} ${CFLAGS} -o $@ makenimitoki.o -nimisewi: nimisewi.o nimitoki.o - ${CC} ${CFLAGS} -o $@ nimisewi.o nimitoki.o +nimisewi: main.o nimisewi.o nimitoki.o + ${CC} ${CFLAGS} -o $@ main.o nimisewi.o nimitoki.o + +cgi: nimitoki.o cgi.o nimisewi.o + ${CC} ${CFLAGS} -o nimisewi.cgi cgi.o nimisewi.o nimitoki.o + +cgi_gemini: nimitoki.o nimisewi.o cgi_gemini.o + ${CC} ${CFLAGS} -o nimisewi.cgi cgi_gemini.o nimisewi.o nimitoki.o clean: - find . \( -name "*.o" -o -name nimisewi -o -name makenimitoki \) -delete + find . \( -name "*.o" \ + -o -name nimisewi \ + -o -name nimisewi.cgi \ + -o -name makenimitoki \) -delete distclean: find . \( -name "*.o" \ -o -name nimisewi \ + -o -name nimisewi.cgi \ -o -name makenimitoki \ -o -name nimitoki.c \ -o -name nimitoki.h \) -delete
M README.mdREADME.md

@@ -17,6 +17,24 @@ $ make

$ doas make install ``` +if you want to use nimisewi as cgi script, you can compile it with: + +```terminal +$ make distclean +$ configure --static # if your cgi will be served from chroot +$ make cgi +``` + +or if you want a cgi script for gemini protocol, run: + +```terminal +$ make distclean +$ configure --static # if your cgi will be served from chroot +$ make cgi_gemini +``` + +now throw that `nimisewi.cgi` into your cgi-bin folder and serve it as you wish. + ## usage ```
A cgi.c

@@ -0,0 +1,94 @@

+/* Copyright (c) 2021, la-ninpre + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * ************************************************************************* + * + * this file contains code for cgi version of nimisewi. + * + * i know that there are libraries for cgi in c, but c'mon, it's so small and + * simple. + * stylesheet is arbitrary, replace with anything you want if you don't like it. + */ + +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include "cgi.h" + +#include "nimisewi.h" + +void +print_response_header(void) +{ + printf("Status: 200 OK\r"); + printf("Content-Type: text/html\r"); +} + +void +print_html_header(void) +{ + printf("<!doctype html\n"); + printf("<html>\n"); + printf("<head>\n"); + print_html_stylesheet(); + printf("</head>\n"); + printf("<body>\n"); +} + +void +print_html_stylesheet(void) +{ + printf("<style>\n"); + printf("body { background: #ff8; }\n"); + printf("h1 { text-align: center; font: bold 48pt monospace; color: #4ad }\n"); + printf("</style>\n"); +} + +void +print_html_footer(void) +{ + printf("</body>\n"); + printf("</html>\n"); +} + +int +main(void) +{ +#ifdef __OpenBSD__ + if (pledge("stdio", NULL) == -1) { + err(EXIT_FAILURE, "pledge"); + } +#endif + + char *ns; + ns = nimi_sewi(); + if (ns == NULL) { + err(EXIT_FAILURE, "memory could'n be allocated"); + } + + print_response_header(); + print_html_header(); + + printf("<h1>"); + printf("%s", ns); + printf("</h1>\n"); + + weka_e_nimi_sewi(ns); + + print_html_footer(); + + return EXIT_SUCCESS; +}
A cgi.h

@@ -0,0 +1,24 @@

+/* Copyright (c) 2021, la-ninpre + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef NIMISEWI_CGI_H +#define NIMISEWI_CGI_H + +void print_response_header(void); +void print_html_header(void); +void print_html_stylesheet(void); +void print_html_footer(void); + +#endif /* NIMISEWI_CGI_H */
A cgi_gemini.c

@@ -0,0 +1,29 @@

+#include <stdio.h> +#include <err.h> +#include <stdlib.h> +#include <unistd.h> + +#include "nimisewi.h" + +int +main(void) +{ +#ifdef __OpenBSD__ + if (pledge("stdio", NULL) == -1) { + err(EXIT_FAILURE, "pledge failed"); + } +#endif + + char *ns; + + ns = nimi_sewi(); + if (ns == NULL) { + err(EXIT_FAILURE, "memory allocation failed"); + } + + printf("20 text/gemini\r\n"); + printf("sina o lukin e nimi sewi:\n\n"); + printf("# %s\n", ns); + + return EXIT_SUCCESS; +}
A conf.mk

@@ -0,0 +1,1 @@

+EXTRAFLAGS=
A configure

@@ -0,0 +1,11 @@

+#!/bin/sh -e + +case $1 in + --static) + EXTRAFLAGS="$EXTRAFLAGS -static" + ;; + *) + ;; +esac + +echo "EXTRAFLAGS=$EXTRAFLAGS" > conf.mk
A main.c

@@ -0,0 +1,48 @@

+/* Copyright (c) 2021, la-ninpre + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * ********************************************************************** + * + * this file contains main code for nimisewi as commandline utility + * that throws it's phrases to stdout. + * + * should be obvious :) + */ + +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include "nimisewi.h" +#include "nimitoki.h" + +int +main(void) +{ +#ifdef __OpenBSD__ + if (pledge("stdio", NULL) == -1) { + err(EXIT_FAILURE, "pledge"); + } +#endif + char *ns; + ns = nimi_sewi(); + + printf("%s\n", ns); + + weka_e_nimi_sewi(ns); + + return EXIT_SUCCESS; +} +
M makenimitoki.cmakenimitoki.c

@@ -42,6 +42,8 @@ _MAKENIMITOKI_COMMENT_

"#ifndef NIMI_TOKI_H\n" "#define NIMI_TOKI_H\n\n" + "#include <stdlib.h>\n" + "extern const char *nimi_toki[]; /* list of words */\n" "extern const unsigned long suli_pi_nimi_toki /* length of word list */;\n\n"
M nimisewi.cnimisewi.c

@@ -20,16 +20,21 @@ * nimisewi is a small program that generates random toki pona noun phrase.

* toki pona is a small constructed language created by sonja lang * (see https://tokipona.org). * - * functions and variables here a primarily named in tokipona, just because i - * can. but just in case there are annotations in english. + * functions and variables here a primarily named in tokipona, just because + * i can. but just in case there are annotations in english. * - * sona nanpa li ike. taso ona li pali e nimi pona. + * sona nanpa li ike. taso ona li pali e ilo pona. */ #include <err.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> + +#include <string.h> +#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined( _NetBSD__) || defined(__DragonFly__) +#define HAS_STRLCAT +#endif #include <sys/types.h> #include <sys/time.h>

@@ -37,8 +42,8 @@

#include "nimisewi.h" #include "nimitoki.h" /* nimi_toki, suli_pi_nimi_toki */ -void -open_e_nanpa_sewi() +static void +open_e_nanpa_sewi(void) { /* initialize pseudorandom generator using pid, microseconds and seconds *

@@ -54,10 +59,8 @@ pid = getpid();

srand(pid * time.tv_usec * time.tv_sec); } -const char -*pana_e_nimi(const char *nimi_mute[], - const int suli_pi_nimi_mute, - const int nanpa_nimi) +static const char +*pana_e_nimi(const int nanpa_nimi) { /* wrapper function to get word from array *

@@ -76,95 +79,137 @@ * this functions inserts 'pi' in the middle to avoid generating

* very heavy phrases. */ - if (nanpa_nimi > suli_pi_nimi_mute) { - err(EXIT_FAILURE, "index out of bounds"); - } else if (nanpa_nimi == -1) { + if (nanpa_nimi == -1) { return "pi"; + } else if ((unsigned long) nanpa_nimi > suli_pi_nimi_toki) { + err(EXIT_FAILURE, "index out of bounds"); } else { - return nimi_mute[nanpa_nimi]; + return nimi_toki[nanpa_nimi]; } } -void -pana_e_nanpa_nimi(struct nanpa_nimi *nn) +static void +nanpa_nimi_pana_e_pi(struct nanpa_nimi *nn) { - /* generate random number, which is later used as number of words - * in the phrase - * - * also here is made decision, whether to insert 'pi' - */ - nn->pi_li_lon = 0; - nn->nanpa_pi = -1; - nn->nanpa_nimi = (rand() % 6); - + /* handle a 'pi' instertion */ if (nn->nanpa_nimi == 2) { + /* this is made to allow for phrases with following structures: + * + * - word1 word2 word3 + * - word1 pi word2 word3 + */ nn->pi_li_lon = rand() % 2; } else if (nn->nanpa_nimi > 2) { nn->pi_li_lon = 1; } if (nn->pi_li_lon) { + /* since we insert whole word, number of words must be increased too */ nn->nanpa_nimi++; nn->nanpa_pi = (nn->nanpa_nimi / 2); } } -void -pana_e_nanpa_pi_nimi_sewi(int *nanpa_sewi_mute, - const int suli_nimi, - struct nanpa_nimi *nn) +static struct nanpa_nimi +*pana_e_nanpa_nimi(void) { - /* create specified amount of random numbers + /* generate nanpa_nimi with all the values useful for phrase generation * - * they are used later as indices to get words from wordlist + * when used, one should call weka_e_nanpa_nimi(); */ int i; + struct nanpa_nimi *nn; + nn = malloc(sizeof(struct nanpa_nimi)); + if (nn == NULL) { + return NULL; + } + + /* initialize nanpa_nimi with default values */ + nn->pi_li_lon = 0; + nn->nanpa_pi = -1; + nn->nanpa_sewi_nimi = NULL; + nn->suli_pi_nimi_sewi = 0; + + nn->nanpa_nimi = (rand() % 6); + + /* to use with arbitrary wordlist, remove following function call */ + nanpa_nimi_pana_e_pi(nn); + + nn->nanpa_sewi_nimi = calloc(nn->nanpa_nimi + 1, sizeof(int)); + if (nn->nanpa_sewi_nimi == NULL) { + free(nn); + return NULL; + } for (i = 0; i <= nn->nanpa_nimi; i++) { - nanpa_sewi_mute[i] = rand() % suli_nimi; + nn->nanpa_sewi_nimi[i] = rand() % suli_pi_nimi_toki; + } + if (nn->pi_li_lon) { + nn->nanpa_sewi_nimi[nn->nanpa_pi] = -1; + } + + for (i = 0; i <= nn->nanpa_nimi; i++) { + nn->suli_pi_nimi_sewi += sizeof(char); + nn->suli_pi_nimi_sewi += strlen(pana_e_nimi(nn->nanpa_sewi_nimi[i])); } - if (nn->pi_li_lon) { - nanpa_sewi_mute[nn->nanpa_pi] = -1; + return nn; +} + +static void +weka_e_nanpa_nimi(struct nanpa_nimi *nn) +{ + if (nn != NULL) { + free(nn->nanpa_sewi_nimi); + free(nn); } } -int -main(void) +static void +string_cat(char *dst, const char *src, size_t size) { +#ifdef HAS_STRLCAT + strlcat(dst, src, size); +#else + strcat(dst, src); +#endif +} + +char +*nimi_sewi() { - int *nanpa_sewi_nimi; /* container for random indices */ int i; - struct nanpa_nimi nn; /* see nimisewi.h */ + char *nimi_pana; + struct nanpa_nimi *nn; -#ifdef __OpenBSD__ - if (pledge("stdio", NULL) == -1) { - err(EXIT_FAILURE, "pledge"); - } -#endif open_e_nanpa_sewi(); - pana_e_nanpa_nimi(&nn); + nn = pana_e_nanpa_nimi(); - nanpa_sewi_nimi = (int *) calloc(nn.nanpa_nimi + 1, sizeof(int)); - if (nanpa_sewi_nimi == NULL) { - err(EXIT_FAILURE, "calloc"); + nimi_pana = calloc(nn->suli_pi_nimi_sewi + 1, sizeof(char)); + if (nimi_pana == NULL) { + weka_e_nanpa_nimi(nn); + return NULL; } - pana_e_nanpa_pi_nimi_sewi(nanpa_sewi_nimi, suli_pi_nimi_toki, &nn); - - /* i think that this section could be improved. i had an idea that - * it would be cool to include options to output in cgi format instead - * of just text - */ - for (i = 0; i < nn.nanpa_nimi; i++) { - printf("%s ", - pana_e_nimi(nimi_toki, suli_pi_nimi_toki, nanpa_sewi_nimi[i])); + for (i = 0; i < nn->nanpa_nimi; i++) { + string_cat(nimi_pana, + pana_e_nimi(nn->nanpa_sewi_nimi[i]), + nn->suli_pi_nimi_sewi); + string_cat(nimi_pana, " ", nn->suli_pi_nimi_sewi); } - printf("%s", pana_e_nimi(nimi_toki, suli_pi_nimi_toki, nanpa_sewi_nimi[i])); - printf("\n"); + string_cat(nimi_pana, + pana_e_nimi(nn->nanpa_sewi_nimi[i]), + nn->suli_pi_nimi_sewi); - free(nanpa_sewi_nimi); + weka_e_nanpa_nimi(nn); - return 0; + return nimi_pana; } +void +weka_e_nimi_sewi(char *nimi_sewi) +{ + if (nimi_sewi != NULL) { + free(nimi_sewi); + } +}
M nimisewi.hnimisewi.h

@@ -16,23 +16,19 @@

#ifndef NIMI_SEWI_H #define NIMI_SEWI_H +#include <stdlib.h> + /* struct to hold stuff useful for random index generation */ struct nanpa_nimi { - int nanpa_nimi; /* number of words */ + int nanpa_nimi; /* number of words - 1 */ int pi_li_lon; /* whether to insert 'pi' or not */ int nanpa_pi; /* index to insert 'pi', if pi_li_lon is 1 */ + int *nanpa_sewi_nimi; /* random indices of words */ + size_t suli_pi_nimi_sewi; /* length of generated phrase */ }; -void open_e_nanpa_sewi(void); - -void pana_e_nanpa_nimi(struct nanpa_nimi *nn); +char *nimi_sewi(void); -void pana_e_nanpa_pi_nimi_sewi(int *nanpa_sewi_mute, - const int suli_nimi, - struct nanpa_nimi *nn); - -const char *pana_e_nimi(const char *nimi_mute[], - const int suli_pi_nimi_mute, - const int nanpa_nimi); +void weka_e_nimi_sewi(char *nimi_sewi); #endif /* NIMI_SEWI_H */
M nimitoki.hnimitoki.h

@@ -4,6 +4,7 @@ */

#ifndef NIMI_TOKI_H #define NIMI_TOKI_H +#include <stdlib.h> extern const char *nimi_toki[]; /* list of words */ extern const unsigned long suli_pi_nimi_toki /* length of word list */;