author | Olivier Brunel
<jjk@jjacky.com> 2023-01-16 16:05:51 UTC |
committer | Olivier Brunel
<jjk@jjacky.com> 2023-01-16 20:40:54 UTC |
parent | be0977a859fa86455d621a7149d4c4657d61478c |
.gitignore | +3 | -0 |
doc/die.3.md | +58 | -0 |
doc/open_createat.3.md | +37 | -0 |
doc/open_exclat.3.md | +37 | -0 |
doc/out.3.md | +39 | -0 |
doc/put.3.md | +46 | -0 |
doc/ret.3.md | +28 | -0 |
doc/warn.3.md | +34 | -0 |
include/limb/output.h | +55 | -0 |
include/limb/unix-transactional.h | +9 | -0 |
meta/deps-lib | +1 | -0 |
meta/deps/comain/version | +1 | -1 |
meta/deps/skalibs/get_version | +2 | -0 |
meta/deps/skalibs/git | +1 | -0 |
meta/deps/skalibs/incdir | +1 | -0 |
meta/deps/skalibs/include | +0 | -0 |
meta/deps/skalibs/libdir | +1 | -0 |
meta/deps/skalibs/library | +1 | -0 |
meta/deps/skalibs/version | +1 | -0 |
meta/desc | +7 | -0 |
project.mk | +1 | -7 |
src/open_createat.c | +9 | -0 |
src/open_exclat.c | +9 | -0 |
src/openc_createat.c | +9 | -0 |
src/openc_exclat.c | +9 | -0 |
src/put.c | +34 | -0 |
diff --git a/.gitignore b/.gitignore index 7ccd516..fe2f03b 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,6 @@ *.o *.lo *.d +liblimb.a +liblimb.so +/skalibs diff --git a/doc/die.3.md b/doc/die.3.md new file mode 100644 index 0000000..79eb6fe --- /dev/null +++ b/doc/die.3.md @@ -0,0 +1,58 @@ +% limb manual +% die(3) +% limb 0.0.1 +% 2023.01.16 + +# NAME + +die, dief, diefu, diesys, diefsys, diefusys - write a message to stderr and terminate + +# SYNOPSIS + + #include <limb/output.h> + extern const char *PROG; + +```pre hl +void die(<em>e</em>, ...) +void dief(<em>e</em>, ...) +void diefu(<em>e</em>, ...) +void diesys(<em>e</em>, ...) +void diefsys(<em>e</em>, ...) +void diefusys(<em>e</em>, ...) + +void dieusage(<em>e</em>, <em>usage</em>) +void diehelp(<em>e</em>, <em>usage</em>, <em>help</em>) + +void dieversion(<em>version</em>, <em>year1</em>, <em>year2</em>, <em>author</em>, <em>url</em>, <em>license</em>) +``` + +# DESCRIPTION + +All of those are implemented as macros (to [put](3)) and will write the +specified strings to /stderr/, with a new line added at the end, then terminate +the calling process via [_exit](3) using `e`. + +All messages will be prefixed by the program's name (i.e. value of `PROG`), a +colon and a space. + +`dief`() will add "fatal: " after the prefix and before the given strings. + +`diefu`() will also add "unable to " before the specified strings. + +The `diesys`(), `diefsys`() and `diefusys`() macros are similar, only the +specified strings will be followed by a colon, a space and the error description +provided by [strerror](3) according to `errno`. + + +The `dieusage`() macro writes the word "usage: " followed by the program's name +and a space as prefix, then the `usage` string. + +The `diehelp`() macro is similar to `dieusage`(), only adding two new lines +followed by the string `help`. + +The `dieversion`() macro writes the program's name (i.e. value of `PROG`), the +string " version " then the specified `version` and a new line. +On a second line is written "Copyright (C) " then `year1`, followed by a dash +and `year2` if it differs from `year1`, then ' - ' followed by `url` +Lastly, if `license` is not `NULL` it is written, else on a new line a line for +"License GPL-2.0" is written. diff --git a/doc/open_createat.3.md b/doc/open_createat.3.md new file mode 100644 index 0000000..edc0f45 --- /dev/null +++ b/doc/open_createat.3.md @@ -0,0 +1,37 @@ +% limb manual +% open_createat(3) +% limb 0.0.1 +% 2023.01.16 + +# NAME + +open_createat, openc_createat - open file relative to directory file descriptor + +# SYNOPSIS + + #include <limb/unix-transactional.h> + +```pre hl +int open_createat(int <em>fd</em>, const char *<em>file</em>); +int openc_createat(int <em>fd</em>, const char *<em>file</em>); +``` + +# DESCRIPTION + +The `open_createat`() function opens a file for writing, creating it if it +doesn't exist, in non-blocking mode. + +The `openc_createat`() function is similar, only with the *FD_CLOEXEC* flag set +for the file descriptor. + +# RETURN VALUE + +Upon successful completion, these functions shall open the file and return a +non-negative integer representing the lowest numbered unused file descriptor. +Otherwise, these functions shall return -1 and set errno to indicate the error. +If -1 is returned, no files shall be created or modified. + +# ERRORS + +These functions may fail and set errno for any of the errors specified for the +routine [openat](2). diff --git a/doc/open_exclat.3.md b/doc/open_exclat.3.md new file mode 100644 index 0000000..f92f94a --- /dev/null +++ b/doc/open_exclat.3.md @@ -0,0 +1,37 @@ +% limb manual +% open_exclat(3) +% limb 0.0.1 +% 2023.01.16 + +# NAME + +open_exclat, openc_exclat - create file relative to directory file descriptor + +# SYNOPSIS + + #include <limb/unix-transactional.h> + +```pre hl +int open_exclat(int <em>fd</em>, const char *<em>file</em>); +int openc_exclat(int <em>fd</em>, const char *<em>file</em>); +``` + +# DESCRIPTION + +The `open_exclat`() function attempts to create a new file and open it for +writing, in non-blocking mode, failing with *EEXIST* if it already exists. + +The `openc_exclat`() function is similar, only with the *FD_CLOEXEC* flag set +for the file descriptor. + +# RETURN VALUE + +Upon successful completion, these functions shall open the file and return a +non-negative integer representing the lowest numbered unused file descriptor. +Otherwise, these functions shall return -1 and set errno to indicate the error. +If -1 is returned, no files shall be created or modified. + +# ERRORS + +These functions may fail and set errno for any of the errors specified for the +routine [openat](2). diff --git a/doc/out.3.md b/doc/out.3.md new file mode 100644 index 0000000..ba7b22c --- /dev/null +++ b/doc/out.3.md @@ -0,0 +1,39 @@ +% limb manual +% out(3) +% limb 0.0.1 +% 2023.01.16 + +# NAME + +out, err, sys, outdie, errdie, sysdie - write text to standard output/error (and terminate process) + +# SYNOPSIS + + #include <limb/output.h> + +```pre hl +void out(...) +void err(...) +void sys(...) + +void outdie(<em>e</em>, ...) +void errdie(<em>e</em>, ...) +void sysdie(<em>e</em>, ...) +``` + +# DESCRIPTION + +All of those are implemented as macros (to [put](3)) and will write to +either standard outpout or standard error, then maybe terminate the calling +process or return. + +The macro `out`() writes given strings to /stdout/. + +The macro `err`() writes given strings to /stderr/. + +The macro `sys`() is similar to `err`() put will add a colon, a space and the +error description from [strerror](3) on `errno`. + +Macros `outdie`(), `errdie`() and `sysdie`() are similar to `out`(), `err`() and +`sys`() respectively but will terminate the calling process (via [_exit](3) +using `e`). diff --git a/doc/put.3.md b/doc/put.3.md new file mode 100644 index 0000000..de872c5 --- /dev/null +++ b/doc/put.3.md @@ -0,0 +1,46 @@ +% limb manual +% put(3) +% limb 0.0.1 +% 2023.01.16 + +# NAME + +put - write text to standard output/error + +# SYNOPSIS + + #include <limb/output.h> + +```pre hl +void put(int <em>ret</em>, unsigned int <em>opts</em>, const char * const *<em>as</em>, unsigned int <em>n</em>) +``` + +# DESCRIPTION + +The `put`() function will write `n` strings, given in the array `as`, either to +/stdout/ (by default) or /stderr/ if `PUT_ERR` was given in `opts`. + +If `PUT_SYS` was specified, a suffix composed of a colon and a space is added, +followed by the text return by [strerror](3) for `errno`. + +A new line is always added at the end. + +If `PUT_DIE` was specified, the program then ends - calling [_exit](3) with +the value of `ret`. + +# FLAGS + +Values for `opts` are constructed by a bitwise-inclusive OR of flags from the +following list : + +: `PUT_OUT` +:: Write to standard output. This is the default, unless `PUT_ERR` is specified. + +: `PUT_ERR` +:: Write to standard error. + +: `PUT_SYS` +:: Append a colon, a space, and the error string computed from `errno` + +: `PUT_DIE` +:: Terminate the calling process, returning `ret & 0377` as exit status diff --git a/doc/ret.3.md b/doc/ret.3.md new file mode 100644 index 0000000..c050fd5 --- /dev/null +++ b/doc/ret.3.md @@ -0,0 +1,28 @@ +% limb manual +% ret(3) +% limb 0.0.1 +% 2023.01.16 + +# NAME + +retw, retw, retwsys, retwusys - write a warning to standard error and return + +# SYNOPSIS + + #include <limb/output.h> + extern const char *PROG; + +```pre hl +int retw(<em>r</em>, ...) +int retwu(<em>r</em>, ...) +int retwsys(<em>r</em>, ...) +int retwusys(<em>r</em>, ...) +``` + +# DESCRIPTION + +All of those are implemented as macros to write the specified strings as warning +to /stderr/ with a new line added at the end (via [put](3)), then return `r`. + +All of then actually use [warn](3), [warnu](3), [warnsys](3) and [warnusys](3) +macros before calling `return r`. diff --git a/doc/warn.3.md b/doc/warn.3.md new file mode 100644 index 0000000..3216978 --- /dev/null +++ b/doc/warn.3.md @@ -0,0 +1,34 @@ +% limb manual +% warn(3) +% limb 0.0.1 +% 2023.01.16 + +# NAME + +warn, warnu, warnsys, warnusys - write a warning to standard error + +# SYNOPSIS + + #include <limb/output.h> + extern const char *PROG; + +```pre hl +void warn(..) +void warnu(...) +void warnsys(...) +void warnusys(...) +``` + +# DESCRIPTION + +All of those are implemented as macros (to [put](3)) and will write the +specified strings as warning to /stderr/, with a new line added at the end. + +All warnings will be prefixed by the program's name (i.e. value of `PROG`), the +word "warning " in between colon and a space. + +`warnu`() will add "unable to " after the prefix and before the given strings. + +The `warnsys`() and `warnusys`() macros are similar, only the specified strings +will be followed by a colon, a space and the error description provided by +[strerror](3) according to `errno`. diff --git a/include/limb/output.h b/include/limb/output.h new file mode 100644 index 0000000..45d5094 --- /dev/null +++ b/include/limb/output.h @@ -0,0 +1,55 @@ +#ifndef LIMB_OUTPUT_H +#define LIMB_OUTPUT_H + +enum { + PUT_OUT = 0, /* implied default unless PUT_ERR is set */ + PUT_ERR = (1 << 0), + PUT_SYS = (1 << 1), + PUT_DIE = (1 << 2), +}; + +extern void put(int e, unsigned int opts, const char * const *as, unsigned int n); + +extern const char *PROG; + +#define outarray(...) ((char const * const []) {__VA_ARGS__}) +#define outalen(...) (sizeof(outarray(__VA_ARGS__)) / sizeof(char const *)) + +#define out(...) put(0, PUT_OUT, outarray(__VA_ARGS__), outalen(__VA_ARGS__)) +#define err(...) put(0, PUT_ERR, outarray(__VA_ARGS__), outalen(__VA_ARGS__)) +#define sys(...) put(0, PUT_ERR | PUT_SYS, outarray(__VA_ARGS__), outalen(__VA_ARGS__)) +#define outdie(e, ...) put(e, PUT_OUT | PUT_DIE, outarray(__VA_ARGS__), outalen(__VA_ARGS__)) +#define errdie(e, ...) put(e, PUT_ERR | PUT_DIE, outarray(__VA_ARGS__), outalen(__VA_ARGS__)) +#define sysdie(e, ...) put(e, PUT_ERR | PUT_SYS | PUT_DIE, outarray(__VA_ARGS__), outalen(__VA_ARGS__)) + +#define warn(...) err(PROG, ": warning: ", __VA_ARGS__) +#define warnu(...) warn("unable to ", __VA_ARGS__) +#define warnsys(...) sys(PROG, ": warning: ", __VA_ARGS__) +#define warnusys(...) warnsys("unable to ", __VA_ARGS__) + +#define die(e, ...) errdie(e, PROG, ": ", __VA_ARGS__) +#define dief(e, ...) die(e, "fatal: ", __VA_ARGS__) +#define diefu(e, ...) dief(e, "unable to ", __VA_ARGS__) +#define diesys(e, ...) sysdie(e, PROG, ": ", __VA_ARGS__) +#define diefsys(e, ...) diesys(e, "fatal: ", __VA_ARGS__) +#define diefusys(e, ...) diefsys(e, "unable to ", __VA_ARGS__) + +#define dieusage(e, u) errdie(e, "usage: ", PROG, " ", u) +#define diehelp(e, u, h) errdie(e, "usage: ", PROG, " ", u, "\n\n", h) + +#define dieversion(v , yb, ye, a, u, l) \ + outdie(0, PROG, " version ", v, "\n", \ + "Copyright (C) ", yb, \ + ((strcmp(yb, ye)) ? "-" : ""), \ + ((strcmp(yb, ye)) ? ye : ""), \ + " ", a, " - ", u, \ + (!l) ? "\nLicense GPL-2.0. This is free software: " \ + "you are free to change and redistribute it.\n" \ + "There is NO WARRANTY, to the extent permitted by law." : l) + +#define retw(r, ...) do { warn(__VA_ARGS__); return r; } while (0) +#define retwu(r, ...) do { warnu(__VA_ARGS__); return r; } while (0) +#define retwsys(r, ...) do { warnsys(__VA_ARGS__); return r; } while (0) +#define retwusys(r, ...) do { warnusys(__VA_ARGS__); return r; } while (0) + +#endif /* LIMB_OUTPUT_H */ diff --git a/include/limb/unix-transactional.h b/include/limb/unix-transactional.h new file mode 100644 index 0000000..9a5a8f1 --- /dev/null +++ b/include/limb/unix-transactional.h @@ -0,0 +1,9 @@ +#ifndef LIMB_UNIXTRANSACTIONAL_H +#define LIMB_UNIXTRANSACTIONAL_H + +extern int openc_createat(int fd, const char *file); +extern int open_createat(int fd, const char *file); +extern int openc_exclat(int fd, const char *file); +extern int open_exclat(int fd, const char *file); + +#endif /* LIMB_UNIXTRANSACTIONAL_H */ diff --git a/meta/deps-lib b/meta/deps-lib new file mode 100644 index 0000000..a8be909 --- /dev/null +++ b/meta/deps-lib @@ -0,0 +1 @@ +limb: src/put.o src/open_exclat.o src/open_createat.o src/openc_exclat.o src/openc_createat.o skalibs diff --git a/meta/deps/comain/version b/meta/deps/comain/version index 77d6f4c..8acdd82 100644 --- a/meta/deps/comain/version +++ b/meta/deps/comain/version @@ -1 +1 @@ -0.0.0 +0.0.1 diff --git a/meta/deps/skalibs/get_version b/meta/deps/skalibs/get_version new file mode 100755 index 0000000..55041f5 --- /dev/null +++ b/meta/deps/skalibs/get_version @@ -0,0 +1,2 @@ +#!/bin/sh +grep SKALIBS_VERSION "$@/skalibs/config.h" | cut -d\" -f2 diff --git a/meta/deps/skalibs/git b/meta/deps/skalibs/git new file mode 100644 index 0000000..5965139 --- /dev/null +++ b/meta/deps/skalibs/git @@ -0,0 +1 @@ +git://lila.oss/skalibs.git diff --git a/meta/deps/skalibs/incdir b/meta/deps/skalibs/incdir new file mode 100644 index 0000000..e4484e2 --- /dev/null +++ b/meta/deps/skalibs/incdir @@ -0,0 +1 @@ +src/include diff --git a/meta/deps/skalibs/include b/meta/deps/skalibs/include new file mode 100644 index 0000000..e69de29 diff --git a/meta/deps/skalibs/libdir b/meta/deps/skalibs/libdir new file mode 100644 index 0000000..5baacc7 --- /dev/null +++ b/meta/deps/skalibs/libdir @@ -0,0 +1 @@ +skalibs diff --git a/meta/deps/skalibs/library b/meta/deps/skalibs/library new file mode 100644 index 0000000..39971a0 --- /dev/null +++ b/meta/deps/skalibs/library @@ -0,0 +1 @@ +skarnet diff --git a/meta/deps/skalibs/version b/meta/deps/skalibs/version new file mode 100644 index 0000000..0ab9020 --- /dev/null +++ b/meta/deps/skalibs/version @@ -0,0 +1 @@ +2.8.0.0 diff --git a/meta/desc b/meta/desc new file mode 100644 index 0000000..71dcfbd --- /dev/null +++ b/meta/desc @@ -0,0 +1,7 @@ +lila's core library + +A simple C library (based on [skalibs]) with common APIs used by all lila's +software. + + +[skalibs]: https://skarnet.org/software/skalibs diff --git a/project.mk b/project.mk index 0892fd9..63a3fe3 100644 --- a/project.mk +++ b/project.mk @@ -1,7 +1 @@ -$(error You need to edit project.mk) - -# binaries: -- don't forget to set meta/deps-bin with all deps & .o files -BINS = - -# librairies -- don't forget to set meta/deps-lib with all deps & .o files -LIBS = +LIBS = limb diff --git a/src/open_createat.c b/src/open_createat.c new file mode 100644 index 0000000..fcc59fc --- /dev/null +++ b/src/open_createat.c @@ -0,0 +1,9 @@ +#include <fcntl.h> +#include <skalibs/unix-transactional.h> +#include "limb/unix-transactional.h" + +int +open_createat(int fd, const char *file) +{ + return open3_at(fd, file, O_WRONLY | O_CREAT | O_NONBLOCK, 0666); +} diff --git a/src/open_exclat.c b/src/open_exclat.c new file mode 100644 index 0000000..bf5f89e --- /dev/null +++ b/src/open_exclat.c @@ -0,0 +1,9 @@ +#include <fcntl.h> +#include <skalibs/unix-transactional.h> +#include "limb/unix-transactional.h" + +int +open_exclat(int fd, const char *file) +{ + return open3_at(fd, file, O_WRONLY | O_CREAT | O_EXCL | O_NONBLOCK, 0666); +} diff --git a/src/openc_createat.c b/src/openc_createat.c new file mode 100644 index 0000000..aca4886 --- /dev/null +++ b/src/openc_createat.c @@ -0,0 +1,9 @@ +#include <fcntl.h> +#include <skalibs/unix-transactional.h> +#include "limb/unix-transactional.h" + +int +openc_createat(int fd, const char *file) +{ + return open3_at(fd, file, O_WRONLY | O_CREAT | O_NONBLOCK | O_CLOEXEC, 0666); +} diff --git a/src/openc_exclat.c b/src/openc_exclat.c new file mode 100644 index 0000000..e3066b9 --- /dev/null +++ b/src/openc_exclat.c @@ -0,0 +1,9 @@ +#include <fcntl.h> +#include <skalibs/unix-transactional.h> +#include "limb/unix-transactional.h" + +int +openc_exclat(int fd, const char *file) +{ + return open3_at(fd, file, O_WRONLY | O_CREAT | O_EXCL | O_NONBLOCK | O_CLOEXEC, 0666); +} diff --git a/src/put.c b/src/put.c new file mode 100644 index 0000000..018d69f --- /dev/null +++ b/src/put.c @@ -0,0 +1,34 @@ +#include <errno.h> +#include <unistd.h> /* _exit() */ +#include <skalibs/buffer.h> +#include <skalibs/strerr.h> +#include "limb/output.h" + +void +put(int r, unsigned int opts, const char * const *as, unsigned int n) +{ + int e = errno; + buffer *b = (opts & PUT_ERR) ? buffer_2 : buffer_1; + + for(;;) { + unsigned int i; + for (i = 0; i < n; ++i) + if (as[i] && as[i][0] && !buffer_puts(b, as[i])) + break; + if (i < n) + break; + + if ((opts & PUT_SYS) + && (!buffer_put(b, ": ", 2) || !buffer_puts(b, strerror(e))) + ) + break; + + if (!buffer_putflush(b, "\n", 1)) + break; + + errno = e; + if (opts & PUT_DIE) _exit(r); + return; + } + strerr_die6sys(55, PROG, ": fatal: ", "unable to ", "print to ", (opts & PUT_ERR) ? "stderr" : "stdout", ": "); +}