Compare commits

..
26 Commits
Author SHA1 Message Date
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
33 changed files with 769 additions and 46 deletions

No files matched your search

+17 -1
View File
@@ -3,6 +3,21 @@ Change Log
All notable changes to the project are documented in this file.
[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
-----------------------
@@ -324,7 +339,8 @@ problems this may cause!
Initial extraction of frog DNA from [Finit][]. See [README][] for API details.
[UNRELEASED]: https://github.com/troglobit/libite/compare/v2.0.2...HEAD
[UNRELEASED]: https://github.com/troglobit/libite/compare/v2.1.0...HEAD
[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
+1 -1
View File
@@ -1,6 +1,6 @@
ACLOCAL_AMFLAGS = -I m4
doc_DATA = README.md LICENSE
doc_DATA = README.md LICENSE ChangeLog.md
EXTRA_DIST = README.md LICENSE ChangeLog.md
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libite.pc
+22 -3
View File
@@ -284,6 +284,20 @@ Generic Functions
`delete`, it is now called `opt`. The APIs are 100% compatible if the
value `1` was used.
- `strmatch()`, `strnmatch()`
Find matching string in an array of strings. Returns index in array
on match, or `-1` on error or not found.
- `telnet_open(), telnet_close(), telnet_expect()`
Poor mans telnet expect in C. Opens connection to a Telnet service;
FTP, Telnet, similar, and run an expect-like script.
- `telnet_session()`
Wrapper for the above three in one API.
- `tempfile()`
Secure replacement for `tmpfile()`. Creates an invisible temporary
@@ -303,6 +317,11 @@ Generic Functions
**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
-------------
@@ -384,9 +403,9 @@ as a light weight utility library, these days NetBSD should also work.
sudo make install-strip
sudo ldconfig
**Note:** When checking code from GitHub, use <kbd>./autogen.sh</kbd> to
generate a `configure` script. It is a generated file and otherwise only
included in released tarballs.
**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.
[1]: https://github.com/troglobit/finit
+1 -1
View File
@@ -1,4 +1,4 @@
AC_INIT(libite, 2.0.2, https://github.com/troglobit/libite/issues)
AC_INIT(libite, 2.1.0, https://github.com/troglobit/libite/issues)
AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz])
AM_SILENT_RULES([yes])
+7
View File
@@ -1,3 +1,10 @@
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
+1 -1
View File
@@ -1 +1 @@
9
10
+17 -16
View File
@@ -1,18 +1,18 @@
Source: libite
Priority: optional
Maintainer: Joachim Nilsson <troglobit@gmail.com>
Build-Depends: dpkg-dev (>= 1.14.9), debhelper (>= 9), dh-autoreconf
Standards-Version: 3.9.6
Build-Depends: dpkg-dev (>= 1.14.9), debhelper (>= 10)
Standards-Version: 4.1.0
Section: libs
Homepage: https://github.com/troglobit/libite/
Vcs-Git: https://github.com/troglobit/libite.git
Vcs-Browser: https://github.com/troglobit/libite/
Package: libite-dev
Priority: extra
Priority: optional
Section: libdevel
Architecture: any
Depends: ${misc:Depends}, libite (= ${binary:Version})
Depends: ${misc:Depends}, libite5 (= ${binary:Version})
Description: static library, header files, and docs for libite
Static library, header files, and documentation for libite.
.
@@ -31,21 +31,22 @@ Description: static library, header files, and docs for libite
license used by OpenBSD, and BSD licenses, all of them are extremely
liberal and can be used freely in proprietary software if needed.
Package: libite
Package: libite5
Architecture: any
Depends: ${misc:Depends}, ${shlibs:Depends}
Description: That missing frog DNA you've been looking for. MIT/X11/ISC/BSD License.
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.
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
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.
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.
+13 -1
View File
@@ -61,9 +61,13 @@ Copyright: 2009 William Ahern
License: MIT
Files: strlcat.c strlcpy.c
Copyright: 998, 2015 Todd C. Miller <Todd.Miller@courtesan.com>
Copyright: 1998, 2015 Todd C. Miller <Todd.Miller@courtesan.com>
License: MIT
Files: strmatch.c
Copyright: 2009-2018 Joachim Nilsson <troglobit@gmail.com>
License: ISC
Files: strnlen.c
Copyright: 2016 Joachim Nilsson <troglobit@gmail.com>
License: ISC
@@ -72,6 +76,10 @@ Files: strtonum.c
Copyright: 2004 Ted Unangst and Todd Miller
License: ISC
Files: telnet.c
Copyright: 2010, 2013, 2019 Joachim Nilsson <troglobit@gmail.com>
License: ISC
Files: tempfile.c
Copyright: 2015-2016 Joachim Nilsson <troglobit@gmail.com>
License: ISC
@@ -80,5 +88,9 @@ Files: tree.c
Copyright: 2015 Joachim Nilsson <troglobit@gmail.com>
License: ISC
Files: yorn.c
Copyright: 2009 Joachim Nilsson <troglobit@gmail.com>
License: ISC
Files: tests/*.c
License: public-domain
View File
File renamed without changes.
View File
File renamed without changes.
+7
View File
@@ -1,4 +1,5 @@
#!/usr/bin/make -f
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
@@ -6,3 +7,9 @@
%:
dh $@ --with autoreconf
override_dh_auto_install:
dh_auto_install
-rm -f debian/libite/usr/share/doc/libite/LICENSE
override_dh_installchangelogs:
dh_installchangelogs ChangeLog.md
+1
View File
@@ -0,0 +1 @@
compression=xz
+4 -2
View File
@@ -14,11 +14,13 @@ libite_la_SOURCES = chomp.c copyfile.c \
reallocarray.c rsync.c \
strlcpy.c strlcat.c strtonum.c \
strdupa.h strndupa.h strnlen.h \
tempfile.c which.c \
strmatch.c telnet.c tempfile.c \
yorn.c which.c \
lite.h strlite.h \
queue.h tree.h
## Distribute these header files in the <lite/...> name space
pkgincludedir = $(includedir)/lite
pkginclude_HEADERS = lite.h queue.h conio.h tree.h strlite.h strdupa.h strndupa.h strnlen.h
pkginclude_HEADERS = lite.h queue.h conio.h tree.h strlite.h strdupa.h \
strndupa.h strnlen.h
+27 -5
View File
@@ -15,6 +15,11 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef __cplusplus
extern "C"
{
#endif
#ifndef CONIO_H_
#define CONIO_H_
@@ -77,17 +82,34 @@
void initscr(int *row, int *col);
/* Print table heading @line to @fp, with optional leading newline */
/* Print table heading @line to @fp, with optional leading newline
* Example:
* _________________ <-- Empty line with UNDERSCORE to frame first heading
* First heading <-- In normal/RESETATTR
* SUBHEADING <-- In REVERSE and with capital letters like 'top'
*/
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), "");
}
static inline void printheader(FILE *fp, const char *line, int nl)
{
fprintf(fp ?: stdout,
"%s\033[7m%s%*s\033[0m\n",
nl ? "\n" : "",
line, SCREEN_WIDTH - (int)strlen(line), "");
printhdr(fp, line, nl, REVERSE);
}
#endif /* CONIO_H_ */
#ifdef __cplusplus
}
#endif
/**
* Local Variables:
* indent-tabs-mode: t
+5 -5
View File
@@ -25,17 +25,17 @@
#include <unistd.h>
/**
* fexist - Check if a file exists and is a directory.
* @file: File to look for, with full path.
* fisdir - Check if a path exists and is a directory.
* @path: Path to file or directory
*
* Returns:
* %TRUE(1) if the file exists and is a directory, otherwise %FALSE(0).
* %TRUE(1) if @path exists and is a directory, otherwise %FALSE(0).
*/
int fisdir(const 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;
+2 -2
View File
@@ -51,8 +51,8 @@ ssize_t fsendfile(FILE *src, FILE *dst, size_t len)
errno = EINVAL;
return -1;
}
buf = (char *)malloc(BUFSIZ);
buf = malloc(BUFSIZ);
if (!buf)
return -1;
+18 -1
View File
@@ -22,6 +22,11 @@
* THE SOFTWARE.
*/
#ifdef __cplusplus
extern "C"
{
#endif
#ifndef LITE_H_
#define LITE_H_
@@ -52,12 +57,13 @@
#define LITE_FOPT_KEEP_MTIME 0x02
typedef struct lfile lfile_t;
typedef struct sdbuf sdbuf_t;
char *chomp (char *str);
char *fparseln (FILE *, size_t *, size_t *, const char[3], int);
int fexist (const char *file);
int fisdir (const char *file);
int fisdir (const char *path);
FILE *tempfile (void);
ssize_t copyfile (const char *src, const char *dst, int len, int opt);
@@ -90,6 +96,13 @@ void *reallocarray(void *optr, size_t nmemb, size_t size);
void progress (int percent, int max_width);
void progress_simple(int percent);
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 yorn (const char *fmt, ...);
char *which (const char *cmd);
int whichp (const char *cmd);
@@ -183,6 +196,10 @@ static inline int fisslashdir(const char *dir)
#endif /* LITE_H_ */
#ifdef __cplusplus
}
#endif
/**
* Local Variables:
* indent-tabs-mode: t
+3 -3
View File
@@ -111,10 +111,10 @@ int pidfile_signal(const char *pidfile, int signal)
return 1;
ret = kill(pid, signal);
if ((ret == -1) || (signal == SIGTERM) || (signal == SIGKILL))
(void)remove(pidfile);
if (!ret && signal == SIGKILL)
ret = remove(pidfile);
return 0;
return ret;
}
/**
+9
View File
@@ -32,6 +32,11 @@
* @(#)queue.h 8.5 (Berkeley) 8/20/94
*/
#ifdef __cplusplus
extern "C"
{
#endif
#ifndef _SYS_QUEUE_H_
#define _SYS_QUEUE_H_
@@ -531,3 +536,7 @@ struct { \
} while (0)
#endif /* !_SYS_QUEUE_H_ */
#ifdef __cplusplus
}
#endif
+10
View File
@@ -23,6 +23,12 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE.
* ==========================================================================
*/
#ifdef __cplusplus
extern "C"
{
#endif
#ifndef LITE_STRDUPA_H
#define LITE_STRDUPA_H
@@ -50,3 +56,7 @@
#endif /* !HAVE_STRDUPA */
#endif /* LITE_STRDUPA_H */
#ifdef __cplusplus
}
#endif
+12
View File
@@ -21,6 +21,11 @@
* THE SOFTWARE.
*/
#ifdef __cplusplus
extern "C"
{
#endif
#ifndef LITE_STRING_H_
#define LITE_STRING_H_
@@ -49,6 +54,9 @@
})
#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
@@ -103,3 +111,7 @@ static inline int string_case_compare(const char *a, const char *b)
}
#endif /* LITE_STRING_H_ */
#ifdef __cplusplus
}
#endif
+89
View File
@@ -0,0 +1,89 @@
/* Simple string matcher function, finds partial matches.
*
* Copyright (c) 2009-2018 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 <string.h>
/**
* strnmatch - Finds matching strings from a finite list
* @str: String to look for
* @list: List of strings to search.
* @num: Number of entries in @list.
*
* This function searches the @list of strings for @str. If a (partial) match
* is found it returns the index in the @list.
*
* Very similar in function to strmatch(), but works for sets of strings that
* are not %NULL 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;
}
/**
* strmatch - Finds matching strings from a list
* @str: String to look for
* @list: %NULL terminated list of strings to search.
*
* This function searches the @list of strings for @str. If a (partial) match
* is found it returns the index in the @list.
*
* Please note, the @list MUST be terminated by a %NULL element. If that is
* not possible for you, 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:
*/
+10
View File
@@ -23,6 +23,12 @@
* USE OR OTHER DEALINGS IN THE SOFTWARE.
* ==========================================================================
*/
#ifdef __cplusplus
extern "C"
{
#endif
#ifndef LITE_STRNDUPA_H_
#define LITE_STRNDUPA_H_
@@ -51,3 +57,7 @@
#endif /* !HAVE_STRNDUPA */
#endif /* GNU_STRING_STRNDUPA_H */
#ifdef __cplusplus
}
#endif
+9
View File
@@ -15,6 +15,11 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef __cplusplus
extern "C"
{
#endif
#ifndef LITE_STRNLEN_H_
#define LITE_STRNLEN_H_
@@ -41,3 +46,7 @@ static inline size_t xstrnlen(const char *str, size_t lim)
#endif
#endif /* LITE_STRNLEN_H_ */
#ifdef __cplusplus
}
#endif
+1 -1
View File
@@ -58,7 +58,7 @@ strtonum(const char *numstr, long long minval, long long maxval,
error = INVALID;
} else {
ll = strtoll(numstr, &ep, 10);
if (numstr == ep || *ep != '\0')
if (errno == EINVAL || numstr == ep || *ep != '\0')
error = INVALID;
else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
error = TOOSMALL;
+291
View File
@@ -0,0 +1,291 @@
/* Poor mans telnet expect in C.
*
* Copyright (c) 2010, 2013, 2019 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 <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
struct sdbuf {
int sd;
char *buf;
} sdbuf;
/* Open telnet connection to @addr:@port and connect. */
sdbuf_t *telnet_open(int addr, short port)
{
struct sockaddr_in *sin;
struct sockaddr s;
sdbuf_t *ctx;
int saved_errno;
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 = errno;
// perror ("Failed creating socket");
free(ctx->buf);
free(ctx);
errno = saved_errno;
return NULL;
}
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))) {
saved_errno = errno;
// perror ("Cannot connect to telnet daemon");
telnet_close(ctx);
errno = saved_errno;
return NULL;
}
return ctx;
}
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;
}
}
/**
* telnet_expect - Poor man's telnet expect
* @ctx: Telnet session context from telnet_open()
* @script: %NULL terminated list of expect and response strings
* @output: Optional output from session
*
* Issues @script sequence on telnet session specified in @ctx, with
* optional @output from session.
*
* The @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 %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;
}
/**
* telnet_session - Very simple expect-like implementation for telnet.
* @addr: Must be in network byte order, use htonl().
* @port: IP port to connect to, use htons().
* @script: Expect like script of paired 'expect', 'response' strings.
* @output: A &FILE pointer to a tmpfile() for output from the last command.
*
* This is a very simple expect-like implementation for querying and
* operating daemons remotely over telnet.
*
* The @script is a query-response type of list of strings leading up to
* a final command, which output is then written to the given @output file.
*
* Returns:
* POSIX OK(0), or non-zero with 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:
*/
+9
View File
@@ -24,6 +24,11 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef __cplusplus
extern "C"
{
#endif
#ifndef _SYS_TREE_H_
#define _SYS_TREE_H_
@@ -746,3 +751,7 @@ name##_RB_MINMAX(struct name *head, int val) \
(x) = (y))
#endif /* _SYS_TREE_H_ */
#ifdef __cplusplus
}
#endif
+92
View File
@@ -0,0 +1,92 @@
/* Safe yes-or-no with prompt
*
* Copyright (c) 2009 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 <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;
}
/**
* yorn - Pose a a Yes or No question and return answer
* @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:
*/
+2
View File
@@ -12,7 +12,9 @@ pidfile
progress
rsync
str
strmatch
tempfile
touch
tree
which
yorn
+4 -2
View File
@@ -11,12 +11,14 @@ TESTS += fsendfile
TESTS += lfile
TESTS += makepath
TESTS += pidfile
TESTS += str
TESTS += touch
TESTS += progress
TESTS += rsync
TESTS += str
TESTS += strmatch
TESTS += touch
TESTS += tempfile
TESTS += which
TESTS += yorn
check_PROGRAMS = $(TESTS)
+9 -1
View File
@@ -2,18 +2,26 @@
int main(void)
{
char buf[10];
int val;
val = atonum("42");
if (val != 42)
return 1;
if (!string_match("eth1", "eth1234"))
return 1;
if (string_compare("eth1", "eth1234"))
return 1;
if (!string_case_compare("somestring", "SoMeSTRING"))
return 1;
strlcpy(buf, "tooloongstring", sizeof(buf));
if (buf[9] == 'r')
return 1;
return 0;
}
+44
View File
@@ -0,0 +1,44 @@
#include "check.h"
#define SYSLOG_NAMES
#include <syslog.h>
#define SEVERITY_LEVEL { \
CHOOSE(SEVERITY_NONE, "none"), \
CHOOSE(SEVERITY_DEBUG, "debug"), \
CHOOSE(SEVERITY_INFO, "info"), \
CHOOSE(SEVERITY_NOTICE, "notice"), \
CHOOSE(SEVERITY_WARNING, "warning"), \
CHOOSE(SEVERITY_ERR, "err"), \
CHOOSE(SEVERITY_CRIT, "crit"), \
CHOOSE(SEVERITY_ALERT, "alert"), \
CHOOSE(SEVERITY_EMERG, "emerg") \
}
#define CHOOSE(a, b) b
const char *levels[] = SEVERITY_LEVEL;
#undef CHOOSE
#define CHOOSE(a, b) a
typedef enum SEVERITY_LEVEL severity_level_t;
int main(void)
{
size_t i;
int num;
struct {
char *str;
int val;
} t[] = {
{ "warn", SEVERITY_WARNING },
{ "alert", SEVERITY_ALERT },
{ NULL, 0 }
};
for (i = 0; t[i].str; i++) {
num = strmatch(t[i].str, levels);
fail_unless(num >= 0);
fail_unless(num == t[i].val);
}
return 0;
}
+32
View File
@@ -0,0 +1,32 @@
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include "check.h"
int main(int argc, char *argv[])
{
int chan[2];
int status;
pipe(chan);
if (fork() > 0) {
dup2(chan[0], STDIN_FILENO);
if (yorn("Do you really wanna do this (y/N)? ")) {
printf("Affirmative!\n");
_exit(0);
}
printf("OK, aborting!\n");
_exit(1);
}
sleep(1);
if (write(chan[1], "Y", 1) != 1)
return 1;
wait(&status);
return WEXITSTATUS(status);
}