Compare commits

..
513 Commits
Author SHA1 Message Date
Joachim Wiberg 8120492fc8 Update changelogs and bump version for v2.5.1
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-12-02 00:43:02 +01:00
Joachim Wiberg 2065165ae9 debian: use dh_link(1) instead to create /usr/inclute/lite symlink
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-12-02 00:42:19 +01:00
Joachim Wiberg 95e5fdba9b Bump version for v2.5.0 release
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-11-30 07:01:09 +01:00
Joachim Wiberg b21d1c8e9b More syntactic sugar
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-11-29 18:49:20 +01:00
Joachim Wiberg 5b670951a3 More experimenting and some reflow of a paragraph
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-11-29 00:33:10 +01:00
Joachim Wiberg 612290c9e2 Experiment with syntax highlighting
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-11-29 00:28:39 +01:00
Joachim Wiberg 80d11dccf7 Update changelogs for upcoming v2.5.0 release
This should be it, but let's sleep on it for good measure.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-11-29 00:25:53 +01:00
Joachim Wiberg 438e7a2722 debian: update libite-dev, headers in libite/*.h and lite symlink
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-11-29 00:25:21 +01:00
Joachim Wiberg 96e023e58e Update README wrt the namespace change
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-11-29 00:23:24 +01:00
Joachim Wiberg 67a9b379ba Update comments, also namespace is one word
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-11-29 00:22:38 +01:00
Joachim Wiberg 1c0988b8e2 Fix #18: optional compat symlink lite -> libite/
Default is to create the symlink, to facilitate upgrades.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-11-28 19:22:45 +01:00
Joachim Wiberg 407b8f6dbf Prefix include guards with LIBITE_ to safe guard name space
The tree.h and queue.h include guards must remain so users don't
accidentally get their system queue.h included as well.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-11-28 19:20:53 +01:00
Joachim Wiberg bc72e1c3ad Change -lite include path/name space; lite/*.h -> libite/*.h
First step in fixing issue #18.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-11-28 19:09:55 +01:00
Joachim Wiberg 2d10cf0402 Prepare ChangeLog for upcoming v2.5.0 release
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-11-28 19:08:32 +01:00
Joachim Wiberg 7adf2a01f2 Bump version for v2.5.0 release cycle (-dev)
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-11-28 19:07:54 +01:00
Joachim Wiberg a4ff8cce01 strnlen(): defensive programming, check limit before indexing array
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-11-28 16:36:43 +01:00
Joachim Wiberg 12b9196c65 Bump ABI version 5.3.0 -> 5.3.1 according to doc/HACKING.md
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-09 09:21:41 +02:00
Joachim Wiberg 6eee1b1baf doc: update project name
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-09 09:19:49 +02:00
Joachim Wiberg 1a5b184391 debian: add doxygen to Build-Depends-Indep
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-09 09:13:09 +02:00
Joachim Wiberg 832c4a936b Update changelogs and bump version for v2.4.1 release
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-09 08:57:49 +02:00
Joachim Wiberg a712364d49 tempfile(): use same fallback also when O_TMPFILE is missing
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-06 18:05:45 +02:00
Joachim Wiberg fae83c9be3 Use mkostemp() instead of insecure tmpfile() as fallback
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-06 17:51:07 +02:00
Joachim Wiberg 48202ef19e Slightly rearrange and fix URL
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-03 22:40:11 +02:00
Joachim Wiberg 7c36f715c7 Split README.md in two, create a new doc/API.md
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-03 22:37:55 +02:00
Joachim Wiberg 328b28f2d1 Restore spacing between badges
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-03 22:32:08 +02:00
Joachim Wiberg 970fa47ecf Update code docs for string functions and macros as well
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-03 22:30:20 +02:00
Joachim Wiberg 0a98f5bbd1 Mention API documentation
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-03 21:34:12 +02:00
Joachim Wiberg 85336b1f2b Link to blog post, to free up GitHub home URL for docs
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-03 21:31:59 +02:00
Joachim Wiberg 8128e63898 Add codedocs status badge
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-03 21:29:16 +02:00
Joachim Wiberg b52f1e5ad6 debian: drop sdbuf, unused internal variable
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-03 19:14:22 +02:00
Joachim Wiberg 5d1e884d6f Initial codedocs.xyz integration
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-03 19:10:45 +02:00
Joachim Wiberg 6537b11e34 doc: initial effort to enable doxygen
Framework from libuEv.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-03 19:08:40 +02:00
Joachim Wiberg 03598fc01e .github: rename test result artifact
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-03 14:55:42 +02:00
Joachim Wiberg d4649b8284 test: clean up any lingering core file after systemf() test
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-03 13:22:01 +02:00
Joachim Wiberg 3d2a975f11 Fix issue with tempfile() returning EOPNOTSUPP on Azure
Turns out O_TMPFILE can fail in interesting ways when the underlying
filesystem doesn't support unnamed inodes, e.g. Azure used by GitHub
Actions.  Here's the exact qoute from open(2):

  "O_TMPFILE requires support by the underlying filesystem; only a
  subset of Linux filesystems provide that support.  In the initial
  implementation, support was provided in the ext2, ext3, ext4, UDF,
  Minix, and shmem filesystems.  Support for other filesystems has
  subsequently been added as follows: XFS (Linux 3.15); Btrfs (Linux
  3.16); F2FS (Linux 3.16); and ubifs (Linux 4.9)"

This patch adds a silent fallback to tmpfile() in these cases.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-03 12:55:01 +02:00
Joachim Wiberg 1b6707f44e test: investigate why tempfile() fails on debian:stable
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-03 12:42:16 +02:00
Joachim Wiberg bdebca9681 .github: separate check and distcheck steps, use -j3
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-03 12:35:21 +02:00
Joachim Wiberg d364f6b4e1 .github: if debian distcheck fails, show test-suite.log
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-03 12:29:52 +02:00
Joachim Wiberg 6db730aeff Bump version for v2.4.1 release cycle (-beta1)
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-03 12:24:21 +02:00
Joachim Wiberg c512e1cabd .github: prepare initial release general
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-03 12:23:23 +02:00
Joachim Wiberg 5d94ca9a14 .github: add coverity scan workflow
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-03 12:23:23 +02:00
Joachim Wiberg f0efcb5340 Minor updates and fixes
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-03 12:23:23 +02:00
Joachim Wiberg 4ee5ca61b8 Drop Travis-CI in favor of GitHub Actions
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-03 12:22:48 +02:00
Joachim Wiberg ed491ecdba .github: enable bob
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-03 12:22:33 +02:00
Joachim Wiberg b6940814f4 .github: enable funding for this repo
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-03 12:22:33 +02:00
Joachim Wiberg 1e91e7ea3f .github: add contributing guidelines
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-03 12:22:33 +02:00
Joachim Wiberg 332861430d Minor, cleanup
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-03 12:22:33 +02:00
Joachim Wiberg 0813084aa7 Import release related fixes to top Makefile from libuEv
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-03 12:22:33 +02:00
Joachim Wiberg 990ee6874c Relocate libite.pc.in to src/
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-03 12:22:33 +02:00
Joachim Wiberg ef4a8691d3 test: fix build warnings for most tests
Let rsync.c continue to warn, it's not complete ...

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-03 12:22:33 +02:00
Joachim Wiberg 75139cdf3c Relocate lesser used docs to doc/
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-03 12:22:33 +02:00
Joachim Wiberg c9633ffbb0 Rename tests/ -> test/ and update internal refs.
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-03 12:22:33 +02:00
Joachim Wiberg 692dbadd3a Prefix CFLAGS/CPPFLAGS/etc with AM_ to prevent env. clashes
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-03 12:22:33 +02:00
Joachim Wiberg b1a2975a76 Replace obsolete AM_CONFIG_HEADER with AC_CONFIG_HEADERS
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-10-03 12:21:03 +02:00
Joachim Wiberg 67529f2283 debian: update symbols file
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-03-27 10:24:05 +01:00
Joachim Wiberg 8e69676943 Increment ABI version 5.2.0 -> 5.3.0
The GNU libtool numbers are just SO confusing.

 - New interfaces (new functions) added/removed/changed: 7 -> 8
 - Interfaces added: 2 -> 3

End result, steps 5.2.0 to 5.3.0, which makes sense.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-03-27 09:26:04 +01:00
Joachim Wiberg 76faae4292 Update changelogs, and bump version in prep. for v2.4.0 release
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-03-27 09:18:22 +01:00
Joachim Wiberg e928c30fbd Revert "Travis-CI: disable clang temporarily for Coverity Scan run"
This reverts commit 951050fdd2.
2021-03-27 09:05:31 +01:00
Joachim Wiberg 3512201a58 Travis-CI: install to /tmp/foo and run distcheck at the end
- We shouldn't run ls -lr /tmp, in particular when Coverity runs, it
  keeps a LOT of files in /tmp causing Travis to terminate our jobs
- make check is cool, but distcheck also verifies our Makefile.am
  rules, ensuring make check also works from an unpacked tarball

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-03-27 08:56:27 +01:00
Joachim Wiberg dc5c4ae36c systemf(): simplify further, exited OK or was signaled
Coverity highlighted a problem with logically dead code from the change
prior that triggered this refactor.  When system() returns we may have
exited either normally or due to a signal.

My reasoning behind systemf() is to allow users to treat external calls
as any other syscall, abstracting away the WIFFOO() macros.  This leaves
us with either the return value of the external program >= 0, or -1 and
errno for everything else.  I.e., if fork() or alloca() fails we may get
ENOMEM and if the program doesn't catch signals properly, EINTR.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-03-27 08:48:09 +01:00
Joachim Wiberg 748948b665 Minor, use .svg Travis status badge
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-03-27 08:48:01 +01:00
Joachim Wiberg 951050fdd2 Travis-CI: disable clang temporarily for Coverity Scan run
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-03-27 08:09:17 +01:00
Joachim Wiberg d5c5996f03 Minor, whitespace
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-03-27 08:06:17 +01:00
Joachim Wiberg f5808e557e Add strtrim(), trims leading and trailing white-space from a string
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-03-27 08:05:36 +01:00
Joachim Wiberg d4b554ccdc Add erasef(), formatted version of erase()
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-03-27 07:08:49 +01:00
Joachim Wiberg 098a020843 Bump version, 2.4.0 development cycle
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-03-26 12:39:32 +01:00
Joachim Wiberg 2040569f0a Add touchf(), formatted version of touch()
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-03-26 12:39:32 +01:00
Joachim Wiberg 733a7062e9 Minor, whitespace
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-03-26 12:37:05 +01:00
Joachim Wiberg 7ad11a31df touch(): behavioral change, call utimensat() first, then mknod()
Optimize for the case the file exists already.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-03-26 12:35:41 +01:00
Joachim Wiberg 8ce46eb439 systemf(): fix improper handling of WEXITSTATUS()
The call to system() may return -1, e.g. if fork() fails or return
status from execl() cannot be read.  In these cases we should end
immediately and not call WIFEXITED() et al.

Also, WEXITSTATUS() should only be called if WEXITED() returns true.

For details, see system(3) and wait(2).

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-03-26 12:32:43 +01:00
Joachim Wiberg c15e883427 tests: update systemf() test to detect improper return code on error
Non-existing programs should return 127, and
killing ourselves with -9 should return -1

For details, see system(3).

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-03-26 12:29:55 +01:00
Joachim Wiberg 63d82da62d Update changelogs and bump version for v2.3.1 release
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-02-12 15:13:40 +01:00
Joachim Wiberg dd1c67b2b6 debian: add missing files to copyright
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-02-12 15:10:05 +01:00
Joachim Wiberg 08d9a90945 Makefile: use debuild to build .deb packages, also runs lintian
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-02-12 09:29:42 +01:00
Joachim Wiberg beba419a0f debian: makepath.c is copyright me, licensed as isc
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-02-12 09:29:01 +01:00
Joachim Wiberg 3d695eede5 Update copyright years and author surname
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-02-12 09:28:41 +01:00
Joachim Wiberg 6e18edea93 debian: set dist to stable, that's the only channel currently
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-02-12 08:28:18 +01:00
Joachim Wiberg 9c89daf770 Update changelogs and bump version for v2.3.0 release
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-02-12 08:24:30 +01:00
Joachim Wiberg b3d4674bf7 Makefile: add .sha256 checksums to release target
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-02-12 08:23:07 +01:00
Joachim Wiberg aa4576d5ea configure: enable tar.gz dist archives, by popular demand
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-02-12 08:22:32 +01:00
Joachim Wiberg ae56c9e33c debian: sync rules with libuev
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-02-12 08:21:42 +01:00
Joachim Wiberg 3387c737be debian: update symbols file, new functions introduced in 2.3.0
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-02-12 08:21:23 +01:00
Joachim Wiberg 8d90ede158 Update changelog with new function
Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
2021-02-01 19:12:44 +01:00
Joachim Nilsson b1fe8a1271 debian: Update .gitignore
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-06-02 06:56:41 +02:00
Joachim Nilsson 044c2621ac Add support for truncatef(), formatted truncate() replacement
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-06-02 06:56:02 +02:00
Joachim Nilsson 7396dd83c7 Merge pull request #15 from yangfl/upstream
Fix #14: Avoid (some) hard-coded pathes in tests
2020-06-01 17:18:11 +02:00
yangfl e5fe988cdc Avoid (some) hard-coded pathes in tests 2020-06-01 23:04:29 +08:00
Joachim Nilsson 824da13977 Update ChangeLog, added fremove()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-04-29 00:33:39 +02:00
Joachim Nilsson efb1470008 Update ChangeLog with ETIMEDOUT fix to telnet_open()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-04-27 23:23:21 +02:00
Joachim Nilsson d2d0792c06 telnet_open(): Handle ETIMEDOUT in connect()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-04-27 23:20:55 +02:00
Joachim Nilsson 711c59e3a6 telnet: Refactor, rename local variable
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-04-27 23:20:55 +02:00
Joachim Nilsson f85ff3c835 tests: Add fremove() pass to fopenf() unit test for cleanup
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-04-27 23:18:47 +02:00
Joachim Nilsson 16ea69adb4 Add support for fremove(), formatted remove() replacement
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-04-27 23:18:10 +02:00
Joachim Nilsson ae492581f8 tests: Keep same width for pass sub-headings as as test framework
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-04-27 23:17:50 +02:00
Joachim Nilsson d16385415c Simplify va_start/_end handling and return ENOMEM if alloca() fails
Be consistent with errno codes from libite, we already have other APIs
that return ENOMEM if alloca() fails, so let's do the same for these
new ones as well.

Also, simplify va_start()/va_end() handling in these APIs, no point
in the extra complexity before this patch.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-04-27 23:14:56 +02:00
Joachim Nilsson d27518c5b8 Bump version for 2.3.0-dev release cycle
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-04-27 22:45:41 +02:00
Joachim Nilsson 724926896a Add mising bullet and document new APIs better 2020-03-26 05:41:41 +01:00
Joachim Nilsson ef04307b4a debian: Update symbols file, new APIs introduced in v2.2.0
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-03-16 17:41:44 +01:00
Joachim Nilsson 5d035d955e debian: Add missing libtool to Build-Depends
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-03-16 17:38:25 +01:00
Joachim Nilsson b65175782d Bump ABI version, new APIs added
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-03-16 17:38:25 +01:00
Joachim Nilsson c27a8e7ec6 Update changelogs and bump version for v2.2.0 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-03-16 16:01:46 +01:00
Joachim Nilsson d231c1e1eb Revert "Travis-CI: Disable clang temporarily for Coverity Scan run"
This reverts commit 2a6adeebcd.
2020-03-16 10:41:27 +01:00
Joachim Nilsson 247fb67274 Add Coverity Scan badge
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-03-16 10:37:21 +01:00
Joachim Nilsson c716cc5835 copyfile(): Check return value of fstat(), prevent faulty futimens()
Found by Coverity Scan

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-03-16 10:31:50 +01:00
Joachim Nilsson e81ce85867 rsync(): Fix possible memory leak, found by Coverity Scan
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-03-16 10:31:50 +01:00
Joachim Nilsson 549f325c21 rsync(): Fix variable shadowing, found by clang-tidy
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-03-16 10:31:46 +01:00
Joachim Nilsson 2a6adeebcd Travis-CI: Disable clang temporarily for Coverity Scan run
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-03-14 10:56:23 +01:00
Joachim Nilsson cb2beacf2c Travis-CI: Add support for Coverity Scan
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-03-14 10:55:27 +01:00
Joachim Nilsson 256b6ba038 Add origin section to README, better place for history or project
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-03-14 10:48:55 +01:00
Joachim Nilsson 61d9b5fac7 Update Changelog for upcoming v2.2.0 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-03-14 10:43:48 +01:00
Joachim Nilsson 38ad841389 Bump version for v2.2.0 release cycle
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-03-14 10:39:17 +01:00
Joachim Nilsson f1a1a21569 Add support for systemf(), formatted system() replacement
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-03-14 10:32:52 +01:00
Joachim Nilsson 7f3f4df9e9 Add support for fmkpath(), formatted string mkpath()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-03-11 20:03:03 +01:00
Joachim Nilsson 02a42a1cad Add support for fopenf(), formatted string fopen()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-03-10 09:07:56 +01:00
Joachim Nilsson 28c11f010a Check for existence of AM_PROG_AR macro
This patch facilitates building newer versions of libite on systems with
older versions of autoconf and automake.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-02-22 15:47:28 +01:00
Joachim Nilsson 20d8d40285 Update changelogs and bump version for v2.1.2
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-02-22 15:06:28 +01:00
Joachim Nilsson 4dc24f37e3 debian: Fix breakage when upgrading libite -> libite5
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-02-22 15:05:56 +01:00
Joachim Nilsson 11f8846f63 Update changelogs and bump version for v2.1.1 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-02-22 13:57:39 +01:00
Joachim Nilsson 41778fb3ce debian: Add missing symbols file, pointed out by lintian
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-02-22 13:57:39 +01:00
Joachim Nilsson 59d1f0d60c Update .gitignore files
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-02-22 13:57:39 +01:00
Joachim Nilsson afc4289326 debian: Fix lintian warning for package short description
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-02-22 13:57:39 +01:00
Joachim Nilsson 67267659f7 configure: Put auxilliary files in aux and check for install
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-02-22 13:57:39 +01:00
Joachim Nilsson 188509d811 debian: Update changelog for 2.1.1 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-02-22 13:57:39 +01:00
Joachim Nilsson c10cd67266 Update release hook and fix formatting in release target
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-02-22 13:57:39 +01:00
Joachim Nilsson 82db75cac6 debian: Update to Standards-Version 4.3.0
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-02-22 12:46:14 +01:00
Joachim Nilsson 51970ff86e Update copyright years
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-02-22 11:32:43 +01:00
Joachim Nilsson d6fa3cde96 Update ChangeLog for v2.1.1 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-02-22 11:17:14 +01:00
Joachim Nilsson 9d50de3ec7 tests: Add example of how to use printhdr()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2020-02-22 11:14:27 +01:00
Joachim Nilsson 2aed5a6b3f chomp: Check for beginning of string while removing \n's
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2019-09-25 08:51:56 +02:00
Joachim Nilsson f873635cfe Bump version for v2.1.0 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2019-08-26 21:59:57 +02:00
Joachim Nilsson c3d5588298 Prepare ChangeLogs for next release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2019-08-26 21:59:11 +02:00
Joachim Nilsson a65b2dfd71 debian: Update copyright, new files, and fix year
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2019-08-26 21:59:11 +02:00
Joachim Nilsson 6e8d8fc32c debian: Drop LICENSE file and install ChangeLog.md
The LICENSE file is replaced with copyright in Debian

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2019-08-26 21:59:11 +02:00
Joachim Nilsson 966aee09cd Install ChangeLog.md in doc/, debian supports this now
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2019-08-26 21:59:11 +02:00
Joachim Nilsson f93e298875 debian: Update package descriptions
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2019-08-26 21:59:11 +02:00
Joachim Nilsson c8ec83f20c debian: Update to standards version 4.1.0
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2019-08-26 21:59:11 +02:00
Joachim Nilsson 835e09a9fe debian: Step library name to match SONAME, fixes lintian warning
This patch fixes the lintian warning package-name-doesnt-match-sonames,
which is a reminder to step the library version to match the soname.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2019-08-26 21:59:05 +02:00
Joachim Nilsson 13ffe87d10 tests: Update unit test for string functions
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2019-08-22 22:26:07 +02:00
Joachim Nilsson 72d1cb6501 Add printhdr(), replacement for printheader() with ANSI attribute
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2019-08-21 23:57:29 +02:00
Joachim Nilsson 83ace4f12d ChangeLog: Add missing telnet APIs
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2019-08-21 16:07:44 +02:00
Joachim Nilsson 9bdc5e94b5 Update ChangeLog with latest fixes & feature
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2019-08-19 23:51:50 +02:00
Joachim Nilsson 83047d4413 Add support for a simple telnet expect set of APIs
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2019-06-09 18:06:47 +02:00
Joachim Nilsson b2c2d032e8 Add support for yorn(), safe yes-or-no prompt
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2019-05-29 15:57:11 +02:00
Joachim Nilsson 7f053f7624 Fix #13: Support C-linkage for C++ compilation
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2019-05-24 21:57:57 +02:00
Joachim Nilsson b15a14e920 strtonum(): POSIX strtoll() returns EINVAL, check for that too
From FreeBSD.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-12-10 09:43:20 +01:00
Joachim Nilsson 7e8534e36b pidfile_signal(): Return result of kill() and only remove on SIGKILL
If kill() is successful, and the signal was SIGKILL, we remove() the PID
file and return the rc of remove(), otherwise we always return the rc of
kill().

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-10-22 13:08:19 +02:00
Joachim Nilsson 3989d91d36 Minor, refactor and fix function doc comment
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-07-22 14:46:08 +02:00
Joachim Nilsson fe3673a5e1 Mention new strnmatch() API family
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-07-05 22:47:28 +02:00
Joachim Nilsson 1bdcb1bfe4 Document new functions: strmatch(), strnmatch()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-07-03 17:09:42 +02:00
Joachim Nilsson 75d3f1978e Minor, grammar
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-07-02 17:48:43 +02:00
Joachim Nilsson c07bfbda58 Bump version for v2.1.0 release cycle
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-07-02 16:39:50 +02:00
Joachim Nilsson 0ef509c393 Minor, reorder tests alphabetically
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-07-02 16:38:47 +02:00
Joachim Nilsson 5620faf7bf Add unit test for strmatch()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-07-02 16:38:39 +02:00
Joachim Nilsson b6a9ed3c6d New function(s): strnmatch() and strmatch()
These two functions look for a string in a (terminate) list of strings
and returns the index to that string, or -1 if not found or error.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-06-29 18:38:56 +02:00
Joachim Nilsson 9d63302337 Minor, whitespace + simplify
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-06-29 18:35:52 +02:00
Joachim Nilsson 02d9d9f8c1 Update ChangeLog and bump version for v2.0.2 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-05-10 19:13:56 +02:00
Joachim Nilsson 9f92a9d572 Fix #12: Add missing includes for INT32_MAX and MIN()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-05-10 19:06:07 +02:00
Joachim Nilsson f0e3ed3342 Add basic unit test for strlite.h
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-05-10 19:05:48 +02:00
Joachim Nilsson 34f23a77f8 Missing defines for LLONG_MAX and LLONG_MIN
Some systems may not yet have defined LLONG_MAX and LLONG_MIN in
limits.h, in particular older GLIBC installs are affected.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2018-02-28 10:43:08 +01:00
Joachim Nilsson 261cf3a01b debian/changelog; Update for new upstream release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-22 12:12:34 +01:00
Joachim Nilsson 2c9c13bd07 Update ChangeLog for v2.0.1
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-22 12:08:05 +01:00
Joachim Nilsson 59ce0c0dc4 Minor ABI bump, changes to lite.h, const + fixed up touch()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-22 12:08:05 +01:00
Joachim Nilsson a603208da9 Redo 60406c3, this is a bug-fix release only: 2.1.0-pre --> 2.0.1
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-22 12:08:05 +01:00
Joachim Nilsson eaac01871b Simplify introduction, and tone it down a bit ...
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-22 12:08:05 +01:00
Joachim Nilsson 8cefa12675 Remove Emacs hinting
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-22 12:08:05 +01:00
Joachim Nilsson 5893010074 Move TODO items to TODO.md
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-22 12:08:05 +01:00
Joachim Nilsson d84bcb3847 copyfile(),movefile(): constify
A `const` string is a declaration to the user of an API that the
implementation does not touch the contents.

We do some `(char *)` casting in this patch, but the resulting
code still does not touch the contents of the original pointer.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-22 11:34:46 +01:00
Joachim Nilsson a9a3a2dda1 constify
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-22 11:34:24 +01:00
Joachim Nilsson 20af39300c ifconfig(): constify
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-22 11:33:55 +01:00
Joachim Nilsson 7b612cda83 lfile: constify
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-22 11:33:37 +01:00
Joachim Nilsson 60406c33f6 Bump version, -pre, for v2.1.0 release cycle
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-22 10:57:37 +01:00
Joachim Nilsson 1d21b11802 lftok(): Refactor, collapse and simplify a bit
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-22 10:56:54 +01:00
Joachim Nilsson a3badc85f8 Fix FTBFS, add missing fcntl.h header for AT_FDCWD
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-21 17:15:39 +01:00
Joachim Nilsson ac936448f5 Only define min() and max() macros if not already defined
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-21 14:19:45 +01:00
Joachim Nilsson 3a26ab28b2 Fix #11: Allow relative paths to touch()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-21 14:17:43 +01:00
Joachim Nilsson 123108fbf9 Fix #10: Supply a default PATH for test
Set a default PATH matching the root user's defaults.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-07 23:09:19 +01:00
Joachim Nilsson 3545d63d2e Fix #9: Use /usr/bin/which, not /bin/which, for unit test.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-12-07 22:15:40 +01:00
Joachim Nilsson 3e921d72e5 conio.h: Add initscr() declaration after relocation to conio.c
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-22 15:39:16 +01:00
Joachim Nilsson 1c9c038c06 Update copyfile() and rsync() API descriptions, new option flags
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-22 14:18:27 +01:00
Joachim Nilsson e5b79443b8 Bump version for v2.0.0 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-22 14:01:44 +01:00
Joachim Nilsson 589465f48b Update ChangeLog for v2.0.0 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-22 14:01:44 +01:00
Joachim Nilsson 1f745ff9a0 Add head-up to users about changes in v2.0 early in text
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-22 13:58:01 +01:00
Joachim Nilsson 71a0c53029 Bump ABI version, major changes in this release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-22 13:57:44 +01:00
Joachim Nilsson 6608d2e8c9 Remove tree() from libite, moved to troglobit/toolbox.git instead
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-22 13:49:05 +01:00
Joachim Nilsson 62334c80fd Remove fmode() from libite, it's safer to use stat() instead
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-22 12:51:49 +01:00
Joachim Nilsson 626d5456f7 copyfile(): Reduce dependency and simplify, already called stat()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-22 12:49:49 +01:00
Joachim Nilsson e3dff8e5be Reorder source files, sort of alphabetically
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-22 12:46:39 +01:00
Joachim Nilsson bbb951dc23 conio.h: Move initscr() function to conio.c
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-22 10:28:07 +01:00
Joachim Nilsson 94800e7d5c Use distcheck in release target, verifies generated tarball is buildable
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-22 09:04:28 +01:00
Joachim Nilsson 3442d8e12b Update unit test suite with new path to library and header files
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-22 09:03:54 +01:00
Joachim Nilsson 75f57283bd Don't guess where conio.h is, rely on check.h instead
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-22 09:02:51 +01:00
Joachim Nilsson daf41d326b Relocate source files to an src/ sub directory
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-22 09:02:21 +01:00
Joachim Nilsson 3179be4348 Update ChangeLog, hint at future v2.0
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-21 23:57:31 +01:00
Joachim Nilsson 56530a8c78 Ignore global indexing files
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-20 18:37:59 +01:00
Joachim Nilsson abd6e3abd6 Update rsync() unit test slightly, does not verify MTIME yet ...
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-20 17:32:31 +01:00
Joachim Nilsson b078a8676f rsync(): Refactor @delete argument into an @opt to keep mtime
This patch changes the @delete rsync() argument to @opt.  The first bit
is reserved for %LITE_FOPT_RSYNC_DELETE, for backwards compatibility.

A new %LITE_FOPT_KEEP_MTIME option is also added.  If set the mtime of
the @src file is set on @dst, both directories and regular files are
fully supported.  However, if the base @dst directory does not exist,
and rsync() has to create it, its mtime will be the time of the last
file copied into it.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-20 17:29:39 +01:00
Joachim Nilsson c2b92a38ef copyfile(): Refactor @sym argument into an @opt to keep mtime
This patch changes the @sym copyfile() argument to @opt.  The first bit
is reserved for %LITE_FOPT_COPYFILE_SYM, for backwards compatibility.

A new %LITE_FOPT_KEEP_MTIME option is also added.  If set the mtime of
the @src file is set on @dst.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-20 17:24:08 +01:00
Joachim Nilsson 98b2e9d426 debian/changelog: New upstream release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-19 22:43:03 +01:00
Joachim Nilsson 96d3e5dd8b Bump version for v1.9.4 release cycle (-pre)
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-16 21:31:33 +01:00
Joachim Nilsson ff626acb73 Update ChangeLog for upcoming v1.9.4
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-11-16 21:31:20 +01:00
Joachim Nilsson ba3f7c89fb Update makepath() unit test
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-10-31 21:08:21 +01:00
Joachim Nilsson 714ea88cc9 makepath(): Update doc, recommend mkpath() over this function
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-10-31 21:08:21 +01:00
Joachim Nilsson add4d5d325 Fix #8: constify mkpath() and makepath()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-10-31 21:08:21 +01:00
Joachim Nilsson be6f276557 Fix #7: inconsistent return value in mkpath()
When the required `dir` argument is missing `mkpath()` inconsistently
returns 1 instead of -1.  Found by @jesponde

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-10-31 00:33:19 +01:00
Joachim Nilsson 6daebf4ea4 Bump version for v1.9.3 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-10-24 15:56:30 +02:00
Joachim Nilsson 4d6e3e060e Update ChangeLog(s) for v1.9.3
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-10-24 15:56:17 +02:00
Joachim Nilsson 86eef8e38d tree(): Increase internal buffer size, result may be truncated
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-10-24 08:42:55 +02:00
Joachim Nilsson d5d3dafc78 Slight ABI bump due to changes in initscr()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-10-24 08:38:10 +02:00
Joachim Nilsson 2534c398ea initscr(): Use stdout, not stderr, just like other conio.h macros
A program's stderr may have been redirected by the operator.  We want to
query the size of stdout, even though it is buffered, so add fflush() to
handle that.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-10-24 08:33:02 +02:00
Joachim Nilsson 3691044007 conio.h: initscr() requires termios.h as well
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-10-24 08:32:30 +02:00
Joachim Nilsson 6770dad0cc conio.h: Minor, whitespace only
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-10-24 08:32:18 +02:00
Joachim Nilsson ef0db5e766 initscr(): Check if stdin and stdout are TTYs first
Programs that may be called in the background or with the stdin/stdout
redirected are not proper TTYs and we should not try to perform any
tricks on them.  This patch checks isatty() and returns standard term
sizes as a fallback.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-10-24 08:31:43 +02:00
Joachim Nilsson 485463c70e Update tree() test, use /usr/sbin instead of /sbin
Seems Debian finally went through with their move to symlink /bin and
/sbin to /usr/bin and /usr/sbin, respectively.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-09-30 11:13:23 +02:00
Joachim Nilsson 4b77eb1423 Update ChangeLog diff URLs
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-09-22 16:27:08 +02:00
Joachim Nilsson 0b54dc6015 Update Debian packaging, v1.9.2-1
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-08-15 08:15:30 +02:00
Joachim Nilsson 9d6df87d0d Update ChangeLog and bump version for v1.9.2 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-09 15:52:29 +02:00
Joachim Nilsson 5b2eee6aff conio.h: Minor refactor, cleanup
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-09 15:46:49 +02:00
Joachim Nilsson 6904f6e0fe conio.h: Add initscr(), probes terminal rows + cols
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-07 13:19:53 +02:00
Joachim Nilsson 877ba02d13 conio.h: Revert 018e607, fails unit tests
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-07 13:19:23 +02:00
Joachim Nilsson 25dfded835 conio.h: Update copyright years
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-07 12:51:43 +02:00
Joachim Nilsson 1323a88e94 conio.h: Convert printheader() to static inline function
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-07 12:51:25 +02:00
Joachim Nilsson 018e607290 conio.h: Use stderr instead of stdout because it's non-buffered
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-07 11:58:48 +02:00
Joachim Nilsson e48c9c5589 Bump version and update ChangeLog for v1.9.1, minor fix release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-03 12:57:52 +02:00
Joachim Nilsson 2c875afe06 which: Allow which("ps aux"), which skips any arguments to command
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-03 12:48:02 +02:00
Joachim Nilsson 10e4a1d057 Update which() unit test, check for /bin/which and /bin/ps aux
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-03 12:45:33 +02:00
Joachim Nilsson 3dde2922c3 Add whichp() predicate function to which()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-03 12:34:05 +02:00
Joachim Nilsson 4dd9459f65 Update debian/changelog for v1.9.0-1
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-02 19:23:49 +02:00
Joachim Nilsson 7172f487d5 Bump version for v1.9.0 GA release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-02 19:18:55 +02:00
Joachim Nilsson 4c0967405d Bump ABI version, removed UNUSED() added which(), fixed touch()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-02 19:18:55 +02:00
Joachim Nilsson fd65af31db Update HACKING document, mostly wrt library versioning
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-02 19:18:55 +02:00
Joachim Nilsson e55976d137 Update ChangeLog for v1.9 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-02 19:18:55 +02:00
Joachim Nilsson 1b1ffb33f1 Bump version to v1.9 due to new functionality, which()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-02 16:51:21 +02:00
Joachim Nilsson d018a5215f which.c: C implementation of UNIX which(1)
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-02 16:50:58 +02:00
Joachim Nilsson 0d70c116d7 Update .gitignore files
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-02 16:33:00 +02:00
Joachim Nilsson 32c774deef tree(): Refactor, flatten tree
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-07-02 16:32:04 +02:00
Joachim Nilsson 441d5f58d7 Add simple ocular unit test for printheader()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-06-30 20:28:31 +02:00
Joachim Nilsson 2a59289d53 conio.h: Add top-like heading macro, printheader()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-06-30 20:27:59 +02:00
Joachim Nilsson f89c3c88de Clear build warnings for unit tests
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-06-30 17:43:11 +02:00
Joachim Nilsson 705b402344 Remove UNUSED() macro, just use -Wno-unused instead
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-06-30 17:36:10 +02:00
Joachim Nilsson fe82ab953c Fix non-writable tempfile(), "rw" --> "w+", found by Westermo
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-06-18 18:18:08 +02:00
Joachim Nilsson 6ec2a31042 Update tempfile() unit test to detect failed write + read
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-06-18 18:14:39 +02:00
Joachim Nilsson 9f5e852084 Bump version in preparation for 1.8.4 bug-fix release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-05-20 09:29:26 +02:00
Joachim Nilsson 628c5597b9 Fix issue #6: touch does not update mtime if file exists
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-05-19 17:50:44 +02:00
Joachim Nilsson b7b635a3f4 Add unit test for touch to replicate issue #6
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-05-19 17:50:22 +02:00
Joachim Nilsson dd53c3ae9e Minor refactor of unit tests
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-05-19 17:50:07 +02:00
Joachim Nilsson 16a30a293c Add support for make package to build .deb files
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-03-12 17:43:53 +01:00
Joachim Nilsson 325fcbe149 lite.h: Add whitespace to compat macros, for readability
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-03-12 17:43:31 +01:00
Joachim Nilsson cbb1604ea0 New release for .deb package, 1.8.3-1
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-01-08 15:22:42 +01:00
Joachim Nilsson 8587971fb9 Update ChangeLog and bump version for v1.8.3 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-01-08 15:17:17 +01:00
Joachim Nilsson 6545ac8fd4 Bump ABI revision 3:0:0 --> 3:1:0
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-01-08 15:16:36 +01:00
Joachim Nilsson 9105e8d3d8 Update pidfile() documentation
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-01-08 15:16:00 +01:00
Joachim Nilsson 3555af6a6a Update ChangeLog and bump version for upcoming v1.8.3 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-01-07 13:58:59 +01:00
Joachim Nilsson 42715eab8a ChangeLog: Add missing link to v1.8.2 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-01-07 13:57:57 +01:00
Joachim Nilsson 497d58dbf0 ChangeLog: Minor Markdown fixes
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-01-07 13:57:21 +01:00
Joachim Nilsson 9ab70ebbcd Build all unit tests static, for easier debugging
- Add -static to LDFLAGS
- Remove CFLAGS override, respect input from configure script

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-01-07 13:00:08 +01:00
Joachim Nilsson bad363883d Fix leaky makepath() unit test
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-01-07 12:59:27 +01:00
Joachim Nilsson 7f3215b3e6 Update pidfile unit test to cover new use-case
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-01-07 12:59:02 +01:00
Joachim Nilsson 729cc5307f pidfile: Add support for absolute path
The OpenBSD version of pidfile() makes sure to place all PID files in
the same, canonical, location: _PATH_VARRUN.  On Linux, however, some
disitributions prefer to place PID files in a sub-directory under the
canonical location: _PATH_VARRUN + __progname/ ...

This patch adds support for creating PID files in any location. If the
PID file name argument starts with a '/', the function assumes the rest
of the string is the full PATH to the PID file.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-01-07 12:55:26 +01:00
Joachim Nilsson 66290d132f pidfile: Re-create file on consequetive calls if it doesn't exist
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-01-07 08:15:49 +01:00
Joachim Nilsson 59f7a78441 pidfile: Always initialize global variables
Always initialize global variables, even though they cannot be used in
current code paths without being initialized at runtime.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-01-07 08:15:42 +01:00
Joachim Nilsson b716776863 tests/pidfile: Cleanup test files from /tmp
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-01-07 06:53:21 +01:00
Joachim Nilsson 018ecaca15 debian/source/format: Change to native mode to allow building from GIT
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2017-01-07 04:10:21 +01:00
Joachim Nilsson a293c37777 debian/: Support for building .deb packages
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-11-29 08:32:06 +01:00
Joachim Nilsson a4937a93e2 Add reminder about umask()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-10-02 12:13:43 +02:00
Joachim Nilsson 94d547c9ec Unit test: fix search path for library header
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-09-05 00:19:52 +02:00
Joachim Nilsson 68cf8b6576 Update ChangeLog and bump version for v1.8.2 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-09-05 00:13:03 +02:00
Joachim Nilsson b6a55fcc46 Add err.h include to tests
lite.h no longer includes err.h it has to be included in each test.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-09-05 00:07:24 +02:00
Joachim Nilsson 5f29ef6413 Convert touch() et al to inline functions
The touch(), makedir(), makefifo(), and erase() macros print warnings to
stderr, which mess up the logging in Finit.  This patch refactors these
macros into inline functions and in the process removes the warn() use.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-09-04 23:58:32 +02:00
Joachim Nilsson 627c47caff Bump version for v1.8.2 devel
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-08-22 01:33:12 +02:00
Joachim Nilsson 7c2ed556b9 Replace \e GNUism w/ ISO \033 for escape sequences
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-08-22 01:31:49 +02:00
Joachim Nilsson 6dec4e3858 Extend lfile test with fstab parser
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-08-02 00:29:52 +02:00
Joachim Nilsson dff92356b3 Remove sys/cdefs.h include, does not exist in musl libc
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-07-19 15:39:57 +02:00
Joachim Nilsson 883c90112d Update modification date
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-07-04 12:46:44 +02:00
Joachim Nilsson a2c8dddaad Free pidfile_path atexit()
To prevent warnings from tools like Valgrind, or handle issues
with RAM leaks on non-MMU systems like uClinux, we must free
the memory allocated by pidfile().

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-07-04 12:42:22 +02:00
Joachim Nilsson 14f547b638 Add ldconfig to build instructions, thanks rooth!
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-30 18:53:59 +02:00
Joachim Nilsson 6f2a03bba7 Update ChangeLog & bump version for v1.8.1 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-25 12:50:21 +02:00
Joachim Nilsson cdfffa312b Update ChangeLog for upcoming v1.8.1 fix release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-08 07:18:30 +02:00
Joachim Nilsson 50cb72018f pidfile: Portability fix, utimensat() in sys/time.h
For building libite on NetBSD, and probably other BSD's as well.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-08 06:25:02 +02:00
Joachim Nilsson e8a3117158 fparseln: Portability fix _DIAGASSERT()
Only define _DIAGASSERT() if it's not already defined.
For building libite on NetBSD.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-08 06:23:34 +02:00
Joachim Nilsson 7cf2a3786c Bump version and ABI for v1.8.0 release
- Change from v1.7.1 to v1.8.0 due to amount of changes
  including ABI bump
- Update ChangeLog
- Bump library ABI version due to change in API semantics

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 19:05:26 +02:00
Joachim Nilsson 1c1d5c94e3 Clarify ABI versioning and encourage more unit tests
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 19:00:14 +02:00
Joachim Nilsson 23703c75da tests/dir.c: Remove nested checker function
Move nested check function is_startup_config() outside main().

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 18:15:47 +02:00
Joachim Nilsson efae15416c Bump version to -rc1, many changes since last release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 18:11:03 +02:00
Joachim Nilsson 661b4b4d0b Remove last remnants of old build/unit test framework
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 18:09:59 +02:00
Joachim Nilsson 682b662bd5 Add unit test for chomp()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 18:09:29 +02:00
Joachim Nilsson 75d4edb424 check.h: Add stdlib.h for exit()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 18:08:54 +02:00
Joachim Nilsson 141d4f6936 Add unit test for copyfile()/fcopyfile()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 17:59:52 +02:00
Joachim Nilsson 63aa6c5d07 Add unit test for dir()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 17:56:13 +02:00
Joachim Nilsson 1d698418c7 dir(): Do not assert(), return -1 and errno
The dir() function, although useless compared to glob(), called assert()
and perror() instead of returning an error code.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 17:56:13 +02:00
Joachim Nilsson 92d81280a9 Add unit test for fexist()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 17:45:19 +02:00
Joachim Nilsson 267465f3d2 Add unit test for fisdir()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 17:42:31 +02:00
Joachim Nilsson c22a6e64d9 Add unit test for progress bars
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 17:39:31 +02:00
Joachim Nilsson 16ae343df2 Add missing progress bar API's
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 17:39:31 +02:00
Joachim Nilsson 6e558e98f0 Add unit test for rsync
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 17:28:41 +02:00
Joachim Nilsson 69291d3e74 Add unit test for fsendfile()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 17:20:58 +02:00
Joachim Nilsson 6fdffeb355 fsendfile(): Change return type size_t --> ssize_t
Most send/recv/read/write API's return -1 on error and today use the
agreed upon type ssize_t for this purpose.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 17:19:54 +02:00
Joachim Nilsson b2f6721813 Clarify LITE file API in README
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 17:12:42 +02:00
Joachim Nilsson 3c350b8862 Add unit test for LITE file API
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 17:11:22 +02:00
Joachim Nilsson 5b786ce221 Add unit test for tempfile()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 17:07:14 +02:00
Joachim Nilsson 86b883e2af strdupa.h: Unify header guards with other headers
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 15:32:35 +02:00
Joachim Nilsson 2d6e8850a2 Add unit test for tree
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 15:32:35 +02:00
Joachim Nilsson d8cb477861 Ignore *.log and *.trs files in unit test dir
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 15:31:24 +02:00
Joachim Nilsson 27644677dd Clean *.trs and *.log files from unit test dir
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 15:31:24 +02:00
Joachim Nilsson 3588c9b01f Rename unit tests, drop _func suffix
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 15:31:24 +02:00
Joachim Nilsson ca3ea5ae92 Add unit test for mkpath() and makepath() funcs
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 15:31:23 +02:00
Joachim Nilsson 188d968f89 Remove previous pidfilefn() unit test makefile
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 15:03:56 +02:00
Joachim Nilsson 8e2c58501c Build all unit tests with -W -Wall -Wextra
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 14:02:36 +02:00
Joachim Nilsson 1da317ce1e Add missing signal.h include
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 14:02:27 +02:00
Joachim Nilsson fe39284d50 Travis-CI: Verify installation and run unit tests
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 12:42:33 +02:00
Joachim Nilsson c3c23b9aef Update ChangeLog for upcoming v1.7.1 fix release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 12:39:50 +02:00
Joachim Nilsson d45f2bad5b Update pidfile() description with hidden features
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 12:35:01 +02:00
Joachim Nilsson 61fb7aeca2 New unit test framework, first test pidfile funcs
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 12:30:35 +02:00
Joachim Nilsson dedcaf92d5 Minor style fix, to keep with pidfile.c style
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 12:16:14 +02:00
Joachim Nilsson c009c49a92 Expose __pidfile_path to override _PATH_VARRUN
This patch makes it possible to override the default pidfile() path used
for PID files, _PATH_VARRUN, with a custom path, e.g. _PATH_TMP.

This change does not affect the ABI of pidfile()

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 12:14:26 +02:00
Joachim Nilsson 12f619a320 Fix minor build error in new strndupa() header
Wrong path to local strnlen.h file.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-06 11:04:17 +02:00
Joachim Nilsson c1b3b76ea3 Update ChangeLog and bump version for v1.7.0 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-05 00:36:43 +02:00
Joachim Nilsson 8108b8ec14 Add HACKING.md for release policy ABI versioning etc.
Most of the text shamelessly stolen from the libConfuse project :)

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-04 19:01:18 +02:00
Joachim Nilsson 0e2d365eb9 Update ChangeLog with fixes and new features
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-04 18:56:07 +02:00
Joachim Nilsson 8b499aa9cd Add compat strnlen() implementation for non-GLIBC systems
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-04 18:51:25 +02:00
Joachim Nilsson f4fa44fe60 Add strndupa.h to distribution and update README
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-04 15:13:16 +02:00
Joachim Nilsson be08bcd09d strndupa.h: #error if building with non-GCC on non-GNU systems
At the moment only GCC is supported on non-GNU systems, unfortunately.
GNU systems usually have GLIBC, or another library with strndupa().
This strndupa() implementation requires GCC for the builtin alloca API.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-04 15:12:02 +02:00
Joachim Nilsson 1495a3f858 Add compat strndupa() implementation from libnostd
This patch adds compat support, to *BSD and other UNIX, for the GLIBC
strndupa() function.  The implementation is taken from libnostd written
by William Ahern.

http://www.25thandclement.com/~william/projects/libnostd.html

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-04 15:07:17 +02:00
Joachim Nilsson 5eb816b4c0 Update ChangeLog and README with new strdupa()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-03 23:12:50 +02:00
Valery Frolov 456c58d52d Add new headers, for strdupa(), to distribution
Signed-off-by: Valery Frolov <fvgenn@gmail.com>
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-03 23:08:08 +02:00
Joachim Nilsson 59869b876e strdupa.h: #error if building with non-GCC on non-GNU systems
At the moment only GCC is supported on non-GNU systems, unfortunately.
GNU systems usually have GLIBC, or another library with strdupa().  This
strdupa() implementation requires GCC for the builtin alloca API.

Followup to pull-request #4

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-02 19:51:43 +02:00
Joachim Nilsson 113c3487bd Add info on building directly from GIT
Followup to pullrequest #4

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-06-02 19:44:49 +02:00
Joachim Nilsson de73e268d3 Merge branch 'abs0-master'
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-05-30 22:32:43 +02:00
Joachim Nilsson b57c257f09 Cleanup of old shared rules.mk file, now only used by unit tests.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-05-30 22:31:59 +02:00
Joachim Nilsson 94d42b3df7 Add compat strdupa() implementation from libnostd
This patch adds compat support, to *BSD and other UNIX, for GLIBC
strdupa() function, used in mkpath().  The implementation is taken
from http://www.25thandclement.com/~william/projects/libnostd.html
by William Ahern.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-05-30 22:29:30 +02:00
Joachim Nilsson 94ad65a121 Factor out string functions to lite/strlite.h
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-05-30 22:27:41 +02:00
David Brownlee f3f6947604 Handle old Linux/(G)LIBC and UNIX systems the same
Linux systems pre Linux 3.11, and UNIX do not have the O_TMPFILE flag,
so let's treat them the same, by wrapping tmpfile().

Signed-off-by: David Brownlee <abs@absd.org>
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-05-30 21:05:21 +02:00
Joachim Nilsson 613d397161 Fix mkpath() to handle relative dirs
After input from both StackOverflow and Valery Frolov.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-05-23 09:15:50 +02:00
Joachim Nilsson 7df1b75fa0 Bump version for v1.6.0 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-05-13 07:22:25 +02:00
Joachim Nilsson 9b1b7ca4cf ChangeLog: Fix Markdown links in v1.6.0 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-05-13 07:21:45 +02:00
Joachim Nilsson 1e064b8b4d Update ChangeLog for v1.6.0 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-05-12 21:13:10 +02:00
Joachim Nilsson 18dde87f0a Add NetBSD fparseln(3) v1.10
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-05-09 19:14:05 +02:00
Joachim Nilsson fcb38c9cc5 Constify fisdir() argument
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-05-09 19:10:05 +02:00
Joachim Nilsson ab69ae8374 Add OpenBSD reallocarray(3) v1.2
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-05-09 00:37:05 +02:00
Joachim Nilsson 95f7a91a8a Bump version for v1.6.0 release cycle
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-05-09 00:33:16 +02:00
Joachim Nilsson aab5a1145c Remove Emacs version-control handling
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-05-07 22:35:49 +02:00
Joachim Nilsson fe1a3a731d Update ChangeLog and bump version for v1.5.1 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-04-17 16:27:02 +02:00
Joachim Nilsson cd073f5221 fcopyfile: Westermo fixes and code simplification
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-04-17 16:17:00 +02:00
Joachim Nilsson 1a9d3bd91b Spellcheck
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-04-17 01:25:46 +02:00
Joachim Nilsson 8cc267f259 Markdown formatting
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-04-17 01:03:53 +02:00
Joachim Nilsson 35d396ec27 Is --> Are, a --> an ...
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-04-17 01:02:09 +02:00
Joachim Nilsson 7e91307138 Add Table of Contents
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-04-17 00:54:22 +02:00
Joachim Nilsson 2b8f54fbc7 Update build & install instructions
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-04-17 00:53:57 +02:00
Joachim Nilsson 2e58dd3203 Simplify configure script
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-04-17 00:47:21 +02:00
Joachim Nilsson 41392f7e85 Remove bogus autoconf version requirement
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-04-17 00:46:58 +02:00
Joachim Nilsson e4329d6c25 Add some integration tips when using GNU autotools
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-04-17 00:46:14 +02:00
Joachim Nilsson 7113b3d1d8 Add basic TODO file to keep track of stuff
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-04-11 01:24:53 +02:00
Joachim Nilsson 9b6ef1f053 pidfile(): Activate use of utimensat() to update atime+mtime
Due to problems with the unit tests the use of utimensat() in pidfile()
was disabled, and forgotten.  This patch enables it, but beware, this
thing is QUICK on any system with a L2 cache or better.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-04-11 01:18:57 +02:00
Joachim Nilsson efc70e3a75 Update ChangeLog and bump version for v1.5.0 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-03-20 02:24:26 +01:00
Joachim Nilsson 147df0c6da ABI revision bump
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-03-20 02:21:33 +01:00
Joachim Nilsson 7f89000c6c pidfilefn.c: Update unittests, add mtime test and prettyfy output
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-03-20 02:15:35 +01:00
Joachim Nilsson 7607148d46 Build unit tests with -g -O0 for debugging
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-03-20 02:14:55 +01:00
Joachim Nilsson 979f76aea7 pidfile(): Use utimensat() to update atime+mtime
This patch update the `-lite` patch to OpenBSD `pidfile()` by changing
the update atime+mtime patch from writing the PID again to instead use
utimensat(). Less overhead and nanosecond resolution.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-03-20 02:14:30 +01:00
Joachim Nilsson ac41fa70aa Update ChangeLog and bump version to v1.5.0-dev
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-03-13 01:59:41 +01:00
Joachim Nilsson 5f820b17b6 Change namespace for header files libite/lite.h --> lite/lite.h
The `libite/` namespace for header files has been the same since the
first public release in v1.0.0.  This patch surprisingly changes it to
the less surprising `lite/`.  Hopefully there aren't that many users of
this library out there yet, apart from myself.

Apologies if you are affected!

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-03-13 01:58:56 +01:00
Joachim Nilsson 53b715c094 Remove surprise from pkg-config output
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-03-13 00:38:53 +01:00
Joachim Nilsson 1b4cd7b20b Update ChangeLog and bump version for v1.4.4 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-02-23 14:23:12 +01:00
Joachim Nilsson 8e379ca358 Update ChangeLog
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-02-22 19:11:29 +01:00
Joachim Nilsson 12241dcdfe libite.pc.in: Remove spurious @LTLIBINTL@ after copy-paste from libConfuse
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-02-20 22:26:24 +01:00
Joachim Nilsson 0ce1b3bf44 Add pkg-config support
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-02-20 22:03:25 +01:00
Joachim Nilsson 38ff0af61a Update ChangeLog with details on issue #3
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-02-15 18:20:25 +01:00
Joachim Nilsson 00737a5b74 Merge pull request #3 from askerin/tempfile-archfix
Tempfile() is dependent on $ARCH

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-02-12 16:15:53 +01:00
Joachim Nilsson 1b8b164ed4 Test build with both GCC and Clang (LLVM)
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-02-12 16:15:15 +01:00
Joachim Nilsson 9f279c0fec Disable sudo for build while auto-tests are reintegrated
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-02-12 16:14:59 +01:00
Johan Askerin 4d7e6d4f78 In tempfile(): O_DIRECTORY is dependent on $ARCH, don't hardcore O_TMPFILE
Signed-off-by: Johan Askerin <johan.askerin@gmail.com>
2016-02-12 15:17:25 +01:00
Joachim Nilsson 0a57f2128f Update ChangeLog and bump version for v1.4.3 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-02-02 09:37:40 +01:00
Joachim Nilsson e254db48a8 Remove AUTHORS file from distribution, doesn't exist
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-02-02 08:40:14 +01:00
Joachim Nilsson 0fe429dcbe Update ChangeLog in preparation for v1.4.3 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-02-02 08:25:16 +01:00
Joachim Nilsson f1a2e01775 Makefile.am: Update to install and distribute README.md, LICENSE, etc.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-02-02 08:24:15 +01:00
Joachim Nilsson e5eef2ae59 Remove confusing symlinks, it's a brave Markdown world
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-02-02 08:22:13 +01:00
Joachim Nilsson f9caffc9b7 Update ChangeLog and bump version for v1.4.2 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-23 11:29:50 +01:00
Joachim Nilsson 604b503b84 Fix issue #2: GCC6 -Wmisleading-indentation causing FTBFS in pimd
- Add function comment
- Fix misleading indentaion
- Fix coding sttle

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-23 11:16:53 +01:00
Joachim Nilsson 5fc248522c Update ChangeLog and bump version for v1.4.1 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-22 01:07:35 +01:00
Joachim Nilsson c0b8bab164 Use pkginclude_HEADERS for libite include files
The v1.4.0 release installs the header files in $(prefix)/include, this
patch installs them in the proper $(prefix)/include/$(PACKAGE) dir.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-22 01:03:19 +01:00
Joachim Nilsson c0e9c0431a Bump version for 1.4.1-dev cycle
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-22 01:01:22 +01:00
Joachim Nilsson efdd61648a Update ChangeLog and bump version for release v1.4.0
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-22 00:05:01 +01:00
Joachim Nilsson 2e8e64fd2a Step ABI version 2:0:0 --> 2:1:0
Slight change in how `pidfile()` behaves, now exporting __pidfile_name.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-22 00:01:19 +01:00
Joachim Nilsson c4109e7e74 Add Niels Provos' famous splay and red-black tree implementation
This is the OpenBSD sys/tree.h r1.14

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-21 23:51:40 +01:00
Joachim Nilsson 5d07594709 Update pidfile() documentation and add unit test for __pidfile_name
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-21 23:30:08 +01:00
Joachim Nilsson 253460b4b8 Make pidfile() name accessible (read-only) to daemon as __pidfile_name
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-21 23:28:59 +01:00
Joachim Nilsson acc59e0c1f Remove AM_MAINTAINER_MODE from configure script, not recommended anymore
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-21 22:32:23 +01:00
Joachim Nilsson 90374fc237 README: Add a Build & Install section
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-18 20:11:19 +01:00
Joachim Nilsson 7f375b6e9d Remove -Werror due to O_TMPFILE is missing on older kernels
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-14 21:49:49 +01:00
Joachim Nilsson e4236db2bd Ignore all generated files from build system
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-14 21:43:02 +01:00
Joachim Nilsson 42a5a906fc ChangeLog: Prepare for upcoming v1.4.0 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-14 21:28:08 +01:00
Joachim Nilsson 10b28127f5 Update .gitignore, add bogus m4/.gitignore to make Travis-CI happy
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-14 21:27:04 +01:00
Joachim Nilsson d265a05422 Update build script for Travis-CI with GNU configure and build system
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-14 18:56:01 +01:00
Joachim Nilsson f07c05138d Initial conversion to the GNU configure and build system
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-14 17:40:26 +01:00
Joachim Nilsson e1f8224666 Update ChangeLog and bump version for release v1.3.0
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-07 02:58:06 +01:00
Joachim Nilsson 84650d8836 Update include file boiler plate
We're not in Kansas anymore, Toto.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-07 02:58:06 +01:00
Joachim Nilsson b4fbd54a8c Update copyright years
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-07 02:58:06 +01:00
Joachim Nilsson c14c6a1e62 pidfile.c: Add LITE #ifdef pidfile and comment LITE mtime extension
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-07 02:58:06 +01:00
Joachim Nilsson 8aecba2b7a strtonum.c: Update to OpenBSD v1.7, style tweaks
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-07 02:58:06 +01:00
Joachim Nilsson 74dcaddc55 strlcat.c: Update to OpenBSD v1.14, readability fixes
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-07 02:57:59 +01:00
Joachim Nilsson c5a36ff7bd strlcpy.c: Update to OpenBSD v1.12, readability fixes
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-07 02:57:51 +01:00
Joachim Nilsson 3371e42035 queue.h: Update to OpenBSD v1.43 -- NOTE: Removes CIRCLEQ support!
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-07 02:03:10 +01:00
Joachim Nilsson 4e57a78255 README: Update section on OpenBSD Functions as well
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-06 13:35:35 +01:00
Joachim Nilsson ce3bd4ec8a README: Update documentation for pidfile() fn
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-06 13:31:32 +01:00
Joachim Nilsson 805571a7ef ChangeLog: Fix missing README link
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-05 13:34:41 +01:00
Joachim Nilsson 36435997bf ChangeLog: Fix Markdown links
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-05 13:33:34 +01:00
Joachim Nilsson f961889724 Add documentation for new macros and prepare ChangeLog for v1.3.0
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-05 13:27:40 +01:00
Tobias Waldekranz 6605fb9771 Makefile: Make sure queue.h and conio.h also are installed
This patch adds the BSD queue.h and the Borland inspired conio.h to the
install-dev Makefile target.

Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-05 13:17:16 +01:00
Tobias Waldekranz 61254279b9 lite.h: Add min() and max() macros
These macros take care to avoid double evaluation.

Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-05 13:16:34 +01:00
Joachim Nilsson e42aca8856 Makefile: Split install-dev taget into install-dev and install-data
This makes it possible to skip installing any unnecessary cruft.
Useful for embedded targets.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-05 13:14:37 +01:00
Joachim Nilsson 16611f3e5f Add ChangeLog to project and bump version for new release cycle
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2016-01-05 13:13:26 +01:00
Joachim Nilsson 975df87d6b Update unit test for pidfile()
Add ocular verification step for mtime update when pidfile() is
called more than once.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-12-17 00:15:18 +01:00
Joachim Nilsson 148027674a pidfile: Only update mtime i called multiple times
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-12-16 18:40:34 +01:00
Joachim Nilsson 12ed342d55 Bump version for v1.2.0 release
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-11-23 00:32:56 +01:00
Joachim Nilsson 23badc990d lfile: Improve unittest/example with /etc/group + passwd
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-10-26 00:50:18 +01:00
Joachim Nilsson ca53e097c3 lfile: Initialize strtok_r() save pointer
Must initialize the save pointer in the parser context, otherwise
strtok_r() will fail on statically built embedded targets.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-10-26 00:16:36 +01:00
Joachim Nilsson a7b5c240c1 Add UNIX lfile_t parser API to lite.h
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-10-25 23:25:17 +01:00
Joachim Nilsson c4eb5cb124 Add simple parser for UNIX configuration files.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-10-25 22:50:10 +01:00
Joachim Nilsson db08b20f23 Make sure we don't inherit LDFLAGS from environment.
To pass custom LDFLAGS to libite, use EXTRA_LDFLAGS.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-10-22 18:35:35 +02:00
Joachim Nilsson 8779f54125 Do not allow VERSION to be overloaded by build system.
When integrating libite as a component in another piece of software,
that build system may set VERSION as an environment variable.  We do
not want that version to be set as the version of libite.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-10-03 09:13:37 +02:00
Joachim Nilsson bd9a618ea3 Bump version for v1.1.1 patch release.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-09-27 00:59:54 +02:00
Joachim Nilsson 3f89fafe24 Fix macro definitions for compat APIs
Seems cpp is a bit uptight about spaces.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-09-27 00:56:20 +02:00
Joachim Nilsson ebec48d671 Silence annoying warnings from GNU ar
In (very) modern versions of binutils, for instance v2.25.1 shipped in
Ubuntu 15.10, ar complains about the VERY common `crus` argument.  This
patch silences this noise:

    $ make -j5
      ARCHIVE libite.a
    ar: `u' modifier ignored since `D' is the default (see `U')

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-09-27 00:55:26 +02:00
Joachim Nilsson 4d6c32f81a Bump version to v1.1.0 and drop default optimization.
User of library will likely want to have better control over the default
optimization level.  Either way, defaulting to -Os is a lot more "risky"
than, say -O2.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-09-16 17:25:43 +02:00
Joachim Nilsson 25c725c240 Bump SONAME to libite.so.2 so for upcoming Finit v2.0
We need to lock down the ABI and do a new release on behalf of
Finit.  Finit will have support for using an externally built
libite and libuev, so Finit must lock down to a known ABI.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-09-16 17:23:49 +02:00
Joachim Nilsson 039a92b292 progress.c: Merge in latest changes from troglobit/toolbox@d845e67
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-24 23:52:26 +02:00
Joachim Nilsson 5ae5bfb767 Bump version to indicate new feature status, v1.1.0-beta1
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-23 19:37:08 +02:00
Joachim Nilsson a00e765789 Update README with info on progress() and tree()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-23 19:36:21 +02:00
Joachim Nilsson aff5812c46 Minor whitespace fixes, use Linux KNF
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-23 13:15:18 +02:00
Joachim Nilsson 3809b109c6 Add autotest for progress()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-23 13:11:20 +02:00
Joachim Nilsson 1909dd475c progress(): Very simple ASCII progress bar from troglobit/toolbox@f98c5d0
This patch adds a very simple progress bar I wrote once.  It's revision
f98c5d0 from https://github.com/troglobit/toolbox

Also included in this patch is conio.h, a neat little set of macros for
manipulating your terminal using ANSI escape seequences.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-23 13:07:03 +02:00
Joachim Nilsson a157fe4162 tree: Minor cleanup, also does not need sudo for tests.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-23 05:23:54 +02:00
Joachim Nilsson 42b6a03317 rsync.test: Use homegrown tree, instead of out-of-tree tree ...
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-23 05:19:11 +02:00
Joachim Nilsson 1f1e88a640 New function: tree(), simple /bin/tree replacement.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-23 05:12:38 +02:00
Joachim Nilsson bb67fb749d rsync.c: Refactor unit tests to work on Travis as well.
Travis does not have `/bin/tree` installed, and since we do not
output intermediate results from `make test`, there is no need
to call `/bin/tree` unless `-v` is supplied to the test.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-23 02:33:33 +02:00
Joachim Nilsson 3e337c7078 rules.mk: When V=1 is used, add -v to autotests.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-23 02:32:29 +02:00
Joachim Nilsson 407e954f02 tempfile(): Handle kernels older than 3.11 by wrapping tmpfile()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-23 02:17:45 +02:00
Joachim Nilsson 8978cb9bff Try sudo: true for sake of tests, skip Docker for now.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-23 01:39:08 +02:00
Joachim Nilsson 9c90ec56a6 Attempt to activate autotests in Travis-CI.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-23 01:33:24 +02:00
Joachim Nilsson 44e787c966 Add generic support for running tests as root.
By setting `ASROOT=1` in a unit test makefile a test will now run as
root, using `sudo -n`.

This patch allows us to simplify the pidfilefn() test.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-23 01:30:29 +02:00
Joachim Nilsson e8ff38ad6a Add autotest for fisdir()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-22 23:26:41 +02:00
Joachim Nilsson 1138822d19 Add autotest for fexist()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-22 23:22:38 +02:00
Joachim Nilsson de8f2b087c Add autotest for tempfile()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-22 23:08:22 +02:00
Joachim Nilsson 87d6fe822c Make sure to start the makepath() tests clean.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-22 23:07:56 +02:00
Joachim Nilsson 57c49bfe0c Add autotest for mkpath() and makepath()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-22 23:01:15 +02:00
Joachim Nilsson b59249714b Add autotest for fsendfile()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-22 22:49:48 +02:00
Joachim Nilsson 36da3aa35e Add autotest for dir
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-22 22:46:42 +02:00
Joachim Nilsson ab2b0f00fa Add autotest for pidfilefn et al.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-22 22:41:34 +02:00
Joachim Nilsson bd69aad13a Add autotest for copyfile et al.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-22 22:22:14 +02:00
Joachim Nilsson ebe2ad4a4c Add autotest for chomp
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-22 22:08:25 +02:00
Joachim Nilsson 2ea2357b62 Lay foundation for unit test build framework.
GNU Make double colon rules, rule ;-)

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-22 21:59:52 +02:00
Joachim Nilsson b7a8042c87 Add Travis-CI status icon
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-22 16:11:31 +02:00
Joachim Nilsson 7d1423b5b1 Add dockerized Travis-CI autobuilder support.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-22 16:09:54 +02:00
Joachim Nilsson 117ec58a90 Add some very useful helper macros: NELEMS() and bitops.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-08-21 09:42:43 +02:00
Joachim Nilsson a4cbc7a10e pidfile.c: Upgrade to OpenBSD r1.11, asprintf() fixes.
Do not assume that asprintf() clears the pointer on failure, which
   is non-portable.  Also add missing asprintf() return value checks.
   Signed-off-by: millert@
   Signed-off-by: deraadt@ guenther@ doug@

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-07-22 11:53:44 +02:00
Joachim Nilsson 3eb1fbb31d lite.h: Minor coding style cleanup.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-07-22 11:52:41 +02:00
Joachim Nilsson f5355ecf7b lite.h: Convert from error.h to the more BSD friendly err.h
OpenBSD, and possibly the other BSD's, do not have error.h so we replace
it with err.h, which exists almost everywhere.

This means the macros in lite.h that used error() now instead use
warn(),  with the same semantics as before.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-07-18 15:36:06 +02:00
Joachim Nilsson 61b1b5b457 Add support for 'make distdir' used by GNU configure and build.
This patch adds support for being called with "make distdir" from a GNU
configure and build based project.  This was a requirement to get the
Inadyn v1.99.14 release out.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-07-14 17:26:32 +02:00
Joachim Nilsson 83f83466b5 Fix indentation of description to some API's.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-07-12 13:13:21 +02:00
Joachim Nilsson 6d2717726f Shorten README title heading.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-07-12 12:50:01 +02:00
Joachim Nilsson 2675426845 Update README for release.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-07-12 12:44:39 +02:00
Joachim Nilsson 51c73030e0 Minor change.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-07-12 12:43:57 +02:00
Joachim Nilsson a9d11d0498 ifconfig.c: Fix possible NULL pointer deref.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-07-10 19:27:02 +02:00
Joachim Nilsson 1147e547dc Followup to atonum(), missing include file and const.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-07-10 19:06:17 +02:00
Joachim Nilsson 41c9caff17 Add atonum() - Convert string to natural number, returns -1 on error.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-07-10 19:00:11 +02:00
Joachim Nilsson 4005dd5e2c Add simple IPv4 only ifconfig() function from Finit
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-07-10 18:28:57 +02:00
Joachim Nilsson 614c8cbe47 Update documentation of OpenBSD derived functions with pointers to man pages.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-07-10 18:27:46 +02:00
Joachim Nilsson 8db314623a Followup to pidfilefn.c, add system include file for usleep()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-07-09 03:22:53 +02:00
Joachim Nilsson e731d83881 Add pidfile_poll() from Finit, waits max 5 sec for pidfile.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-07-09 03:19:56 +02:00
Joachim Nilsson c2d0ed0d12 Fix minor issues in pidfile_read() and pidfile_signal(), caught by Coverity
- Simplify pidfile_read(), no need to call access() when fopen() is more
  than capable of failing on its own if we do not have READ access.
- The remove() syscall requires that you check the return value, but we
  don't care about that when having signalled a TERM signal to a process.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-07-09 01:59:10 +02:00
Joachim Nilsson 5a50a6add1 Add client side pidfile functions: pidfile_read(), pidfile_signal().
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-07-09 01:36:58 +02:00
Joachim Nilsson 9ed00baa94 Add pidfile() from NetBSD/OpenBSD, missing in GLIBC.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-07-09 01:25:19 +02:00
Joachim Nilsson 1561e7567e Add recursive mkpath() and makepath(), works like mkdir -p
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-07-09 01:25:19 +02:00
Joachim Nilsson c5366a33da fsendfile(): Break ABI by switching src and dst to match rest of API.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-07-06 02:04:28 +02:00
Joachim Nilsson af39ae5fa9 Refactor copyfile(), and copy_filep() --> fcopyfile() to use same backend.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-07-06 02:03:28 +02:00
Tobias Waldekranz 1423edc044 Factor out fsendfile() to reduce overall size when linking.
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-07-05 15:21:55 +02:00
Joachim Nilsson c48ce14739 Default to silent build, use V=1 to get verbose mode.
Use kernel standard silent mode instead, and adopt kernel nomenclature
for enabling verbose mode.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-07-05 11:46:48 +02:00
Joachim Nilsson 6f19d1407a Default to verbose style build, use SILENT=1 to get silent mode.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-07-05 11:28:03 +02:00
Joachim Nilsson 436a07ee06 Remove STATIC ifdef, always build .a and .so files
Using libite as a GIT submodule in a autoconf/automake based project it
is non-trivial to set a separate environment variable when descending
into the libite subdirectory.

It is better to instead simplify the build process and always build both
.a and .so files.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-07-05 11:06:33 +02:00
Joachim Nilsson e37aad9530 Update on tmpfile() requirements.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-07-03 01:50:15 +02:00
Joachim Nilsson 32827cdea9 Add OpenBSD version of the extremely useful sys/queue.h API
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-07-03 01:47:22 +02:00
Joachim Nilsson e4c5a0e77e copyfile(): Fix potentially dangerous time of check-time of use bug.
Coverity reports a potenatially TOCTOU bug, CWE-367, in copyfile().
Turns out we tried to fall back to copy when readlink() failed, in
the case when the user requested to copy symlinks.

It's better to fail hard if stat() reports symlink and readlink()
right after fails to read the symlink ...

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-06-22 22:39:59 +02:00
Joachim Nilsson 35b43c5c56 Handle missing O_TMPFILE gracefully and document tempfile() in README
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-06-22 22:02:39 +02:00
Joachim Nilsson c5434a4bc0 Add tempfile() - a secure tmpfile() replacement using O_TMPFILE.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-06-22 21:42:38 +02:00
Joachim Nilsson 84c3667eba Default to -fPIC, bloats archives slightly, but works for everyone.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-06-18 02:24:17 +02:00
Joachim Nilsson 262f8b8936 Cleanup: Fix install/uninstall of both static and dynamic builds.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-06-18 02:14:55 +02:00
Joachim Nilsson c045bc7264 Add small clarification on licenses used in libite (-lite)
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-06-18 01:06:05 +02:00
Joachim Nilsson 82ca189a52 Fix buggy chomp() -- Chop off only trailing newlines, all of them.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-06-17 23:45:39 +02:00
Joachim Nilsson 1b4dd15614 Document helper macros.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-06-17 23:10:50 +02:00
Tobias Waldekranz 121e8ee888 Add Westermo chomp() function, slightly improved from Finit original.
Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-06-17 22:07:10 +02:00
Joachim Nilsson 745256909e Shorten title.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-06-17 21:57:29 +02:00
Joachim Nilsson 552f917b9b Update README slightly.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-06-17 21:56:03 +02:00
Joachim Nilsson 08ce3d503e Add basic README.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-06-17 21:26:58 +02:00
Joachim Nilsson 22a79ee947 Make libite standalone
Add basic .gitignore, cleanup inherited Makefile from Finit
and add a small rules.mk from libuEv.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-06-17 21:13:02 +02:00
Joachim Nilsson 1758f9a847 rsync.c: Use makedir() from lite.h
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-06-17 20:57:05 +02:00
Joachim Nilsson 9f0979daea Add some helper macros and wrappers for C library functions.
- touch()    - Create a file, or update mtime.  Errors on stderr
- makedir()  - Create directory, like mkdir().  Errors on stderr
- makefifo() - Create a FIFO, like mkfifo().  Errors on stderr
- erase()    - Erase file/directory with remove().  Errors on stderr
- chardev()  - Create character device
- blkdev()   - Create block device
- S_ISEXEC() - Mysteriously missing from GLIBC
- UNUSED()   - Shorter and more readable version of __attribute__ ((unused))

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-06-17 20:56:07 +02:00
Joachim Nilsson 95922a9536 Add standard MIT/X11 license, from Finit.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-06-17 16:14:14 +02:00
Joachim Nilsson f35f64f06f Fix last part of issue #8: Libite install problem with --enable-static
Skip install of .so libs when user has configured with --enable-static

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-03-10 22:12:26 +01:00
Joachim Nilsson 8b7eb36d2a Overhaul build system and add support for disabling inetd support.
This patch adds support for a configure script and with it
support for disabling inetd support.  See the output from

    ./configure --help

* Add configure script
* Sprinkle #ifdef fairy dust on svc.c when inetd support is disabled
* Use GCC built-in autodep calculator (-MMD -MP)
* Fix name space issue with include files, use relative paths
* Disable username/group name to uid/gid functions in static builds
* Bug out (error) if a user tries to build the bootmisc plugin static

Possibly fixes GitHub issue #5 and issue #6.

NOTE: The static build has not received any testing at all!

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-03-10 10:25:46 +01:00
Joachim Nilsson 5e31d05110 Initial support for building Finit statically (incomplete)
This patch adresses issue #5.  However, there still remains a few issues
to work around before Finit can be built completely standalone.

    $ make clean all STATIC=1
    LINK    finit
    helpers.o: In function `getgroup':
    helpers.c:(.text+0x10a7): warning: Using 'getgrnam' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
    helpers.o: In function `getuser':
    helpers.c:(.text+0x108e): warning: Using 'getpwnam' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
    inetd.o: In function `getent':
    inetd.c:(.text+0x127): warning: Using 'getprotobyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
    inetd.c:(.text+0xce): warning: Using 'getservbyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking

The problem is the NSS plugins and similar issues that prevent static
linking when using the above functions.  See issue #5 for more on this.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2015-03-06 21:58:56 +01:00
Joachim Nilsson 5d184794b4 Fix various problems with unchecked return values from syscalls.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2014-11-27 00:12:07 +01:00
Joachim Nilsson 0701b688fd libite/rsync.c: Fix build regression from previous commit.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2014-11-26 23:37:04 +01:00
Joachim Nilsson e0c84e25a7 Fix problem with unchecked return value of mkdir(), wrap in makedir() macro.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2014-11-26 23:27:15 +01:00
Joachim Nilsson e540ea8735 libite:rsync.c - Break out nested function.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2014-10-31 14:56:51 +01:00
Joachim Nilsson 949d0a020f Bump version for release and update copyright years.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2014-04-21 16:03:54 +02:00
Joachim Nilsson 36d24ce366 lite.h: Add some helper string comparison methods.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2014-04-21 15:45:23 +02:00
Joachim Nilsson 80c2a132cd libite: Fix cppcheck warnings in rsync unit test
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2014-04-12 16:34:57 +02:00
Joachim Nilsson 5eb4f640b1 libite: Minor style cleanup of fsendfile()
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2014-04-12 16:21:41 +02:00
Joachim Nilsson 6b64189d14 libite: Simplify and fix another memleak in copyfile()
- Simplify: reduce indentation depth
- Always check for error condition first, cleaner code
- Make sure buffer is always freed, use same exit everyhere
- Use readable, but still short, local variable names

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2014-04-12 16:11:59 +02:00
Joachim Nilsson bf9d1ec012 libite: Copy utility fixes and new functionality
- Add support for symlinks to copyfile()
- Fix memory leak in copy_filep()
- New function, fsendfile(), copy data between FILE streams

Also, minor whitespace and coding style cleanup.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2014-04-12 15:08:56 +02:00
Joachim Nilsson 499f4d45d3 libite: Add strtonum() from OpenBSD
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2013-05-21 19:55:41 +02:00
Mattias Walström cd63f8a73d libite: Fix memory leak in dir()
Signed-off-by: Mattias Walström <lazzer@gmail.com>
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2013-05-19 19:01:44 +02:00
Joachim Nilsson ddf5ecc907 libite: Improve error handling for copyfile() and rsync()
When using the simple rsync() or copyfile() functions of libite some
error codes should not be interpreted as error.  I.e., if a file or
directory already exists when attempting to create it.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2013-05-19 18:00:31 +02:00
Mattias Walström 77971a31b2 libite: Add strlcat and strlcpy.
These function only exist on uClibc and BSD, so if they
not already defined in string.h, define them here.
2013-01-29 13:29:45 +01:00
Joachim Nilsson 7627b5848a Fix incorrect use of variable arguments in run_parts() and simplify code
The run_parts() implementation used variable arguments in a bad way,
resulting in it not working properly.  Replaced va_*() code with a
simple cmd argument that's passed to each script called.

Also, the opendir()/readdir() code has been replaced with scandir()
using regular alphasort(). This simplifies the code somewhat as well.

Otherwise, minor cleanups.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
2012-10-06 15:45:42 +02:00
122 changed files with 12877 additions and 1058 deletions

No files matched your search

+193
View File
@@ -0,0 +1,193 @@
# CodeDocs.xyz Configuration File
#
# Rename this example to '.codedocs' and put it in the root directory of your
# repository. This file is optional, documentation will still be generated
# without it using sensible defaults.
#---------------------------------------------------------------------------
# CodeDocs Configuration
#---------------------------------------------------------------------------
# Include the Doxygen configuration from another file.
# The file must be a relative path with respect to the root of the repository.
# If any of the options in this doxyfile include a path (ie, INPUT), these
# paths will be considered relative to the root of the repository, not the
# location of the DOXYFILE.
DOXYFILE = doc/Doxyfile
# Specify external repository to link documentation with.
# This is similar to Doxygen's TAGFILES option, but will automatically link to
# tags of other repositories already using CodeDocs. List each repository to
# link with by giving its location in the form of owner/repository.
# For example:
# TAGLINKS = doxygen/doxygen CodeDocs/osg
# Note: these repositories must already be built on CodeDocs.
TAGLINKS =
#---------------------------------------------------------------------------
# Doxygen Configuration
#---------------------------------------------------------------------------
# Doxygen configuration may also be placed in this file.
# Currently, the following Doxygen configuration options are available. Refer
# to http://doxygen.org/manual/config.html for detailed explanation of the
# options. To request support for more options, contact support@codedocs.xyz.
#
# ABBREVIATE_BRIEF =
# ALIASES =
# ALLEXTERNALS =
# ALLOW_UNICODE_NAMES =
# ALPHABETICAL_INDEX =
# ALWAYS_DETAILED_SEC =
# AUTOLINK_SUPPORT =
# BRIEF_MEMBER_DESC =
# BUILTIN_STL_SUPPORT =
# CALLER_GRAPH =
# CALL_GRAPH =
# CASE_SENSE_NAMES =
# CITE_BIB_FILES =
# CLASS_DIAGRAMS =
# CLASS_GRAPH =
# COLLABORATION_GRAPH =
# COLS_IN_ALPHA_INDEX =
# CPP_CLI_SUPPORT =
# DIAFILE_DIRS =
# DIRECTORY_GRAPH =
# DISABLE_INDEX =
# DISTRIBUTE_GROUP_DOC =
# DOTFILE_DIRS =
# DOT_FONTNAME =
# DOT_FONTSIZE =
# DOT_GRAPH_MAX_NODES =
# DOT_IMAGE_FORMAT =
# DOT_TRANSPARENT =
# DOXYFILE_ENCODING =
# ENABLED_SECTIONS =
# ENABLE_PREPROCESSING =
# ENUM_VALUES_PER_LINE =
# EXAMPLE_PATH =
# EXAMPLE_PATTERNS =
# EXAMPLE_RECURSIVE =
EXCLUDE = src/README.md
# EXCLUDE_PATTERNS =
# EXCLUDE_SYMBOLS =
# EXPAND_AS_DEFINED =
# EXPAND_ONLY_PREDEF =
# EXTENSION_MAPPING =
# EXTERNAL_GROUPS =
# EXTERNAL_PAGES =
# EXTRACT_ALL =
# EXTRACT_ANON_NSPACES =
# EXTRACT_LOCAL_CLASSES =
# EXTRACT_LOCAL_METHODS =
# EXTRACT_PACKAGE =
# EXTRACT_PRIVATE =
# EXTRACT_STATIC =
# EXT_LINKS_IN_WINDOW =
# FILE_PATTERNS =
# FORCE_LOCAL_INCLUDES =
# FORMULA_FONTSIZE =
# FORMULA_TRANSPARENT =
# FULL_PATH_NAMES =
# GENERATE_BUGLIST =
# GENERATE_DEPRECATEDLIST =
# GENERATE_LEGEND =
# GENERATE_TESTLIST =
# GENERATE_TODOLIST =
# GENERATE_TREEVIEW =
# GRAPHICAL_HIERARCHY =
# GROUP_GRAPHS =
# GROUP_NESTED_COMPOUNDS =
# HIDE_COMPOUND_REFERENCE= =
# HIDE_FRIEND_COMPOUNDS =
# HIDE_IN_BODY_DOCS =
# HIDE_SCOPE_NAMES =
# HIDE_UNDOC_CLASSES =
# HIDE_UNDOC_MEMBERS =
# HIDE_UNDOC_RELATIONS =
# HTML_COLORSTYLE_GAMMA =
# HTML_COLORSTYLE_HUE =
# HTML_COLORSTYLE_SAT =
# HTML_DYNAMIC_SECTIONS =
# HTML_EXTRA_FILES =
# HTML_EXTRA_STYLESHEET =
# HTML_FOOTER =
# HTML_HEADER =
# HTML_INDEX_NUM_ENTRIES =
# HTML_STYLESHEET =
# HTML_TIMESTAMP =
# IDL_PROPERTY_SUPPORT =
# IGNORE_PREFIX =
# IMAGE_PATH =
# INCLUDED_BY_GRAPH =
# INCLUDE_FILE_PATTERNS =
# INCLUDE_GRAPH =
# INCLUDE_PATH =
# INHERIT_DOCS =
# INLINE_GROUPED_CLASSES =
# INLINE_INFO =
# INLINE_INHERITED_MEMB =
# INLINE_SIMPLE_STRUCTS =
# INLINE_SOURCES =
INPUT = src/ README.md doc/API.md
# INPUT_ENCODING =
# INTERACTIVE_SVG =
# INTERNAL_DOCS =
# JAVADOC_AUTOBRIEF =
# LAYOUT_FILE =
# MACRO_EXPANSION =
# MARKDOWN_SUPPORT =
# MAX_DOT_GRAPH_DEPTH =
# MSCFILE_DIRS =
# MULTILINE_CPP_IS_BRIEF =
# OPTIMIZE_FOR_FORTRAN =
# OPTIMIZE_OUTPUT_FOR_C =
# OPTIMIZE_OUTPUT_JAVA =
# OPTIMIZE_OUTPUT_VHDL =
# OUTPUT_LANGUAGE =
# PLANTUML_JAR_PATH =
# PREDEFINED =
# PROJECT_BRIEF =
# PROJECT_LOGO =
# PROJECT_NAME =
# PROJECT_NUMBER =
# QT_AUTOBRIEF =
# RECURSIVE =
# REFERENCED_BY_RELATION =
# REFERENCES_LINK_SOURCE =
# REFERENCES_RELATION =
# REPEAT_BRIEF =
# SEARCHENGINE =
# SEARCH_INCLUDES =
# SEPARATE_MEMBER_PAGES =
# SHORT_NAMES =
# SHOW_FILES =
# SHOW_GROUPED_MEMB_INC =
# SHOW_INCLUDE_FILES =
# SHOW_NAMESPACES =
# SHOW_USED_FILES =
# SIP_SUPPORT =
# SKIP_FUNCTION_MACROS =
# SORT_BRIEF_DOCS =
# SORT_BY_SCOPE_NAME =
# SORT_GROUP_NAMES =
# SORT_MEMBERS_CTORS_1ST =
# SORT_MEMBER_DOCS =
# SOURCE_BROWSER =
# SOURCE_TOOLTIPS =
# STRICT_PROTO_MATCHING =
# STRIP_CODE_COMMENTS =
# STRIP_FROM_INC_PATH =
# STRIP_FROM_PATH =
# SUBGROUPING =
# TAB_SIZE =
# TEMPLATE_RELATIONS =
# TREEVIEW_WIDTH =
# TYPEDEF_HIDES_STRUCT =
# UML_LIMIT_NUM_FIELDS =
# UML_LOOK =
USE_MDFILE_AS_MAINPAGE = README.md
# VERBATIM_HEADERS =
#
+90
View File
@@ -0,0 +1,90 @@
Contributing to the Project
===========================
Thank you for considering contributing back to [Free Software][1]!
There are a few things we would like you to consider when filing an
issue or pull request with this project:
1. If you are filing a bug report or feature request
Please take the time to check if an issue already has been filed
matching your problem
2. What version are you running, have you tried the latest release?
UNIX distributions often package and test software for their
particular brand. If you are using a pre-packaged version,
then please file a bug with that distribution instead.
3. Coding Style
Lines are allowed to be longer than 72 characters these days, there
is no enforced max. length.
> **Tip:** Always submit code that follows the style of surrounding code!
The coding style itself is strictly Linux [KNF][], like GIT it is
becoming a de facto standard for C programming
https://www.kernel.org/doc/Documentation/CodingStyle
4. Logical Change Sets
Changes should be broken down into logical units that add a feature
or fix a bug. Keep changes separate from each other and do not mix a
bug fix with a whitespace cleanup or a new feature addition.
This is important not only for readability, or for the possibility of
maintainers to revert changes, but does also increase your chances of
having a change accepted.
5. Commit messages
Commit messages exist to track *why* a change was made. Try to be as
clear and concise as possible in your commit messages, and always, be
proud of your work and set up a proper GIT identity for your commits:
git config --global user.name "J. Random Hacker"
git config --global user.email random.j.hacker@example.com
See this helpful guide for how to write simple, readable commit
messages, or have at least a look at the below example.
http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
Example
-------
Example commit message from the [Pro Git][gitbook] online book, notice
how `git commit -s` is used to automatically add a `Signed-off-by`:
Capitalized, short (50 chars or less) summary
More detailed explanatory text, if necessary. Wrap it to about 72
characters or so. In some contexts, the first line is treated as the
subject of an email and the rest of the text as the body. The blank
line separating the summary from the body is critical (unless you omit
the body entirely); tools like rebase can get confused if you run the
two together.
Write your commit message in the imperative: "Fix bug" and not "Fixed bug"
or "Fixes bug." This convention matches up with commit messages generated
by commands like git merge and git revert.
Further paragraphs come after blank lines.
- Bullet points are okay, too
- Typically a hyphen or asterisk is used for the bullet, followed by a
single space, with blank lines in between, but conventions vary here
- Use a hanging indent
Signed-off-by: J. Random Hacker <random.j.hacker@example.com>
[1]: http://www.gnu.org/philosophy/free-sw.en.html
[KNF]: https://en.wikipedia.org/wiki/Kernel_Normal_Form
[gitbook]: https://git-scm.com/book/ch5-2.html
+3
View File
@@ -0,0 +1,3 @@
# These are supported funding model platforms
github: [troglobit]
+71
View File
@@ -0,0 +1,71 @@
name: Bob the Builder
# Run on all branches, including all pull requests, except the 'dev'
# branch since that's where we run Coverity Scan (limited tokens/day)
on:
push:
branches:
- '**'
- '!dev'
pull_request:
branches:
- '**'
jobs:
build:
# Verify we can build on latest Ubuntu with both gcc and clang
name: ${{ matrix.compiler }}
runs-on: ubuntu-latest
strategy:
matrix:
compiler: [gcc, clang]
fail-fast: false
env:
MAKEFLAGS: -j3
CC: ${{ matrix.compiler }}
steps:
- name: Install dependencies
run: |
sudo apt-get -y update
sudo apt-get -y install tree doxygen
- uses: actions/checkout@v2
- name: Configure
run: |
./autogen.sh
./configure --prefix= --disable-silent-rules
- name: Build
run: |
make
- name: Install to ~/tmp and Inspect
run: |
DESTDIR=~/tmp make install-strip
tree ~/tmp
- name: Run Unit Tests
run: |
make check || (cat test/test-suite.log; false)
- name: Upload Test Results
uses: actions/upload-artifact@v2
with:
name: libite-test-${{ matrix.compiler }}
path: test/*
debian:
name: Verify Debian Package
runs-on: ubuntu-latest
container: debian:stable
env:
MAKEFLAGS: -j3
steps:
- uses: actions/checkout@v2
- name: Installing dependencies
run: |
apt-get update
apt-get install -y build-essential autoconf automake pkg-config doxygen \
dpkg-dev debhelper devscripts
- name: Building Debian package
run: |
./autogen.sh
./configure
make check || (cat test/test-suite.log; false)
make distcheck
make package
cat ../*.changes
+82
View File
@@ -0,0 +1,82 @@
name: Coverity Scan
on:
push:
branches:
- 'dev'
env:
PROJECT_NAME: libite
CONTACT_EMAIL: troglobit@gmail.com
COVERITY_NAME: troglobit-libite
COVERITY_PROJ: troglobit%2Flibite
jobs:
coverity:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Fetch latest Coverity Scan MD5
id: var
env:
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
run: |
wget -q https://scan.coverity.com/download/cxx/linux64 \
--post-data "token=$TOKEN&project=${COVERITY_PROJ}&md5=1" \
-O coverity-latest.tar.gz.md5
export MD5=$(cat coverity-latest.tar.gz.md5)
echo "Got MD5 $MD5"
echo ::set-output name=md5::${MD5}
- uses: actions/cache@v2
id: cache
with:
path: coverity-latest.tar.gz
key: ${{ runner.os }}-coverity-${{ steps.var.outputs.md5 }}
restore-keys: |
${{ runner.os }}-coverity-${{ steps.var.outputs.md5 }}
${{ runner.os }}-coverity-
${{ runner.os }}-coverity
- name: Download Coverity Scan
env:
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
run: |
if [ ! -f coverity-latest.tar.gz ]; then
wget -q https://scan.coverity.com/download/cxx/linux64 \
--post-data "token=$TOKEN&project=${COVERITY_PROJ}" \
-O coverity-latest.tar.gz
else
echo "Latest Coverity Scan available from cache :-)"
md5sum coverity-latest.tar.gz
fi
mkdir coverity
tar xzf coverity-latest.tar.gz --strip 1 -C coverity
- name: Install dependencies
run: |
sudo apt-get -y update
sudo apt-get -y install pkg-config
- name: Configure
run: |
./autogen.sh
./configure --prefix= --disable-silent-rules
- name: Build
run: |
export PATH=`pwd`/coverity/bin:$PATH
cov-build --dir cov-int make
- name: Submit results to Coverity Scan
env:
TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
run: |
tar czvf ${PROJECT_NAME}.tgz cov-int
curl \
--form project=${COVERITY_NAME} \
--form token=$TOKEN \
--form email=${CONTACT_EMAIL} \
--form file=@${PROJECT_NAME}.tgz \
--form version=trunk \
--form description="${PROJECT_NAME} $(git rev-parse HEAD)" \
https://scan.coverity.com/builds?project=${COVERITY_PROJ}
- name: Upload build.log
uses: actions/upload-artifact@v2
with:
name: coverity-build.log
path: cov-int/build-log.txt
+62
View File
@@ -0,0 +1,62 @@
name: Release General
on:
push:
tags:
- 'v*'
jobs:
release:
name: Create GitHub release
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')
outputs:
upload_url: ${{ steps.create_release.outputs.upload_url }}
release_id: ${{ steps.create_release.outputs.id }}
steps:
- uses: actions/checkout@v2
- name: Extract ChangeLog entry ...
# Hack to extract latest entry for body_path below
run: |
awk '/-----*/{if (x == 1) exit; x=1;next}x' ChangeLog.md \
|head -n -1 > release.md
cat release.md
- name: Create release ...
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: Libite (-lite) ${{ github.ref }}
body_path: release.md
draft: false
prerelease: false
tarball:
name: Build and upload release tarball
needs: release
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Installing dependencies ...
run: |
sudo apt-get -y update
sudo apt-get -y install tree doxygen
- name: Creating Makefiles ...
run: |
./autogen.sh
./configure
- name: Build release ...
run: |
make release || (cat test/test-suite.log; false)
ls -lF ../
mkdir -p artifacts/
mv ../*.tar.* artifacts/
- name: Upload release artifacts ...
uses: skx/github-action-publish-binaries@release-0.15
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
releaseId: ${{ needs.release.outputs.release_id }}
args: artifacts/*
+21
View File
@@ -0,0 +1,21 @@
*~
ID
GPATH
GRTAGS
GTAGS
compile
config.*
configure
depcomp
install-sh
libtool
ltmain.sh
missing
stamp-h1
Makefile
Makefile.in
aclocal.m4
ar-lib
autom4te.cache
test-driver
libite.pc
+506
View File
@@ -0,0 +1,506 @@
Change Log
==========
All notable changes to the project are documented in this file.
[v2.5.1][] - 2021-12-02
-----------------------
Debian-only fix.
### Fixes
- Use `dh_link(1)` to install `/usr/include/lite -> libite/`. The
symlink created by libite installer itself is not kept.
[v2.5.0][] - 2021-11-30
-----------------------
> **Note:** namespace change; the -lite library include files have moved
> from `lite/*.h` to `libite/*.h` due to an unfortunate clash
> with "LiTE is a Toobox Engine", from the DirectFB project.
> For a transitional period, however, a compatibility symlink
> is installed; `lite -> libite/`.
### Changes
- Header files have moved from `lite/*.h` to `libite/*.h` to prevent
clashing with DirectFB LiTE library.
- Include guards in header files have been renamed, much in the same
fashion as the move (above), from `LITE_foo_H_` to `LIBITE_FOO_H_`
- Add configure option to disable compatibility symlink, for systems
that do not want name clashes with DirectFB/LiTE, or do not need to
be backwards compatible; use `configure --without-symlink`
### Fixes
- Minor, use defensive coding in `strnlen()` replacement. Only used
on systems that do not have a native implementation.
[v2.4.1][] - 2021-10-09
-----------------------
### Changes
- Add doxygen API documentation to project, included in tarball, and
automatically generated at https://codedocs.xyz/troglobit/libite/
- Relocate `tests/` to `test/` in source tree
- Relocate `docs/` to `doc/` in source tree
### Fixes
- Prefix CFLAGS/CPPFLAGS/etc with `AM_` in `test/Makefile.am` to prevent
clashing with environment. Fix imported from libuEv
- Replace obsolete `AM_CONFIG_HEADER` with `AC_CONFIG_HEADERS`
- Fix issue with `tempfile()` returning EOPNOTSUPP on Azure, use
fallback to `mkostemp()` with `O_CLOEXEC` flag set
[v2.4.0][] - 2021-03-27
-----------------------
### Changes
- Add support for `touchf()`, formatted string support for `touch()`
- Add support for `erasef()`, formatted string support for `erase()`
- Add support for `strtrim()`, trims leading and trailing white-space
from a string
### Fixes
- Fix `systemf()` improper handling of `system()` return value. Now
checks if exited OK, then returning the exit status of the command, or
if not exited OK, then checks if the command was signaled, and returns
-1 with `errno` set. This also allows for returning 127, like
`system()`, if the shell, or the program itself, did not exist
[v2.3.1][] - 2021-02-12
-----------------------
### Changes
- Copyright updates, including LICENSE file, year + author last name
### Fixes
- Debian packaging fixes only
[v2.3.0][] - 2021-02-12
-----------------------
### Changes
- Add support for `fremove()`, formatted `remove()` replacement
- Add support for `truncatef()`, formatted `truncate()` replacement
- Add tar.gz archives to distribution
### Fixes
- Handle `ETIMEDOUT` error for `connect()` call in `telnet_open()`
[v2.2.0][] - 2020-03-16
-----------------------
### Changes
- Add support for `systemf()`, formatted string `system()` replacement
- Add support for `fmkpath()`, formatted string `mkpath()`
- Add support for `fopenf()`, formatted string `fopen()` replacement
### Fixes
- Fix possible memory leak in `rsync()`, found by Coverity Scan
- Check return value of `fstat()` to prevent bogus destination file
times when using `copyfile()`, found by Coverity Scan
[v2.1.2][] - 2020-02-22
-----------------------
### Fixes
- Fix Debian package upgrade from libite -> libite5
[v2.1.1][] - 2020-02-22
-----------------------
### Changes
- Add test/example for `printhdr()`
- Update copyright years
### Fixes
- chomp: Check for beginning of string while removing \n's
[v2.1.0][] - 2019-08-26
-----------------------
### Changes
- Add support for `strmatch()` and `strnmatch()`
- Add support for `yorn()`, safe yes-or-no prompt
- Add support for telnet expect/session APIs
- Add modified `printhdr()` which takes ANSI attribute
### Fixes
- Fix `pidfile_signal()`: always return result of `kill()`, or the
result of `remove()` if we successfully sent `SIGKILL`
- Fix `strtonum()`: POSIX `strtoll()` returns `EINVAL`, check that
- Fix #13, support C++ `extern "C" {}` for header files
[v2.0.2][] - 2018-05-10
-----------------------
### Fixes
- Fix issue #12, missing includes in `strlite.h` for standalone use
- FTBFS `strtonum.c` on older systems w/o `LLONG_MAX` and `LLONG_MIN`
[v2.0.1][] - 2017-12-22
-----------------------
### Changes
- Add missing `initscr()` declaration, regression in [v2.0.0][]
- Add `#ifdef` guards around `min()` and `max()` macros
- Add `const` to `char *` args in multiple API:s:
- `fexist()`
- `fgetint()`
- `fisslashdir()`
- `copyfile()`
- `movefile()`
- `ifconfig()`
- `lfopen()`
- `lfgetkey()`
- `lfgetint()`
### Fixes
- Fix #9, uncommon location of `which` command in unit test
- Fix #10, supply unit test with a default `$PATH`
- Fix #11, `touch()` command cannot handle relative paths when updating
the mtime of an existing file
[v2.0.0][] - 2017-11-22
-----------------------
### Changes
- Remove `tree()`, moved to toolbox.git instead
- Remove `fmode()`, please use `stat()` instead, it's safer
- Add support for keeping mtime in `copy()` and `rsync()`
- Move source files to an `src/` sub-directory
- Move `initscr()` from `conio.h` to `conio.c`
- Update docs, recommend `mkpath()` over `makepath()`
- Bump ABI version, major changes to library
### Fixes
- Fix #7, inconsistent return value in `mkpath()` and `makepath()`
- Fix #8, constify `mkpath()` and `makepath()`
[v1.9.3][] - 2017-10-24
-----------------------
### Changes
- `initscr()`, use stdout, not stderr, like the rest of the
`conio.h` macros. Also, stderr may be redirected by user
- `tree()`, update unit test, use standard directries
### Fixes
- `initscr()`, verify that both stdin and stdout are real TTYs
before messing up output or blocking on input for the user
- `tree()`, increase internal buffer slightly, output may be
truncated otherwise. Found by GCC 7.2
[v1.9.2][] - 2017-07-09
-----------------------
### Changes
- Add `initscr()` function to query screen size
- Convert `printheader()` to a static inline function
[v1.9.1][] - 2017-07-03
-----------------------
### Changes
- Add missing `whichp()` predicate function to accompany `which()`
- Allow `which("ps aux")`, which skips any arguments to command
[v1.9.0][] - 2017-07-02
-----------------------
### Changes
- Add `which()`, a C implementation of UNIX which(1)
- Add `printheader()`, prints a top-like table heading for client tools
- Remove `UNUSED()` macro, recommended to disable GCC warning instead
### Fixes
- Fix issue #6: `touch()` does not update mtime if file exists
- Fix non-writable `tempfile()`, now with proper unit test
[v1.8.3][] - 2017-01-08
-----------------------
### Changes
- Support absolute path in `pidfile()`. Needed by, e.g. Inadyn
- Add initial `debian/` packaging
- Update README with note on remembering to set `umask()`
### Fixes
- In use-cases when `pidfile()` is called consecutively, e.g. on
`SIGHUP`, recreate PID file if it no longer exists
[v1.8.2][] - 2016-09-05
-----------------------
### Changes
- Updated build instructions in README.
- Converted `touch()`, `makedir()`, `makefifo()`, and `erase()` from
macros to inline functions. Also removed implicit logging to stderr
on error.
### Fixes
- Fix small memory leak in `pidfile()` ... at exit.
- Fixes for building on musl libc
[v1.8.1][] - 2016-06-25
-----------------------
### Fixes
- `fparseln()`, portability fix for NetBSD
- `pidfile()`, portability fix for NetBSD and OpenBSD
[v1.8.0][] - 2016-06-06
-----------------------
### Changes
- Change return type of `fsendfile()` from `size_t` to `ssize_t`
- Change `dir()` semantics: do not assert and always return error
without calling `perror()` or similar.
- The OpenBSD `pidfile()` function's prefix path `_PATH_VARRUN`
can now be overridden by setting the hidden `__pidfile_path`
variable. E.g., to `_PATH_TMP`. Make sure read the docs!
- Add new unit test framework `make check`.
### Fixes
- Fix bad path in new `strndupa()` header file.
- Add missing progress bar API's to `lite.h`
[v1.7.0][] - 2016-06-05
-----------------------
### Changes
- Add support for GNU `strdupa()`, for [Inadyn][] on NetBSD.
- Add support for GNU `strndupa()` and `strnlen()`
### Fixes
- Fix `mkpath()` to handle creating relative directories.
[v1.6.0][] - 2016-05-13
-----------------------
### Changes
- Add support for NetBSD `fparaseln()` for the benefit of [Mg][]
- Add support for OpenBSD `reallocarray()` for the benefit of [Mg][]
- Constify `fisdir()` argument
[v1.5.1][] - 2016-04-17
-----------------------
Minor fix release.
### Changes
- Update README.md, add help when libite is used in autotools projects.
Spell checking and minor cleanup.
### Fixes
- Activate use of `utimensat()` when `pidfile()` is called multiple
times. This reduces the overhead of calling open+write+close to
simply updating the mtime of the PID file.
- Westermo fixes for `fcopyfile()`: nothing copied on embedded PPC
system when using `tmpfile()` as source.
[v1.5.0][] - 2016-03-20
-----------------------
This release changes the header file namespace. Apologies for any
problems this may cause!
### Changes
- Change namespace for header files: `libite/` to `lite/`, e.g. using
`pkg-config` your C program must now `#include <lite/lite.h>`
- Update `pidfile()` to use `utimensat()` to update atime+mtime instead
of opening and writing PID again. Less overhead and nanonsecond res.
[v1.4.4][] - 2016-02-23
-----------------------
### Changes
- Add `ibite.pc.in` for `pkg-config` support.
### Fixes
- Fix issue #3: `tempfile()` fails with bad `O_TMPFILE` on some embedded
targets, in particular PowerPC. On systems with older GLIBC but with
a sufficiently new kernel `O_TMPFILE` is missing and the local libite
definition was wrong, hard coded for x86. Fixed by Johan Askerin.
[v1.4.3][] - 2016-02-02
-----------------------
### Fixes
- Remove symlinks to Markdown files from GIT
- Distribute and install Markdown files: README.md, etc.
[v1.4.2][] - 2016-01-23
-----------------------
### Fixes
- Fix issue #2: GCC6 `-Wmisleading-indentation` causing FTBFS in pimd,
which enables `-Werror`
[v1.4.1][] - 2016-01-22
-----------------------
### Fixes
- Fix install path for include files, regression in v1.4.0 With the
introduction of GNU autotools include file namespace was unfortunately
lost. All include files were therefore installed in $(prefix)/include
instead of $(prefix)/include/libite.
[v1.4.0][] - 2016-01-22
-----------------------
### Changes
- Change to GNU configure and build system
- Add Niels Provos' splay and red-black tree implementation from OpenBSD
`sys/tree.h`, r1.14
- Make `pidfile()` file name accessible as `__pidfile_name`
- Step ABI revision to 2.1, with help from http://250bpm.com/blog:41
[v1.3.0][] - 2016-01-07
-----------------------
### Changes
- Add highly useful typeless `min()`/`max()` macros to `lite.h`,
courtesy of Tobias Waldekranz
- Add BSD `queue.h` and Borland inspired `conio.h` to `install-dev`
target. Needed by [Finit][].
- Note, this release update `queue.h` to OpenBSD v1.43, which removes
support for circular queues (CIRCLEQ).
- Update `strlcpy.c` to OpenBSD v1.12, readability fixes.
- Update `strlcat.c` to OpenBSD v1.14, readability fixes.
- Update `strtonum.c` to OpenBSD v1.7, tiniest of style tweaks.
### Fixes
- Only update mtime if `pidfile()` is called more than once, do not
install multiple `atexit()` handlers.
- Add `#ifndef pidfile`, as for other BSD functions, in case the user
already have a local copy, or a C library with one.
[v1.2.0][] - 2015-11-23
-----------------------
### Changes
- Add simple parser for UNIX configuration files, e.g. `/etc/group`,
`/etc/passwd`, and `/etc/protocols`:
- `lfopen()`
- `lfclose()`
- `lftok()`
- `lfgetkey()`
- `lfgetint()`
- `fgetint()`
### Fixes
- Do not allow `VERSION` to be overloaded by build system.
- Make sure we don't inherit `LDFLAGS` from environment.
[v1.1.1][] - 2015-09-27
-----------------------
### Fixes
* Silence annoying warnings from GNU ar
* Fix macro definitions for compat APIs
[v1.1.0][] - 2015-09-16
-----------------------
### Changes
- Support for `make distdir` used by automake based projects
- `lite.h` move from `error.h` to more BSD friendly `err.h`
- Add highly useful `NELEMS()` and bitmanip macros
- Lots of autotests added
- Add support for running autotests from Travis
- Add `progress()` simple progress bar
- Add `tree()` simple command line tree replacement
- Bump `SONAME` to `libite.so.2` on behalf of [Finit][]
### Fixes
- `pidfile()` upgrade to OpenBSD r1.11
- Lots of README updates, fixes and additions
[v1.0.0][] - 2015-07-12
-----------------------
Initial extraction of frog DNA from [Finit][]. See [README][] for API details.
[UNRELEASED]: https://github.com/troglobit/libite/compare/v2.5.1...HEAD
[v2.5.1]: https://github.com/troglobit/libite/compare/v2.5.0...v2.5.1
[v2.5.0]: https://github.com/troglobit/libite/compare/v2.4.1...v2.5.0
[v2.4.1]: https://github.com/troglobit/libite/compare/v2.4.0...v2.4.1
[v2.4.0]: https://github.com/troglobit/libite/compare/v2.3.1...v2.4.0
[v2.3.1]: https://github.com/troglobit/libite/compare/v2.3.0...v2.3.1
[v2.3.0]: https://github.com/troglobit/libite/compare/v2.2.1...v2.3.0
[v2.2.1]: https://github.com/troglobit/libite/compare/v2.2.0...v2.2.1
[v2.2.0]: https://github.com/troglobit/libite/compare/v2.1.2...v2.2.0
[v2.1.2]: https://github.com/troglobit/libite/compare/v2.1.1...v2.1.2
[v2.1.1]: https://github.com/troglobit/libite/compare/v2.1.0...v2.1.1
[v2.1.0]: https://github.com/troglobit/libite/compare/v2.0.2...v2.1.0
[v2.0.2]: https://github.com/troglobit/libite/compare/v2.0.1...v2.0.2
[v2.0.1]: https://github.com/troglobit/libite/compare/v2.0.0...v2.0.1
[v2.0.0]: https://github.com/troglobit/libite/compare/v1.9.3...v2.0.0
[v1.9.3]: https://github.com/troglobit/libite/compare/v1.9.2...v1.9.3
[v1.9.2]: https://github.com/troglobit/libite/compare/v1.9.1...v1.9.2
[v1.9.1]: https://github.com/troglobit/libite/compare/v1.9.0...v1.9.1
[v1.9.0]: https://github.com/troglobit/libite/compare/v1.8.3...v1.9.0
[v1.8.3]: https://github.com/troglobit/libite/compare/v1.8.2...v1.8.3
[v1.8.2]: https://github.com/troglobit/libite/compare/v1.8.1...v1.8.2
[v1.8.1]: https://github.com/troglobit/libite/compare/v1.8.0...v1.8.1
[v1.8.0]: https://github.com/troglobit/libite/compare/v1.7.0...v1.8.0
[v1.7.0]: https://github.com/troglobit/libite/compare/v1.6.0...v1.7.0
[v1.6.0]: https://github.com/troglobit/libite/compare/v1.5.1...v1.6.0
[v1.5.1]: https://github.com/troglobit/libite/compare/v1.5.0...v1.5.1
[v1.5.0]: https://github.com/troglobit/libite/compare/v1.4.4...v1.5.0
[v1.4.4]: https://github.com/troglobit/libite/compare/v1.4.3...v1.4.4
[v1.4.3]: https://github.com/troglobit/libite/compare/v1.4.2...v1.4.3
[v1.4.2]: https://github.com/troglobit/libite/compare/v1.4.1...v1.4.2
[v1.4.1]: https://github.com/troglobit/libite/compare/v1.4.0...v1.4.1
[v1.4.0]: https://github.com/troglobit/libite/compare/v1.3.0...v1.4.0
[v1.3.0]: https://github.com/troglobit/libite/compare/v1.2.0...v1.3.0
[v1.2.0]: https://github.com/troglobit/libite/compare/v1.1.1...v1.2.0
[v1.1.1]: https://github.com/troglobit/libite/compare/v1.1.0...v1.1.1
[v1.1.0]: https://github.com/troglobit/libite/compare/v1.0.0...v1.1.0
[v1.0.0]: https://github.com/troglobit/libite/compare/TAIL...v1.0.0
[Finit]: https://github.com/troglobit/finit/
[Inadyn]: https://github.com/troglobit/inadyn/
[Mg]: https://github.com/troglobit/mg
[README]: https://github.com/troglobit/libite/blob/v1.0.0/README.md
+20
View File
@@ -0,0 +1,20 @@
Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
Copyright (c) 2008-2021 Joachim Wiberg <troglobit@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-79
View File
@@ -1,79 +0,0 @@
# Finit libite -- Light-weight utility functions and C-library extensions
#
# Copyright (c) 2008-2012 Joachim Nilsson <troglobit@gmail.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
.EXPORT_ALL_VARIABLES:
.PHONY: all install clean
include ../common.mk
CFLAGS += -fPIC
HEADERS = lite.h
OBJS := copyfile.o dir.o fexist.o fisdir.o fmode.o rsync.o
DEPS := $(addprefix ., $(OBJS:.o=.d))
VER = 0
LIBNAME = libite
TARGET = $(LIBNAME).so
VERLIB = $(TARGET).$(VER)
STATICLIB = $(LIBNAME).a
CHECK_FLAGS = $(CFLAGS) $(CPPFLAGS)
all: $(TARGET)
$(OBJS): Makefile
$(TARGET): $(OBJS)
@printf " LINK %s\n" $@
# @$(AR) $(ARFLAGS) $(STATICLIB) $(OBJS)
@$(CC) $(LDFLAGS) -shared $(OBJS) -lrt -lcrypt -Wl,-soname,$@ -o $@
@ln -sf $@ $(VERLIB)
install-exec: all
@install -d $(DESTDIR)$(libdir)
@echo " INSTALL $(DESTDIR)$(libdir)/$(TARGET)"
@$(STRIPINST) $(TARGET) $(DESTDIR)$(libdir)/$(TARGET)
@ln -sf $(TARGET) $(DESTDIR)$(libdir)/$(VERLIB)
install-dev:
@for file in $(HEADERS); do \
printf " INSTALL $(DESTDIR)$(incdir)/$$file\n"; \
$(INSTALL) -m 0644 $$file $(DESTDIR)$(incdir)/$$file; \
done
install: install-dev install-exec
uninstall:
-@$(RM) $(DESTDIR)$(libdir)/$(VERLIB)
-@$(RM) $(DESTDIR)$(libdir)/$(TARGET)
clean: uninstall
-@$(RM) $(OBJS) $(DEPS) $(TARGET) $(VERLIB) $(STATICLIB)
distclean: clean
-@$(RM) $(JUNK) unittest *.o .*.d *.unittest
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),distclean)
-include $(DEPS)
endif
endif
+58
View File
@@ -0,0 +1,58 @@
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src test
doc_DATA = README.md LICENSE ChangeLog.md
EXTRA_DIST = README.md LICENSE ChangeLog.md
if ENABLE_DOXYGEN
SUBDIRS += doc
.PHONY: doc
doc:
$(MAKE) -C @top_builddir@/doc $@
## The distribution should include man pages, which are generated
dist-hook: doc
else
doc:
@echo "Doxygen documentation (html + man) disabled, skipping ..."
endif
## Check if tagged in git
release-hook:
@if [ ! `git tag -l v$(PACKAGE_VERSION) | grep $(PACKAGE_VERSION)` ]; then \
echo; \
printf "\e[1m\e[41mCannot find release tag $(PACKAGE_VERSION)\e[0m\n"; \
printf "\e[1m\e[5mDo release anyway?\e[0m "; read yorn; \
if [ "$$yorn" != "y" -a "$$yorn" != "Y" ]; then \
printf "OK, aborting release.\n"; \
exit 1; \
fi; \
echo; \
else \
echo; \
printf "\e[1m\e[42mFound GIT release tag $(PACKAGE_VERSION)\e[0m\n"; \
printf "\e[1m\e[44m>>Remember to push tags!\e[0m\n"; \
echo; \
fi
## Generate .deb package
package:
@debuild -uc -us -B --lintian-opts --profile debian -i -I --show-overrides
## Target to run when building a release
release: release-hook distcheck
@for file in $(DIST_ARCHIVES); do \
md5sum $$file > ../$$file.md5; \
sha256sum $$file > ../$$file.sha256; \
done
@mv $(DIST_ARCHIVES) ../
@echo
@echo "Resulting release files:"
@echo "================================================================="
@for file in $(DIST_ARCHIVES); do \
printf "%-32s Distribution tarball\n" $$file; \
printf "%-32s " $$file.md5; cat ../$$file.md5 | cut -f1 -d' '; \
printf "%-32s " $$file.sha256; cat ../$$file.sha256 | cut -f1 -d' '; \
done
@for file in `cd ..; ls $(PACKAGE)*_$(VERSION)*`; do \
printf "%-32s Debian/Ubuntu package\n" $$file; \
done
+149
View File
@@ -0,0 +1,149 @@
-lite | Frog DNA, basically
===========================
[![GitHub Status][]][GitHub] [![codedocs status][]][codedocs] [![Coverity Status][]][Coverity Scan]
Table of Contents
-----------------
* [Introduction](#introduction)
* [Using -lite](#using--lite)
* [API](doc/API.md#overview)
* [Important Node](doc/API.md#important-note)
* [Helper Macros](doc/API.md#helper-macros)
* [Generic Functions](doc/API.md#generic-functions)
* [GNU Functions](doc/API.md#gnu-functions)
* [OpenBSD/NetBSD/FreeBSD Functions](doc/API.md#openbsd-netbsd-freebsd-functions)
* [Build & Install](#build--install)
* [Origin & References](#origin--references)
> **NOTE:** Incompatible changes in v2.0 compared to v1.x!
Introduction
------------
Libite is a lightweight library of *frog DNA* that can be used to fill
the gaps in any dinosaur project. It holds useful functions and macros
developed by both [Finit][1] and the [OpenBSD][2] project. Most notably
the string functions: [strlcpy(3)][3], [strlcat(3)][3] and the highly
useful *BSD [sys/queue.h][4] and [sys/tree.h][7] API's.
Libite holds many of the missing pieces in GNU libc, although -lite does
not aim to become another [GLIB][5]. One noticeable gap in GLIBC is the
`_SAFE` macros available in the BSD `sys/queue.h` API &mdash; highly
recommended when traversing lists to delete/free nodes.
The code is open sourced under a mix of permissive Open Source licenses:
[MIT/X11 license][MIT], [ISC license][ISC], and [BSD licenses][BSD].
> **Tip:** have a look at my blog post about other useful UNIX API's!
> https://troglobit.com/post/2020-02-22-useful-unix-apis/
Using -lite
-----------
Libite is by default installed as a library and a set of include files.
To prevent clashing with include files of the same name `-lite` employs
an include file namespace `libite/`, which is strongly recommended to
use in your applications:
```C
#include <libite/lite.h>
#include <libite/conio.h>
#include <libite/queue.h>
#include <libite/tree.h>
```
> **Note:** prior to v2.5.0, the `lite/` namespace was used for headers,
> which is still available in the default install. This clashed with
> the headers of the LiTE library from the DirectFB project.
The output from the `pkg-config` tool holds no surprises:
```bash
$ pkg-config --libs --static --cflags libite
-I/usr/local/include -D_LIBITE_LITE -L/usr/local/lib -lite
```
> **Note:** `_LIBITE_LITE` is defined since v2.5.0, useful for software
> that want to be able to build against headers from an older libite:
>
> ```C
> #ifdef _LIBITE_LITE
> # include <libite/lite.h>
> #else
> # include <lite/lite.h>
> #endif
> ```
The prefix path `/usr/local/` shown here is only the default. Use the
`configure` script to select a different prefix when installing libite.
For GNU autotools based projects, use the following in `configure.ac`:
```m4
# Check for required libraries
PKG_CHECK_MODULES([lite], [libite >= 1.5.0])
```
and in your `Makefile.am`:
```Makefile
proggy_CFLAGS = $(lite_CFLAGS)
proggy_LDADD = $(lite_LIBS)
```
> API Documentaion: https://codedocs.xyz/troglobit/libite/
Build & Install
---------------
This library was initially built for and developed on GNU/Linux systems
as a light weight utility library, these days NetBSD should also work.
```bash
$ ./configure
$ make -j5
$ sudo make install-strip
$ sudo ldconfig
```
Use <kbd>./configure --without-symlink</kbd> to prevent the install step
from creating the `lite -> libite/` compatibility symlink for the header
files, required for systems with DirectFB LiTE. The default, however,
is to install the symlink to ensure compatibility with existing software
that depends on the `-lite` library headers in their previous namespace.
**Note:** When checking out code from GIT, use <kbd>./autogen.sh</kbd>
to generate a `configure` script. It is a generated file and otherwise
only included in released tarballs.
Origin & References
-------------------
Much of the code in libite (-lite) is written by [Claudio Matsuoka][]
for the original [Finit][original finit] and released under the MIT/X11
license. Joachim Wiberg later improved on the [Finit][1] code base and
included pieces of software released under the ISC and BSD licenses.
See each respective file for license details.
[1]: https://github.com/troglobit/finit
[2]: http://www.openbsd.org/
[3]: http://www.openbsd.org/cgi-bin/man.cgi?query=strlcpy
[4]: http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man3/LIST_EMPTY.3
[5]: https://developer.gnome.org/glib/
[7]: http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man3/SPLAY_FOREACH.3
[MIT]: https://en.wikipedia.org/wiki/MIT_License
[ISC]: https://en.wikipedia.org/wiki/ISC_license
[BSD]: https://en.wikipedia.org/wiki/BSD_licenses
[GitHub]: https://github.com/troglobit/libite/actions/workflows/build.yml/
[GitHub Status]: https://github.com/troglobit/libite/actions/workflows/build.yml/badge.svg
[Coverity Scan]: https://scan.coverity.com/projects/20602
[Coverity Status]: https://img.shields.io/coverity/scan/20602.svg
[codedocs]: https://codedocs.xyz/troglobit/libite.log
[codedocs status]: https://codedocs.xyz/troglobit/libite.svg
[Claudio Matsuoka]: https://github.com/cmatsuoka
[original finit]: http://helllabs.org/finit/
Executable
+3
View File
@@ -0,0 +1,3 @@
#!/bin/sh
autoreconf -W portability -visfm
+39
View File
@@ -0,0 +1,39 @@
AC_INIT(libite, 2.5.1, https://github.com/troglobit/libite/issues)
AC_CONFIG_AUX_DIR(aux)
AM_INIT_AUTOMAKE([1.11 foreign dist-xz])
AM_SILENT_RULES([yes])
AC_CONFIG_SRCDIR(src/lite.h)
AC_CONFIG_HEADERS(config.h)
AC_CONFIG_FILES([Makefile doc/Makefile doc/Doxyfile src/Makefile src/libite.pc test/Makefile])
AC_CONFIG_MACRO_DIR([m4])
AC_PROG_CC
AC_PROG_INSTALL
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
LT_INIT
# Check for Doxygen and enable its features.
# For details, see m4/ax_prog_doxygen.m4 and
# http://www.bioinf.uni-freiburg.de/~mmann/HowTo/automake.html#doxygenSupport
DX_DOXYGEN_FEATURE(ON)
DX_DOT_FEATURE(OFF)
DX_CHI_FEATURE(OFF)
DX_RTF_FEATURE(OFF)
DX_XML_FEATURE(OFF)
DX_PDF_FEATURE(OFF)
DX_PS_FEATURE(OFF)
DX_CHM_FEATURE(OFF)
DX_HTML_FEATURE(ON)
DX_MAN_FEATURE(OFF)
DX_INIT_DOXYGEN(${PACKAGE_NAME}, [${top_builddir}/doc/Doxyfile], [${top_builddir}/doc])
AC_ARG_WITH([symlink],
AS_HELP_STRING([--without-symlink], [Disable compat /usr/include/lite -> libite symlink]),,
[with_symlink=yes])
AM_CONDITIONAL([ENABLE_DOXYGEN], [test "x${DX_FLAG_doc}" = x1])
AM_CONDITIONAL([ENABLE_HTML], [test "x${DX_FLAG_html}" = x1])
AM_CONDITIONAL([COMPAT_SYMLINK], [test "x$with_symlink" != "xno"])
AC_OUTPUT
-317
View File
@@ -1,317 +0,0 @@
/* Fastinit (finit) copyfile() implementation.
*
* Copyright (c) 2008 Claudio Matsuoka <http://helllabs.org/finit/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/param.h> /* MAX(), isset(), setbit(), TRUE, FALSE, et consortes. :-) */
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "lite.h"
static int __isdir_and_append_filename(char *src, char **dst);
/**
* copyfile - Copy a file to another.
* @src: Source file.
* @dst: Target file.
* @len: Number of bytes to copy, zero (0) for entire file.
*
* This is a C implementation of the command line cp(1) utility. It is one
* of the classic missing links in the UNIX C library. This version is from
* the finit project, http://helllabs.org/finit/, which is a reimplementation
* of fastinit for the Asus EeePC.
*
* Only some small changes to save stack space have been introduced.
*
* Returns:
* The number of bytes copied, zero may be error (check errno!), but it
* may also indicate that @src was empty. If @src is a directory errno
* will be set to %EISDIR since copyfile() is not recursive.
*/
ssize_t copyfile(char *src, char *dst, int len)
{
char *buffer;
int s, d, n, isdir = 0, saved_errno = 0;
ssize_t size = 0;
errno = 0; /* Reset before leaving this function. */
// fprintf (stderr, "%s() src: %s, dst: %s, len: %d\n", __func__, src, dst, len);
buffer = malloc(BUFSIZ);
if (!buffer)
return 0;
if (fisdir(src)) {
errno = EISDIR; /* Error: source is a directory */
return 0;
}
/* Check if target is a directory, then append the src base filename. */
isdir = __isdir_and_append_filename(src, &dst);
/* Len == 0 means copy entire file */
if (len == 0) {
/* XXX: This feels a bit unsafe, but 2047 MiB may be sufficient for us.
* --Jocke 2008-08-11 */
len = INT_MAX;
}
if ((s = open(src, O_RDONLY)) >= 0) {
if ((d =
open(dst, O_WRONLY | O_CREAT | O_TRUNC,
fmode(src))) >= 0) {
do {
int clen = len > BUFSIZ ? BUFSIZ : len;
if ((n = read(s, buffer, clen)) > 0) {
size += write(d, buffer, n);
}
len -= clen;
}
while (len > 0 && n == BUFSIZ);
close(d);
} else {
saved_errno = errno;
}
close(s);
} else {
saved_errno = errno;
}
free(buffer);
if (isdir)
free(dst);
errno = saved_errno;
return size;
}
/**
* movefile - Move a file to another location
* @src: Source file.
* @dst: Target file, or location.
*
* This is a C implementation of the command line mv(1) utility.
* Usually the rename() API is sufficient, but not when moving across
* file system boundaries.
*
* The @src argument must include the full path to the source file,
* whereas the @dst argument may only be a directory, in which case the
* same file name from @src is used.
*
* Returns:
* POSIX OK(0), or non-zero with errno set.
*/
int movefile(char *src, char *dst)
{
int isdir, result = 0;
/* Check if target is a directory, then append the src base filename. */
isdir = __isdir_and_append_filename(src, &dst);
if (rename(src, dst)) {
if (errno == EXDEV) {
errno = 0;
copyfile(src, dst, 0);
if (errno)
result = 1;
else
result = remove(src);
} else {
result = 1;
}
}
if (isdir)
free(dst);
return result;
}
/**
* copy_filep - Copy between FILE *fp.
* @src: Source FILE.
* @dst: Destination FILE.
*
* Function takes signals into account and will restart the syscalls as long
* as error is %EINTR.
*
* Returns:
* POSIX OK(0), or non-zero with errno set on error.
*/
int copy_filep(FILE *src, FILE *dst)
{
int result = 0;
char *buf = (char *)malloc(BUFSIZ);
if (!src || !dst)
return EINVAL;
if (!buf)
return errno;
while (1) {
if (!fgets(buf, BUFSIZ, src)) {
if (errno == EINTR) {
clearerr(src);
continue;
}
if (feof(src))
break;
result = errno;
goto exit;
}
while (EOF == fputs(buf, dst)) {
if (errno == EINTR) {
clearerr(dst);
continue;
}
result = errno;
goto exit;
}
}
exit:
free(buf);
return errno = result;
}
/* Tests if dst is a directory, if so, reallocates dst and appends src filename returning 1 */
static int __isdir_and_append_filename(char *src, char **dst)
{
int isdir = 0;
if (fisdir(*dst)) {
int slash = 0;
char *tmp, *ptr = strrchr(src, '/');
if (!ptr)
ptr = src;
else
ptr++;
// fprintf (stderr, "Yes %s is a dir --> add %s\n", *dst, ptr);
tmp = malloc(strlen(*dst) + strlen(ptr) + 2);
if (!tmp) {
errno = EISDIR;
return 0;
}
isdir = 1; /* Free dst before exit! */
slash = fisslashdir(*dst);
sprintf(tmp, "%s%s%s", *dst, slash ? "" : "/", ptr);
*dst = tmp;
// fprintf (stderr, "NEW DST:%s\n", *dst);
}
return isdir;
}
#ifdef UNITTEST
#include <stdio.h>
/* XXX: Make a real set of unit tests ... */
#if 0
int main(int argc, char *argv[])
{
if (argc < 3) {
fprintf(stderr,
"Usage: %s <src> <dst>\nCopies the <src> file to the <dst> file.\n",
argv[0]);
return 1;
}
printf("Copying file %s to %s\n", argv[1], argv[2]);
return copyfile(argv[1], argv[2], 0);
}
#else
int main(void)
{
int i = 0;
char *files[] = {
"/etc/passwd", "/tmp/tok", "/tmp/tok",
"/etc/passwd", "/tmp/", "/tmp/passwd",
"/etc/passwd", "/tmp", "/tmp/passwd",
NULL
};
FILE *src, *dst;
fprintf(stderr, "\n=>Start testing copy_filep()\n");
while (files[i]) {
fprintf(stderr, "copy_filep(%s, %s)\t", files[i],
files[i + 1]);
src = fopen(files[i], "r");
dst = fopen(files[i + 1], "w");
if (copy_filep(src, dst))
perror("Failed");
if (src)
fclose(src);
if (dst)
fclose(dst);
if (fexist(files[i + 2]))
fprintf(stderr, "OK => %s\n", files[i + 2]);
remove(files[i + 2]);
i += 3;
}
printf("\n\n=>Start testing copyfile()\n");
i = 0;
while (files[i]) {
fprintf(stderr, "copyfile(%s, %s)\t", files[i], files[i + 1]);
if (!copyfile(files[i], files[i + 1], 0))
perror("Failed");
if (fexist(files[i + 2]))
fprintf(stderr, "OK => %s\n", files[i + 2]);
remove(files[i + 2]);
i += 3;
}
return 0;
}
#endif
#endif /* UNITTEST */
/**
* Local Variables:
* compile-command: "gcc -g -I../include -o unittest -DUNITTEST copyfile.c && ./unittest"
* version-control: t
* kept-new-versions: 2
* c-file-style: "ellemtel"
* End:
*/
+12
View File
@@ -0,0 +1,12 @@
*.log
*.substvars
.debhelper/*
tmp/*
libite/*
libite5/*
libite-dev/*
autoreconf*
debhelper*
files
!*.dirs
!*.install
+154
View File
@@ -0,0 +1,154 @@
libite (2.5.1) stable; urgency=medium
* Use dh_link(1) to install `/usr/include/lite -> libite/`.
-- Joachim Wiberg <troglobit@gmail.com> Thu, 02 Dec 2021 00:08:41 +0100
libite (2.5.0) stable; urgency=medium
* Header files have moved from `lite/*.h` to `libite/*.h` to prevent
clashing with DirectFB LiTE library. For a transitional period,
however, a compatibility symlink is installed; `lite -> libite/`.
-- Joachim Wiberg <troglobit@gmail.com> Tue, 30 Nov 2021 06:57:17 +0100
libite (2.4.1) stable; urgency=medium
* Add doxygen documentation, https://codedocs.xyz/troglobit/libite/
* Fix issue with tempfile() returning EOPNOTSUP on certain file systems,
added fallback that uses mkstemp() with O_CLOEXEC flag set
-- Joachim Wiberg <troglobit@gmail.com> Sat, 09 Oct 2021 08:56:43 +0200
libite (2.4.0) stable; urgency=medium
* New functions:
- touchf(), formatted string support for touch()
- erasef(), formatted string support for erase()
- strtrim(), trims leading and trailing white-space from a string
* Fix systemf() improper handling of system() return value. Now checks
if exited OK, then returning the exit status of the command, or if not
exited OK, then checks if the command was signaled, and returns -1 with
errno set. This also allows for returning 127, like system(), if the
shell, or the program itself, did not exist.
-- Joachim Wiberg <troglobit@gmail.com> Sat, 27 Mar 2021 09:12:32 +0100
libite (2.3.1) stable; urgency=medium
* Minor packaging fixes.
* Copyright updates, including LICENSE file, year + author last name
-- Joachim Wiberg <troglobit@gmail.com> Fri, 12 Feb 2021 15:10:42 +0100
libite (2.3.0) stable; urgency=medium
* New functions:
- Add support for fremove(), formatted remove() replacement
- Add support for truncatef(), formatted truncate() replacement
* Fixes
- Handle ETIMEDOUT error for connect() call in telnet_open()
-- Joachim Wiberg <troglobit@gmail.com> Fri, 12 Feb 2021 08:03:47 +0100
libite (2.2.0) stable; urgency=medium
* New functions:
- systemf(), formatted string system() replacement
- fmkpath(), formatted string mkpath() replacement
- fopenf(), formatted string fopen() replacement
* Fixes
- possible memory leak in rsync()
- Check return value of fstat() to prevent bogus destination file
times when using copyfile()
-- Joachim Nilsson <troglobit@gmail.com> Mon, 16 Mar 2020 15:42:02 +0100
libite (2.1.2) stable; urgency=high
* Fix upgrade of base package, new library name to match SONAME
breaks upgrade from libite_2.0.x.deb to libite5_2.1.x.deb
-- Joachim Nilsson <troglobit@gmail.com> Sat, 22 Feb 2020 15:04:27 +0100
libite (2.1.1) stable; urgency=medium
* Fix to chomp(), ensure stopping before beginning of string
* Added example of printhdr()
* Update copyright years
* Add missing libite5.symbols file, found by lintian
* Fix package short description, found by linitian
-- Joachim Nilsson <troglobit@gmail.com> Sat, 22 Feb 2020 13:52:24 +0100
libite (2.1.0) unstable; urgency=medium
* New functions; strmatch(), strnmatch(), yorn(), telnet expect APIs
* Fixes to pidfile_signal(), strtonum() and C++ linking
-- Joachim Nilsson <troglobit@gmail.com> Mon, 26 Aug 2019 20:21:46 +0200
libite (2.0.2) unstable; urgency=medium
* Fix issues with using `strlite.h` standalone
* Fix build issue with `strtonum.c` older GLIBC
-- Joachim Nilsson <troglobit@gmail.com> Thu, 10 May 2018 19:12:57 +0200
libite (2.0.1-1) unstable; urgency=medium
* New upstream release, v2.0.1, fixes to:
- touch(), cannot handle relative paths when updating mtime
- unit test for which()
- add missing initscr() declaration in conio.h
- ifdef guards around min()/max() macros
-- Joachim Nilsson <troglobit@gmail.com> Fri, 22 Dec 2017 12:11:41 +0100
libite (2.0.0-1) unstable; urgency=low
* New upstream release, v2.0.0, fixes to:
- makepath(), mkpath()
* Changes to
- rsync(), API changes
- copyfile(), API changes
- tree(), removed from library
- fmode(), removed from library
-- Joachim Nilsson <troglobit@gmail.com> Sun, 19 Nov 2017 22:42:51 +0100
libite (1.9.3-1) unstable; urgency=low
* New upstream release, v1.9.3, fixes to conio.h, initscr() and tree().
-- Joachim Nilsson <troglobit@gmail.com> Tue, 24 Oct 2017 08:49:54 +0200
libite (1.9.2-1) unstable; urgency=low
* New upstream reelase, v1.9.2, see upstream ChangeLog for details.
-- Joachim Nilsson <troglobit@gmail.com> Tue, 15 Aug 2017 08:15:14 +0200
libite (1.9.1-1) unstable; urgency=low
* New upstream reelase, v1.9.1.
-- Joachim Nilsson <troglobit@gmail.com> Sun, 02 Jul 2017 19:23:00 +0100
libite (1.9.0-1) unstable; urgency=low
* New upstream reelase.
-- Joachim Nilsson <troglobit@gmail.com> Sun, 02 Jul 2017 19:23:00 +0100
libite (1.8.3-1) unstable; urgency=low
* New upstream reelase.
-- Joachim Nilsson <troglobit@gmail.com> Sun, 08 Jan 2017 15:22:26 +0100
libite (1.8.2-1) unstable; urgency=low
* Initial release.
-- Joachim Nilsson <troglobit@gmail.com> Tue, 29 Nov 2016 08:23:35 +0100
+1
View File
@@ -0,0 +1 @@
config.log
+1
View File
@@ -0,0 +1 @@
10
+56
View File
@@ -0,0 +1,56 @@
Source: libite
Section: libs
Priority: optional
Maintainer: Joachim Wiberg <troglobit@gmail.com>
Build-Depends: debhelper (>= 10)
Build-Depends-Indep: doxygen
Standards-Version: 4.3.0
Homepage: https://github.com/troglobit/libite/
Vcs-Browser: https://github.com/troglobit/libite/
Vcs-Git: https://github.com/troglobit/libite.git
Package: libite-dev
Priority: optional
Section: libdevel
Architecture: any
Depends: ${misc:Depends}, libite5 (= ${binary:Version})
Description: static library, header files, and docs for libite
Static library, header files, and documentation for libite.
.
Libite is a lightweight library of frog DNA. It can be used to fill
the gaps in any dinosaur project. It holds useful functions and macros
developed by both Finit and the OpenBSD project. Most notably the
string functions: strlcpy(3), strlcat(3) and the highly useful *BSD
sys/queue.h and sys/tree.h API's.
.
Libite is the frog DNA missing in GNU libc. However, -lite does not
aim to become another GLIB! One noticeable gap in GLIBC is the missing
_SAFE macros in the BSD sys/queue.h API — highly recommended when
traversing lists to delete/free nodes.
.
The code is open sourced under a mix of the MIT/X11 license, the ISC
license used by OpenBSD, and BSD licenses, all of them are extremely
liberal and can be used freely in proprietary software if needed.
Package: libite5
Replaces: libite
Conflicts: libite
Provides: libite
Architecture: any
Depends: ${misc:Depends}, ${shlibs:Depends}
Description: That missing frog DNA you've been looking for
Libite, or -lite, is a lightweight library of frog DNA. It can be used
to fill the gaps in any dinosaur project. It holds useful functions
and macros developed by both Finit and the OpenBSD project. Most
notably the string functions: strlcpy(3), strlcat(3) and the highly
useful *BSD sys/queue.h and sys/tree.h API's.
.
Libite is the frog DNA missing in GNU libc. However, -lite does not
aim to become another GLIB! One noticeable gap in GLIBC is the missing
_SAFE macros in the BSD sys/queue.h API — highly recommended when
traversing lists to delete/free nodes.
.
The code is open source software under a mix of the MIT/X11 license,
the ISC license used by OpenBSD, and BSD licenses, all of them are
extremely liberal and can be used freely in proprietary software if
needed.
+128
View File
@@ -0,0 +1,128 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Source: https.//github.com/troglobit/libite/
Files: *
Copyright:
2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
2008-2021 Joachim Wiberg <troglobit@gmail.com>
License: MIT
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Files: chomp.c
Copyright: 2014-2021 Joachim Wiberg <troglobit@gmail.com>
License: ISC
Files: conio.?
Copyright: 2009-2021 Joachim Wiberg <troglobit@gmail.com>
License: ISC
Files: dir.c
Copyright: 2008-2021 Joachim Wiberg <troglobit@gmail.com>
License: ISC
Files: fopenf.c fremove.c systemf.c truncatef.c
Copyright: 2021 Joachim Wiberg <troglobit@gmail.com>
License: ISC
Files: fparseln.c
Copyright: 1997 Christos Zoulas
License: BSD-2-clause
Files: fsendfile.c
Copyright: 2013 Tobias Waldekranz <tobias@waldekranz.com>
License: MIT
Files: lfile.c
Copyright: 2015-2021 Joachim Wiberg <troglobit@gmail.com>
License: ISC
Files: makepath.c
Copyright: 2016-2021 Joachim Wiberg <troglobit@gmail.com>
License: ISC
Files: pidfile.c
Copyright: 1999 The NetBSD Foundation, Inc.
License: BSD-2-clause
Files: pidfilefn.c
Copyright: 2009-2021 Joachim Wiberg <troglobit@gmail.com>
License: ISC
Files: progress.c
Copyright: 2012-2021 Joachim Wiberg <troglobit@gmail.com>
License: ISC
Files: queue.h
Copyright: 1991, 1993 The Regents of the University of California.
License: BSD-3-clause
Files: reallocarray.c
Copyright: 2008 Otto Moerbeek <otto@drijf.net>
License: ISC
Files: rsync.c
Copyright: 2011-2021 Joachim Wiberg <troglobit@gmail.com>
License: ISC
Files: strdupa.h strndupa.h
Copyright: 2009 William Ahern
License: MIT
Files: strlcat.c strlcpy.c
Copyright: 1998, 2015 Todd C. Miller <Todd.Miller@courtesan.com>
License: MIT
Files: strlite.h
Copyright: 2008-2021 Joachim Wiberg <troglobit@gmail.com>
License: MIT
Files: strmatch.c
Copyright: 2009-2021 Joachim Wiberg <troglobit@gmail.com>
License: ISC
Files: strnlen.c
Copyright: 2016-2021 Joachim Wiberg <troglobit@gmail.com>
License: ISC
Files: strtonum.c
Copyright: 2004 Ted Unangst and Todd Miller
License: ISC
Files: telnet.c
Copyright: 2010-2021 Joachim Wiberg <troglobit@gmail.com>
License: ISC
Files: tempfile.c
Copyright: 2015-2021 Joachim Wiberg <troglobit@gmail.com>
License: ISC
Files: tree.h
Copyright: 2002 Niels Provos <provos@citi.umich.edu>
License: BSD-2-clause
Files: which.c
Copyright: 2017-2021 Joachim Wiberg <troglobit@gmail.com>
License: ISC
Files: yorn.c
Copyright: 2009-2021 Joachim Wiberg <troglobit@gmail.com>
License: ISC
Files: test/*.c
License: public-domain
Vendored
+1
View File
@@ -0,0 +1 @@
README.md
+2
View File
@@ -0,0 +1,2 @@
usr/lib
usr/include
+4
View File
@@ -0,0 +1,4 @@
usr/include/libite/*.h
usr/lib/*/lib*.a
usr/lib/*/lib*.so
usr/lib/*/pkgconfig/lib*.pc
+1
View File
@@ -0,0 +1 @@
/usr/include/libite /usr/include/lite
+1
View File
@@ -0,0 +1 @@
usr/lib
+1
View File
@@ -0,0 +1 @@
usr/lib/*/lib*.so.*
+52
View File
@@ -0,0 +1,52 @@
libite.so.5 libite5 #MINVER#
* Build-Depends-Package: libite-dev
__pidfile_name@Base 2.0.0
__pidfile_path@Base 2.0.0
chomp@Base 2.0.0
copyfile@Base 2.0.0
dir@Base 2.0.0
erasef@Base 2.4.0
fcopyfile@Base 2.0.0
fexist@Base 2.0.0
fgetint@Base 2.0.0
fisdir@Base 2.0.0
fmkpath@Base 2.2.0
fopenf@Base 2.2.0
fparseln@Base 2.0.0
fremove@Base 2.3.0
fsendfile@Base 2.0.0
ifconfig@Base 2.0.0
initscr@Base 2.0.0
lfclose@Base 2.0.0
lfgetint@Base 2.0.0
lfgetkey@Base 2.0.0
lfopen@Base 2.0.0
lftok@Base 2.0.0
makepath@Base 2.0.0
mkpath@Base 2.0.0
movefile@Base 2.0.0
pidfile@Base 2.0.0
pidfile_poll@Base 2.0.0
pidfile_read@Base 2.0.0
pidfile_signal@Base 2.1.0
progress@Base 2.0.0
progress_simple@Base 2.0.0
reallocarray@Base 2.0.0
rsync@Base 2.0.0
strlcat@Base 2.0.0
strlcpy@Base 2.0.0
strmatch@Base 2.1.0
strnmatch@Base 2.1.0
strtonum@Base 2.1.0
strtrim@Base 2.4.0
systemf@Base 2.2.0
telnet_close@Base 2.1.0
telnet_expect@Base 2.1.0
telnet_open@Base 2.1.0
telnet_session@Base 2.1.0
tempfile@Base 2.0.0
touchf@Base 2.4.0
truncatef@Base 2.3.0
which@Base 2.0.0
whichp@Base 2.0.0
yorn@Base 2.1.0
Vendored Executable
+17
View File
@@ -0,0 +1,17 @@
#!/usr/bin/make -f
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
%:
dh $@ --with autoreconf
override_dh_auto_configure:
dh_auto_configure -- --without-symlink
override_dh_installchangelogs:
dh_installchangelogs ChangeLog.md
override_dh_auto_install:
dh_auto_install
find debian -name LICENSE -delete
+1
View File
@@ -0,0 +1 @@
3.0 (native)
+1
View File
@@ -0,0 +1 @@
compression=xz
-228
View File
@@ -1,228 +0,0 @@
/* Functions for operating on files in directories.
*
* Copyright (c) 2008-2012 Joachim Nilsson <troglobit@gmail.com>
*
* 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.
*/
#include <assert.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static const char *matcher_type = NULL;
static int (*matcher_filter) (const char *file) = NULL;
static int matcher(const struct dirent *entry)
{
char *pos = strrchr(entry->d_name, '.');
if (matcher_filter && !matcher_filter(entry->d_name))
/* User matcher overrides the rest. */
return 0;
/* Skip current dir "." from list of files. */
if ((1 == strlen(entry->d_name) && entry->d_name[0] == '.') ||
(2 == strlen(entry->d_name) && !strcmp(entry->d_name, "..")))
return 0;
/* filetype == "" */
if (matcher_type[0] == 0)
return 1;
/* Entry has no "." */
if (!pos)
return 0;
return !strcmp(pos, matcher_type);
}
/**
* dir - List all files of a certain type in the given directory.
* @dir: Base directory for dir operation.
* @type: File type suffix, e.g. ".cfg".
* @filter: Optional file name filter.
* @list: Pointer to an array of file names.
* @strip: Flag, if set dir() strips the file type.
*
* This function returns a @list of files, matching the @type suffix,
* in the given directory @dir.
*
* The @list argument is a pointer to where to store the dynamically
* allocated list of file names. This list should be free'd by first
* calling free() on each file name and then on the list itself.
*
* If @filter is not %NULL it will be called for each file found. If
* @filter returns non-zero the @file argument will be included in the
* resulting @list. If @filter returns zero for given @file it will
* be discarded.
*
* If the @strip flag is set the resulting @list of files has their
* file type stripped, including the dot. So a match "config0.cfg"
* would be returned as "config0".
*
* Returns:
* Number of files in @list, zero if no matching files of @type.
*/
int dir(const char *dir, const char *type, int (*filter) (const char *file), char ***list, int strip)
{
int i, n, num = 0;
char **files;
struct dirent **namelist;
assert(list);
if (!dir)
/* Assuming current directory */
dir = ".";
if (!type)
/* Assuming all files. */
type = "";
matcher_type = type;
matcher_filter = filter;
n = scandir(dir, &namelist, matcher, alphasort);
if (n < 0) {
perror("scandir");
} else {
files = (char **)malloc(n * sizeof(char *));
for (i = 0; i < n; i++) {
if (files) {
char *name = namelist[i]->d_name;
char *type = strrchr(name, '.');
if (type && strip)
*type = 0;
files[i] = strdup(name);
num++;
}
free(namelist[i]);
}
free(namelist);
}
if (num)
*list = files;
return num;
}
#ifdef UNITTEST
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "otn/c.h"
#define DIR_TYPE_IMAGE ".img"
#define DIR_TYPE_SYSLOG ""
#define DIR_TYPE_CONFIG ".cfg"
#define STARTUP_CONFIG "startup-config.cfg"
int simulate_files(int creat)
{
int i;
char *files[] =
{ "config0.cfg", "config1.cfg", "config2.cfg", "config3.cfg",
"rr109.img", "rx100.img", "rx107.img", "rm957.img", "messages"
};
for (i = 0; i < ARRAY_ELEMENTS(files); i++) {
if (creat)
touch(files[i]);
else
remove(files[i]);
}
if (creat)
symlink("config2.cfg", STARTUP_CONFIG);
else
remove(STARTUP_CONFIG);
return 0;
}
static int cfg_dir_filter(const char *file)
{
/* Skip the STARTUP_CONFIG file, it is a symbolic link to the
* current startup configuration. */
return ! !strcmp(file, STARTUP_CONFIG);
}
int main(int argc, char *argv[])
{
int i, num;
char *type = DIR_TYPE_CONFIG;
char **files;
int once = 1;
int is_startup_config(const char *entry) {
static char file[80];
if (once) {
int len = readlink(STARTUP_CONFIG, file, sizeof(file));
if (len == -1)
return 0;
file[len] = 0;
once = 0; /* Only once per call to dir() */
}
//printf ("Comparing link %s with entry %s\n", file, entry);
return !strcmp(file, entry);
}
simulate_files(1);
if (argc >= 2) {
if (!strcasecmp("CONFIG", argv[1])) {
type = DIR_TYPE_CONFIG;
system("ls -l *" DIR_TYPE_CONFIG);
}
if (!strcasecmp("IMAGE", argv[1])) {
type = DIR_TYPE_IMAGE;
system("ls -l *" DIR_TYPE_IMAGE);
}
if (!strcasecmp("SYSLOG", argv[1])) {
type = DIR_TYPE_SYSLOG;
system("ls -l *");
}
}
num = dir(NULL, type, cfg_dir_filter, &files, 0);
if (num) {
for (i = 0; i < num; i++) {
printf("%s", files[i]);
if (is_startup_config(files[i]))
printf(" --> startup-config");
printf("\n");
free(files[i]);
}
free(files);
}
simulate_files(0);
return 0;
}
#endif /* UNITTEST */
/**
* Local Variables:
* compile-command: "gcc -g -DUNITTEST -o unittest dir.c"
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+3
View File
@@ -0,0 +1,3 @@
html/*
libite.tag
Doxyfile
+376
View File
@@ -0,0 +1,376 @@
API Documentation
=================
Important Note
--------------
When using functions like `mkpath()`, `makepath()`, and `makefifo()`,
make sure your `umask()` is correct so you do not accidentally create
files and directories accessible to other users than intended.
Helper Macros
-------------
- `atonum(str)`
Convert string to natural number, works for 32-bit non-negative
integers. Returns -1 on error. (Uses `strtonum()` internally.)
- `blkdev(dev)`
Create block device
- `chardev(dev)`
Create character device
- `erase(path)`
Erase file/directory with `remove()`. Errors on `stderr`
- `erasef(fmt, ...)`
Like `erase()` but takes a formatted printf-like string as argument.
- `makedir(path)`
Create directory, like `mkdir()`. Errors on `stderr`
- `makefifo(path)`
Create a FIFO, like `mkfifo()`. Errors on `stderr`
- `min(a,b)`/`max(a,b)`
These macros take care to avoid double evaluation.
- `touch(path)`
Create a file, or update mtime. Errors on `stderr`
- `touchf(fmt, ...)`
Like `touch()` but takes a formatted printf-like string as argument.
- `S_ISEXEC(mode_t m)`
Mysteriously missing from GLIBC
- `ISCLR(word,bit)`
Is bit in (integer) word cleared?
- `ISSET(word,bit)`
Is bit in (integer) word set?
- `ISOTHER(word,bit)`
Are any other bits, except bit, in (integer) word set?
- `SETBIT(word,bit)`
Set bit in (integer) word.
- `CLRBIT(word,bit)`
Clear bit in (integer) word.
- `NELEMS(array)`
Returns the number of elements in an array. From the great book, The
Practice of Programming, by Kernighan and Pike.
Generic Functions
-----------------
- `chomp(str)`
Perl like chomp function, chop off last char if newline.
- `copyfile(src, dst, len, opt)`
Like the shell `cp(1)` and `dd(1),`, can also copy symlinks and
preserve the mtime of the source file. The opt argument can be
a mask of:
- `LITE_FOPT_COPYFILE_SYM (0x01)`
- `LITE_FOPT_KEEP_MTIME (0x02)`
In releases prior to v2.0 the opt argument was called `symlink`.
The APIs are 100% compatible if the value `1` was used to enable
the symlink option.
- `dir(dir, ext, filter, list, strip)`
Wrapper for `scandir()` with optional filter. Returns a list of
names: files and directories that must be freed after use. See
the unit test for an example, or take a look at `glob(3)`, it's
probably what you want anyway.
- `fcopyfile(src, dst)`
Like `copyfile()` but uses already open `FILE *` pointers. Copies
from current file positions to current file positions until EOF.
- `fexist(file)`
Check for the existence of a file, returns True(1) or False(0).
- `fisdir(path)`
Check for the existence of a directory, returns True(1) or False(0).
- `fopenf(mode, fmt, ...)`
Like `fopen()`, but takes a formatted string as argument. This
greatly simplifies operations that usually consist of composing a
filename from parts into a dynamic buffer before actually opening
the file.
> **Notice:** the swapped order of `pathname` and `mode`!
- `fremove(fmt, ...)`
Like `remove()`, but takes a formatted string as argument. This
greatly simplifies operations that usually consist of composing a
filename from parts into a dynamic buffer before actually removing
the file.
- `fsendfile(src, dst, len)`
Copy data between file streams, very similar to `fcopyfile()`, but
`dst` is allowed to be `NULL` to be able to read and discard `len`
bytes from `src`.
- `ifconfig(ifname, addr, mask, up)`
Basic ifconfig like operations on an interface. Only supports IPv4
addresses. Note that mask is not CIDR notation.
- `lfopen(file, sep)`, `lfclose(lf)`
LITE file API for parsing UNIX style configuration files like
`/etc/protocols` and `/etc/services`.
- `lftok(lf)`
Read tokens, delimited by `sep`, from file opened with `lfopen()`.
- `lfgetkey(lf, key)`
Find `key` in file opened with `lfopen()`, return value/argument.
- `lfgetint(lf, key)`
Wrapper for `lfgetkey()`, returns positive integer value to `key`,
or `-1` if `key` is not found.
- `fgetint(file, sep, key)`
Wrapper for `lfopen()`, `lfgetint()`, and `lfclose()`. Useful for
when only reading a single `key` from a file.
- `makepath(dir)`
Create all components of the specified directory.
- `mkpath(dir, mode)`
Like `makepath()`, but also takes a `mode_t` permission mode argument.
- `fmkpath(mode, fmt, ...)`
Like `mkpath()`, but takes a formatted string as argument.
> **Notice:** the swapped order of `pathname` and `mode`!
- `movefile(src, dst)`
Like `copyfile()`, but renames `src` to `dst`, or recreates symlink
with the `dst` name. On successful operation the source is removed
and the function returns POSIX OK (0).
- `pidfile(name)`
Create a daemon PID file using either the `name` as a full path, if
`name` starts with `/`, or in `_PATH_VARRUN` using `name` as the
basename of the application. If `name` is `NULL`, then `__progname`
is used as the basename. The resulting file name is available to the
user as a read-only pointer:
extern char *__pidfile_name;
Use this function to create a PID file for your daemon when it is
ready to receive signals. A client application may poll for the
existence of this file, so make sure to have your signal handlers
properly setup before calling this function.
The PID file is removed when the program exits, using an `atexit()`
handler. However, depending on how the program terminates the file
may still exist even though the program is no longer running.
Calling this function multiple times updates the mtime of the file.
Only one `atexit()` handler is created, regardless of the amount of
times the function is called. If the file is removed, subsequent
calls to this function will recreate the file.
See below for a link to OpenBSD man page.
- `pidfile_read(pidfile)`
Read PID from pid file created by `pidfile()`.
- `pidfile_signal(pidfile, signal)`
Send signal to PID found in pid file created by `pidfile()`.
- `progress(percent, max_width)`
Simple ASCII progress bar with a spinner. Start it with `percent=0`
and set the `max_width=chars` to indicate width of the progress bar.
Called multiple times with the same percentage value cause spinner to
spin.
- `rsync(src, dst, opt, *filter())`
Very simple `rsync()` to copy files and directories recursively. It
supports pruning files from the destination tree that do not exist in
the source tree and preserving the mtime of the source files. The opt
argument can be a mask of:
- `LITE_FOPT_RSYNC_DELETE (0x01)`
- `LITE_FOPT_KEEP_MTIME (0x02)`
In releases prior to v2.0 the argument controlling pruning was called
`delete`, it is now called `opt`. The APIs are 100% compatible if the
value `1` was used.
- `strmatch(str, list)`, `strnmatch(str, list, len)`
Find matching string in an array of strings. Returns index in array on
match, or `-1` on error or not found. `strnmatch()` takes an extra arg
to compare only `len` number of characters from `str`.
- `strtrim(str)`
Trims a string from any leading and trailing white-space, returns the
trimmed result in the same buffer.
- `systemf(fmt, ...)`
Like `system()`, but takes a formatted string as argument. This
greatly simplifies operations that usually consist of composing a
command from parts into a dynamic buffer before calling it.
- `telnet_open(addr, port), telnet_close(ctx), telnet_expect(ctx, script, output)`
Poor mans telnet expect in C. Opens connection to a Telnet service;
FTP, Telnet, similar, and run an expect-like script.
- `telnet_session(addr, port, script output)`
Wrapper for the above three in one API.
- `tempfile()`
Secure replacement for `tmpfile()`. Creates an invisible temporary
file in `/tmp` that is removed when the returned `FILE` pointer is
closed.
**Note:** Requires Linux v3.11, or later, will fall back to the old
and unsafe `tmpfile()` on older systems.
- `truncatef(length, fmt, ...)`
Like `truncate()`, but takes a formatted string as argument. This
simplifies some operations when the filename otherwise have to be
composed from parts into a separate array before calling the real
function.
- `which(cmd)`, `whichp(cmd)`
C implementation of UNIX which(1). Returns a malloc'ed string with the
full path to `cmd` on success, otherwise `NULL`.
`whichp()` is a predicate function, returns `TRUE` or `FALSE`.
**Note:** `which("/bin/ps aux")` will return `/bin/ps`, or `TRUE`,
provided of course `/bin/ps` exists.
- `yorn(fmt, ...)`
Pose a question to user, appended with `(y/N)?`, returns `TRUE` for
yes (both `y` and `Y` are handled) and `FALSE` for everything else.
GNU Functions
-------------
The following are useful GNU functions, that do not exist on *BSD, and
some other platforms.
- `strdupa(str)`
http://man7.org/linux/man-pages/man3/strdupa.3.html
- `strndupa(str)`
http://man7.org/linux/man-pages/man3/strndupa.3.html
- `strnlen(str, lim)`
http://man7.org/linux/man-pages/man3/strnlen.3.html
OpenBSD/NetBSD/FreeBSD Functions
--------------------------------
The following are popular functions and highly useful macros from the
*BSD world of UNIX that are sadly missing on Linux.
- `fparseln(fp, *len, *lineno, delim, flags)`
http://man.openbsd.org/OpenBSD-current/man3/fparseln.3
- `pidfile(basename)`
http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man3/pidfile.3
**Note:** the version of `pidfile()` in -lite has been extended to
handle it being called multiple times, i.e. to not create multiple
`atexit()` handlers, and also to export a few internal paths:
- `__pidfile_path`: prefix path, default `_PATH_VARRUN`. Notice the
trailing slash requirement if you want to override it!
- `__pidfile_name`: full path to PID file , similar to `__progname`.
See previous section for details.
- `reallocarray(ptr, nmemb, size)`
http://man.openbsd.org/OpenBSD-current/man3/reallocarray.3
- `strlcpy(dst, src, len)`
http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man3/strlcpy.3
- `strlcat(dst, src, len)`
http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man3/strlcat.3
- `strtonum()`
http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man3/strtonum.3
- `sys/queue.h` API
http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man3/LIST_EMPTY.3
- `sys/tree.h` API
Niels Provos' famous splay and red-black tree implementation.
http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man3/SPLAY_FOREACH.3
+2579
View File
File diff suppressed because it is too large. Load diff
+104
View File
@@ -0,0 +1,104 @@
Maintenance and Release Checklist
=================================
Maintenance
-----------
* Encourage contributors to write tests, in particular for new features
* Run tests regularly, use Travis-CI to do this automatically
* Leverage GitHub issues for milestone planning
* Reference issues from GitHub pull requests to alert issue subscribers
* Bump library ABI version just before release!
Release Checklist
-----------------
* Update ChangeLog, follow http://keepachangelog.com/ loosely
- Inform users in a plain language of changes and bug fixes
- Do *not* copy-paste GIT commit logs!
- Order entrys according to importance, most relevant first
* Run unit tests: `make check`
* Do we need to bump the ABI version? (Probably, see below)
* Tag
* Push last commit(s) *and* tags to GitHub
* Make release
make distclean
./autogen.sh
./configure
make release
* Create new release in GitHub releases page
* Copy and paste ChangeLog entry, check any stale links!
* Upload release tarball and MD5 files
Library Versioning
------------------
Libite (-lite) relies on GNU Libtool for building the library. For a
user of the library it is important to maintain a clear ABI versioning
scheme. This is not the same as the library version, but rather the
library "compatibility level".
The ABI version is specified in `src/Makefile.am` and looks like this:
libite_la_LDFLAGS = -version-info 0:0:0
\ \ `-- age
\ `--- revision
`---- current
It must be updated according to the [GNU Libtool recommendations][1]:
1. Start with version information of `0:0:0` for each libtool library.
2. Update the version information only immediately before a public
release of your software. More frequent updates are unnecessary, and
only guarantee that the current interface number gets larger faster.
3. If the library *source code has changed at all* since the last update,
then increment revision (`c:r:a` becomes `c:r+1:a`).
4. If any *interfaces have been added, removed, or changed* since the
last update, increment current, and set revision to 0.
5. If any *interfaces have been added* since the last public release,
then increment age.
6. If any *interfaces have been removed or changed* since the last
public release, then set age to 0.
The libtool ABI versioning logic is very confusing but works if you just
disable your brain and follow the rules, one by one.
**Example #1:** a new function has been added, none of the existing ones
have changed. The initial version is 1:0:0, we follow the rules above to
the letter: increase revision, increase current and set revision to zero,
and finally increase age. This, rather confusingly, gives us 2:0:1 which
libtool then translates to `libite.so.1.1.0`.
**Example #2:** some existing functions are changed, they now return an
`int` instead of `void`. The initial version is 0:0:0, and we follow the
rules again: increment revision, increment current and set revision to
zero, set age to zero. This gives us 1:0:0, which is then translated to
`libite.so.1.0.0`.
### Note
Usually, non-developers have no interest in running development versions
(releases are frequent enough), and developers are expected to know how
to juggle versions. In such an ideal world, it is good enough to bump
the library version just prior to a release, point 2.
However, if releases are few and far between, distributors may start to
use snapshots. When a distributor uses a snapshot, the distributor has
to handle the library version manually. Things can get ugly when the
distributor has released an intermediate version with a bumped library
version, and when the official release is bumped to that version, the
distributor will then have to bump the library version for the official
release, and it can be confusing if someone reports bugs on versions
that you didn't even know existed.
The problem with bumping the version with every change is that if your
interface is not finished, the version number might run away, and it
looks pretty bad if a library is at version 262. It kind of tells the
user that the library interface is volatile, which is not good for
business.
[1]: https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
+22
View File
@@ -0,0 +1,22 @@
dist_doc_DATA = API.md
EXTRA_DIST = API.md Doxyfile.in
DISTCLEANFILES = libite.tag
if ENABLE_HTML
pkghtmldir = $(docdir)/html
pkghtml_DATA = html/*
#
# Doxygen rules from m4/ax_prog_doxygen.m4
#
@DX_RULES@
$(pkghtml_DATA): doxygen-doc
all-local: doc
clean-local:
-rm -rf html libite.tag
doc: doxygen-doc
endif
+8
View File
@@ -0,0 +1,8 @@
TODO ... in no particular order
===============================
* Improve documentation, possibly use kdoc or gdoc2 to generate docs from API
* Continuously, update OpenBSD functions/macros
* Investigate adding FreeBSD pidfile_open() et al
* Investigate FreeBSD libutil library, could be useful for porting between unices
-57
View File
@@ -1,57 +0,0 @@
/* File mode bit operations
*
* Copyright (c) 2008 Claudio Matsuoka <http://helllabs.org/finit/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
/**
* fmode - Return a file's mode bits.
* @file: File to look for, with full path.
*
* Returns:
* The mode bits or zero when @file does not exist and errno set to %ENOENT.
*/
mode_t fmode(char *file)
{
struct stat sb;
if (!file) {
errno = EINVAL;
return 0; /* Doesn't exist ... */
}
if (!stat(file, &sb))
return sb.st_mode;
return 0;
}
/**
* Local Variables:
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
-61
View File
@@ -1,61 +0,0 @@
/* Collection of utility funcs and C library extensions for finit & its plugins
*
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
* Copyright (c) 2008-2012 Joachim Nilsson <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef FINIT_LITE_H_
#define FINIT_LITE_H_
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int fexist (char *file);
int fisdir (char *file);
mode_t fmode (char *file);
ssize_t copyfile (char *src, char *dst, int len);
int movefile (char *src, char *dst);
int copy_filep (FILE *src, FILE *dst);
int dir (const char *dir, const char *type, int (*filter) (const char *file), char ***list, int strip);
int rsync (char *src, char *dst, int delete, int (*filter) (const char *file));
static inline int fisslashdir(char *dir)
{
if (!dir) return 0;
if (strlen (dir) > 0) return dir[strlen (dir) - 1] == '/';
return 0;
}
#endif /* FINIT_LITE_H_ */
/**
* Local Variables:
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+1
View File
@@ -0,0 +1 @@
*.m4
+585
View File
@@ -0,0 +1,585 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_prog_doxygen.html
# ===========================================================================
#
# SYNOPSIS
#
# DX_INIT_DOXYGEN(PROJECT-NAME, [DOXYFILE-PATH], [OUTPUT-DIR], ...)
# DX_DOXYGEN_FEATURE(ON|OFF)
# DX_DOT_FEATURE(ON|OFF)
# DX_HTML_FEATURE(ON|OFF)
# DX_CHM_FEATURE(ON|OFF)
# DX_CHI_FEATURE(ON|OFF)
# DX_MAN_FEATURE(ON|OFF)
# DX_RTF_FEATURE(ON|OFF)
# DX_XML_FEATURE(ON|OFF)
# DX_PDF_FEATURE(ON|OFF)
# DX_PS_FEATURE(ON|OFF)
#
# DESCRIPTION
#
# The DX_*_FEATURE macros control the default setting for the given
# Doxygen feature. Supported features are 'DOXYGEN' itself, 'DOT' for
# generating graphics, 'HTML' for plain HTML, 'CHM' for compressed HTML
# help (for MS users), 'CHI' for generating a seperate .chi file by the
# .chm file, and 'MAN', 'RTF', 'XML', 'PDF' and 'PS' for the appropriate
# output formats. The environment variable DOXYGEN_PAPER_SIZE may be
# specified to override the default 'a4wide' paper size.
#
# By default, HTML, PDF and PS documentation is generated as this seems to
# be the most popular and portable combination. MAN pages created by
# Doxygen are usually problematic, though by picking an appropriate subset
# and doing some massaging they might be better than nothing. CHM and RTF
# are specific for MS (note that you can't generate both HTML and CHM at
# the same time). The XML is rather useless unless you apply specialized
# post-processing to it.
#
# The macros mainly control the default state of the feature. The use can
# override the default by specifying --enable or --disable. The macros
# ensure that contradictory flags are not given (e.g.,
# --enable-doxygen-html and --enable-doxygen-chm,
# --enable-doxygen-anything with --disable-doxygen, etc.) Finally, each
# feature will be automatically disabled (with a warning) if the required
# programs are missing.
#
# Once all the feature defaults have been specified, call DX_INIT_DOXYGEN
# with the following parameters: a one-word name for the project for use
# as a filename base etc., an optional configuration file name (the
# default is '$(srcdir)/Doxyfile', the same as Doxygen's default), and an
# optional output directory name (the default is 'doxygen-doc'). To run
# doxygen multiple times for different configuration files and output
# directories provide more parameters: the second, forth, sixth, etc
# parameter are configuration file names and the third, fifth, seventh,
# etc parameter are output directories. No checking is done to catch
# duplicates.
#
# Automake Support
#
# The DX_RULES substitution can be used to add all needed rules to the
# Makefile. Note that this is a substitution without being a variable:
# only the @DX_RULES@ syntax will work.
#
# The provided targets are:
#
# doxygen-doc: Generate all doxygen documentation.
#
# doxygen-run: Run doxygen, which will generate some of the
# documentation (HTML, CHM, CHI, MAN, RTF, XML)
# but will not do the post processing required
# for the rest of it (PS, PDF).
#
# doxygen-ps: Generate doxygen PostScript documentation.
#
# doxygen-pdf: Generate doxygen PDF documentation.
#
# Note that by default these are not integrated into the automake targets.
# If doxygen is used to generate man pages, you can achieve this
# integration by setting man3_MANS to the list of man pages generated and
# then adding the dependency:
#
# $(man3_MANS): doxygen-doc
#
# This will cause make to run doxygen and generate all the documentation.
#
# The following variable is intended for use in Makefile.am:
#
# DX_CLEANFILES = everything to clean.
#
# Then add this variable to MOSTLYCLEANFILES.
#
# LICENSE
#
# Copyright (c) 2009 Oren Ben-Kiki <oren@ben-kiki.org>
# Copyright (c) 2015 Olaf Mandel <olaf@mandel.name>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 20
## ----------##
## Defaults. ##
## ----------##
DX_ENV=""
AC_DEFUN([DX_FEATURE_doc], ON)
AC_DEFUN([DX_FEATURE_dot], OFF)
AC_DEFUN([DX_FEATURE_man], OFF)
AC_DEFUN([DX_FEATURE_html], ON)
AC_DEFUN([DX_FEATURE_chm], OFF)
AC_DEFUN([DX_FEATURE_chi], OFF)
AC_DEFUN([DX_FEATURE_rtf], OFF)
AC_DEFUN([DX_FEATURE_xml], OFF)
AC_DEFUN([DX_FEATURE_pdf], ON)
AC_DEFUN([DX_FEATURE_ps], ON)
## --------------- ##
## Private macros. ##
## --------------- ##
# DX_ENV_APPEND(VARIABLE, VALUE)
# ------------------------------
# Append VARIABLE="VALUE" to DX_ENV for invoking doxygen and add it
# as a substitution (but not a Makefile variable). The substitution
# is skipped if the variable name is VERSION.
AC_DEFUN([DX_ENV_APPEND],
[AC_SUBST([DX_ENV], ["$DX_ENV $1='$2'"])dnl
m4_if([$1], [VERSION], [], [AC_SUBST([$1], [$2])dnl
AM_SUBST_NOTMAKE([$1])])dnl
])
# DX_DIRNAME_EXPR
# ---------------
# Expand into a shell expression prints the directory part of a path.
AC_DEFUN([DX_DIRNAME_EXPR],
[[expr ".$1" : '\(\.\)[^/]*$' \| "x$1" : 'x\(.*\)/[^/]*$']])
# DX_IF_FEATURE(FEATURE, IF-ON, IF-OFF)
# -------------------------------------
# Expands according to the M4 (static) status of the feature.
AC_DEFUN([DX_IF_FEATURE], [ifelse(DX_FEATURE_$1, ON, [$2], [$3])])
# DX_REQUIRE_PROG(VARIABLE, PROGRAM)
# ----------------------------------
# Require the specified program to be found for the DX_CURRENT_FEATURE to work.
AC_DEFUN([DX_REQUIRE_PROG], [
AC_PATH_TOOL([$1], [$2])
if test "$DX_FLAG_[]DX_CURRENT_FEATURE$$1" = 1; then
AC_MSG_WARN([$2 not found - will not DX_CURRENT_DESCRIPTION])
AC_SUBST(DX_FLAG_[]DX_CURRENT_FEATURE, 0)
fi
])
# DX_TEST_FEATURE(FEATURE)
# ------------------------
# Expand to a shell expression testing whether the feature is active.
AC_DEFUN([DX_TEST_FEATURE], [test "$DX_FLAG_$1" = 1])
# DX_CHECK_DEPEND(REQUIRED_FEATURE, REQUIRED_STATE)
# -------------------------------------------------
# Verify that a required features has the right state before trying to turn on
# the DX_CURRENT_FEATURE.
AC_DEFUN([DX_CHECK_DEPEND], [
test "$DX_FLAG_$1" = "$2" \
|| AC_MSG_ERROR([doxygen-DX_CURRENT_FEATURE ifelse([$2], 1,
requires, contradicts) doxygen-DX_CURRENT_FEATURE])
])
# DX_CLEAR_DEPEND(FEATURE, REQUIRED_FEATURE, REQUIRED_STATE)
# ----------------------------------------------------------
# Turn off the DX_CURRENT_FEATURE if the required feature is off.
AC_DEFUN([DX_CLEAR_DEPEND], [
test "$DX_FLAG_$1" = "$2" || AC_SUBST(DX_FLAG_[]DX_CURRENT_FEATURE, 0)
])
# DX_FEATURE_ARG(FEATURE, DESCRIPTION,
# CHECK_DEPEND, CLEAR_DEPEND,
# REQUIRE, DO-IF-ON, DO-IF-OFF)
# --------------------------------------------
# Parse the command-line option controlling a feature. CHECK_DEPEND is called
# if the user explicitly turns the feature on (and invokes DX_CHECK_DEPEND),
# otherwise CLEAR_DEPEND is called to turn off the default state if a required
# feature is disabled (using DX_CLEAR_DEPEND). REQUIRE performs additional
# requirement tests (DX_REQUIRE_PROG). Finally, an automake flag is set and
# DO-IF-ON or DO-IF-OFF are called according to the final state of the feature.
AC_DEFUN([DX_ARG_ABLE], [
AC_DEFUN([DX_CURRENT_FEATURE], [$1])
AC_DEFUN([DX_CURRENT_DESCRIPTION], [$2])
AC_ARG_ENABLE(doxygen-$1,
[AS_HELP_STRING(DX_IF_FEATURE([$1], [--disable-doxygen-$1],
[--enable-doxygen-$1]),
DX_IF_FEATURE([$1], [don't $2], [$2]))],
[
case "$enableval" in
#(
y|Y|yes|Yes|YES)
AC_SUBST([DX_FLAG_$1], 1)
$3
;; #(
n|N|no|No|NO)
AC_SUBST([DX_FLAG_$1], 0)
;; #(
*)
AC_MSG_ERROR([invalid value '$enableval' given to doxygen-$1])
;;
esac
], [
AC_SUBST([DX_FLAG_$1], [DX_IF_FEATURE([$1], 1, 0)])
$4
])
if DX_TEST_FEATURE([$1]); then
$5
:
fi
if DX_TEST_FEATURE([$1]); then
$6
:
else
$7
:
fi
])
## -------------- ##
## Public macros. ##
## -------------- ##
# DX_XXX_FEATURE(DEFAULT_STATE)
# -----------------------------
AC_DEFUN([DX_DOXYGEN_FEATURE], [AC_DEFUN([DX_FEATURE_doc], [$1])])
AC_DEFUN([DX_DOT_FEATURE], [AC_DEFUN([DX_FEATURE_dot], [$1])])
AC_DEFUN([DX_MAN_FEATURE], [AC_DEFUN([DX_FEATURE_man], [$1])])
AC_DEFUN([DX_HTML_FEATURE], [AC_DEFUN([DX_FEATURE_html], [$1])])
AC_DEFUN([DX_CHM_FEATURE], [AC_DEFUN([DX_FEATURE_chm], [$1])])
AC_DEFUN([DX_CHI_FEATURE], [AC_DEFUN([DX_FEATURE_chi], [$1])])
AC_DEFUN([DX_RTF_FEATURE], [AC_DEFUN([DX_FEATURE_rtf], [$1])])
AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])])
AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])])
AC_DEFUN([DX_PDF_FEATURE], [AC_DEFUN([DX_FEATURE_pdf], [$1])])
AC_DEFUN([DX_PS_FEATURE], [AC_DEFUN([DX_FEATURE_ps], [$1])])
# DX_INIT_DOXYGEN(PROJECT, [CONFIG-FILE], [OUTPUT-DOC-DIR], ...)
# --------------------------------------------------------------
# PROJECT also serves as the base name for the documentation files.
# The default CONFIG-FILE is "$(srcdir)/Doxyfile" and OUTPUT-DOC-DIR is
# "doxygen-doc".
# More arguments are interpreted as interleaved CONFIG-FILE and
# OUTPUT-DOC-DIR values.
AC_DEFUN([DX_INIT_DOXYGEN], [
# Files:
AC_SUBST([DX_PROJECT], [$1])
AC_SUBST([DX_CONFIG], ['ifelse([$2], [], [$(srcdir)/Doxyfile], [$2])'])
AC_SUBST([DX_DOCDIR], ['ifelse([$3], [], [doxygen-doc], [$3])'])
m4_if(m4_eval(3 < m4_count($@)), 1, [m4_for([DX_i], 4, m4_count($@), 2,
[AC_SUBST([DX_CONFIG]m4_eval(DX_i[/2]),
'm4_default_nblank_quoted(m4_argn(DX_i, $@),
[$(srcdir)/Doxyfile])')])])dnl
m4_if(m4_eval(3 < m4_count($@)), 1, [m4_for([DX_i], 5, m4_count($@,), 2,
[AC_SUBST([DX_DOCDIR]m4_eval([(]DX_i[-1)/2]),
'm4_default_nblank_quoted(m4_argn(DX_i, $@),
[doxygen-doc])')])])dnl
m4_define([DX_loop], m4_dquote(m4_if(m4_eval(3 < m4_count($@)), 1,
[m4_for([DX_i], 4, m4_count($@), 2, [, m4_eval(DX_i[/2])])],
[])))dnl
# Environment variables used inside doxygen.cfg:
DX_ENV_APPEND(SRCDIR, $srcdir)
DX_ENV_APPEND(PROJECT, $DX_PROJECT)
DX_ENV_APPEND(VERSION, $PACKAGE_VERSION)
# Doxygen itself:
DX_ARG_ABLE(doc, [generate any doxygen documentation],
[],
[],
[DX_REQUIRE_PROG([DX_DOXYGEN], doxygen)
DX_REQUIRE_PROG([DX_PERL], perl)],
[DX_ENV_APPEND(PERL_PATH, $DX_PERL)])
# Dot for graphics:
DX_ARG_ABLE(dot, [generate graphics for doxygen documentation],
[DX_CHECK_DEPEND(doc, 1)],
[DX_CLEAR_DEPEND(doc, 1)],
[DX_REQUIRE_PROG([DX_DOT], dot)],
[DX_ENV_APPEND(HAVE_DOT, YES)
DX_ENV_APPEND(DOT_PATH, [`DX_DIRNAME_EXPR($DX_DOT)`])],
[DX_ENV_APPEND(HAVE_DOT, NO)])
# Man pages generation:
DX_ARG_ABLE(man, [generate doxygen manual pages],
[DX_CHECK_DEPEND(doc, 1)],
[DX_CLEAR_DEPEND(doc, 1)],
[],
[DX_ENV_APPEND(GENERATE_MAN, YES)],
[DX_ENV_APPEND(GENERATE_MAN, NO)])
# RTF file generation:
DX_ARG_ABLE(rtf, [generate doxygen RTF documentation],
[DX_CHECK_DEPEND(doc, 1)],
[DX_CLEAR_DEPEND(doc, 1)],
[],
[DX_ENV_APPEND(GENERATE_RTF, YES)],
[DX_ENV_APPEND(GENERATE_RTF, NO)])
# XML file generation:
DX_ARG_ABLE(xml, [generate doxygen XML documentation],
[DX_CHECK_DEPEND(doc, 1)],
[DX_CLEAR_DEPEND(doc, 1)],
[],
[DX_ENV_APPEND(GENERATE_XML, YES)],
[DX_ENV_APPEND(GENERATE_XML, NO)])
# (Compressed) HTML help generation:
DX_ARG_ABLE(chm, [generate doxygen compressed HTML help documentation],
[DX_CHECK_DEPEND(doc, 1)],
[DX_CLEAR_DEPEND(doc, 1)],
[DX_REQUIRE_PROG([DX_HHC], hhc)],
[DX_ENV_APPEND(HHC_PATH, $DX_HHC)
DX_ENV_APPEND(GENERATE_HTML, YES)
DX_ENV_APPEND(GENERATE_HTMLHELP, YES)],
[DX_ENV_APPEND(GENERATE_HTMLHELP, NO)])
# Seperate CHI file generation.
DX_ARG_ABLE(chi, [generate doxygen seperate compressed HTML help index file],
[DX_CHECK_DEPEND(chm, 1)],
[DX_CLEAR_DEPEND(chm, 1)],
[],
[DX_ENV_APPEND(GENERATE_CHI, YES)],
[DX_ENV_APPEND(GENERATE_CHI, NO)])
# Plain HTML pages generation:
DX_ARG_ABLE(html, [generate doxygen plain HTML documentation],
[DX_CHECK_DEPEND(doc, 1) DX_CHECK_DEPEND(chm, 0)],
[DX_CLEAR_DEPEND(doc, 1) DX_CLEAR_DEPEND(chm, 0)],
[],
[DX_ENV_APPEND(GENERATE_HTML, YES)],
[DX_TEST_FEATURE(chm) || DX_ENV_APPEND(GENERATE_HTML, NO)])
# PostScript file generation:
DX_ARG_ABLE(ps, [generate doxygen PostScript documentation],
[DX_CHECK_DEPEND(doc, 1)],
[DX_CLEAR_DEPEND(doc, 1)],
[DX_REQUIRE_PROG([DX_LATEX], latex)
DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
DX_REQUIRE_PROG([DX_DVIPS], dvips)
DX_REQUIRE_PROG([DX_EGREP], egrep)])
# PDF file generation:
DX_ARG_ABLE(pdf, [generate doxygen PDF documentation],
[DX_CHECK_DEPEND(doc, 1)],
[DX_CLEAR_DEPEND(doc, 1)],
[DX_REQUIRE_PROG([DX_PDFLATEX], pdflatex)
DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
DX_REQUIRE_PROG([DX_EGREP], egrep)])
# LaTeX generation for PS and/or PDF:
if DX_TEST_FEATURE(ps) || DX_TEST_FEATURE(pdf); then
DX_ENV_APPEND(GENERATE_LATEX, YES)
else
DX_ENV_APPEND(GENERATE_LATEX, NO)
fi
# Paper size for PS and/or PDF:
AC_ARG_VAR(DOXYGEN_PAPER_SIZE,
[a4wide (default), a4, letter, legal or executive])
case "$DOXYGEN_PAPER_SIZE" in
#(
"")
AC_SUBST(DOXYGEN_PAPER_SIZE, "")
;; #(
a4wide|a4|letter|legal|executive)
DX_ENV_APPEND(PAPER_SIZE, $DOXYGEN_PAPER_SIZE)
;; #(
*)
AC_MSG_ERROR([unknown DOXYGEN_PAPER_SIZE='$DOXYGEN_PAPER_SIZE'])
;;
esac
# Rules:
AS_IF([[test $DX_FLAG_html -eq 1]],
[[DX_SNIPPET_html="## ------------------------------- ##
## Rules specific for HTML output. ##
## ------------------------------- ##
DX_CLEAN_HTML = \$(DX_DOCDIR)/html]dnl
m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
\$(DX_DOCDIR]DX_i[)/html]])[
"]],
[[DX_SNIPPET_html=""]])
AS_IF([[test $DX_FLAG_chi -eq 1]],
[[DX_SNIPPET_chi="
DX_CLEAN_CHI = \$(DX_DOCDIR)/\$(PACKAGE).chi]dnl
m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).chi]])["]],
[[DX_SNIPPET_chi=""]])
AS_IF([[test $DX_FLAG_chm -eq 1]],
[[DX_SNIPPET_chm="## ------------------------------ ##
## Rules specific for CHM output. ##
## ------------------------------ ##
DX_CLEAN_CHM = \$(DX_DOCDIR)/chm]dnl
m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
\$(DX_DOCDIR]DX_i[)/chm]])[\
${DX_SNIPPET_chi}
"]],
[[DX_SNIPPET_chm=""]])
AS_IF([[test $DX_FLAG_man -eq 1]],
[[DX_SNIPPET_man="## ------------------------------ ##
## Rules specific for MAN output. ##
## ------------------------------ ##
DX_CLEAN_MAN = \$(DX_DOCDIR)/man]dnl
m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
\$(DX_DOCDIR]DX_i[)/man]])[
"]],
[[DX_SNIPPET_man=""]])
AS_IF([[test $DX_FLAG_rtf -eq 1]],
[[DX_SNIPPET_rtf="## ------------------------------ ##
## Rules specific for RTF output. ##
## ------------------------------ ##
DX_CLEAN_RTF = \$(DX_DOCDIR)/rtf]dnl
m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
\$(DX_DOCDIR]DX_i[)/rtf]])[
"]],
[[DX_SNIPPET_rtf=""]])
AS_IF([[test $DX_FLAG_xml -eq 1]],
[[DX_SNIPPET_xml="## ------------------------------ ##
## Rules specific for XML output. ##
## ------------------------------ ##
DX_CLEAN_XML = \$(DX_DOCDIR)/xml]dnl
m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
\$(DX_DOCDIR]DX_i[)/xml]])[
"]],
[[DX_SNIPPET_xml=""]])
AS_IF([[test $DX_FLAG_ps -eq 1]],
[[DX_SNIPPET_ps="## ----------------------------- ##
## Rules specific for PS output. ##
## ----------------------------- ##
DX_CLEAN_PS = \$(DX_DOCDIR)/\$(PACKAGE).ps]dnl
m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).ps]])[
DX_PS_GOAL = doxygen-ps
doxygen-ps: \$(DX_CLEAN_PS)
]m4_foreach([DX_i], [DX_loop],
[[\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).ps: \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag
\$(DX_V_LATEX)cd \$(DX_DOCDIR]DX_i[)/latex; \\
rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \\
\$(DX_LATEX) refman.tex; \\
\$(DX_MAKEINDEX) refman.idx; \\
\$(DX_LATEX) refman.tex; \\
countdown=5; \\
while \$(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \\
refman.log > /dev/null 2>&1 \\
&& test \$\$countdown -gt 0; do \\
\$(DX_LATEX) refman.tex; \\
countdown=\`expr \$\$countdown - 1\`; \\
done; \\
\$(DX_DVIPS) -o ../\$(PACKAGE).ps refman.dvi
]])["]],
[[DX_SNIPPET_ps=""]])
AS_IF([[test $DX_FLAG_pdf -eq 1]],
[[DX_SNIPPET_pdf="## ------------------------------ ##
## Rules specific for PDF output. ##
## ------------------------------ ##
DX_CLEAN_PDF = \$(DX_DOCDIR)/\$(PACKAGE).pdf]dnl
m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).pdf]])[
DX_PDF_GOAL = doxygen-pdf
doxygen-pdf: \$(DX_CLEAN_PDF)
]m4_foreach([DX_i], [DX_loop],
[[\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).pdf: \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag
\$(DX_V_LATEX)cd \$(DX_DOCDIR]DX_i[)/latex; \\
rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \\
\$(DX_PDFLATEX) refman.tex; \\
\$(DX_MAKEINDEX) refman.idx; \\
\$(DX_PDFLATEX) refman.tex; \\
countdown=5; \\
while \$(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \\
refman.log > /dev/null 2>&1 \\
&& test \$\$countdown -gt 0; do \\
\$(DX_PDFLATEX) refman.tex; \\
countdown=\`expr \$\$countdown - 1\`; \\
done; \\
mv refman.pdf ../\$(PACKAGE).pdf
]])["]],
[[DX_SNIPPET_pdf=""]])
AS_IF([[test $DX_FLAG_ps -eq 1 -o $DX_FLAG_pdf -eq 1]],
[[DX_SNIPPET_latex="## ------------------------------------------------- ##
## Rules specific for LaTeX (shared for PS and PDF). ##
## ------------------------------------------------- ##
DX_V_LATEX = \$(_DX_v_LATEX_\$(V))
_DX_v_LATEX_ = \$(_DX_v_LATEX_\$(AM_DEFAULT_VERBOSITY))
_DX_v_LATEX_0 = @echo \" LATEX \" \$][@;
DX_CLEAN_LATEX = \$(DX_DOCDIR)/latex]dnl
m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
\$(DX_DOCDIR]DX_i[)/latex]])[
"]],
[[DX_SNIPPET_latex=""]])
AS_IF([[test $DX_FLAG_doc -eq 1]],
[[DX_SNIPPET_doc="## --------------------------------- ##
## Format-independent Doxygen rules. ##
## --------------------------------- ##
${DX_SNIPPET_html}\
${DX_SNIPPET_chm}\
${DX_SNIPPET_man}\
${DX_SNIPPET_rtf}\
${DX_SNIPPET_xml}\
${DX_SNIPPET_ps}\
${DX_SNIPPET_pdf}\
${DX_SNIPPET_latex}\
DX_V_DXGEN = \$(_DX_v_DXGEN_\$(V))
_DX_v_DXGEN_ = \$(_DX_v_DXGEN_\$(AM_DEFAULT_VERBOSITY))
_DX_v_DXGEN_0 = @echo \" DXGEN \" \$<;
.PHONY: doxygen-run doxygen-doc \$(DX_PS_GOAL) \$(DX_PDF_GOAL)
.INTERMEDIATE: doxygen-run \$(DX_PS_GOAL) \$(DX_PDF_GOAL)
doxygen-run:]m4_foreach([DX_i], [DX_loop],
[[ \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag]])[
doxygen-doc: doxygen-run \$(DX_PS_GOAL) \$(DX_PDF_GOAL)
]m4_foreach([DX_i], [DX_loop],
[[\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag: \$(DX_CONFIG]DX_i[) \$(pkginclude_HEADERS)
\$(DX_V_DXGEN)\$(DX_ENV) DOCDIR=\$(DX_DOCDIR]DX_i[) \$(DX_DOXYGEN) \$(DX_CONFIG]DX_i[)
\$(A""M_V_at)echo Timestamp >\$][@
]])dnl
[DX_CLEANFILES = \\]
m4_foreach([DX_i], [DX_loop],
[[ \$(DX_DOCDIR]DX_i[)/doxygen_sqlite3.db \\
\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag \\
]])dnl
[ -r \\
\$(DX_CLEAN_HTML) \\
\$(DX_CLEAN_CHM) \\
\$(DX_CLEAN_CHI) \\
\$(DX_CLEAN_MAN) \\
\$(DX_CLEAN_RTF) \\
\$(DX_CLEAN_XML) \\
\$(DX_CLEAN_PS) \\
\$(DX_CLEAN_PDF) \\
\$(DX_CLEAN_LATEX)"]],
[[DX_SNIPPET_doc=""]])
AC_SUBST([DX_RULES],
["${DX_SNIPPET_doc}"])dnl
AM_SUBST_NOTMAKE([DX_RULES])
#For debugging:
#echo DX_FLAG_doc=$DX_FLAG_doc
#echo DX_FLAG_dot=$DX_FLAG_dot
#echo DX_FLAG_man=$DX_FLAG_man
#echo DX_FLAG_html=$DX_FLAG_html
#echo DX_FLAG_chm=$DX_FLAG_chm
#echo DX_FLAG_chi=$DX_FLAG_chi
#echo DX_FLAG_rtf=$DX_FLAG_rtf
#echo DX_FLAG_xml=$DX_FLAG_xml
#echo DX_FLAG_pdf=$DX_FLAG_pdf
#echo DX_FLAG_ps=$DX_FLAG_ps
#echo DX_ENV=$DX_ENV
])
-280
View File
@@ -1,280 +0,0 @@
/* Micro "rsync" implementation.
*
* Copyright (c) 2011, 2012 Joachim Nilsson <troglobit@gmail.com>
*
* 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.
*/
#include <errno.h>
#include <stdlib.h> /* NULL, free() */
#include <string.h> /* strlen() */
#include <strings.h> /* rindex() */
#include <stdio.h>
#include <sys/param.h> /* MAX(), isset(), setbit(), TRUE, FALSE, et consortes. :-) */
#include <sys/stat.h>
#include <sys/types.h>
#include "lite.h"
#include "../helpers.h"
static int makedir(char *buf, size_t buf_len, char *dir, char *name, mode_t mode);
static int prune(char *dst, char **new_files, int new_num);
/**
* rsync - Synchronize contents and optionally remove non-existing backups
* @src: Source directory
* @dst: Destination directory
* @delete: Prune files from @dst that no longer exist in @src.
* @filter: Optional filtering function for source directory.
*
* This is a miniature implementation of the famous rsync for local use only.
* In fact, it is not even a true rsync since it copies all files from @src
* to @dst. The @delete option is useful for creating backups, when set all
* files removed from src since last backup are pruned from the destination
* (backup) directory.
*
* The filter callback, @filter, if provided, is used to determine what files to
* include from the source directory when backing up. If a file is to be skipped
* the callback should simply return zero.
*
* Returns:
* POSIX OK(0), or non-zero with @errno set on error.
*/
int rsync(char *src, char *dst, int delete, int (*filter) (const char *file))
{
char source[256];
char dest[256];
int i = 0, num = 0, result = 0;
char **files; /* Array of file names. */
void copy(char *src, char *dst)
{
errno = 0;
copyfile(src, dst, 0);
if (errno) result++;
}
if (!fisdir(dst))
mkdir(dst, 0755);
if (!fisdir(src)) {
if (!fexist(src))
return 1;
copy(src, dst);
return errno;
}
/* Copy dir as well? */
if (!fisslashdir(src)) {
char *ptr = rindex(src, '/');
if (!ptr)
ptr = src;
else
ptr++;
if (makedir(dest, sizeof(dest), dst, ptr, fmode(src)))
return 1;
dst = dest;
}
num = dir(src, "", filter, &files, 0);
for (i = 0; i < num; i++) {
/* Recursively copy sub-directries */
snprintf(source, sizeof(source), "%s%s%s", src, fisslashdir(src) ? "" : "/", files[i]);
if (fisdir(source)) {
char dst2[256];
strcat(source, "/");
if (makedir (dst2, sizeof(dst2), dst, files[i], fmode(source))) {
result++;
continue;
}
rsync(source, dst2, delete, filter);
continue; /* Next file/dir in @src to copy... */
}
copy(source, dst);
}
/* We ignore any errors from the pruning, that phase albeit useful is only
* cosmetic. --Jocke 2011-03-24 */
if (delete)
prune(dst, files, num);
if (num) {
for (i = 0; i < num; i++)
free(files[i]);
free(files);
}
return result;
}
/* Creates dir/name @mode ... skipping / if dir already ends so. */
static int makedir(char *buf, size_t buf_len, char *dir, char *name, mode_t mode)
{
snprintf(buf, buf_len, "%s%s%s/", dir, fisslashdir(dir) ? "" : "/", name);
if (mkdir(buf, mode))
return 1;
return 0;
}
/* Prune old files, no longer existing on source, from destination directory. */
static int prune(char *dst, char **new_files, int new_num)
{
int i, num, result = 0;
char **files;
int find(char *file) {
int n;
for (n = 0; n < new_num; n++)
if (!strncmp (new_files[n], file, MAX(strlen(new_files[n]), strlen(file))))
return 1;
return 0;
}
num = dir(dst, "", NULL, &files, 0);
if (num) {
for (i = 0; i < num; i++) {
if (!find(files[i])) {
char *name;
size_t len = strlen(files[i]) + 2 + strlen(dst);
name = malloc(len);
if (name) {
snprintf(name, len, "%s%s%s", dst, fisslashdir(dst) ? "" : "/", files[i]);
if (remove(name))
result++;
free(name);
}
}
free(files[i]);
}
free(files);
}
return result;
}
#ifdef UNITTEST
#define BASE "/tmp/.unittest/"
#define SRC BASE "src/"
#define DST BASE "dst/"
char *files[] = {
SRC "sub1/1.tst",
SRC "sub1/2.tst",
SRC "sub1/3.tst",
SRC "sub2/4.tst",
SRC "sub2/5.tst",
SRC "sub2/6.tst",
SRC "sub3/7.tst",
SRC "sub3/8.tst",
SRC "sub3/9.tst",
NULL
};
void cleanup_test(void)
{
system("rm -rf " BASE);
}
void setup_test(void)
{
int i;
char cmd[256];
mode_t dir_modes[] = { 755, 700 };
mode_t file_modes[] = { 644, 600 };
cleanup_test();
mkdir(BASE, 0755);
mkdir(SRC, 0755);
mkdir(DST, 0755);
for (i = 0; files[i]; i++) {
snprintf(cmd, sizeof(cmd), "mkdir -m %d -p `dirname %s`",
dir_modes[i % 2], files[i]);
system(cmd);
snprintf(cmd, sizeof(cmd), "touch %s; chmod %d %s", files[i],
file_modes[i % 2], files[i]);
system(cmd);
}
}
int run_test()
{
#if 0
setup_test();
puts("Before:");
system("tree -np " BASE);
rsync(SRC, DST, 0, NULL);
puts("After:");
system("tree -np " BASE);
cleanup_test();
#endif
setup_test();
rsync(BASE "src", DST, 0, NULL);
puts("Only partial rsync of src <-- No slash!");
system("tree -np " BASE);
#if 0
cleanup_test();
setup_test();
rsync(BASE "src/sub1", BASE "dst", 0, NULL);
puts("Only partial rsync of src/sub1 <-- No slashes!!");
system("tree -np " BASE);
cleanup_test();
setup_test();
rsync(BASE "src/sub1/", DST, 0, NULL);
puts("Only partial rsync of src/sub1/");
system("tree -np " BASE);
cleanup_test();
setup_test();
rsync(BASE "src/sub1", DST, 0, NULL);
puts("Only partial rsync of src/sub1 <-- No slash!");
system("tree -np " BASE);
rsync("/etc", "/var/tmp", 0, NULL);
puts("Real life test:");
system("tree -np /var/tmp");
#endif
return 0;
}
int main(int argc, char *argv[])
{
atexit(cleanup_test);
return run_test();
}
#endif /* UNITTEST */
/**
* Local Variables:
* compile-command: "make -f rsync.mk"
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
-22
View File
@@ -1,22 +0,0 @@
# Unittest makefile for rsync.c
.PHONY: clean
SRC = rsync.c
OBJS = dir.o copyfile.o fexist.o fisdir.o fmode.o
UNIT = rsync.unittest
#CPPFLAGS = -DDEBUG -I../../.. -I../../include
all: build run
clean:
@rm -f $(OBJS) $(UNIT)
# This rule also forces a cleanup of built objects to not leave any object files
# lingering in the tree to interfere with cross builds.
build: clean $(OBJS)
$(CC) $(CFLAGS) $(CPPFLAGS) -o $(UNIT) -DUNITTEST $(SRC) $(OBJS)
@rm -f $(OBJS)
run:
@./$(UNIT)
+3
View File
@@ -0,0 +1,3 @@
*.la
.libs/*
libite_la*
+45
View File
@@ -0,0 +1,45 @@
lib_LTLIBRARIES = libite.la
libite_la_CPPFLAGS = -D_GNU_SOURCE
libite_la_CFLAGS = -W -Wall -Wextra
libite_la_LDFLAGS = $(AM_LDFLAGS) -version-info 8:1:3
libite_la_SOURCES = chomp.c copyfile.c \
conio.c conio.h dir.c \
erasef.c fopenf.c fremove.c \
fexist.c fisdir.c \
fparseln.c fsendfile.c \
ifconfig.c lfile.c \
makepath.c progress.c \
pidfile.c pidfilefn.c \
reallocarray.c rsync.c strtrim.c \
strlcpy.c strlcat.c strtonum.c \
strdupa.h strndupa.h strnlen.h \
strmatch.c systemf.c touchf.c \
telnet.c tempfile.c truncatef.c \
yorn.c which.c \
lite.h strlite.h \
queue.h tree.h
## Distribute these header files in the <libite/...> namespace
pkgincludedir = $(includedir)/libite
pkginclude_HEADERS = lite.h queue.h conio.h tree.h strlite.h strdupa.h \
strndupa.h strnlen.h
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libite.pc
## For compatibility with previous <lite/...> namespace
if COMPAT_SYMLINK
install-data-hook:
link=$(DESTDIR)$(includedir)/lite; \
if [ ! -f $$link ]; then \
$(LN_S) libite $$link; \
fi
uninstall-hook:
link=$(shell readlink $(DESTDIR)$(includedir)/lite); \
if [ "$$link" = "libite" ]; then \
$(RM) $(DESTDIR)$(includedir)/lite; \
fi
endif
+59
View File
@@ -0,0 +1,59 @@
/* Perl inspired chomp() implementation.
*
* Copyright (c) 2014-2021 Joachim Wiberg <troglobit@gmail.com>
*
* 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.
*/
/**
* @file chomp.c
* @author Joachim Wiberg
* @date 2014-2021
* @copyright ISC License
*/
#include <errno.h>
#include <string.h>
/**
* Perl like chomp function, chop off last char(s) if newline.
* @param str String to chomp
*
* This function is like Perl chomp, but it's set to chop of all
* trailing newlines. Useful in combination with fgets().
*
* @returns @a str, or @c NULL with @a errno set, if @a str is not a valid pointer.
* @exception EINVAL if the input argument is not a valid pointer.
*/
char *chomp(char *str)
{
char *p;
if (!str || strlen(str) < 1) {
errno = EINVAL;
return NULL;
}
p = str + strlen(str) - 1;
while (p >= str && *p == '\n')
*p-- = 0;
return str;
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+104
View File
@@ -0,0 +1,104 @@
/* A conio.h like implementation for VTANSI displays.
*
* Copyright (c) 2009-2021 Joachim Wiberg <troglobit@gmail.com>
*
* 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.
*/
/**
* @file conio.c
* @author Joachim Wiberg
* @date 2009-2021
* @copyright ISC License
*/
#include <poll.h>
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
/**
* Probe terminal size
* @param row pointer to integer to store number of rows
* @param col pointer to integer to store number of columns
*
* This function checks if stdin and stdout isatty() and then sets the
* TTY in raw mode to silently ask the size using ANSI escape sequences.
* This is achieved by trying to go to corner 999,999 followed by
* querying the cursor position. Afterwards the TTY is returned to the
* state if was before, e.g. cooked. The number of rows and columns is
* returned in the input arguments to this function.
*
* If stdio is @a not a TTY, then a default 24x80 is returned.
*/
void initscr(int *row, int *col)
{
if (!row || !col)
return;
#if defined(TCSANOW) && defined(POLLIN)
struct termios tc, saved;
struct pollfd fd = { STDIN_FILENO, POLLIN, 0 };
if (!isatty(STDIN_FILENO) || !isatty(STDOUT_FILENO)) {
*row = 24;
*col = 80;
return;
}
/* Disable echo to terminal while probing */
tcgetattr(STDOUT_FILENO, &tc);
saved = tc;
tc.c_cflag |= (CLOCAL | CREAD);
tc.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
tcsetattr(STDOUT_FILENO, TCSANOW, &tc);
/*
* Save cursor pos+attr
* Diable top+bottom margins
* Set cursor at the far bottom,right pos
* Query term for resulting pos
*/
fprintf(stdout, "\e7" "\e[r" "\e[999;999H" "\e[6n");
fflush(stdout);
/*
* Wait here for terminal to echo back \e[row,lineR ...
*/
if (poll(&fd, 1, 300) <= 0 || scanf("\e[%d;%dR", row, col) != 2) {
*row = 24;
*col = 80;
}
/*
* Restore above saved cursor pos+attr
*/
fprintf(stdout, "\e8");
fflush(stdout);
/* Restore terminal */
tcsetattr(STDOUT_FILENO, TCSANOW, &saved);
return;
#else
*row = 24;
*col = 80;
#endif
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+144
View File
@@ -0,0 +1,144 @@
/* A conio.h like implementation for VTANSI displays.
*
* Copyright (c) 2009-2021 Joachim Wiberg <troglobit@gmail.com>
*
* 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.
*/
/**
* @file conio.h
* @author Joachim Wiberg
* @date 2009-2021
* @copyright ISC License
*
* Helper macros and functions for interacting with TTY terminals.
*/
#ifdef __cplusplus
extern "C"
{
#endif
#ifndef LIBITE_CONIO_H_
#define LIBITE_CONIO_H_
#include <stdio.h>
/** Attributes */
#define RESETATTR 0
#define BRIGHT 1
#define DIM 2
#define UNDERSCORE 4
#define BLINK 5 /* May not work on all displays. */
#define REVERSE 7
#define HIDDEN 8
/** Colors for text and background */
#define BLACK 0x0
#define RED 0x1
#define GREEN 0x2
#define BROWN 0x3
#define BLUE 0x4
#define MAGENTA 0x5
#define CYAN 0x6
#define LIGHTGREY 0x7
#define DARKGREY 0x10
#define LIGHTRED 0x11
#define LIGHTGREEN 0x12
#define YELLOW 0x13
#define LIGHTBLUE 0x14
#define LIGHTMAGENTA 0x15
#define LIGHTCYAN 0x16
#define WHITE 0x17
#ifndef SCREEN_WIDTH
#define SCREEN_WIDTH 80 /**< Fallback screen width, possible to override. */
#endif
/** Clear screen and move cursor to 1,1 (upper left) pos. */
#define clrscr() fputs("\033[2J\033[1;1H", stdout)
/** Erases from the current cursor position to the end of the current line. */
#define clreol() fputs("\033[K", stdout)
/** Erases the entire current line. */
#define delline() fputs("\033[2K", stdout)
/** Moves the cursor to the specified position (coordinates) */
#define gotoxy(x,y) fprintf(stdout, "\033[%d;%dH", y, x)
/** Hide Cursor */
#define hidecursor() fputs("\033[?25l", stdout)
/** Show Cursor */
#define showcursor() fputs("\033[?25h", stdout)
/** Set Graphics Mode (attr, color, val) */
#define __set_gm(a,c,v) \
if (!c) \
fprintf(stdout, "\033[%dm", a); \
else \
fprintf(stdout, "\033[%d;%dm", c & 0x10 ? 1 : 0, (c & 0xF) + v)
/** Set text attribute */
#define textattr(attr) __set_gm(attr, 0, 0)
/** Set text color */
#define textcolor(color) __set_gm(RESETATTR, color, 30)
/** Set text background */
#define textbackground(color) __set_gm(RESETATTR, color, 40)
void initscr(int *row, int *col);
/**
* Print table heading, with optional leading newline.
* @param fp output stream
* @param line string to print
* @param nl leading newline or not
* @param attr attribute
*
* @verbatim
* _________________ <-- Empty line with UNDERSCORE to frame first heading
* First heading <-- In normal/RESETATTR
* SUBHEADING <-- In REVERSE and with capital letters like 'top'
* @endverbatim
*/
static inline void printhdr(FILE *fp, const char *line, int nl, int attr)
{
if (attr < 0 || attr > 8)
attr = REVERSE;
fprintf(fp ?: stdout,
"%s\033[%dm%s%*s\033[0m\n",
nl ? "\n" : "", attr, line,
SCREEN_WIDTH - (int)strlen(line), "");
}
/**
* Print reverse mode table heading, e.g. black text on white background.
* @param fp output stream
* @param line string to print
* @param nl leading newline or not
*/
static inline void printheader(FILE *fp, const char *line, int nl)
{
printhdr(fp, line, nl, REVERSE);
}
#endif /* LIBITE_CONIO_H_ */
#ifdef __cplusplus
}
#endif
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+289
View File
@@ -0,0 +1,289 @@
/* Fastinit (finit) copyfile() implementation.
*
* Copyright (c) 2008 Claudio Matsuoka <http://helllabs.org/finit/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* @file copyfile.c
* @author Claudio Matsuoka
* @date 2008
* @copyright MIT License
*/
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include "lite.h"
/* Tests if dst is a directory, if so, reallocates dst and appends src filename returning 1 */
static int adjust_target(const char *src, char **dst)
{
int isdir = 0;
if (fisdir(*dst)) {
int slash = 0;
char *tmp, *ptr = strrchr(src, '/');
if (!ptr)
ptr = (char *)src;
else
ptr++;
tmp = malloc(strlen(*dst) + strlen(ptr) + 2);
if (!tmp) {
errno = EISDIR;
return 0;
}
isdir = 1; /* Free dst before exit! */
slash = fisslashdir(*dst);
sprintf(tmp, "%s%s%s", *dst, slash ? "" : "/", ptr);
*dst = tmp;
}
return isdir;
}
/* Actual copy loop, used by both copyfile() and fcopyfile()
* breaks loop on error and EOF */
static ssize_t do_copy(int in, int out, size_t num, char *buffer, size_t len)
{
ssize_t ret = 0, size = 0;
do {
size_t count = num > len ? len : num;
ret = read(in, buffer, count);
if (ret <= 0) {
if (ret == -1 && EINTR == errno)
continue;
break;
}
if (ret > 0)
size += write(out, buffer, ret);
num -= count;
} while (num > 0);
return size;
}
static void set_mtime(int in, int out)
{
struct stat st;
struct timespec tv[2];
if (fstat(in, &st))
return;
tv[0] = st.st_atim;
tv[1] = st.st_mtim;
futimens(out, tv);
}
/**
* Copy a file to another.
* @param src Full path name to source file.
* @param dst Full path name to target file.
* @param len Number of bytes to copy, zero (0) for entire file.
* @param opt An option mask of ::LITE_FOPT_COPYFILE_SYM, ::LITE_FOPT_KEEP_MTIME
*
* This is a C implementation of the command line cp(1) utility. It is one
* of the classic missing links in the UNIX C library. This version is from
* the finit project, http://helllabs.org/finit/, which is a reimplementation
* of fastinit for the Asus EeePC.
*
* The @a opt field replaces the @a sym argument in previous releases
* and works as follows. To maintain backwards compatibility with @a
* sym the ::LITE_FOPT_COPYFILE_SYM has a value of @c 1. Supported
* option flags are:
*
* - ::LITE_FOPT_COPYFILE_SYM Recreate symlink or follow to copy target
* - ::LITE_FOPT_KEEP_MTIME Preserve modification time
*
* @returns The number of bytes copied, or zero, which may be an error
* (check @a errno, see Exceptions below), but it may also indicate that
* @a src was empty. See exceptions, below.
*
* @exception EISDIR if @a src is a directory, since copyfile() is not recursive.
*/
ssize_t copyfile(const char *src, const char *dst, int len, int opt)
{
char *buffer, *dest = (char *)dst;
int sym = (opt & LITE_FOPT_COPYFILE_SYM) != 0;
int keep_mtim = (opt & LITE_FOPT_KEEP_MTIME) != 0;
int in, out, isdir = 0, saved_errno = 0;
size_t num;
ssize_t size = 0;
struct stat st;
errno = 0;
buffer = malloc(BUFSIZ);
if (!buffer)
return 0;
if (fisdir(src)) {
saved_errno = EISDIR; /* Error: source is a directory */
goto exit;
}
/* Check if target is a directory, then append src filename. */
isdir = adjust_target(src, &dest);
/* Check if the source file is a symlink ... */
if (stat(src, &st)) {
size = -1;
goto exit;
}
/* ... only try readlink() if symlink and @sym is set. */
if (sym && (st.st_mode & S_IFMT) == S_IFLNK) {
size = readlink(src, buffer, BUFSIZ);
if (size > 0) {
if (size >= (ssize_t)BUFSIZ) {
saved_errno = ENOBUFS;
size = -1;
} else {
buffer[size] = 0;
size = !symlink(buffer, dest);
}
}
/* Don't fall back to copy, that is a potentially
* dangerous race condition, see CWE-367. */
goto exit;
}
/* 0: copy entire file */
if (len == 0)
num = st.st_size;
else
num = (size_t)len;
in = open(src, O_RDONLY);
if (in < 0) {
saved_errno = errno;
goto exit;
}
out = open(dest, O_WRONLY | O_CREAT | O_TRUNC, st.st_mode);
if (out < 0) {
close(in);
saved_errno = errno;
goto exit;
}
size = do_copy(in, out, num, buffer, BUFSIZ);
if (!size && errno)
saved_errno = errno;
else if (keep_mtim)
set_mtime(in, out);
close(out);
close(in);
exit:
free(buffer);
if (isdir)
free(dest);
errno = saved_errno;
return size;
}
/**
* Move a file to another location
* @param src Source file.
* @param dst Target file, or location.
*
* This is a C implementation of the command line mv(1) utility.
* Usually the rename() API is sufficient, but not when moving across
* file system boundaries.
*
* The @p src argument must include the full path to the source file,
* whereas the @p dst argument may only be a directory, in which case
* the same file name from @p src is used.
*
* @returns POSIX OK(0), or non-zero with @a errno set.
*/
int movefile(const char *src, const char *dst)
{
char *dest = (char *)dst;
int isdir, result = 0;
/* Check if target is a directory, then append the src base filename. */
isdir = adjust_target(src, &dest);
if (rename(src, dest)) {
if (errno == EXDEV) {
errno = 0;
copyfile(src, dest, 0, 1);
if (errno)
result = 1;
else
result = remove(src);
} else {
result = 1;
}
}
if (isdir)
free(dest);
return result;
}
/**
* Copy between FILE *fp.
* @param src Source FILE.
* @param dst Destination FILE.
*
* @returns POSIX OK(0), or non-zero with @a errno set on error.
*/
int fcopyfile(FILE *src, FILE *dst)
{
char *buf;
if (!src || !dst) {
errno = EINVAL;
return -1;
}
buf = malloc(BUFSIZ);
if (!buf)
return -1;
while (fgets(buf, BUFSIZ, src))
fputs(buf, dst);
free(buf);
return 0;
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+136
View File
@@ -0,0 +1,136 @@
/* Functions for operating on files in directories.
*
* Copyright (c) 2008-2021 Joachim Wiberg <troglobit@gmail.com>
*
* 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.
*/
/**
* @file dir.c
* @author Joachim Wiberg
* @date 2008-2021
* @copyright ISC License
*/
#include <errno.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
static const char *matcher_type = NULL;
static int (*matcher_filter) (const char *file) = NULL;
static int matcher(const struct dirent *entry)
{
char *pos = strrchr(entry->d_name, '.');
if (matcher_filter && !matcher_filter(entry->d_name))
/* User matcher overrides the rest. */
return 0;
/* Skip current dir "." from list of files. */
if ((1 == strlen(entry->d_name) && entry->d_name[0] == '.') ||
(2 == strlen(entry->d_name) && !strcmp(entry->d_name, "..")))
return 0;
/* filetype == "" */
if (matcher_type[0] == 0)
return 1;
/* Entry has no "." */
if (!pos)
return 0;
return !strcmp(pos, matcher_type);
}
/**
* List all files of a certain type in the given directory.
* @param dir Base directory for dir operation.
* @param type File type suffix, e.g. ".cfg".
* @param filter Optional file name filter.
* @param list Pointer to an array of file names.
* @param strip Flag, if set dir() strips the file type.
*
* This function returns a @a list of files, matching the @a type
* suffix, in the given directory @a dir.
*
* The @a list argument is a pointer to where to store the dynamically
* allocated list of file names. This list should be free'd by first
* calling free() on each file name and then on the list itself.
*
* If @a filter is not @c NULL it will be called for each file found.
* If @a filter returns non-zero the @a file argument is included in the
* resulting @a list. If @a filter returns zero for given @a file it is
* discarded. If the @a strip flag is set the resulting @a list of
* files has their file type stripped, including the dot. So a match
* "config0.cfg" would be returned as "config0".
*
* @returns The number of files in @a list, zero if no matching files of
* @a type, or non-zero on error with @a errno set.
*/
int dir(const char *dir, const char *type, int (*filter) (const char *file), char ***list, int strip)
{
int i, n, num = 0;
char **files;
struct dirent **namelist;
if (!list) {
errno = EINVAL;
return -1;
}
if (!dir)
/* Assuming current directory */
dir = ".";
if (!type)
/* Assuming all files. */
type = "";
matcher_type = type;
matcher_filter = filter;
n = scandir(dir, &namelist, matcher, alphasort);
if (n < 0)
return -1;
if (n > 0) {
files = (char **)malloc(n * sizeof(char *));
for (i = 0; i < n; i++) {
if (files) {
char *name = namelist[i]->d_name;
char *type = strrchr(name, '.');
if (type && strip)
*type = 0;
files[i] = strdup(name);
num++;
}
free(namelist[i]);
}
if (num)
*list = files;
}
if (namelist)
free(namelist);
return num;
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+72
View File
@@ -0,0 +1,72 @@
/* Formatted erase()
*
* Copyright (c) 2021 Joachim Wiberg <troglobit@gmail.com>
*
* 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.
*/
/**
* @file erasef.c
* @author Joachim Wiberg
* @date 2021
* @copyright ISC License
*/
#include <errno.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#include "lite.h"
/**
* Like erase() but with formatted string support.
* @param fmt Formatted string to be composed into a pathname
*
* This is a wrapper for the erase() function in lite.h, lessening the
* burden of having to compose the filename from parts in a seprate
* buffer.
*
* @returns Upon successful completion erasef() returns POSIX OK(0),
* otherwise, -1 is returned and @a errno is set to indicate the error.
*/
int erasef(const char *fmt, ...)
{
va_list ap;
char *file;
int len;
va_start(ap, fmt);
len = vsnprintf(NULL, 0, fmt, ap);
va_end(ap);
file = alloca(len + 1);
if (!file) {
errno = ENOMEM;
return -1;
}
va_start(ap, fmt);
vsnprintf(file, len + 1, fmt, ap);
va_end(ap);
return erase(file);
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+11 -6
View File
@@ -21,17 +21,23 @@
* THE SOFTWARE.
*/
/**
* @file fexist.c
* @author Claudio Matsuoka
* @date 2008
* @copyright MIT License
*/
#include <errno.h>
#include <unistd.h>
/**
* fexist - Check if a file exists in the file system.
* @file: File to look for, with full path.
* Check if a file exists in the file system.
* @param file File to look for, with full path.
*
* Returns:
* %TRUE(1) if the file exists, otherwise %FALSE(0).
* @returns @c TRUE(1) if the @a file exists, otherwise @c FALSE(0).
*/
int fexist(char *file)
int fexist(const char *file)
{
if (!file) {
errno = EINVAL;
@@ -46,7 +52,6 @@ int fexist(char *file)
/**
* Local Variables:
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
+12 -8
View File
@@ -21,22 +21,27 @@
* THE SOFTWARE.
*/
#include <sys/types.h>
/**
* @file fisdir.c
* @author Claudio Matsuoka
* @date 2008
* @copyright MIT License
*/
#include <sys/stat.h>
#include <unistd.h>
/**
* fexist - Check if a file exists and is a directory.
* @file: File to look for, with full path.
* Check if a path exists and is a directory.
* @param path Path to file or directory
*
* Returns:
* %TRUE(1) if the file exists and is a directory, otherwise %FALSE(0).
* @returns @c TRUE(1) if @p path exists and is a directory, otherwise @c FALSE(0).
*/
int fisdir(char *file)
int fisdir(const char *path)
{
struct stat sb;
if (!stat(file, &sb) && S_ISDIR(sb.st_mode))
if (!stat(path, &sb) && S_ISDIR(sb.st_mode))
return 1;
return 0;
@@ -44,7 +49,6 @@ int fisdir(char *file)
/**
* Local Variables:
* version-control: t
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
+70
View File
@@ -0,0 +1,70 @@
/* Formatted fopen()
*
* Copyright (c) 2021 Joachim Wiberg <troglobit@gmail.com>
*
* 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.
*/
/**
* @file fopenf.c
* @author Joachim Wiberg
* @date 2021
* @copyright ISC License
*/
#include <errno.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
/**
* Open a file based on the formatted string and optional arguments
* @param mode An fopen() mode string, e.g. "w+"
* @param fmt Formatted string to be composed into a pathname
*
* This function is an extension to the fopen() family, lessening the burden
* of first having to compose the filename from parts in a seprate buffer.
*
* @returns Upon successful completion, fopenf() returns a FILE pointer.
* Otherwise, @c NULL is returned and @a errno is set to indicate the
* error.
*/
FILE *fopenf(const char *mode, const char *fmt, ...)
{
va_list ap;
char *file;
int len;
va_start(ap, fmt);
len = vsnprintf(NULL, 0, fmt, ap);
va_end(ap);
file = alloca(len + 1);
if (!file) {
errno = ENOMEM;
return NULL;
}
va_start(ap, fmt);
vsnprintf(file, len + 1, fmt, ap);
va_end(ap);
return fopen(file, mode);
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+221
View File
@@ -0,0 +1,221 @@
/* $NetBSD: fparseln.c,v 1.10 2009/10/21 01:07:45 snj Exp $ */
/*
* Copyright (c) 1997 Christos Zoulas. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file fparseln.c
* @author Christos Zoulas
* @date 1997
* @copyright 2-clause BSD License
*/
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "lite.h"
#ifndef _DIAGASSERT
#define _DIAGASSERT(t)
#endif
static int isescaped(const char *, const char *, int);
/* isescaped():
* Return true if the character in *p that belongs to a string
* that starts in *sp, is escaped by the escape character esc.
*/
static int
isescaped(const char *sp, const char *p, int esc)
{
const char *cp;
size_t ne;
_DIAGASSERT(sp != NULL);
_DIAGASSERT(p != NULL);
/* No escape character */
if (esc == '\0')
return 0;
/* Count the number of escape characters that precede ours */
for (ne = 0, cp = p; --cp >= sp && *cp == esc; ne++)
continue;
/* Return true if odd number of escape characters */
return (ne & 1) != 0;
}
/**
* Read a line from a file parsing continuations and trailing newlines
* @param fp FILE pointer to read from
* @param size The resulting length of the string, unused if @c NULL
* @param lineno Incremented with number of lines read, unused if @c NULL
* @param str Characters to look for, escape character, continuation, and comment
* @param flags ::FPARSELN_UNESCCOMM, ::FPARSELN_UNESCCONT, ::FPARSELN_UNESCESC, ::FPARSELN_UNESCREST, ::FPARSELN_UNESCALL
*
* This function reads a line from a file, parsing continuations ending
* in '\' and eliminating trailing newlines, or comments starting with
* the comment char '#'.
*
* If @a size is not @c NULL, the resulting length of the returned string
* is stored in @a size.
*
* If @a lineno is not @c NULL, it is incremented for each actual line
* read from @a fp.
*
* @returns the line read from @a fp, or @c NULL on EOF or error.
*/
char *
fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags)
{
static const char dstr[3] = { '\\', '\\', '#' };
ssize_t s;
size_t len, ptrlen;
char *buf;
char *ptr, *cp;
int cnt;
char esc, con, nl, com;
_DIAGASSERT(fp != NULL);
len = 0;
buf = NULL;
ptrlen = 0;
ptr = NULL;
cnt = 1;
if (str == NULL)
str = dstr;
esc = str[0];
con = str[1];
com = str[2];
/*
* XXX: it would be cool to be able to specify the newline character,
* getdelim(3) does let us, but supporting it would diverge from BSDs.
*/
nl = '\n';
flockfile(fp);
while (cnt) {
cnt = 0;
if (lineno)
(*lineno)++;
s = getline(&ptr, &ptrlen, fp);
if (s < 0)
break;
if (s && com) { /* Check and eliminate comments */
for (cp = ptr; cp < ptr + s; cp++)
if (*cp == com && !isescaped(ptr, cp, esc)) {
s = cp - ptr;
cnt = s == 0 && buf == NULL;
break;
}
}
if (s && nl) { /* Check and eliminate newlines */
cp = &ptr[s - 1];
if (*cp == nl)
s--; /* forget newline */
}
if (s && con) { /* Check and eliminate continuations */
cp = &ptr[s - 1];
if (*cp == con && !isescaped(ptr, cp, esc)) {
s--; /* forget continuation char */
cnt = 1;
}
}
if (s == 0) {
/*
* nothing to add, skip realloc except in case
* we need a minimal buf to return an empty line
*/
if (cnt || buf != NULL)
continue;
}
if ((cp = realloc(buf, len + s + 1)) == NULL) {
funlockfile(fp);
free(buf);
free(ptr);
return NULL;
}
buf = cp;
(void) memcpy(buf + len, ptr, s);
len += s;
buf[len] = '\0';
}
funlockfile(fp);
free(ptr);
if ((flags & FPARSELN_UNESCALL) != 0 && esc && buf != NULL &&
strchr(buf, esc) != NULL) {
ptr = cp = buf;
while (cp[0] != '\0') {
int skipesc;
while (cp[0] != '\0' && cp[0] != esc)
*ptr++ = *cp++;
if (cp[0] == '\0' || cp[1] == '\0')
break;
skipesc = 0;
if (cp[1] == com)
skipesc += (flags & FPARSELN_UNESCCOMM);
if (cp[1] == con)
skipesc += (flags & FPARSELN_UNESCCONT);
if (cp[1] == esc)
skipesc += (flags & FPARSELN_UNESCESC);
if (cp[1] != com && cp[1] != con && cp[1] != esc)
skipesc = (flags & FPARSELN_UNESCREST);
if (skipesc)
cp++;
else
*ptr++ = *cp++;
*ptr++ = *cp++;
}
*ptr = '\0';
len = strlen(buf);
}
if (size)
*size = len;
return buf;
}
+68
View File
@@ -0,0 +1,68 @@
/* Formatted fremove()
*
* Copyright (c) 2021 Joachim Wiberg <troglobit@gmail.com>
*
* 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.
*/
/**
* @file fremove.c
* @author Joachim Wiberg
* @date 2021
* @copyright ISC License
*/
#include <errno.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
/**
* Remove a file based on the formatted string and optional arguments
* @param fmt Formatted string to be composed into a pathname
*
* This function is an extension to remove(), lessening the burden of
* first having to compose the filename from parts in a seprate buffer.
*
* @returns same as remove(3), with an extra @a errno, @c ENOBUFS if
* alloca() fails to get a temporary buffer for composing the file name.
*/
int fremove(const char *fmt, ...)
{
va_list ap;
char *file;
int len;
va_start(ap, fmt);
len = vsnprintf(NULL, 0, fmt, ap);
va_end(ap);
file = alloca(len + 1);
if (!file) {
errno = ENOBUFS;
return -1;
}
va_start(ap, fmt);
vsnprintf(file, len + 1, fmt, ap);
va_end(ap);
return remove(file);
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+92
View File
@@ -0,0 +1,92 @@
/* Copy data between file streams
*
* Copyright (c) 2013 Tobias Waldekranz <tobias@waldekranz.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* @file fsendfile.c
* @author Tobias Waldekranz
* @date 2013
* @copyright MIT License
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
/**
* Copy data between file streams.
* @param src Source stream
* @param dst Destination stream
* @param len Number of bytes to copy
*
* The @p dst argument may be @c NULL, in which case @a len bytes are
* read and discarded from @a src. This can be useful for streams where
* seeking is not permitted. Additionally, @a len may be the special
* value zero (0), in which case fsendfile() copies until @c EOF is seen
* on @a src.
*
* @returns The number of bytes copied. If an error is detected -1 is
* returned and @a errno will be set accordingly.
*/
ssize_t fsendfile(FILE *src, FILE *dst, size_t len)
{
char *buf;
size_t tot = 0;
ssize_t blk = BUFSIZ, num = 0;
if (!src) {
errno = EINVAL;
return -1;
}
buf = malloc(BUFSIZ);
if (!buf)
return -1;
while (!len || tot < len) {
if (len && ((len - tot) < BUFSIZ))
blk = len - tot;
num = fread(buf, 1, blk, src);
if (num == 0)
break;
if (dst && (fwrite(buf, num, 1, dst) != 1)) {
num = -1;
break;
}
tot += num;
}
free(buf);
return (num == -1) ? -1 : (ssize_t)tot;
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+98
View File
@@ -0,0 +1,98 @@
/* Fastinit (finit) ifconfig() implementation.
*
* Copyright (c) 2008-2010 Claudio Matsuoka <http://helllabs.org/finit/>
* Copyright (C) 2009-2021 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* @file ifconfig.c
* @author Claudio Matsuoka
* @author Joachim Wiberg
* @date 2008-2021
* @copyright MIT License
*/
#include <arpa/inet.h>
#include <errno.h>
#include <net/if.h>
#include <netinet/in.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <unistd.h>
extern size_t strlcpy(char *dst, const char *src, size_t siz);
/**
* Basic ifconfig like operations on an interface
* @param ifname Name of interface to operate on
* @param addr If @p up then set this optional IPv4 address
* @param mask If @p up and @p addr, and @p addr is not @c INADDR_ANY, then set netmask
* @param up Control @c IFF_UP flag on interface
*
* @returns POSIX OK(0) on success, or non-zero on error.
*/
int ifconfig(const char *ifname, const char *addr, const char *mask, int up)
{
int sd, ret = -1;
struct ifreq ifr;
struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr;
if ((sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0)
return -1;
memset(&ifr, 0, sizeof (ifr));
strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
ifr.ifr_addr.sa_family = AF_INET;
if (up) {
if (addr) {
if (inet_pton(AF_INET, addr, &sin->sin_addr) == 1)
ret = ioctl(sd, SIOCSIFADDR, &ifr);
}
/* Non-zero IP address */
if (mask && addr && strcmp(addr, "0.0.0.0")) {
if (inet_pton(AF_INET, mask, &sin->sin_addr) == -1)
ret = ioctl(sd, SIOCSIFNETMASK, &ifr);
}
}
if (!ioctl(sd, SIOCGIFFLAGS, &ifr)) {
if (up)
ifr.ifr_flags |= IFF_UP;
else
ifr.ifr_flags &= ~IFF_UP;
ret = ioctl(sd, SIOCSIFFLAGS, &ifr);
}
close(sd);
return ret;
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+196
View File
@@ -0,0 +1,196 @@
/* Parse UNIX /etc configuration files like /etc/protocols and /etc/services
*
* Copyright (c) 2015-2021 Joachim Wiberg <troglobit@gmail.com>
*
* 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.
*/
/**
* @file lfile.c
* @author Joachim Wiberg
* @date 2015-2021
* @copyright ISC License
*/
#include <errno.h>
#include <stdio.h> /* FILE */
#include <stdlib.h> /* atoi() */
#include <string.h> /* strlen(), strncmp(), strtok_r() */
#include <sys/param.h> /* MAX() */
/** @private for internal use only */
typedef struct lfile {
FILE *fp; /**< FILE pointer to current stream */
char buf[256]; /**< Internal buffer, limted to 256 bytes per line */
char *save; /**< Internal save pointer */
const char *sep; /**< Record separator, from lfopen() */
} lfile_t;
/**
* Open file and return parsing context.
* @param file File to parse
* @param sep Separator(s) to use in lftok()
*
* @returns Pointer to an @a lfile_t parser context, or @c NULL on error.
*/
lfile_t *lfopen(const char *file, const char *sep)
{
lfile_t *lf;
if (!file || !sep) {
errno = EINVAL;
return NULL;
}
/* Use calloc for clearing buf on behalf of lftok() */
lf = calloc(sizeof(*lf), sizeof(char));
if (lf) {
lf->fp = fopen(file, "r");
lf->sep = sep;
lf->save = lf->buf;
if (!lf->fp) {
free(lf);
return NULL;
}
}
return lf;
}
/**
* Close a parser context.
* @param lf: Pointer to @a lfile_t parser context from lfopen()
*/
void lfclose(lfile_t *lf)
{
if (!lf)
return;
if (lf->fp)
fclose(lf->fp);
free(lf);
}
/**
* Get next token in file
* @param lf: Pointer to @a lfile_t parser context from lfopen()
*
* @returns Next token, read from file previously opened with lfopen(),
* or @c NULL if EOF.
*/
char *lftok(lfile_t *lf)
{
char *token;
if (!lf || !lf->fp || !lf->sep) {
errno = EINVAL;
return NULL;
}
token = strtok_r(NULL, lf->sep, &lf->save);
if (token)
return token;
while (fgets(lf->buf, sizeof(lf->buf), lf->fp)) {
if (lf->buf[0] == '#')
continue;
token = strtok_r(lf->buf, lf->sep, &lf->save);
if (token)
return token;
}
errno = ENOENT;
return NULL;
}
/**
* Find key in file
* @param lf Pointer to @a lfile_t parser context from lfopen()
* @param key Key to look for
*
* Locate @a key from the current position in the file parser context
* returned from lfopen(). Please note, the search for @a key does not
* start from the beginning of the file, it searches from the current
* position. To restart search from the beginning use rewind() on the
* lf->fp.
*
* @returns The value to @a key, or @c NULL if not found.
*/
char *lfgetkey(lfile_t *lf, const char *key)
{
char *token;
while ((token = lftok(lf))) {
if (token[0] == '#')
continue;
if (!strncmp(token, key, MAX(strlen(token), strlen(key))))
return lftok(lf);
}
return NULL;
}
/**
* Same as lfgetkey() but returns an integer.
* @param lf Pointer to @a lfile_t parser context from lfopen()
* @param key Key to look for
*
* This function is the same as lfgetkey() but returns the positive
* integer value for the matching @a key, if found.
*
* @returns The positive integer value for @a key, or -1 if not found.
*/
int lfgetint(lfile_t *lf, const char *key)
{
char *token = lfgetkey(lf, key);
if (token)
return atoi(token);
return -1;
}
/**
* Find the integer value for key in a file.
* @param file File to search for @a key
* @param sep Separator for tokens in @a file
* @param key Key to look for in @a file
*
* This is a convenience wrapper for lfopen(), lfgetint(), and
* lfclose().
*
* @returns The positive integer value for @a key, or -1 if not found.
*/
int fgetint(const char *file, const char *sep, const char *key)
{
int val = -1;
lfile_t *lf;
lf = lfopen(file, sep);
if (lf) {
val = lfgetint(lf, key);
lfclose(lf);
}
return val;
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+11
View File
@@ -0,0 +1,11 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: @PACKAGE@
Description: Frog DNA, basically
Version: @VERSION@
Requires:
Libs: -L${libdir} -lite
Cflags: -I${includedir} -D_LIBITE_LITE
+260
View File
@@ -0,0 +1,260 @@
/* Collection of frog DNA
*
* Copyright (c) 2008-2010 Claudio Matsuoka <cmatsuoka@gmail.com>
* Copyright (c) 2008-2021 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* Collection of frog DNA
* @file lite.h
* @author Claudio Matsuoka (2008-2010)
* @author Joachim Wiberg (2008-2021)
* @copyright MIT License
*
* The latest version of this manual and the libite (-lite) software
* library are available at https://github.com/troglobit/libite/
*/
#ifdef __cplusplus
extern "C"
{
#endif
#ifndef LIBITE_LITE_H_
#define LIBITE_LITE_H_
#include <errno.h>
#include <fcntl.h> /* Definition of AT_* constants for utimensat() */
#include <stdio.h>
#include <stdint.h> /* uint8_t, uint16_t, uint32_t, INT32_MAX, etc. */
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/param.h> /* MAX(), isset(), setbit(), TRUE, FALSE, et consortes. :-) */
#include <unistd.h>
#include "strlite.h"
/*
* fparseln() specific operation flags.
*/
#define FPARSELN_UNESCESC 0x01 /**< Remove escape preceding an escaped comment. */
#define FPARSELN_UNESCCONT 0x02 /**< Remove escape preceding an escaped continuation. */
#define FPARSELN_UNESCCOMM 0x04 /**< Remove escape preceding an escaped escape. */
#define FPARSELN_UNESCREST 0x08 /**< Remove escape preceding any other character. */
#define FPARSELN_UNESCALL 0x0f /**< All of the above. */
/*
* copyfile() and rsync() option flags
*/
#define LITE_FOPT_RSYNC_DELETE 0x01 /**< Prune files from destination that are not in source */
#define LITE_FOPT_COPYFILE_SYM 0x01 /**< Recreate symlink or follow to copy target */
#define LITE_FOPT_KEEP_MTIME 0x02 /**< Preserve modification time */
typedef struct lfile lfile_t; /**< Opqaue context struct for lfile APIs */
typedef struct sdbuf sdbuf_t; /**< Opqaue context struct for telnet APIs */
char *chomp (char *str);
int erasef (const char *fmt, ...);
char *fparseln (FILE *, size_t *, size_t *, const char[3], int);
int fexist (const char *file);
int fisdir (const char *path);
FILE *fopenf (const char *mode, const char *fmt, ...);
int fremove (const char *fmt, ...);
FILE *tempfile (void);
ssize_t copyfile (const char *src, const char *dst, int len, int opt);
int movefile (const char *src, const char *dst);
int fcopyfile (FILE *src, FILE *dst);
ssize_t fsendfile (FILE *src, FILE *dst, size_t len);
int truncatef (off_t length, const char *fmt, ...);
int ifconfig (const char *ifname, const char *addr, const char *mask, int up);
lfile_t*lfopen (const char *file, const char *sep);
void lfclose (lfile_t *lf);
char *lftok (lfile_t *lf);
char *lfgetkey (lfile_t *lf, const char *key);
int lfgetint (lfile_t *lf, const char *key);
int fgetint (const char *file, const char *sep, const char *key);
int fmkpath (mode_t mode, const char *fmt, ...);
int mkpath (const char *dir, mode_t mode);
int makepath (const char *dir);
int dir (const char *dir, const char *type, int (*filter) (const char *file), char ***list, int strip);
int rsync (char *src, char *dst, int opt, int (*filter) (const char *file));
int pidfile (const char *basename);
int pidfile_signal(const char *pidfile, int signal);
pid_t pidfile_read (const char *pidfile);
pid_t pidfile_poll (const char *pidfile);
void *reallocarray(void *optr, size_t nmemb, size_t size);
void progress (int percent, int max_width);
void progress_simple(int percent);
int systemf (const char *fmt, ...);
sdbuf_t*telnet_open (int addr, short port);
int telnet_close (sdbuf_t *ctx);
int telnet_expect (sdbuf_t *ctx, char *script[], FILE *output);
int telnet_session (int addr, short port, char *script[], FILE *output);
int touchf (const char *fmt, ...);
int yorn (const char *fmt, ...);
char *which (const char *cmd);
int whichp (const char *cmd);
#ifndef touch
#include <sys/stat.h> /* utimensat() */
#include <sys/time.h> /* utimensat() on *BSD */
/**
* Create a file, ignoring errors for already existing files
* @param path Path to file to create.
*
* @returns POSIX OK(0), or non-zero on error.
*/
static inline int touch(const char *path)
{
if (utimensat(AT_FDCWD, path, NULL, 0)) {
if (errno == ENOENT)
return mknod((path), S_IFREG|0644, 0);
return -1;
}
return 0;
}
#endif
#ifndef makedir
/**
* Create a directory, ignoring errors for already existing files
* @param path Path to directory to create.
*
* @returns POSIX OK(0), or non-zero on error.
*/
static inline int makedir(const char *path, mode_t mode)
{
if (mkdir(path, mode) && errno != EEXIST)
return -1;
return 0;
}
#endif
#ifndef makefifo
/**
* Create a FIFO, ignoring errors for already existing files
* @param path Path to FIFO to create.
*
* @returns POSIX OK(0), or non-zero on error.
*/
static inline int makefifo(const char *path, mode_t mode)
{
if (mkfifo(path, mode) && errno != EEXIST)
return -1;
return 0;
}
#endif
#ifndef erase
/**
* Remove a file, ignoring errors for missing files
* @param path Path to file to remove.
*
* @returns POSIX OK(0), or non-zero on error.
*/
static inline int erase(const char *path)
{
if (remove(path) && errno != ENOENT)
return -1;
return 0;
}
#endif
#ifndef chardev
# define chardev(x,m,maj,min) mknod((x), S_IFCHR|(m), makedev((maj),(min)))
#endif
#ifndef blkdev
# define blkdev(x,m,maj,min) mknod((x), S_IFBLK|(m), makedev((maj),(min)))
#endif
#ifndef S_ISEXEC
# define S_ISEXEC(m) (((m) & S_IXUSR) == S_IXUSR)
#endif
/* Unline isset(), setbit() et al, these work with integers/shorts/longwords/etc. */
#ifndef ISCLR
#define ISCLR(word,bit) ((word & (1 << (bit)) ? 0 : 1)) /**< Is bit cleared in word? */
#endif
#ifndef ISSET
#define ISSET(word,bit) ((word & (1 << (bit)) ? 1 : 0)) /**< Is bit set in word? */
#endif
#ifndef ISOTHER
#define ISOTHER(word,bit) ((word & ~(1 << (bit)) ? 1 : 0)) /**< Is any other bit set? */
#endif
#ifndef SETBIT
#define SETBIT(word,bit) (word |= (1 << (bit))) /**< Set bit in word. */
#endif
#ifndef CLRBIT
#define CLRBIT(word,bit) (word &= ~(1 << (bit))) /**< Clear bit in word. */
#endif
/* From The Practice of Programming, by Kernighan and Pike */
#ifndef NELEMS
#define NELEMS(array) (sizeof(array) / sizeof(array[0])) /**< Number of elements in array. */
#endif
/**
* Does directory end with a slash?
* @param dir Path string to check.
*
* @returns @c TRUE(1) or @c FALSE(0)
*/
static inline int fisslashdir(const char *dir)
{
if (!dir)
return 0;
if (strlen(dir) > 0)
return dir[strlen(dir) - 1] == '/';
return 0;
}
/* Compat */
#define copy_filep(src, dst) fcopyfile(src, dst)
#define pidfile_read_pid(file) pidfile_read(file)
#define signal_pidfile(file, signo) pidfile_signal(file, signo)
#endif /* LIBITE_LITE_H_ */
#ifdef __cplusplus
}
#endif
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+115
View File
@@ -0,0 +1,115 @@
/* mkpath() -- Create all components leading up to a given directory
*
* Copyright (c) 2013-2021 Joachim Wiberg <troglobit@gmail.com>
*
* 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.
*/
/**
* @file makepath.c
* @author Joachim Wiberg
* @date 2013-2021
* @copyright ISC License
*/
#include <errno.h>
#include <libgen.h>
#include <stdarg.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "lite.h"
/**
* makepath() but takes a mode_t argument.
* @param dir Directory to created, relative or absolute
* @param mode A &mode_t mode to create @a dir with
*
* @returns POSIX OK(0) on success, otherwise -1 with @a errno set.
*/
int mkpath(const char *dir, mode_t mode)
{
struct stat sb;
if (!dir) {
errno = EINVAL;
return -1;
}
if (!stat(dir, &sb))
return 0;
mkpath(dirname(strdupa(dir)), mode);
return mkdir(dir, mode);
}
/**
* Formatted version of mkpath().
* @param mode A mode_t mode to create directories with
* @param fmt Formatted string to be composed into a pathname
*
* @note Notice the swapped arguments, compared to mkpath()!
*
* @returns POSIX OK(0) on success, otherwise -1 with @a errno set.
*/
int fmkpath(mode_t mode, const char *fmt, ...)
{
va_list ap;
char *path;
int len;
va_start(ap, fmt);
len = vsnprintf(NULL, 0, fmt, ap);
va_end(ap);
path = alloca(len + 1);
if (!path) {
errno = ENOMEM;
return -1;
}
va_start(ap, fmt);
len = vsnprintf(path, len + 1, fmt, ap);
va_end(ap);
return mkpath(path, mode);
}
/**
* Create all components of the specified directory.
* @param dir Directory to create.
*
* @note It is strongly recommended to use mkpath() over this function
* since it has the @a mode argument while this function default to
* 0777, which in most cases is insecure.
*
* @returns POSIX OK (0) on success, otherwise -1 and @a errno set
* appropriately.
*
* @exception EINVAL on bad argument, or
* @exception ENOMEM when it fails allocating temporary memory.
*
* For other error codes see the mkdir(2) syscall description.
*/
int makepath(const char *dir)
{
return mkpath(dir, 0777);
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+153
View File
@@ -0,0 +1,153 @@
/* Updated by troglobit for libite/finit/uftpd projects 2016/07/04 */
/* $OpenBSD: pidfile.c,v 1.11 2015/06/03 02:24:36 millert Exp $ */
/* $NetBSD: pidfile.c,v 1.4 2001/02/19 22:43:42 cgd Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jason R. Thorpe.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file pidfile.c
* @author NetBSD Foundation Inc.
* @date 1999
* @copyright 2-clause BSD License
*/
#include <sys/stat.h> /* utimensat() */
#include <sys/time.h> /* utimensat() on *BSD */
#include <sys/types.h>
#include <errno.h>
#include <paths.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#ifndef pidfile
static char *pidfile_path = NULL;
static pid_t pidfile_pid = 0;
static void pidfile_cleanup(void);
const char *__pidfile_path = _PATH_VARRUN; /* Note: includes trailing slash '/' */
const char *__pidfile_name = NULL;
extern char *__progname;
/**
* Create or update mtime of process PID file.
* @param basename Program name, or @c NULL, may start with '/'
*
* This function is intended to be used by UNIX daemons to save the PID of the main process
* responsible for handling signals. If @p basename is @c NULL the implicit @a __progname
* variable from the C-library is used. The @p basename may also start with '/', in which
* case it is interpreted as the absolute path to the PID file.
*
* @returns POSIX OK(0) on success, otherwise non-zero on error.
*/
int pidfile(const char *basename)
{
int save_errno;
int atexit_already;
pid_t pid;
FILE *f;
if (basename == NULL)
basename = __progname;
pid = getpid();
atexit_already = 0;
if (pidfile_path != NULL) {
if (!access(pidfile_path, R_OK) && pid == pidfile_pid) {
utimensat(0, pidfile_path, NULL, 0);
return (0);
}
free(pidfile_path);
pidfile_path = NULL;
__pidfile_name = NULL;
atexit_already = 1;
}
if (basename[0] != '/') {
if (asprintf(&pidfile_path, "%s%s.pid", __pidfile_path, basename) == -1)
return (-1);
} else {
if (asprintf(&pidfile_path, "%s", basename) == -1)
return (-1);
}
if ((f = fopen(pidfile_path, "w")) == NULL) {
save_errno = errno;
free(pidfile_path);
pidfile_path = NULL;
errno = save_errno;
return (-1);
}
if (fprintf(f, "%ld\n", (long)pid) <= 0 || fflush(f) != 0) {
save_errno = errno;
(void) fclose(f);
(void) unlink(pidfile_path);
free(pidfile_path);
pidfile_path = NULL;
errno = save_errno;
return (-1);
}
(void) fclose(f);
__pidfile_name = pidfile_path;
/*
* LITE extension, no need to set up another atexit() handler
* if user only called us to update the mtime of the PID file
*/
if (atexit_already)
return (0);
pidfile_pid = pid;
if (atexit(pidfile_cleanup) < 0) {
save_errno = errno;
(void) unlink(pidfile_path);
free(pidfile_path);
pidfile_path = NULL;
pidfile_pid = 0;
errno = save_errno;
return (-1);
}
return (0);
}
static void
pidfile_cleanup(void)
{
if (pidfile_path != NULL && pidfile_pid == getpid()) {
(void) unlink(pidfile_path);
free(pidfile_path);
pidfile_path = NULL;
}
}
#endif
+135
View File
@@ -0,0 +1,135 @@
/* Functions for dealing with PID files (client side)
*
* Copyright (c) 2009-2021 Joachim Wiberg <troglobit@gmail.com>
*
* 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.
*/
/**
* @file pidfilefn.c
* @author Joachim Wiberg
* @date 2009-2021
* @copyright ISC License
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
extern char *chomp(char *str);
/**
* Reads a PID value from a pidfile.
* @param pidfile File containing PID, usually in @c /var/run/PROCNAME.pid
*
* This function takes a @p pidfile and returns the PID found therein.
*
* @returns On invalid @p pidfile, -1 with @a errno set. If the @p
* pidfile is empty, or when its contents cannot be translated, this
* function returns zero (0), on success this function returns a PID
* value greater than one.
*
* @note PID 1 is reserved for the system init process.
*
* @exception EINVAL on invalid @p pidfile, or
* @exception ENOENT when @p pidfile does not exist.
*/
pid_t pidfile_read(const char *pidfile)
{
int pid = 0;
char buf[16];
FILE *fp;
if (!pidfile) {
errno = EINVAL;
return -1;
}
fp = fopen(pidfile, "r");
if (!fp)
return -1;
if (fgets(buf, sizeof(buf), fp)) {
char *ptr = chomp(buf);
if (ptr) {
errno = 0;
pid = strtoul(ptr, NULL, 0);
if (errno)
pid = 0; /* Failed conversion. */
}
}
fclose(fp);
return pid;
}
/**
* Poll for the existence of a pidfile and return PID.
* @param pidfile Path to pidfile to poll for
*
* This function polls for the pidfile at @p pidfile for at most 5
* seconds before timing out. If the file is created within that time
* span the file is read and its PID contents returned.
*
* @returns The PID read from @p pidfile, or zero on timeout.
*/
pid_t pidfile_poll(const char *pidfile)
{
pid_t pid = 0;
int tries = 0;
/* Timeout = 100 * 50ms = 5s */
while ((pid = pidfile_read(pidfile)) <= 0 && tries++ < 100)
usleep(50000); /* Wait 50ms between retries */
if (pid < 0)
pid = 0;
return pid;
}
/**
* Send signal to a PID and cleanup pidfile afterwards.
* @param pidfile File containing PID, usually in @c /var/run/PROCNAME.pid
* @param signal Signal to send to PID found in @p pidfile.
*
* If @p signal is any of @c SIGTERM or @c SIGKILL, or if kill(2)
* returns -1, the @p pidfile is removed.
*
* @returns POSIX OK(0) on success, non-zero otherwise.
*/
int pidfile_signal(const char *pidfile, int signal)
{
int pid = -1, ret = -1;
pid = pidfile_read(pidfile);
if (pid <= 0)
return 1;
ret = kill(pid, signal);
if (!ret && signal == SIGKILL)
ret = remove(pidfile);
return ret;
}
/**
* Local Variables:
* compile-command: "make V=1 -f pidfilefn.mk"
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+133
View File
@@ -0,0 +1,133 @@
/* Simple termios based progress bar
*
* Copyright (c) 2012-2021 Joachim Wiberg <troglobit@gmail.com>
*
* 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.
*/
/**
* @file progress.c
* @author Joachim Wiberg
* @date 2012-2021
* @copyright ISC License
*/
#include <limits.h> /* INT_MAX */
#include <stdio.h>
#include <string.h>
#include "conio.h"
#define SPINNER_THROB ".oOo"
#define SPINNER_PULSAR ".oO°Oo."
#define SPINNER_ARROW "v<^>"
#define SPINNER_STAR ".oO@*"
#define SPINNER_DEFAULT "|/-\\"
static char spinner(char *style)
{
size_t num;
static unsigned int i = 0;
if (!style)
style = SPINNER_DEFAULT;
num = strlen(style);
return style[i++ % num]; /* % Number of states in style */
}
/**
* Advanced ASCII progress bar with spinner
* @param percent Start first call with this set to 0, end with 100
* @param max_width Max width of progress bar, in total characters.
*
* This function draws an advanced ASCII progressbar at the current
* line. It always start from the first column.
*
* The progress bar will hide the cursor if started with @p percent 0
* and show it again at the end, when called with @p percent 100.
*
* While being called with the same percentage the spinner will spin,
* to show the user the process hasn't frozen.
*
* If the output TTY cannot interpret control characters, like `\r`, it
* is advised to instead used the progress_simple() function.
*/
void progress(int percent, int max_width)
{
int i, bar;
/* Adjust for progress bar overhead */
max_width -= 10;
if (0 == percent)
hidecursor();
fprintf(stderr, "\r%3d%% %c [", percent, spinner(NULL));
bar = percent * max_width / 100;
for (i = 0; i < max_width; i++) {
if (i > bar)
fputc(' ', stderr);
else if (i == bar)
fputc('>', stderr);
else
fputc('=', stderr);
}
fprintf(stderr, "]");
if (100 == percent) {
showcursor();
fputc('\n', stderr);
}
}
/**
* Alternative progress bar on systems where progress() doesn't work
* @param percent Start first call with this set to 0, end with 100
*/
void progress_simple(int percent)
{
static int last = 1;
int ratio, numout;
if (!percent && last) {
last = 0;
fputs("0% 25% 50% 75% 100%\n"
"|---------+---------+---------+---------|\n"
"|", stderr);
return;
}
ratio = 40 * percent / 100;
numout = ratio - last;
if (ratio <= last)
return;
last = ratio;
while (numout--) {
if (ratio != 40 || numout)
putc('=', stderr);
else
putc('|', stderr);
}
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+547
View File
@@ -0,0 +1,547 @@
/* $OpenBSD: queue.h,v 1.43 2015/12/28 19:38:40 millert Exp $ */
/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
/*
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)queue.h 8.5 (Berkeley) 8/20/94
*/
#ifdef __cplusplus
extern "C"
{
#endif
#ifndef _SYS_QUEUE_H_
#define _SYS_QUEUE_H_
/**
* @file queue.h
* @author The Regents of the University of California
* @date 1991, 1993
* @copyright 3-clause BSD License
*
* This file defines five types of data structures: singly-linked lists,
* lists, simple queues, tail queues and XOR simple queues.
*
*
* A singly-linked list is headed by a single forward pointer. The elements
* are singly linked for minimum space and pointer manipulation overhead at
* the expense of O(n) removal for arbitrary elements. New elements can be
* added to the list after an existing element or at the head of the list.
* Elements being removed from the head of the list should use the explicit
* macro for this purpose for optimum efficiency. A singly-linked list may
* only be traversed in the forward direction. Singly-linked lists are ideal
* for applications with large datasets and few or no removals or for
* implementing a LIFO queue.
*
* A list is headed by a single forward pointer (or an array of forward
* pointers for a hash table header). The elements are doubly linked
* so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before
* or after an existing element or at the head of the list. A list
* may only be traversed in the forward direction.
*
* A simple queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are singly
* linked to save space, so elements can only be removed from the
* head of the list. New elements can be added to the list before or after
* an existing element, at the head of the list, or at the end of the
* list. A simple queue may only be traversed in the forward direction.
*
* A tail queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are doubly
* linked so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before or
* after an existing element, at the head of the list, or at the end of
* the list. A tail queue may be traversed in either direction.
*
* An XOR simple queue is used in the same way as a regular simple queue.
* The difference is that the head structure also includes a "cookie" that
* is XOR'd with the queue pointer (first, last or next) to generate the
* real pointer value.
*
* For details on the use of these macros, see the queue(3) manual page.
*/
#if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC))
#define _Q_INVALIDATE(a) (a) = ((void *)-1)
#else
#define _Q_INVALIDATE(a)
#endif
/*
* Singly-linked List definitions.
*/
#define SLIST_HEAD(name, type) \
struct name { \
struct type *slh_first; /* first element */ \
}
#define SLIST_HEAD_INITIALIZER(head) \
{ NULL }
#define SLIST_ENTRY(type) \
struct { \
struct type *sle_next; /* next element */ \
}
/*
* Singly-linked List access methods.
*/
#define SLIST_FIRST(head) ((head)->slh_first)
#define SLIST_END(head) NULL
#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head))
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
#define SLIST_FOREACH(var, head, field) \
for((var) = SLIST_FIRST(head); \
(var) != SLIST_END(head); \
(var) = SLIST_NEXT(var, field))
#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = SLIST_FIRST(head); \
(var) && ((tvar) = SLIST_NEXT(var, field), 1); \
(var) = (tvar))
/*
* Singly-linked List functions.
*/
#define SLIST_INIT(head) { \
SLIST_FIRST(head) = SLIST_END(head); \
}
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
(elm)->field.sle_next = (slistelm)->field.sle_next; \
(slistelm)->field.sle_next = (elm); \
} while (0)
#define SLIST_INSERT_HEAD(head, elm, field) do { \
(elm)->field.sle_next = (head)->slh_first; \
(head)->slh_first = (elm); \
} while (0)
#define SLIST_REMOVE_AFTER(elm, field) do { \
(elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \
} while (0)
#define SLIST_REMOVE_HEAD(head, field) do { \
(head)->slh_first = (head)->slh_first->field.sle_next; \
} while (0)
#define SLIST_REMOVE(head, elm, type, field) do { \
if ((head)->slh_first == (elm)) { \
SLIST_REMOVE_HEAD((head), field); \
} else { \
struct type *curelm = (head)->slh_first; \
\
while (curelm->field.sle_next != (elm)) \
curelm = curelm->field.sle_next; \
curelm->field.sle_next = \
curelm->field.sle_next->field.sle_next; \
} \
_Q_INVALIDATE((elm)->field.sle_next); \
} while (0)
/*
* List definitions.
*/
#define LIST_HEAD(name, type) \
struct name { \
struct type *lh_first; /* first element */ \
}
#define LIST_HEAD_INITIALIZER(head) \
{ NULL }
#define LIST_ENTRY(type) \
struct { \
struct type *le_next; /* next element */ \
struct type **le_prev; /* address of previous next element */ \
}
/*
* List access methods.
*/
#define LIST_FIRST(head) ((head)->lh_first)
#define LIST_END(head) NULL
#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head))
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
#define LIST_FOREACH(var, head, field) \
for((var) = LIST_FIRST(head); \
(var)!= LIST_END(head); \
(var) = LIST_NEXT(var, field))
#define LIST_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = LIST_FIRST(head); \
(var) && ((tvar) = LIST_NEXT(var, field), 1); \
(var) = (tvar))
/*
* List functions.
*/
#define LIST_INIT(head) do { \
LIST_FIRST(head) = LIST_END(head); \
} while (0)
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
(listelm)->field.le_next->field.le_prev = \
&(elm)->field.le_next; \
(listelm)->field.le_next = (elm); \
(elm)->field.le_prev = &(listelm)->field.le_next; \
} while (0)
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.le_prev = (listelm)->field.le_prev; \
(elm)->field.le_next = (listelm); \
*(listelm)->field.le_prev = (elm); \
(listelm)->field.le_prev = &(elm)->field.le_next; \
} while (0)
#define LIST_INSERT_HEAD(head, elm, field) do { \
if (((elm)->field.le_next = (head)->lh_first) != NULL) \
(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
(head)->lh_first = (elm); \
(elm)->field.le_prev = &(head)->lh_first; \
} while (0)
#define LIST_REMOVE(elm, field) do { \
if ((elm)->field.le_next != NULL) \
(elm)->field.le_next->field.le_prev = \
(elm)->field.le_prev; \
*(elm)->field.le_prev = (elm)->field.le_next; \
_Q_INVALIDATE((elm)->field.le_prev); \
_Q_INVALIDATE((elm)->field.le_next); \
} while (0)
#define LIST_REPLACE(elm, elm2, field) do { \
if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \
(elm2)->field.le_next->field.le_prev = \
&(elm2)->field.le_next; \
(elm2)->field.le_prev = (elm)->field.le_prev; \
*(elm2)->field.le_prev = (elm2); \
_Q_INVALIDATE((elm)->field.le_prev); \
_Q_INVALIDATE((elm)->field.le_next); \
} while (0)
/*
* Simple queue definitions.
*/
#define SIMPLEQ_HEAD(name, type) \
struct name { \
struct type *sqh_first; /* first element */ \
struct type **sqh_last; /* addr of last next element */ \
}
#define SIMPLEQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).sqh_first }
#define SIMPLEQ_ENTRY(type) \
struct { \
struct type *sqe_next; /* next element */ \
}
/*
* Simple queue access methods.
*/
#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
#define SIMPLEQ_END(head) NULL
#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
#define SIMPLEQ_FOREACH(var, head, field) \
for((var) = SIMPLEQ_FIRST(head); \
(var) != SIMPLEQ_END(head); \
(var) = SIMPLEQ_NEXT(var, field))
#define SIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = SIMPLEQ_FIRST(head); \
(var) && ((tvar) = SIMPLEQ_NEXT(var, field), 1); \
(var) = (tvar))
/*
* Simple queue functions.
*/
#define SIMPLEQ_INIT(head) do { \
(head)->sqh_first = NULL; \
(head)->sqh_last = &(head)->sqh_first; \
} while (0)
#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
(head)->sqh_last = &(elm)->field.sqe_next; \
(head)->sqh_first = (elm); \
} while (0)
#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
(elm)->field.sqe_next = NULL; \
*(head)->sqh_last = (elm); \
(head)->sqh_last = &(elm)->field.sqe_next; \
} while (0)
#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
(head)->sqh_last = &(elm)->field.sqe_next; \
(listelm)->field.sqe_next = (elm); \
} while (0)
#define SIMPLEQ_REMOVE_HEAD(head, field) do { \
if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
(head)->sqh_last = &(head)->sqh_first; \
} while (0)
#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \
if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \
== NULL) \
(head)->sqh_last = &(elm)->field.sqe_next; \
} while (0)
#define SIMPLEQ_CONCAT(head1, head2) do { \
if (!SIMPLEQ_EMPTY((head2))) { \
*(head1)->sqh_last = (head2)->sqh_first; \
(head1)->sqh_last = (head2)->sqh_last; \
SIMPLEQ_INIT((head2)); \
} \
} while (0)
/*
* XOR Simple queue definitions.
*/
#define XSIMPLEQ_HEAD(name, type) \
struct name { \
struct type *sqx_first; /* first element */ \
struct type **sqx_last; /* addr of last next element */ \
unsigned long sqx_cookie; \
}
#define XSIMPLEQ_ENTRY(type) \
struct { \
struct type *sqx_next; /* next element */ \
}
/*
* XOR Simple queue access methods.
*/
#define XSIMPLEQ_XOR(head, ptr) ((__typeof(ptr))((head)->sqx_cookie ^ \
(unsigned long)(ptr)))
#define XSIMPLEQ_FIRST(head) XSIMPLEQ_XOR(head, ((head)->sqx_first))
#define XSIMPLEQ_END(head) NULL
#define XSIMPLEQ_EMPTY(head) (XSIMPLEQ_FIRST(head) == XSIMPLEQ_END(head))
#define XSIMPLEQ_NEXT(head, elm, field) XSIMPLEQ_XOR(head, ((elm)->field.sqx_next))
#define XSIMPLEQ_FOREACH(var, head, field) \
for ((var) = XSIMPLEQ_FIRST(head); \
(var) != XSIMPLEQ_END(head); \
(var) = XSIMPLEQ_NEXT(head, var, field))
#define XSIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = XSIMPLEQ_FIRST(head); \
(var) && ((tvar) = XSIMPLEQ_NEXT(head, var, field), 1); \
(var) = (tvar))
/*
* XOR Simple queue functions.
*/
#define XSIMPLEQ_INIT(head) do { \
arc4random_buf(&(head)->sqx_cookie, sizeof((head)->sqx_cookie)); \
(head)->sqx_first = XSIMPLEQ_XOR(head, NULL); \
(head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \
} while (0)
#define XSIMPLEQ_INSERT_HEAD(head, elm, field) do { \
if (((elm)->field.sqx_next = (head)->sqx_first) == \
XSIMPLEQ_XOR(head, NULL)) \
(head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
(head)->sqx_first = XSIMPLEQ_XOR(head, (elm)); \
} while (0)
#define XSIMPLEQ_INSERT_TAIL(head, elm, field) do { \
(elm)->field.sqx_next = XSIMPLEQ_XOR(head, NULL); \
*(XSIMPLEQ_XOR(head, (head)->sqx_last)) = XSIMPLEQ_XOR(head, (elm)); \
(head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
} while (0)
#define XSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
if (((elm)->field.sqx_next = (listelm)->field.sqx_next) == \
XSIMPLEQ_XOR(head, NULL)) \
(head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
(listelm)->field.sqx_next = XSIMPLEQ_XOR(head, (elm)); \
} while (0)
#define XSIMPLEQ_REMOVE_HEAD(head, field) do { \
if (((head)->sqx_first = XSIMPLEQ_XOR(head, \
(head)->sqx_first)->field.sqx_next) == XSIMPLEQ_XOR(head, NULL)) \
(head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \
} while (0)
#define XSIMPLEQ_REMOVE_AFTER(head, elm, field) do { \
if (((elm)->field.sqx_next = XSIMPLEQ_XOR(head, \
(elm)->field.sqx_next)->field.sqx_next) \
== XSIMPLEQ_XOR(head, NULL)) \
(head)->sqx_last = \
XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
} while (0)
/*
* Tail queue definitions.
*/
#define TAILQ_HEAD(name, type) \
struct name { \
struct type *tqh_first; /* first element */ \
struct type **tqh_last; /* addr of last next element */ \
}
#define TAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).tqh_first }
#define TAILQ_ENTRY(type) \
struct { \
struct type *tqe_next; /* next element */ \
struct type **tqe_prev; /* address of previous next element */ \
}
/*
* Tail queue access methods.
*/
#define TAILQ_FIRST(head) ((head)->tqh_first)
#define TAILQ_END(head) NULL
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
#define TAILQ_LAST(head, headname) \
(*(((struct headname *)((head)->tqh_last))->tqh_last))
/* XXX */
#define TAILQ_PREV(elm, headname, field) \
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
#define TAILQ_EMPTY(head) \
(TAILQ_FIRST(head) == TAILQ_END(head))
#define TAILQ_FOREACH(var, head, field) \
for((var) = TAILQ_FIRST(head); \
(var) != TAILQ_END(head); \
(var) = TAILQ_NEXT(var, field))
#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
for ((var) = TAILQ_FIRST(head); \
(var) != TAILQ_END(head) && \
((tvar) = TAILQ_NEXT(var, field), 1); \
(var) = (tvar))
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
for((var) = TAILQ_LAST(head, headname); \
(var) != TAILQ_END(head); \
(var) = TAILQ_PREV(var, headname, field))
#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
for ((var) = TAILQ_LAST(head, headname); \
(var) != TAILQ_END(head) && \
((tvar) = TAILQ_PREV(var, headname, field), 1); \
(var) = (tvar))
/*
* Tail queue functions.
*/
#define TAILQ_INIT(head) do { \
(head)->tqh_first = NULL; \
(head)->tqh_last = &(head)->tqh_first; \
} while (0)
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
(head)->tqh_first->field.tqe_prev = \
&(elm)->field.tqe_next; \
else \
(head)->tqh_last = &(elm)->field.tqe_next; \
(head)->tqh_first = (elm); \
(elm)->field.tqe_prev = &(head)->tqh_first; \
} while (0)
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
(elm)->field.tqe_next = NULL; \
(elm)->field.tqe_prev = (head)->tqh_last; \
*(head)->tqh_last = (elm); \
(head)->tqh_last = &(elm)->field.tqe_next; \
} while (0)
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
(elm)->field.tqe_next->field.tqe_prev = \
&(elm)->field.tqe_next; \
else \
(head)->tqh_last = &(elm)->field.tqe_next; \
(listelm)->field.tqe_next = (elm); \
(elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
} while (0)
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
(elm)->field.tqe_next = (listelm); \
*(listelm)->field.tqe_prev = (elm); \
(listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
} while (0)
#define TAILQ_REMOVE(head, elm, field) do { \
if (((elm)->field.tqe_next) != NULL) \
(elm)->field.tqe_next->field.tqe_prev = \
(elm)->field.tqe_prev; \
else \
(head)->tqh_last = (elm)->field.tqe_prev; \
*(elm)->field.tqe_prev = (elm)->field.tqe_next; \
_Q_INVALIDATE((elm)->field.tqe_prev); \
_Q_INVALIDATE((elm)->field.tqe_next); \
} while (0)
#define TAILQ_REPLACE(head, elm, elm2, field) do { \
if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \
(elm2)->field.tqe_next->field.tqe_prev = \
&(elm2)->field.tqe_next; \
else \
(head)->tqh_last = &(elm2)->field.tqe_next; \
(elm2)->field.tqe_prev = (elm)->field.tqe_prev; \
*(elm2)->field.tqe_prev = (elm2); \
_Q_INVALIDATE((elm)->field.tqe_prev); \
_Q_INVALIDATE((elm)->field.tqe_next); \
} while (0)
#define TAILQ_CONCAT(head1, head2, field) do { \
if (!TAILQ_EMPTY(head2)) { \
*(head1)->tqh_last = (head2)->tqh_first; \
(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
(head1)->tqh_last = (head2)->tqh_last; \
TAILQ_INIT((head2)); \
} \
} while (0)
#endif /* !_SYS_QUEUE_H_ */
#ifdef __cplusplus
}
#endif
+52
View File
@@ -0,0 +1,52 @@
/* $OpenBSD: reallocarray.c,v 1.2 2014/12/08 03:45:00 bcook Exp $ */
/*
* Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
*
* Permission to use, copy, modify, and 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.
*/
/**
* @file reallocarray.c
* @author Otto Moerbeek
* @date 2008
* @copyright ISC License
*/
#include <sys/types.h>
#include <errno.h>
#include <stdint.h>
#include <stdlib.h>
/*
* This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
* if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
*/
#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
/**
* Similar to realloc() but for an array of items, like calloc()
* @param optr Pointer to old (current) array
* @param nmemb Number of elements
* @param size Size of each element, in bytes
*
* @returns A pointer to the new array, or @c NULL on error.
*/
void *reallocarray(void *optr, size_t nmemb, size_t size)
{
if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
nmemb > 0 && SIZE_MAX / nmemb < size) {
errno = ENOMEM;
return NULL;
}
return realloc(optr, size * nmemb);
}
+244
View File
@@ -0,0 +1,244 @@
/* Micro "rsync" implementation.
*
* Copyright (c) 2011-2021 Joachim Wiberg <troglobit@gmail.com>
*
* 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.
*/
/**
* @file rsync.c
* @author Joachim Wiberg
* @date 2011-2021
* @copyright ISC License
*/
#include <errno.h>
#include <fcntl.h> /* AT_* macros */
#include <stdlib.h> /* NULL, free() */
#include <string.h> /* strlen() */
#include <strings.h> /* rindex() */
#include <stdio.h>
#include <sys/param.h> /* MAX(), isset(), setbit(), TRUE, FALSE, et consortes. :-) */
#include <sys/stat.h>
#include <sys/types.h>
#include "lite.h"
static int copy(char *src, char *dst, int opt);
static int mdir(char *buf, size_t buf_len, char *dir, char *name, struct stat *st);
static int prune(char *dst, char **new_files, int new_num);
static int set_mtime(char *fn, struct stat *st);
/**
* Synchronize contents and optionally remove non-existing backups
* @param src Source directory
* @param dst Destination directory
* @param opt An option mask of ::LITE_FOPT_RSYNC_DELETE, ::LITE_FOPT_KEEP_MTIME
* @param filter Optional filtering function for source directory.
*
* This is a miniature implementation of the famous rsync for local use
* only. In fact, it is not even a true rsync since it copies all files
* from @p src to @p dst. The ::LITE_FOPT_RSYNC_DELETE @p opt flag is
* useful for creating backups, when set all files removed from src
* since last backup are pruned from the destination (backup) directory.
*
* The @p opt parameter to rsync() is an option mask for the most common
* rsync(1) options. Previously this argument was called @p delete and
* to maintain backwards compatibility the value 1 is reserved:
*
* %LITE_FOPT_RSYNC_DELETE: Prune files from @p dst that no longer exist in @p src.
* %LITE_FOPT_KEEP_MTIME: Preserve modification time
*
* The filter callback, @p filter, if provided, is used to determine
* what files to include from the source directory when backing up. If
* a file is to be skipped the callback should simply return zero.
*
* Returns:
* POSIX OK(0), or non-zero with @a errno set on error.
*/
int rsync(char *src, char *dst, int opt, int (*filter)(const char *file))
{
char source[256];
char dest[256];
int delete = (opt & LITE_FOPT_RSYNC_DELETE) != 0;
int keep_mtim = (opt & LITE_FOPT_KEEP_MTIME);
int i = 0, num = 0, result = 0, do_mtim = 0;
char **files; /* Array of file names. */
struct stat st;
if (!fisdir(dst))
makedir(dst, 0755);
if (!fisdir(src)) {
if (!fexist(src))
return 1;
if (copy(src, dst, keep_mtim))
result++;
return errno;
}
/* Copy dir as well? */
if (!fisslashdir(src)) {
char *ptr = rindex(src, '/');
if (!ptr)
ptr = src;
else
ptr++;
if (stat(src, &st))
return 1;
if (mdir(dest, sizeof(dest), dst, ptr, &st))
return 1;
dst = dest;
do_mtim = keep_mtim;
}
num = dir(src, "", filter, &files, 0);
for (i = 0; i < num; i++) {
/* Recursively copy sub-directries */
snprintf(source, sizeof(source), "%s%s%s", src, fisslashdir(src) ? "" : "/", files[i]);
if (fisdir(source)) {
char dst2[256];
struct stat sb;
strcat(source, "/");
if (stat(source, &sb)) {
result++;
continue;
}
if (mdir(dst2, sizeof(dst2), dst, files[i], &sb)) {
result++;
continue;
}
rsync(source, dst2, opt, filter);
if (keep_mtim)
set_mtime(dst2, &sb);
continue; /* Next file/dir in @src to copy... */
}
if (copy(source, dst, keep_mtim))
result++;
}
if (do_mtim)
set_mtime(dest, &st);
/* We ignore any errors from the pruning, that phase albeit useful is only
* cosmetic. --Jocke 2011-03-24 */
if (delete)
prune(dst, files, num);
if (num) {
for (i = 0; i < num; i++)
free(files[i]);
free(files);
}
return result;
}
static int copy(char *src, char *dst, int opt)
{
copyfile(src, dst, 0, opt | LITE_FOPT_COPYFILE_SYM);
if (errno) {
if (errno != EEXIST)
return 1;
errno = 0;
}
return 0;
}
/* Creates dir/name @mode ... skipping / if dir already ends so. */
static int mdir(char *buf, size_t buf_len, char *dir, char *name, struct stat *st)
{
snprintf(buf, buf_len, "%s%s%s", dir, fisslashdir(dir) ? "" : "/", name);
if (mkdir(buf, st->st_mode)) {
if (EEXIST != errno)
return 1;
errno = 0;
}
return 0;
}
static int find(char *file, char **files, int num)
{
int n;
for (n = 0; n < num; n++)
if (!strncmp (files[n], file, MAX(strlen(files[n]), strlen(file))))
return 1;
return 0;
}
/* Prune old files, no longer existing on source, from destination directory. */
static int prune(char *dst, char **new_files, int new_num)
{
int num, result = 0;
char **files;
num = dir(dst, "", NULL, &files, 0);
if (num) {
int i;
for (i = 0; i < num; i++) {
if (!find(files[i], new_files, new_num)) {
char *name;
size_t len = strlen(files[i]) + 2 + strlen(dst);
name = malloc(len);
if (name) {
snprintf(name, len, "%s%s%s", dst, fisslashdir(dst) ? "" : "/", files[i]);
if (remove(name))
result++;
free(name);
}
}
free(files[i]);
}
free(files);
}
return result;
}
static int set_mtime(char *fn, struct stat *st)
{
struct timespec tv[2];
tv[0] = st->st_atim;
tv[1] = st->st_mtim;
return utimensat(AT_FDCWD, fn, tv, AT_SYMLINK_NOFOLLOW);
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+74
View File
@@ -0,0 +1,74 @@
/* ==========================================================================
* strdupa.h - Re-implementation of glibc strdupa.
* --------------------------------------------------------------------------
* Copyright (c) 2009 William Ahern
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
* ==========================================================================
*/
/**
* @file strdupa.h
* @author William Ahern
* @date 2009
* @copyright MIT License
*/
#ifdef __cplusplus
extern "C"
{
#endif
#ifndef LIBITE_STRDUPA_H
#define LIBITE_STRDUPA_H
#if !defined(HAVE_STRDUPA)
#if defined(strdupa)
#define HAVE_STRDUPA 1
#endif
#endif
#if !HAVE_STRDUPA
#if defined(__GNUC__)
#include <stddef.h> /* size_t */
#include <string.h> /* memcpy(3) strlen(3) */
/**
* Duplicate string on stack.
* @param src string to duplicate
* @returns the result of memcpy(3)
*/
#define strdupa(src) (__extension__ ({ \
size_t len_ = strlen(src); \
char *dst_ = __builtin_alloca(len_ + 1); \
dst_[len_] = '\0'; \
(char *)memcpy(dst_, src, len_); \
}))
#else /* If not GCC, e.g. Clang */
#error strdupa() may use an unsupported GNU C API, please forward any fix to maintainer, cheers!
#endif /* __GNUC__ */
#endif /* !HAVE_STRDUPA */
#endif /* LIBITE_STRDUPA_H */
#ifdef __cplusplus
}
#endif
+71
View File
@@ -0,0 +1,71 @@
/* $OpenBSD: strlcat.c,v 1.15 2015/03/02 21:41:08 millert Exp $ */
/*
* Copyright (c) 1998, 2015 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and 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.
*/
/**
* @file strlcat.c
* @author Todd C. Miller
* @date 1998, 2015
* @copyright ISC License
*/
#include <sys/types.h>
#include <string.h>
#ifndef strlcat
/**
* Safe version of strncat() from OpenBSD
* @param dst Destination string
* @param src Source string
* @param dsize Total maximum size of @p dst
*
* Appends @p src to string @p dst of size @p dsize (unlike strncat(),
* @p dsize is the full size of @p dst, not space left). At most
* dsize-1 characters will be copied. Always NUL terminates (unless
* dsize <= strlen(dst)).
*
* @returns strlen(src) + MIN(dsize, strlen(initial dst)).
* If retval >= dsize, truncation occurred.
*/
size_t
strlcat(char *dst, const char *src, size_t dsize)
{
const char *odst = dst;
const char *osrc = src;
size_t n = dsize;
size_t dlen;
/* Find the end of dst and adjust bytes left but don't go past end. */
while (n-- != 0 && *dst != '\0')
dst++;
dlen = dst - odst;
n = dsize - dlen;
if (n-- == 0)
return(dlen + strlen(src));
while (*src != '\0') {
if (n != 0) {
*dst++ = *src;
n--;
}
src++;
}
*dst = '\0';
return(dlen + (src - osrc)); /* count does not include NUL */
}
#endif
+67
View File
@@ -0,0 +1,67 @@
/* $OpenBSD: strlcpy.c,v 1.12 2015/01/15 03:54:12 millert Exp $ */
/*
* Copyright (c) 1998, 2015 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and 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.
*/
/**
* @file strlcpy.c
* @author Todd C. Miller
* @date 1998, 2015
* @copyright ISC License
*/
#include <sys/types.h>
#include <string.h>
#ifndef strlcpy
/**
* Safe version of strncpy() from OpenBSD
* @param dst Destination string
* @param src Source string
* @param dsize Total maximum size of @p dst
*
* This function copies string @p src to buffer @p dst of size @p dsize
* bytes. 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 */
}
#endif
+150
View File
@@ -0,0 +1,150 @@
/* Collection of frog DNA
*
* Copyright (c) 2008-2021 Joachim Wiberg <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* @file strlite.h
* @author Joachim Wiberg
* @date 2008-2021
* @copyright MIT License
*/
#ifdef __cplusplus
extern "C"
{
#endif
#ifndef LIBITE_STRING_H_
#define LIBITE_STRING_H_
#include <stdint.h> /* uint8_t, uint16_t, uint32_t, INT32_MAX, etc. */
#include <string.h>
#include <sys/param.h> /* MAX(), isset(), setbit(), TRUE, FALSE, et consortes. :-) */
#include "strdupa.h"
#include "strndupa.h"
#include "strnlen.h"
#ifndef min
/** Geneirc min() macro, if a < b => a, else b */
#define min(a,b) \
({ \
__typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a < _b ? _a : _b; \
})
#endif
#ifndef max
/** Geneirc max() macro, if a > b => a, else b */
#define max(a,b) \
({ \
__typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a > _b ? _a : _b; \
})
#endif
int strnmatch (const char *str, const char **list, size_t num);
int strmatch (const char *str, const char **list);
#ifndef strlcpy
size_t strlcpy (char *dst, const char *src, size_t siz);
#endif
#ifndef strlcat
size_t strlcat (char *dst, const char *src, size_t siz);
#endif
#ifndef strtonum
long long strtonum (const char *numstr, long long minval, long long maxval, const char **errstrp);
#endif
char *strtrim (char *str);
/**
* Convert string to natural number (0-2147483647)
* @param str string to convert to number.
* @returns -1 on error.
*/
static inline int atonum(const char *str)
{
int val = -1;
const char *errstr;
if (str) {
val = strtonum(str, 0, INT32_MAX, &errstr);
if (errstr)
return -1;
}
return val;
}
/**
* Validate string, non NULL and not zero length
* @param str string to validate
* @returns @c TRUE(1) or @c FALSE(0).
*/
static inline int string_valid(const char *str)
{
return str && strlen(str);
}
/**
* Relaxed comparison, e.g., sys_string_match("small", "smaller") => TRUE
* @param a first string
* @param b second string
* @returns @c TRUE(1) or @c FALSE(0).
*/
static inline int string_match(const char *a, const char *b)
{
size_t min = MIN(strlen(a), strlen(b));
return !strncasecmp(a, b, min);
}
/**
* Strict comparison, e.g., sys_string_match("small", "smaller") => FALSE
* @param a first string
* @param b second string
* @returns @c TRUE(1) or @c FALSE(0).
*/
static inline int string_compare(const char *a, const char *b)
{
return strlen(a) == strlen(b) && !strcmp(a, b);
}
/**
* Strict comparison, like sys_string_compare(), but case insensitive,
* e.g., sys_string_match("small", "SmAlL") => TRUE
* @param a first string
* @param b second string
* @returns @c TRUE(1) or @c FALSE(0).
*/
static inline int string_case_compare(const char *a, const char *b)
{
return strlen(a) == strlen(b) && !strcasecmp(a, b);
}
#endif /* LIBITE_STRING_H_ */
#ifdef __cplusplus
}
#endif
+94
View File
@@ -0,0 +1,94 @@
/* Simple string matcher function, finds partial matches.
*
* Copyright (c) 2009-2021 Joachim Wiberg <troglobit@gmail.com>
*
* 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.
*/
/**
* @file strmatch.c
* @author Joachim Wiberg
* @date 2009-2021
* @copyright ISC License
*/
#include <errno.h>
#include <string.h>
/**
* Finds matching strings from a finite list
* @param str String to look for
* @param list List of strings to search.
* @param num Number of entries in @p list.
*
* This function searches the @p list of strings for @p str. If a
* (partial) match is found it returns the index in the @p list.
*
* Very similar in function to strmatch(), but works for sets of strings
* that are not @c NUL terminated.
*
* @returns -1 on error, otherwise the index to the matching string.
*/
int strnmatch(const char *str, const char **list, size_t num)
{
size_t i;
if (!str || !list) {
errno = EINVAL;
return -1;
}
for (i = 0; i < num; i++) {
if (!strncasecmp (str, list[i], strlen (str)))
return i;
}
errno = ENOENT;
return -1;
}
/**
* Finds matching strings from a list
* @param str String to look for.
* @param list NUL terminated list of strings to search.
*
* This function searches the @p list of strings for @p str. If a
* (partial) match is found it returns the index in the @p list.
*
* Please note, the @p list MUST be terminated by a NUL element. If
* that is not possible, we recommend using strnmatch() instead.
*
* @returns -1 on error, otherwise the index to the matching string.
*/
int strmatch(const char *str, const char **list)
{
size_t i;
if (!list) {
errno = EINVAL;
return -1;
}
for (i = 0; list[i]; i++)
;
return strnmatch(str, list, i);
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+76
View File
@@ -0,0 +1,76 @@
/* ==========================================================================
* strndupa.h - Re-implementation of glibc strndupa.
* --------------------------------------------------------------------------
* Copyright (c) 2009 William Ahern
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
* ==========================================================================
*/
/**
* @file strndupa.h
* @author William Ahern
* @date 2009
* @copyright MIT License
*/
#ifdef __cplusplus
extern "C"
{
#endif
#ifndef LIBITE_STRNDUPA_H_
#define LIBITE_STRNDUPA_H_
#if !defined(HAVE_STRNDUPA)
#if defined(strndupa)
#define HAVE_STRNDUPA 1
#endif
#endif
#if !HAVE_STRNDUPA
#if defined(__GNUC__)
#include <stddef.h> /* size_t */
#include <string.h> /* memcpy(3) */
#include "strnlen.h"
/**
* Duplicate part of string on stack
* @param src string to duplicate
* @param lim number of bytes to dupliate
* @returns the result of memcpy(3)
*/
#define strndupa(src, lim) (__extension__ ({ \
size_t len_ = strnlen(src, lim); \
char *dst_ = __builtin_alloca(len_ + 1); \
dst_[len_] = '\0'; \
(char *)memcpy(dst_, src, len_); \
}))
#else /* If not GCC, e.g. Clang */
+#error strndupa() may use an unsupported GNU C API, please forward any fix to maintainer, cheers!
#endif /* __GNUC__ */
#endif /* !HAVE_STRNDUPA */
#endif /* LIBITE_STRNDUPA_H */
#ifdef __cplusplus
}
#endif
+65
View File
@@ -0,0 +1,65 @@
/* strnlen.h - Re-implementation of GLIBC strnlen()
*
* Copyright (c) 2016-2021 Joachim Wiberg <troglobit@gmail.com>
*
* 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.
*/
/**
* @file strnlen.h
* @author Joachim Wiberg
* @date 2016-2021
* @copyright ISC License
*/
#ifdef __cplusplus
extern "C"
{
#endif
#ifndef LIBITE_STRNLEN_H_
#define LIBITE_STRNLEN_H_
#if !defined(HAVE_STRNLEN)
#if defined(strnlen)
#define HAVE_STRNLEN 1
#endif
#endif
#if !HAVE_STRNLEN
#include <stddef.h> /* size_t */
#define strnlen(str, lim) xstrnlen(str, lim) /**< Wrapper for xstrnlen() */
/**
* Reimplementation of GLIBC strnlen()
* @param str string to return length of
* @param lim max number of bytes to read
* @returns length of @p str in bytes, but at most @lim bytes.
*/
static inline size_t xstrnlen(const char *str, size_t lim)
{
size_t i = 0;
while (i < lim && str[i])
i++;
return i;
}
#endif
#endif /* LIBITE_STRNLEN_H_ */
#ifdef __cplusplus
}
#endif
+112
View File
@@ -0,0 +1,112 @@
/* $OpenBSD: strtonum.c,v 1.7 2013/04/17 18:40:58 tedu Exp $ */
/*
* Copyright (c) 2004 Ted Unangst and Todd Miller
* All rights reserved.
*
* Permission to use, copy, modify, and 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.
*/
/**
* @file strtonum.c
* @author Ted Unangst
* @author Todd Miller
* @date 2004
* @copyright ISC License
*/
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#ifndef strtonum
#define INVALID 1 /**< internal */
#define TOOSMALL 2 /**< internal */
#define TOOLARGE 3 /**< internal */
#ifndef LLONG_MAX
# define LLONG_MAX 0x7fffffffffffffffLL /**< internal */
#endif
#ifndef LLONG_MIN
# define LLONG_MIN (-0x7fffffffffffffffLL - 1) /**< internal */
#endif
/**
* Reliably convert string value to an integer
* @param numstr String to convert to a number
* @param minval Lower bound to check number against
* @param maxval Upper bound to check number against
* @param errstrp Pointer to error string
*
* This function converts the string in @p numstr to a long long value.
* The function was designed to facilitate safe, robust programming and
* overcome the shortcomings of the atoi(3) and strtol(3) family of
* interfaces.
*
* The string may begin with an arbitrary amount of whitespace (as
* determined by isspace(3)) followed by a single optional ‘+’ or ‘-’
* sign.
*
* The remainder of the string is converted to a long long value
* according to base 10.
*
* The value obtained is then checked against the provided @p minval and
* @p maxval bounds. If @p errstrp is non-NULL, strtonum() stores an
* error string in @p *errstrp indicating the failure.
*
* @returns The result of the conversion, unless the value would exceed
* the provided bounds or is invalid. On error, 0 is returned, @a errno
* is set, and @p errstrp points to an error message. @p *errstr* is set
* to @c NULL on success; this fact can be used to differentiate a
* successful return of 0 from an error.
*/
long long
strtonum(const char *numstr, long long minval, long long maxval,
const char **errstrp)
{
long long ll = 0;
int error = 0;
char *ep;
struct errval {
const char *errstr;
int err;
} ev[4] = {
{ NULL, 0 },
{ "invalid", EINVAL },
{ "too small", ERANGE },
{ "too large", ERANGE },
};
ev[0].err = errno;
errno = 0;
if (minval > maxval) {
error = INVALID;
} else {
ll = strtoll(numstr, &ep, 10);
if (errno == EINVAL || numstr == ep || *ep != '\0')
error = INVALID;
else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
error = TOOSMALL;
else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
error = TOOLARGE;
}
if (errstrp != NULL)
*errstrp = ev[error].errstr;
errno = ev[error].err;
if (error)
ll = 0;
return (ll);
}
#endif
+77
View File
@@ -0,0 +1,77 @@
/* Trim a string from whitespace
*
* Copyright (c) 2014 Mattias Walström <lazzer@gmail.com>
* Copyright (c) 2021 Joachim Wiberg <troglobit@gmail.com>
*
* 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.
*/
/**
* @file strtrim.c
* @author Mattias Walström
* @author Joachim Wiberg
* @date 2014,2021
* @copyright ISC License
*/
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include "lite.h"
/**
* Strip leading and trailing whitespace from a string
* @param str The string to trim
*
* Trims a string from any leading and trailing white-space, returns the
* trimmed result in the same buffer.
*
* @returns If @p str is a valid, non-NULL string this function returns
* the same string stripped from whitespace. This function only returns
* @c NULL if @p str itself is @c NULL.
*/
char *strtrim(char *str)
{
char *start, *end;
if (!str) {
errno = EINVAL;
return NULL;
}
start = str;
while (isspace(*start))
start++;
if (*start == 0) {
str[0] = 0;
return str;
}
end = start + strlen(start) - 1;
while (end > start && isspace(*end))
end--;
*(++end) = 0;
memmove(str, start, end - start + 1);
return str;
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+85
View File
@@ -0,0 +1,85 @@
/* Formatted system() which returns actual return status of command
*
* Copyright (c) 2021 Joachim Wiberg <troglobit@gmail.com>
*
* 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.
*/
/**
* @file systemf.c
* @author Joachim Wiberg
* @date 2021
* @copyright ISC License
*/
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
/**
* Like system(), but takes a formatted string as argument.
* @param fmt printf style format list to command to run
*
* This system() wrapper greatly simplifies operations that usually
* consist of composing a command from parts into a dynamic buffer
* before calling it. The return value from system() is also parsed,
* checking for proper exit and signals.
*
* @returns If the command exits normally, the return code of the command
* is returned. Otherwise, if the command is signalled, the return code
* is -1 and @a errno is set to @c EINTR.
*/
int systemf(const char *fmt, ...)
{
va_list ap;
char *cmd;
int len;
int rc;
va_start(ap, fmt);
len = vsnprintf(NULL, 0, fmt, ap);
va_end(ap);
cmd = alloca(++len);
if (!cmd) {
errno = ENOMEM;
return -1;
}
va_start(ap, fmt);
vsnprintf(cmd, len, fmt, ap);
va_end(ap);
rc = system(cmd);
if (rc == -1)
return -1;
if (WIFEXITED(rc)) {
errno = 0;
rc = WEXITSTATUS(rc);
} else if (WIFSIGNALED(rc)) {
errno = EINTR;
rc = -1;
}
return rc;
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+317
View File
@@ -0,0 +1,317 @@
/* Poor mans telnet expect in C.
*
* Copyright (c) 2010-2021 Joachim Wiberg <troglobit@gmail.com>
*
* 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.
*/
/**
* @file telnet.c
* @author Joachim Wiberg
* @date 2010-2021
* @copyright ISC License
*/
#include <errno.h>
#include <poll.h>
#include <unistd.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include "lite.h"
#define EXPECT_DEBUG 0
#define EXPECT_POLL_TIMEOUT 3000 /* 3 sec timeout waiting for server. */
#if EXPECT_DEBUG
# define TELL(fmt, args...) fprintf (stderr, fmt "\n", ##args)
#else
# define TELL(fmt, args...)
#endif
/** @private for internal use only */
struct sdbuf {
int sd;
char *buf;
};
/**
* Open telnet connection to addr:port and connect.
* @param addr Integer encoded IPv4 address in network byte order
* @param port Internet port number in network byte order
*
* @returns An @ref sdbuf_t socket buffer context.
*/
sdbuf_t *telnet_open(int addr, short port)
{
struct sockaddr_in *sin;
struct sockaddr s;
sdbuf_t *ctx;
int saved;
int retries = 10;
ctx = (sdbuf_t *)malloc(sizeof(sdbuf_t));
if (!ctx) {
// perror("Failed allocating expect ctxect");
return NULL;
}
ctx->buf = (char *)malloc(BUFSIZ);
if (!ctx->buf) {
// perror("Failed allocating expect buffer");
free(ctx);
return NULL;
}
ctx->sd = socket(PF_INET, SOCK_STREAM, 0);
if (-1 == ctx->sd) {
saved = errno;
// perror ("Failed creating socket");
free(ctx->buf);
free(ctx);
errno = saved;
return NULL;
}
retry:
sin = (struct sockaddr_in *)&s;
sin->sin_family = AF_INET;
sin->sin_port = port;
sin->sin_addr.s_addr = addr;
if (-1 == connect(ctx->sd, &s, sizeof(s))) {
if (ETIMEDOUT == errno && retries-- > 0) {
sleep(1);
goto retry;
}
saved = errno;
// perror ("Cannot connect to telnet daemon");
telnet_close(ctx);
errno = saved;
return NULL;
}
return ctx;
}
/**
* Close a telnet session previously opened with telnet_open()
* @param ctx An @ref sdbuf_t socket buffer context
*
* @returns Always returns POSIX OK(0).
*/
int telnet_close(sdbuf_t *ctx)
{
free(ctx->buf);
close(ctx->sd);
free(ctx);
return 0;
}
static int wait_substr(sdbuf_t *ctx, char *str)
{
struct pollfd pfd = { ctx->sd, POLLIN, 0 };
ssize_t len, tot = 0;
int err;
while (1) {
err = poll(&pfd, 1, EXPECT_POLL_TIMEOUT);
if (err <= 0) {
if (0 == err)
errno = ETIMEDOUT;
if (EINTR == errno)
continue;
// perror("No prompt");
return 1;
}
len = read(ctx->sd, &ctx->buf[tot], BUFSIZ);
if (len <= 0) {
errno = ENOMSG;
return 1;
}
tot += len;
ctx->buf[tot] = 0;
TELL("Got line: '%s' is it '%s'?", ctx->buf, str);
if (strstr(ctx->buf, str))
return 0;
}
}
/**
* Poor man's telnet expect
* @param ctx Telnet session context from telnet_open()
* @param script @c NULL terminated list of expect and response strings
* @param output Optional output from session
*
* Issues @p script sequence on telnet session specified in @p ctx, with
* optional @p output from session.
*
* The @p script consists of strings of expect and response pairs. For
* example, expect "ogin: " followed by response "root\n", expect
* "assword: "with response "secret\n", concluded by @c NULL.
*
* @returns POSIX OK(0) or non-zero on error.
*/
int telnet_expect(sdbuf_t *ctx, char *script[], FILE *output)
{
struct pollfd fd = { ctx->sd, POLLIN, 0 };
ssize_t len;
int i, first = 1, cont = 1, result = 0;
for (i = 0; script[i]; i++) {
/* when expecting the empty string, just wipe any available input */
if (!strlen(script[i])) {
result = poll(&fd, 1, 0);
if (result > 0)
lseek(ctx->sd, 0, SEEK_END);
} else {
if (wait_substr(ctx, script[i])) {
result = ENOMSG;
return 1;
}
}
i++;
if (strlen(script[i])) {
TELL("Sending line: '%s'", script[i]);
if (-1 == write(ctx->sd, script[i], strlen(script[i]))) {
errno = ENOSPC;
return 1;
}
}
}
while (cont) {
char *ptr = ctx->buf;
char *tmp;
result = poll(&fd, 1, EXPECT_POLL_TIMEOUT);
if (result <= 0) {
if (0 == result)
errno = ETIMEDOUT;
if (EINTR == errno)
continue;
// perror ("No result");
result = errno;
break;
}
/*
* On VERY long outputs we need to send some love back to the
* server, otherwise it terminates the connection. --Jocke
*/
if (-1 == write(ctx->sd, "\n", 1))
goto retry;
len = read(ctx->sd, ctx->buf, BUFSIZ);
if (len == -1) {
retry:
if (EINTR == errno)
continue;
result = errno;
break;
}
ctx->buf[len] = 0;
TELL("Read line: '%s'", ctx->buf);
/* Skip first line -- only an echo of the last command */
if (first) {
first = 0;
ptr = strchr(ctx->buf, '\n');
if (ptr)
ptr++;
else
ptr = ctx->buf;
}
TELL("Comparing '%s' with '%s'", ptr, script[i - 2]);
/* Skip last line -- only the returning prompt. */
tmp = strstr(ptr, script[i - 2]);
if (tmp) {
TELL("OK, last line. Good bye!");
result = 0;
cont = 0;
*tmp = 0;
tmp = strrchr(ptr, '\n');
if (tmp)
*++tmp = 0;
}
if (output && *ptr) {
if (EOF == fputs(ptr, output)) {
/* Only happens when /tmp is full :( */
result = ENOSPC;
/* We must complete read-out of descriptor */
output = NULL;
}
}
}
return result;
}
/**
* Very simple expect-like implementation for telnet.
* @param addr Integer encoded IPv4 address, in network byte order, use htonl().
* @param port Internet port to connect to, in network byte order, use htons().
* @param script Expect like script of paired 'expect', 'response' strings.
* @param output A FILE pointer to a tempfile() for output from the last command.
*
* This is a very simple expect-like implementation for querying and
* operating daemons remotely over telnet.
*
* The @p script is a query-response type of list of strings leading up
* to a final command, which output is then written to the given @p
* output file.
*
* @returns POSIX OK(0), or non-zero with @a errno set on error.
*/
int telnet_session(int addr, short port, char *script[], FILE *output)
{
sdbuf_t *sdbuf;
int result = 0;
sdbuf = telnet_open(addr, port);
if (!sdbuf)
return errno;
if (telnet_expect(sdbuf, script, output))
result = errno;
telnet_close(sdbuf);
return errno = result;
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+86
View File
@@ -0,0 +1,86 @@
/* A secure tmpfile() replacement.
*
* Copyright (c) 2015-2021 Joachim Wiberg <troglobit@gmail.com>
*
* 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.
*/
/**
* @file tempfile.c
* @author Joachim Wiberg
* @date 2015-2021
* @copyright ISC License
*/
#include <errno.h>
#include <paths.h>
#include <fcntl.h> /* O_TMPFILE requires -D_GNU_SOURCE */
#include <stdio.h> /* fdopen() */
#include <stdlib.h> /* mkostemp() */
#include <sys/stat.h> /* umask() */
static FILE *fallback(void)
{
char nm[15] = _PATH_TMP "XXXXXXXX";
int fd;
fd = mkostemp(nm, O_CLOEXEC);
if (-1 == fd)
return NULL;
return fdopen(fd, "w+");
}
/**
* A secure tmpfile() replacement
*
* This is the secure replacement for tmpfile() that does not exist in
* GLIBC. It uses the Linux specific @c O_TMPFILE and @c O_EXCL to hide
* the filename. When the @c FILE is fclose()'ed, the file contents is
* lost. The file is hidden in the @c _PATH_TMP ("/tmp") directory in
* the system.
*
* This function requires Linux 3.11, or later, due to @c O_TMPFILE.
* Not all file systems support hidden inodes, in which case this
* function defaults to call tmpfile() as a fallback.
*
* @returns An open @c FILE pointer, or @c NULL on error.
*/
FILE *tempfile(void)
{
#ifdef O_TMPFILE /* Only on Linux, with fairly recent (G)LIBC */
int fd;
mode_t oldmask;
oldmask = umask(0077);
fd = open(_PATH_TMP, O_TMPFILE | O_RDWR | O_EXCL | O_CLOEXEC, S_IRUSR | S_IWUSR);
umask(oldmask);
if (-1 == fd) {
if (errno == EOPNOTSUPP)
return fallback();
return NULL;
}
return fdopen(fd, "w+");
#else
return fallback();
#endif
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+72
View File
@@ -0,0 +1,72 @@
/* Formatted touch()
*
* Copyright (c) 2021 Joachim Wiberg <troglobit@gmail.com>
*
* 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.
*/
/**
* @file touchf.c
* @author Joachim Wiberg
* @date 2021
* @copyright ISC License
*/
#include <errno.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#include "lite.h"
/**
* Like touch() but with formatted string support
* @param fmt Formatted string to be composed into a pathname
*
* This is a wrapper for the touch() function in lite.h, lessening the
* burden of having to compose the filename from parts in a seprate
* buffer.
*
* @returns Upon successful completion touchf() returns POSIX OK(0),
* otherwise, -1 is returned and @a errno is set to indicate error.
*/
int touchf(const char *fmt, ...)
{
va_list ap;
char *file;
int len;
va_start(ap, fmt);
len = vsnprintf(NULL, 0, fmt, ap);
va_end(ap);
file = alloca(len + 1);
if (!file) {
errno = ENOMEM;
return -1;
}
va_start(ap, fmt);
vsnprintf(file, len + 1, fmt, ap);
va_end(ap);
return touch(file);
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+762
View File
@@ -0,0 +1,762 @@
/* $OpenBSD: tree.h,v 1.14 2015/05/25 03:07:49 deraadt Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef __cplusplus
extern "C"
{
#endif
#ifndef _SYS_TREE_H_
#define _SYS_TREE_H_
/**
* @file tree.h
* @author Niels Provos
* @date 2002
* @copyright 2-clause BSD License
*
* This file defines data structures for different types of trees:
* splay trees and red-black trees.
*
* A splay tree is a self-organizing data structure. Every operation
* on the tree causes a splay to happen. The splay moves the requested
* node to the root of the tree and partly rebalances it.
*
* This has the benefit that request locality causes faster lookups as
* the requested nodes move to the top of the tree. On the other hand,
* every lookup causes memory writes.
*
* The Balance Theorem bounds the total access time for m operations
* and n inserts on an initially empty tree as O((m + n)lg n). The
* amortized cost for a sequence of m accesses to a splay tree is O(lg n);
*
* A red-black tree is a binary search tree with the node color as an
* extra attribute. It fulfills a set of conditions:
* - every search path from the root to a leaf consists of the
* same number of black nodes,
* - each red node (except for the root) has a black parent,
* - each leaf node is black.
*
* Every operation on a red-black tree is bounded as O(lg n).
* The maximum height of a red-black tree is 2lg (n+1).
*/
#define SPLAY_HEAD(name, type) \
struct name { \
struct type *sph_root; /* root of the tree */ \
}
#define SPLAY_INITIALIZER(root) \
{ NULL }
#define SPLAY_INIT(root) do { \
(root)->sph_root = NULL; \
} while (0)
#define SPLAY_ENTRY(type) \
struct { \
struct type *spe_left; /* left element */ \
struct type *spe_right; /* right element */ \
}
#define SPLAY_LEFT(elm, field) (elm)->field.spe_left
#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right
#define SPLAY_ROOT(head) (head)->sph_root
#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL)
/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
(head)->sph_root = tmp; \
} while (0)
#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
(head)->sph_root = tmp; \
} while (0)
#define SPLAY_LINKLEFT(head, tmp, field) do { \
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
tmp = (head)->sph_root; \
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
} while (0)
#define SPLAY_LINKRIGHT(head, tmp, field) do { \
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
tmp = (head)->sph_root; \
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
} while (0)
#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \
SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
} while (0)
/* Generates prototypes and inline functions */
#define SPLAY_PROTOTYPE(name, type, field, cmp) \
void name##_SPLAY(struct name *, struct type *); \
void name##_SPLAY_MINMAX(struct name *, int); \
struct type *name##_SPLAY_INSERT(struct name *, struct type *); \
struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \
\
/* Finds the node with the same key as elm */ \
static __inline struct type * \
name##_SPLAY_FIND(struct name *head, struct type *elm) \
{ \
if (SPLAY_EMPTY(head)) \
return(NULL); \
name##_SPLAY(head, elm); \
if ((cmp)(elm, (head)->sph_root) == 0) \
return (head->sph_root); \
return (NULL); \
} \
\
static __inline struct type * \
name##_SPLAY_NEXT(struct name *head, struct type *elm) \
{ \
name##_SPLAY(head, elm); \
if (SPLAY_RIGHT(elm, field) != NULL) { \
elm = SPLAY_RIGHT(elm, field); \
while (SPLAY_LEFT(elm, field) != NULL) { \
elm = SPLAY_LEFT(elm, field); \
} \
} else \
elm = NULL; \
return (elm); \
} \
\
static __inline struct type * \
name##_SPLAY_MIN_MAX(struct name *head, int val) \
{ \
name##_SPLAY_MINMAX(head, val); \
return (SPLAY_ROOT(head)); \
}
/* Main splay operation.
* Moves node close to the key of elm to top
*/
#define SPLAY_GENERATE(name, type, field, cmp) \
struct type * \
name##_SPLAY_INSERT(struct name *head, struct type *elm) \
{ \
if (SPLAY_EMPTY(head)) { \
SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \
} else { \
int __comp; \
name##_SPLAY(head, elm); \
__comp = (cmp)(elm, (head)->sph_root); \
if(__comp < 0) { \
SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\
SPLAY_RIGHT(elm, field) = (head)->sph_root; \
SPLAY_LEFT((head)->sph_root, field) = NULL; \
} else if (__comp > 0) { \
SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\
SPLAY_LEFT(elm, field) = (head)->sph_root; \
SPLAY_RIGHT((head)->sph_root, field) = NULL; \
} else \
return ((head)->sph_root); \
} \
(head)->sph_root = (elm); \
return (NULL); \
} \
\
struct type * \
name##_SPLAY_REMOVE(struct name *head, struct type *elm) \
{ \
struct type *__tmp; \
if (SPLAY_EMPTY(head)) \
return (NULL); \
name##_SPLAY(head, elm); \
if ((cmp)(elm, (head)->sph_root) == 0) { \
if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\
} else { \
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\
name##_SPLAY(head, elm); \
SPLAY_RIGHT((head)->sph_root, field) = __tmp; \
} \
return (elm); \
} \
return (NULL); \
} \
\
void \
name##_SPLAY(struct name *head, struct type *elm) \
{ \
struct type __node, *__left, *__right, *__tmp; \
int __comp; \
\
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
__left = __right = &__node; \
\
while ((__comp = (cmp)(elm, (head)->sph_root))) { \
if (__comp < 0) { \
__tmp = SPLAY_LEFT((head)->sph_root, field); \
if (__tmp == NULL) \
break; \
if ((cmp)(elm, __tmp) < 0){ \
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
break; \
} \
SPLAY_LINKLEFT(head, __right, field); \
} else if (__comp > 0) { \
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
if (__tmp == NULL) \
break; \
if ((cmp)(elm, __tmp) > 0){ \
SPLAY_ROTATE_LEFT(head, __tmp, field); \
if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
break; \
} \
SPLAY_LINKRIGHT(head, __left, field); \
} \
} \
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
} \
\
/* Splay with either the minimum or the maximum element \
* Used to find minimum or maximum element in tree. \
*/ \
void name##_SPLAY_MINMAX(struct name *head, int __comp) \
{ \
struct type __node, *__left, *__right, *__tmp; \
\
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
__left = __right = &__node; \
\
while (1) { \
if (__comp < 0) { \
__tmp = SPLAY_LEFT((head)->sph_root, field); \
if (__tmp == NULL) \
break; \
if (__comp < 0){ \
SPLAY_ROTATE_RIGHT(head, __tmp, field); \
if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
break; \
} \
SPLAY_LINKLEFT(head, __right, field); \
} else if (__comp > 0) { \
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
if (__tmp == NULL) \
break; \
if (__comp > 0) { \
SPLAY_ROTATE_LEFT(head, __tmp, field); \
if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
break; \
} \
SPLAY_LINKRIGHT(head, __left, field); \
} \
} \
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
}
#define SPLAY_NEGINF -1
#define SPLAY_INF 1
#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y)
#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y)
#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y)
#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y)
#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \
: name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \
: name##_SPLAY_MIN_MAX(x, SPLAY_INF))
#define SPLAY_FOREACH(x, name, head) \
for ((x) = SPLAY_MIN(name, head); \
(x) != NULL; \
(x) = SPLAY_NEXT(name, head, x))
/* Macros that define a red-black tree */
#define RB_HEAD(name, type) \
struct name { \
struct type *rbh_root; /* root of the tree */ \
}
#define RB_INITIALIZER(root) \
{ NULL }
#define RB_INIT(root) do { \
(root)->rbh_root = NULL; \
} while (0)
#define RB_BLACK 0
#define RB_RED 1
#define RB_ENTRY(type) \
struct { \
struct type *rbe_left; /* left element */ \
struct type *rbe_right; /* right element */ \
struct type *rbe_parent; /* parent element */ \
int rbe_color; /* node color */ \
}
#define RB_LEFT(elm, field) (elm)->field.rbe_left
#define RB_RIGHT(elm, field) (elm)->field.rbe_right
#define RB_PARENT(elm, field) (elm)->field.rbe_parent
#define RB_COLOR(elm, field) (elm)->field.rbe_color
#define RB_ROOT(head) (head)->rbh_root
#define RB_EMPTY(head) (RB_ROOT(head) == NULL)
#define RB_SET(elm, parent, field) do { \
RB_PARENT(elm, field) = parent; \
RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \
RB_COLOR(elm, field) = RB_RED; \
} while (0)
#define RB_SET_BLACKRED(black, red, field) do { \
RB_COLOR(black, field) = RB_BLACK; \
RB_COLOR(red, field) = RB_RED; \
} while (0)
#ifndef RB_AUGMENT
#define RB_AUGMENT(x) do {} while (0)
#endif
#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \
(tmp) = RB_RIGHT(elm, field); \
if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) { \
RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \
} \
RB_AUGMENT(elm); \
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \
if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
else \
RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
} else \
(head)->rbh_root = (tmp); \
RB_LEFT(tmp, field) = (elm); \
RB_PARENT(elm, field) = (tmp); \
RB_AUGMENT(tmp); \
if ((RB_PARENT(tmp, field))) \
RB_AUGMENT(RB_PARENT(tmp, field)); \
} while (0)
#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \
(tmp) = RB_LEFT(elm, field); \
if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) { \
RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \
} \
RB_AUGMENT(elm); \
if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) { \
if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
else \
RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
} else \
(head)->rbh_root = (tmp); \
RB_RIGHT(tmp, field) = (elm); \
RB_PARENT(elm, field) = (tmp); \
RB_AUGMENT(tmp); \
if ((RB_PARENT(tmp, field))) \
RB_AUGMENT(RB_PARENT(tmp, field)); \
} while (0)
/* Generates prototypes and inline functions */
#define RB_PROTOTYPE(name, type, field, cmp) \
RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \
RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static)
#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \
attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \
attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
attr struct type *name##_RB_REMOVE(struct name *, struct type *); \
attr struct type *name##_RB_INSERT(struct name *, struct type *); \
attr struct type *name##_RB_FIND(struct name *, struct type *); \
attr struct type *name##_RB_NFIND(struct name *, struct type *); \
attr struct type *name##_RB_NEXT(struct type *); \
attr struct type *name##_RB_PREV(struct type *); \
attr struct type *name##_RB_MINMAX(struct name *, int); \
\
/* Main rb operation.
* Moves node close to the key of elm to top
*/
#define RB_GENERATE(name, type, field, cmp) \
RB_GENERATE_INTERNAL(name, type, field, cmp,)
#define RB_GENERATE_STATIC(name, type, field, cmp) \
RB_GENERATE_INTERNAL(name, type, field, cmp, __attribute__((__unused__)) static)
#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \
attr void \
name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
{ \
struct type *parent, *gparent, *tmp; \
while ((parent = RB_PARENT(elm, field)) && \
RB_COLOR(parent, field) == RB_RED) { \
gparent = RB_PARENT(parent, field); \
if (parent == RB_LEFT(gparent, field)) { \
tmp = RB_RIGHT(gparent, field); \
if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
RB_COLOR(tmp, field) = RB_BLACK; \
RB_SET_BLACKRED(parent, gparent, field);\
elm = gparent; \
continue; \
} \
if (RB_RIGHT(parent, field) == elm) { \
RB_ROTATE_LEFT(head, parent, tmp, field);\
tmp = parent; \
parent = elm; \
elm = tmp; \
} \
RB_SET_BLACKRED(parent, gparent, field); \
RB_ROTATE_RIGHT(head, gparent, tmp, field); \
} else { \
tmp = RB_LEFT(gparent, field); \
if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
RB_COLOR(tmp, field) = RB_BLACK; \
RB_SET_BLACKRED(parent, gparent, field);\
elm = gparent; \
continue; \
} \
if (RB_LEFT(parent, field) == elm) { \
RB_ROTATE_RIGHT(head, parent, tmp, field);\
tmp = parent; \
parent = elm; \
elm = tmp; \
} \
RB_SET_BLACKRED(parent, gparent, field); \
RB_ROTATE_LEFT(head, gparent, tmp, field); \
} \
} \
RB_COLOR(head->rbh_root, field) = RB_BLACK; \
} \
\
attr void \
name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
{ \
struct type *tmp; \
while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \
elm != RB_ROOT(head)) { \
if (RB_LEFT(parent, field) == elm) { \
tmp = RB_RIGHT(parent, field); \
if (RB_COLOR(tmp, field) == RB_RED) { \
RB_SET_BLACKRED(tmp, parent, field); \
RB_ROTATE_LEFT(head, parent, tmp, field);\
tmp = RB_RIGHT(parent, field); \
} \
if ((RB_LEFT(tmp, field) == NULL || \
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
(RB_RIGHT(tmp, field) == NULL || \
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
RB_COLOR(tmp, field) = RB_RED; \
elm = parent; \
parent = RB_PARENT(elm, field); \
} else { \
if (RB_RIGHT(tmp, field) == NULL || \
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\
struct type *oleft; \
if ((oleft = RB_LEFT(tmp, field)))\
RB_COLOR(oleft, field) = RB_BLACK;\
RB_COLOR(tmp, field) = RB_RED; \
RB_ROTATE_RIGHT(head, tmp, oleft, field);\
tmp = RB_RIGHT(parent, field); \
} \
RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
RB_COLOR(parent, field) = RB_BLACK; \
if (RB_RIGHT(tmp, field)) \
RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\
RB_ROTATE_LEFT(head, parent, tmp, field);\
elm = RB_ROOT(head); \
break; \
} \
} else { \
tmp = RB_LEFT(parent, field); \
if (RB_COLOR(tmp, field) == RB_RED) { \
RB_SET_BLACKRED(tmp, parent, field); \
RB_ROTATE_RIGHT(head, parent, tmp, field);\
tmp = RB_LEFT(parent, field); \
} \
if ((RB_LEFT(tmp, field) == NULL || \
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
(RB_RIGHT(tmp, field) == NULL || \
RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
RB_COLOR(tmp, field) = RB_RED; \
elm = parent; \
parent = RB_PARENT(elm, field); \
} else { \
if (RB_LEFT(tmp, field) == NULL || \
RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\
struct type *oright; \
if ((oright = RB_RIGHT(tmp, field)))\
RB_COLOR(oright, field) = RB_BLACK;\
RB_COLOR(tmp, field) = RB_RED; \
RB_ROTATE_LEFT(head, tmp, oright, field);\
tmp = RB_LEFT(parent, field); \
} \
RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
RB_COLOR(parent, field) = RB_BLACK; \
if (RB_LEFT(tmp, field)) \
RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\
RB_ROTATE_RIGHT(head, parent, tmp, field);\
elm = RB_ROOT(head); \
break; \
} \
} \
} \
if (elm) \
RB_COLOR(elm, field) = RB_BLACK; \
} \
\
attr struct type * \
name##_RB_REMOVE(struct name *head, struct type *elm) \
{ \
struct type *child, *parent, *old = elm; \
int color; \
if (RB_LEFT(elm, field) == NULL) \
child = RB_RIGHT(elm, field); \
else if (RB_RIGHT(elm, field) == NULL) \
child = RB_LEFT(elm, field); \
else { \
struct type *left; \
elm = RB_RIGHT(elm, field); \
while ((left = RB_LEFT(elm, field))) \
elm = left; \
child = RB_RIGHT(elm, field); \
parent = RB_PARENT(elm, field); \
color = RB_COLOR(elm, field); \
if (child) \
RB_PARENT(child, field) = parent; \
if (parent) { \
if (RB_LEFT(parent, field) == elm) \
RB_LEFT(parent, field) = child; \
else \
RB_RIGHT(parent, field) = child; \
RB_AUGMENT(parent); \
} else \
RB_ROOT(head) = child; \
if (RB_PARENT(elm, field) == old) \
parent = elm; \
(elm)->field = (old)->field; \
if (RB_PARENT(old, field)) { \
if (RB_LEFT(RB_PARENT(old, field), field) == old)\
RB_LEFT(RB_PARENT(old, field), field) = elm;\
else \
RB_RIGHT(RB_PARENT(old, field), field) = elm;\
RB_AUGMENT(RB_PARENT(old, field)); \
} else \
RB_ROOT(head) = elm; \
RB_PARENT(RB_LEFT(old, field), field) = elm; \
if (RB_RIGHT(old, field)) \
RB_PARENT(RB_RIGHT(old, field), field) = elm; \
if (parent) { \
left = parent; \
do { \
RB_AUGMENT(left); \
} while ((left = RB_PARENT(left, field))); \
} \
goto color; \
} \
parent = RB_PARENT(elm, field); \
color = RB_COLOR(elm, field); \
if (child) \
RB_PARENT(child, field) = parent; \
if (parent) { \
if (RB_LEFT(parent, field) == elm) \
RB_LEFT(parent, field) = child; \
else \
RB_RIGHT(parent, field) = child; \
RB_AUGMENT(parent); \
} else \
RB_ROOT(head) = child; \
color: \
if (color == RB_BLACK) \
name##_RB_REMOVE_COLOR(head, parent, child); \
return (old); \
} \
\
/* Inserts a node into the RB tree */ \
attr struct type * \
name##_RB_INSERT(struct name *head, struct type *elm) \
{ \
struct type *tmp; \
struct type *parent = NULL; \
int comp = 0; \
tmp = RB_ROOT(head); \
while (tmp) { \
parent = tmp; \
comp = (cmp)(elm, parent); \
if (comp < 0) \
tmp = RB_LEFT(tmp, field); \
else if (comp > 0) \
tmp = RB_RIGHT(tmp, field); \
else \
return (tmp); \
} \
RB_SET(elm, parent, field); \
if (parent != NULL) { \
if (comp < 0) \
RB_LEFT(parent, field) = elm; \
else \
RB_RIGHT(parent, field) = elm; \
RB_AUGMENT(parent); \
} else \
RB_ROOT(head) = elm; \
name##_RB_INSERT_COLOR(head, elm); \
return (NULL); \
} \
\
/* Finds the node with the same key as elm */ \
attr struct type * \
name##_RB_FIND(struct name *head, struct type *elm) \
{ \
struct type *tmp = RB_ROOT(head); \
int comp; \
while (tmp) { \
comp = cmp(elm, tmp); \
if (comp < 0) \
tmp = RB_LEFT(tmp, field); \
else if (comp > 0) \
tmp = RB_RIGHT(tmp, field); \
else \
return (tmp); \
} \
return (NULL); \
} \
\
/* Finds the first node greater than or equal to the search key */ \
attr struct type * \
name##_RB_NFIND(struct name *head, struct type *elm) \
{ \
struct type *tmp = RB_ROOT(head); \
struct type *res = NULL; \
int comp; \
while (tmp) { \
comp = cmp(elm, tmp); \
if (comp < 0) { \
res = tmp; \
tmp = RB_LEFT(tmp, field); \
} \
else if (comp > 0) \
tmp = RB_RIGHT(tmp, field); \
else \
return (tmp); \
} \
return (res); \
} \
\
/* ARGSUSED */ \
attr struct type * \
name##_RB_NEXT(struct type *elm) \
{ \
if (RB_RIGHT(elm, field)) { \
elm = RB_RIGHT(elm, field); \
while (RB_LEFT(elm, field)) \
elm = RB_LEFT(elm, field); \
} else { \
if (RB_PARENT(elm, field) && \
(elm == RB_LEFT(RB_PARENT(elm, field), field))) \
elm = RB_PARENT(elm, field); \
else { \
while (RB_PARENT(elm, field) && \
(elm == RB_RIGHT(RB_PARENT(elm, field), field)))\
elm = RB_PARENT(elm, field); \
elm = RB_PARENT(elm, field); \
} \
} \
return (elm); \
} \
\
/* ARGSUSED */ \
attr struct type * \
name##_RB_PREV(struct type *elm) \
{ \
if (RB_LEFT(elm, field)) { \
elm = RB_LEFT(elm, field); \
while (RB_RIGHT(elm, field)) \
elm = RB_RIGHT(elm, field); \
} else { \
if (RB_PARENT(elm, field) && \
(elm == RB_RIGHT(RB_PARENT(elm, field), field))) \
elm = RB_PARENT(elm, field); \
else { \
while (RB_PARENT(elm, field) && \
(elm == RB_LEFT(RB_PARENT(elm, field), field)))\
elm = RB_PARENT(elm, field); \
elm = RB_PARENT(elm, field); \
} \
} \
return (elm); \
} \
\
attr struct type * \
name##_RB_MINMAX(struct name *head, int val) \
{ \
struct type *tmp = RB_ROOT(head); \
struct type *parent = NULL; \
while (tmp) { \
parent = tmp; \
if (val < 0) \
tmp = RB_LEFT(tmp, field); \
else \
tmp = RB_RIGHT(tmp, field); \
} \
return (parent); \
}
#define RB_NEGINF -1
#define RB_INF 1
#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y)
#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
#define RB_FIND(name, x, y) name##_RB_FIND(x, y)
#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y)
#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
#define RB_PREV(name, x, y) name##_RB_PREV(y)
#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF)
#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF)
#define RB_FOREACH(x, name, head) \
for ((x) = RB_MIN(name, head); \
(x) != NULL; \
(x) = name##_RB_NEXT(x))
#define RB_FOREACH_SAFE(x, name, head, y) \
for ((x) = RB_MIN(name, head); \
((x) != NULL) && ((y) = name##_RB_NEXT(x), 1); \
(x) = (y))
#define RB_FOREACH_REVERSE(x, name, head) \
for ((x) = RB_MAX(name, head); \
(x) != NULL; \
(x) = name##_RB_PREV(x))
#define RB_FOREACH_REVERSE_SAFE(x, name, head, y) \
for ((x) = RB_MAX(name, head); \
((x) != NULL) && ((y) = name##_RB_PREV(x), 1); \
(x) = (y))
#endif /* _SYS_TREE_H_ */
#ifdef __cplusplus
}
#endif
+70
View File
@@ -0,0 +1,70 @@
/* Formatted truncate()
*
* Copyright (c) 2021 Joachim Wiberg <troglobit@gmail.com>
*
* 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.
*/
/**
* @file truncatef.c
* @author Joachim Wiberg
* @date 2021
* @copyright ISC License
*/
#include <errno.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
/**
* Truncate a file based on the formatted string
* @param length Size in bytes to truncate file to, zero to empty it
* @param fmt Formatted string to be composed into a pathname
*
* This is an extension to the truncate() family, lessening the burden
* of having to compose the filename from parts in a seprate buffer.
*
* @returns Upon successful completion truncate() returns POSIX OK(0),
* otherwise, -1 is returned and @a errno is set to indicate error.
*/
int truncatef(off_t length, const char *fmt, ...)
{
va_list ap;
char *file;
int len;
va_start(ap, fmt);
len = vsnprintf(NULL, 0, fmt, ap);
va_end(ap);
file = alloca(len + 1);
if (!file) {
errno = ENOMEM;
return -1;
}
va_start(ap, fmt);
vsnprintf(file, len + 1, fmt, ap);
va_end(ap);
return truncate(file, length);
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+140
View File
@@ -0,0 +1,140 @@
/* C implementation of UNIX which(1)
*
* Copyright (c) 2017-2021 Joachim Wiberg <troglobit@gmail.com>
*
* 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.
*/
/**
* @file which.c
* @author Joachim Wiberg
* @date 2017-2021
* @copyright ISC License
*/
#include <ctype.h>
#include <errno.h>
#include <stdio.h> /* snprintf() */
#include <stdlib.h> /* realloc(), free() */
#include <string.h> /* strtok_r() */
#include <unistd.h> /* access() */
/* Strip any arguments in "/path/to/bin --some args", modifies input string */
static char *strip_args(char *path)
{
size_t i = 0;
if (!path)
return NULL;
/* Find first whitespace (space/tab/etc.) */
while (path[i] && !isspace(path[i]))
i++;
path[i] = 0;
return path;
}
/**
* Like which(1), or `command -v foo`
* @param cmd Command to look for in $PATH
*
* @returns A malloc()'ed path to @a cmd on success, or @c NULL.
*/
char *which(const char *cmd)
{
size_t pathlen = 0;
char *ptr, *tok, *env, *path = NULL;
if (!cmd) {
errno = EINVAL;
return NULL;
}
if (cmd[0] == '/') {
path = strip_args(strdup(cmd));
if (!path)
return NULL;
if (!access(path, X_OK))
return path;
if (path)
free(path);
return NULL;
}
ptr = getenv("PATH");
if (!ptr)
return NULL;
env = strdup(ptr);
if (!env)
return NULL;
tok = strtok_r(env, ":", &ptr);
while (tok) {
size_t len = strlen(tok) + strlen(cmd) + 2;
if (pathlen < len) {
path = realloc(path, len);
if (!path) {
free(env);
return NULL;
}
pathlen = len;
}
snprintf(path, pathlen, "%s/%s", tok, cmd);
path = strip_args(path);
if (!path || !access(path, X_OK)) {
free(env);
return path;
}
tok = strtok_r(NULL, ":", &ptr);
}
if (path)
free(path);
free(env);
return NULL;
}
/**
* Predicate variant of which()
* @param cmd Command to look for in $PATH
*
* @returns @c TRUE(1) or @c FALSE(0) if @p cmd exists in $PATH.
*/
int whichp(const char *cmd)
{
char *path;
path = which(cmd);
if (path) {
free(path);
return 1;
}
return 0;
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+98
View File
@@ -0,0 +1,98 @@
/* Safe yes-or-no with prompt
*
* Copyright (c) 2009-2021 Joachim Wiberg <troglobit@gmail.com>
*
* 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.
*/
/**
* @file yorn.c
* @author Joachim Wiberg
* @date 2009-2021
* @copyright ISC License
*/
#include <stdio.h>
#include <stdio_ext.h> /* __fpurge() */
#include <stdarg.h>
#include <termios.h>
#include <unistd.h>
static char rawgetch(void)
{
struct termios savemodes, modmodes;
char val;
if (!isatty(STDIN_FILENO))
return getchar();
/* Backup terminal settings. */
if (tcgetattr(STDIN_FILENO, &savemodes) < 0) {
return -1;
}
/* "stty cbreak -echo" */
modmodes = savemodes;
modmodes.c_lflag &= ~ICANON;
modmodes.c_lflag &= ~ECHO;
modmodes.c_cc[VMIN] = 1;
modmodes.c_cc[VTIME] = 0;
/* Set terminal in raw mode. */
if (tcsetattr(STDIN_FILENO, TCSANOW, &modmodes) < 0) {
tcsetattr(STDIN_FILENO, TCSANOW, &savemodes);
return -1;
}
val = getchar();
/* Restore terminal to previous state. */
tcsetattr(STDIN_FILENO, TCSANOW, &savemodes);
return val;
}
/**
* Pose a a Yes or No question and return answer
* @param fmt Standard printf() style argument(s).
*
* This function prints the given question on screen, waits for user
* input in the form of yes or no.
*
* @returns TRUE(1) or FALSE(0). True if the answer is yes.
*/
int yorn(const char *fmt, ...)
{
va_list ap;
char yorn;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
__fpurge(stdin);
yorn = rawgetch();
printf("%c\n", yorn);
fflush(stdout);
if (yorn != 'y' && yorn != 'Y')
return 0;
return 1;
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+25
View File
@@ -0,0 +1,25 @@
*.o
*.log
*.trs
.deps/
/chomp
/copyfile
/dir
/fexist
/fisdir
/fopenf
/fsendfile
/lfile
/makepath
/pidfile
/printhdr
/progress
/rsync
/str
/strmatch
/systemf
/tempfile
/touch
/tree
/which
/yorn
+41
View File
@@ -0,0 +1,41 @@
# Ignore warnings about unused result, in e.g. write()
AM_CFLAGS = -W -Wall -Wextra -Wno-unused-result
AM_CPPFLAGS = -D_GNU_SOURCE
AM_LDFLAGS = -L../src/ ../src/libite.la -static
EXTRA_DIST = check.h data/fexist/dir/.placeholder data/fexist/executable
EXTRA_DIST += data/fexist/link data/fexist/regular data/lfile/fstab
EXTRA_DIST += data/lfile/group data/lfile/passwd data/lfile/protocols
EXTRA_DIST += data/lfile/services data/which/executable
EXTRA_DIST += data/which/executable-link data/which/regular
CLEANFILES = *~ *.trs *.log
TESTS_ENVIRONMENT = ([ -d data ] || ln -sf $(srcdir)/data) &&
clean-local:
-find -type l -name data -exec rm {} \;
TESTS =
TESTS += chomp
TESTS += copyfile
TESTS += dir
TESTS += fexist
TESTS += fisdir
TESTS += fopenf
TESTS += fsendfile
TESTS += lfile
TESTS += makepath
TESTS += pidfile
TESTS += printhdr
TESTS += progress
TESTS += rsync
TESTS += str
TESTS += strmatch
TESTS += systemf
TESTS += touch
TESTS += tempfile
TESTS += which
TESTS += yorn
check_PROGRAMS = $(TESTS)
+81
View File
@@ -0,0 +1,81 @@
#ifndef LIBLITE_TESTS_CHECK_H_
#define LIBLITE_TESTS_CHECK_H_
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "../src/conio.h"
#include "../src/lite.h"
#define PRINT(args...) if (verbose) printf(args)
#define fail_unless(test) \
do { \
if (!(test)) { \
fprintf(stderr, \
"----------------------------------------------\n" \
"%s:%d: test FAILED:\nFailed test: %s\n" \
"----------------------------------------------\n", \
__FILE__, __LINE__, #test); \
exit(1); \
} \
} while (0)
static inline int test(int result, const char *fmt, ...)
{
char buf[80];
size_t len;
va_list ap;
const char success[] = " \033[1m[ OK ]\033[0m\n";
const char failure[] = " \033[7m[FAIL]\033[0m\n";
const char dots[] = " .....................................................................";
va_start(ap, fmt);
len = vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
write(STDERR_FILENO, buf, len);
write(STDERR_FILENO, dots, 60 - len); /* pad with dots. */
if (!result)
write(STDERR_FILENO, success, strlen(success));
else
write(STDERR_FILENO, failure, strlen(failure));
return result;
}
static inline int timespec_newer(const struct timespec *a, const struct timespec *b)
{
if (a->tv_sec != b->tv_sec)
return a->tv_sec > b->tv_sec;
return a->tv_nsec > b->tv_nsec;
}
static inline char *timespec2str(struct timespec *ts, char *buf, size_t len)
{
size_t ret, pos;
struct tm t;
memset(buf, 0, len);
tzset();
if (localtime_r(&(ts->tv_sec), &t) == NULL)
return buf;
ret = strftime(buf, len, "%F %T", &t);
if (ret == 0)
return buf;
len -= ret - 1;
pos = strlen(buf);
len -= pos;
snprintf(&buf[pos], len, ".%09ld", ts->tv_nsec);
return buf;
}
#endif /* LIBLITE_TESTS_CHECK_H_ */
+24
View File
@@ -0,0 +1,24 @@
#include "check.h"
int main(void)
{
size_t i;
char t[][16] = {
"hej\ndej",
"Slime\n\n\\n",
"Tripple\n\n\n"
};
for (i = 0; i < NELEMS(t); i++) {
char *str = t[i];
size_t len;
chomp(str);
len = strlen(str);
printf("[%02zd]: '%s'\n", i, str);
fail_unless(str[len] != '\n');
}
return 0;
}
+55
View File
@@ -0,0 +1,55 @@
#include <err.h>
#include <errno.h>
#include "check.h"
int main(void)
{
int i = 0;
char *files[] = {
"/etc/passwd", "/tmp/mypwd", "/tmp/mypwd",
"/etc/passwd", "/tmp/", "/tmp/passwd",
"/etc/passwd", "/tmp", "/tmp/passwd",
NULL
};
FILE *src, *dst;
printf("=>Start testing fcopyfile()\n");
while (files[i]) {
printf("fcopyfile(%s, %s)\t", files[i], files[i + 1]);
src = fopen(files[i], "r");
dst = fopen(files[i + 1], "w");
if (fcopyfile(src, dst)) {
if (!fisdir(files[i + 1]))
err(1, "Failed fcopyfile(%s, %s)", files[i], files[i + 1]);
}
if (src)
fclose(src);
if (dst)
fclose(dst);
if (fexist(files[i + 2]))
printf("OK => %s", files[i + 2]);
printf("\n");
erase(files[i + 2]);
i += 3;
}
printf("\n=>Start testing copyfile()\n");
i = 0;
while (files[i]) {
printf("copyfile(%s, %s)\t", files[i], files[i + 1]);
if (!copyfile(files[i], files[i + 1], 0, 0))
err(1, "Failed copyfile(%s, %s)", files[i], files[i + 1]);
if (fexist(files[i + 2]))
printf("OK => %s", files[i + 2]);
printf("\n");
erase(files[i + 2]);
i += 3;
}
return 0;
}
+1
View File
@@ -0,0 +1 @@
nonexistence
View File
Whitespace-only changes.
View File
Whitespace-only changes.
+1
View File
@@ -0,0 +1 @@
regular
View File
Whitespace-only changes.
+3
View File
@@ -0,0 +1,3 @@
UUID=xxxxxxxxxx / xfs defaults 0 1
/dev/sda1 /boot/efi vfat umask=0077 0 1
/dev/sr0 /media/cdrom0 udf,iso9660 user,noauto 0 0
+39
View File
@@ -0,0 +1,39 @@
root:x:0:
daemon:x:1:
bin:x:2:
sys:x:3:
adm:x:4:
tty:x:5:
disk:x:6:
lp:x:7:
mail:x:8:
news:x:9:
uucp:x:10:
man:x:12:
proxy:x:13:
kmem:x:15:
dialout:x:20:
fax:x:21:
voice:x:22:
cdrom:x:24:
floppy:x:25:
tape:x:26:
sudo:x:27:
audio:x:29:
dip:x:30:
www-data:x:33:
backup:x:34:
operator:x:37:
list:x:38:
irc:x:39:
src:x:40:
gnats:x:41:
shadow:x:42:
utmp:x:43:
video:x:44:
sasl:x:45:
plugdev:x:46:
staff:x:50:
games:x:60:
users:x:100:
nogroup:x:65534:
+18
View File
@@ -0,0 +1,18 @@
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
+64
View File
@@ -0,0 +1,64 @@
# Internet (IP) protocols
#
# Updated from http://www.iana.org/assignments/protocol-numbers and other
# sources.
# New protocols will be added on request if they have been officially
# assigned by IANA and are not historical.
# If you need a huge list of used numbers please install the nmap package.
ip 0 IP # internet protocol, pseudo protocol number
hopopt 0 HOPOPT # IPv6 Hop-by-Hop Option [RFC1883]
icmp 1 ICMP # internet control message protocol
igmp 2 IGMP # Internet Group Management
ggp 3 GGP # gateway-gateway protocol
ipencap 4 IP-ENCAP # IP encapsulated in IP (officially ``IP'')
st 5 ST # ST datagram mode
tcp 6 TCP # transmission control protocol
egp 8 EGP # exterior gateway protocol
igp 9 IGP # any private interior gateway (Cisco)
pup 12 PUP # PARC universal packet protocol
udp 17 UDP # user datagram protocol
hmp 20 HMP # host monitoring protocol
xns-idp 22 XNS-IDP # Xerox NS IDP
rdp 27 RDP # "reliable datagram" protocol
iso-tp4 29 ISO-TP4 # ISO Transport Protocol class 4 [RFC905]
dccp 33 DCCP # Datagram Congestion Control Prot. [RFC4340]
xtp 36 XTP # Xpress Transfer Protocol
ddp 37 DDP # Datagram Delivery Protocol
idpr-cmtp 38 IDPR-CMTP # IDPR Control Message Transport
ipv6 41 IPv6 # Internet Protocol, version 6
ipv6-route 43 IPv6-Route # Routing Header for IPv6
ipv6-frag 44 IPv6-Frag # Fragment Header for IPv6
idrp 45 IDRP # Inter-Domain Routing Protocol
rsvp 46 RSVP # Reservation Protocol
gre 47 GRE # General Routing Encapsulation
esp 50 IPSEC-ESP # Encap Security Payload [RFC2406]
ah 51 IPSEC-AH # Authentication Header [RFC2402]
skip 57 SKIP # SKIP
ipv6-icmp 58 IPv6-ICMP # ICMP for IPv6
ipv6-nonxt 59 IPv6-NoNxt # No Next Header for IPv6
ipv6-opts 60 IPv6-Opts # Destination Options for IPv6
rspf 73 RSPF CPHB # Radio Shortest Path First (officially CPHB)
vmtp 81 VMTP # Versatile Message Transport
eigrp 88 EIGRP # Enhanced Interior Routing Protocol (Cisco)
ospf 89 OSPFIGP # Open Shortest Path First IGP
ax.25 93 AX.25 # AX.25 frames
ipip 94 IPIP # IP-within-IP Encapsulation Protocol
etherip 97 ETHERIP # Ethernet-within-IP Encapsulation [RFC3378]
encap 98 ENCAP # Yet Another IP encapsulation [RFC1241]
# 99 # any private encryption scheme
pim 103 PIM # Protocol Independent Multicast
ipcomp 108 IPCOMP # IP Payload Compression Protocol
vrrp 112 VRRP # Virtual Router Redundancy Protocol [RFC5798]
l2tp 115 L2TP # Layer Two Tunneling Protocol [RFC2661]
isis 124 ISIS # IS-IS over IPv4
sctp 132 SCTP # Stream Control Transmission Protocol
fc 133 FC # Fibre Channel
mobility-header 135 Mobility-Header # Mobility Support for IPv6 [RFC3775]
udplite 136 UDPLite # UDP-Lite [RFC3828]
mpls-in-ip 137 MPLS-in-IP # MPLS-in-IP [RFC4023]
manet 138 # MANET Protocols [RFC5498]
hip 139 HIP # Host Identity Protocol
shim6 140 Shim6 # Shim6 Protocol [RFC5533]
wesp 141 WESP # Wrapped Encapsulating Security Payload
rohc 142 ROHC # Robust Header Compression
Loaded 100 of 122 files, more files were not shown because too many files have changed in this diff. Show more