Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@
*.so.*
clitest
compile_commands.json
t/cli_driver
*~
t/cli_driver_plain
87 changes: 32 additions & 55 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
# Build dynamic library by default
DYNAMIC_LIB ?= 1
# Build static library by default
STATIC_LIB ?= 1
# Run tests by default
TESTS ?= 1

UNAME = $(shell sh -c 'uname -s 2>/dev/null || echo not')
# Static library is always built; set DYNAMIC_LIB=1 to also build the shared one
DYNAMIC_LIB ?= 0
# Set USE_ASAN=1 to build t/cli_driver with AddressSanitizer + UBSan
USE_ASAN ?=

DESTDIR =
PREFIX = /usr/local

Expand All @@ -21,81 +18,61 @@ ARFLAGS = rcs
DEBUG = -g
OPTIM = -O3
override CFLAGS += $(DEBUG) $(OPTIM) -Wall -std=c99 -pedantic -Wformat-security -Wno-format-zero-length -Werror -Wwrite-strings -Wformat -fdiagnostics-show-option -Wextra -Wsign-compare -Wcast-align -Wno-unused-parameter
override LDFLAGS += -shared
override LIBPATH += -L.

ifeq ($(UNAME),Darwin)
override LDFLAGS += -Wl,-install_name,$(LIB).$(MAJOR).$(MINOR)
else
override LDFLAGS += -Wl,-soname,$(LIB).$(MAJOR).$(MINOR)
override LDFLAGS += -shared -Wl,-soname,$(LIB).$(MAJOR).$(MINOR)
LIBS = -lcrypt
endif

TARGET_LIBS = $(LIB_STATIC)
ifeq (1,$(DYNAMIC_LIB))
TARGET_LIBS += $(LIB)
endif
ifeq (1,$(STATIC_LIB))
TARGET_LIBS += $(LIB_STATIC)
endif

all: $(TARGET_LIBS) $(if $(filter 1,$(TESTS)),clitest)
all: $(TARGET_LIBS) clitest t/cli_driver

$(LIB_STATIC): libcli.o
$(AR) $(ARFLAGS) $@ $^

$(LIB): libcli.o
$(CC) -o $(LIB).$(MAJOR).$(MINOR).$(REVISION) $^ $(LDFLAGS) $(LIBS)
-rm -f $(LIB) $(LIB).$(MAJOR).$(MINOR)
ln -s $(LIB).$(MAJOR).$(MINOR).$(REVISION) $(LIB).$(MAJOR).$(MINOR)
ln -s $(LIB).$(MAJOR).$(MINOR) $(LIB)

$(LIB_STATIC): libcli.o
$(AR) $(ARFLAGS) $@ $^

%.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) -fPIC -o $@ -c $<

libcli.o: libcli.h

clitest: clitest.o $(LIB)
$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -L. -lcli
clitest: clitest.o $(LIB_STATIC)
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)

# Test driver for the Perl suite in t/. libcli.c is compiled in directly so
# that, with USE_ASAN, the sanitizers instrument the library too.
TEST_CFLAGS = -g -O0 -Wall -std=c99 -pedantic -Werror -Wextra -Wno-unused-parameter
ifneq ($(USE_ASAN),)
TEST_CFLAGS += -fno-omit-frame-pointer -fsanitize=address,undefined
endif

clitest.exe: clitest.c libcli.o
$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< libcli.o -lws2_32
t/cli_driver: t/cli_driver.c libcli.c libcli.h
$(CC) $(CPPFLAGS) $(TEST_CFLAGS) -I. -o $@ t/cli_driver.c libcli.c $(LIBS)

test: t/cli_driver
prove -r t/

lint:
clang-tidy -quiet -warnings-as-errors *.c *.h

clean:
rm -f *.o $(LIB)* $(LIB_STATIC) clitest libcli-$(MAJOR).$(MINOR).$(REVISION).tar.gz
rm -f *.o $(LIB)* $(LIB_STATIC) clitest t/cli_driver

install: $(TARGET_LIBS)
install -d $(DESTDIR)$(PREFIX)/include $(DESTDIR)$(PREFIX)/lib
install -m 0644 libcli.h $(DESTDIR)$(PREFIX)/include
ifeq (1,$(STATIC_LIB))
install -m 0644 $(LIB_STATIC) $(DESTDIR)$(PREFIX)/lib
endif
ifeq (1,$(DYNAMIC_LIB))
ifeq (1,$(DYNAMIC_LIB))
install -m 0755 $(LIB).$(MAJOR).$(MINOR).$(REVISION) $(DESTDIR)$(PREFIX)/lib
cd $(DESTDIR)$(PREFIX)/lib && \
ln -fs $(LIB).$(MAJOR).$(MINOR).$(REVISION) $(LIB).$(MAJOR).$(MINOR) && \
ln -fs $(LIB).$(MAJOR).$(MINOR) $(LIB)
endif

rpmprep:
rm -rf libcli-$(MAJOR).$(MINOR).$(REVISION)
mkdir libcli-$(MAJOR).$(MINOR).$(REVISION)
cp -R libcli.c libcli.h libcli.spec clitest.c Makefile COPYING README.md doc libcli-$(MAJOR).$(MINOR).$(REVISION)
tar zcvf libcli-$(MAJOR).$(MINOR).$(REVISION).tar.gz --exclude CVS --exclude *.tar.gz libcli-$(MAJOR).$(MINOR).$(REVISION)
rm -rf libcli-$(MAJOR).$(MINOR).$(REVISION)

rpm: rpmprep
rpmbuild -ta libcli-$(MAJOR).$(MINOR).$(REVISION).tar.gz --define "debug_package %{nil}" --clean

lint:
clang-tidy -quiet -warnings-as-errors *.c *.h
endif

uninstall:
rm -f $(DESTDIR)$(PREFIX)/include/libcli.h
ifeq (1,$(STATIC_LIB))
rm -f $(DESTDIR)$(PREFIX)/lib/$(LIB_STATIC)
endif
ifeq (1,$(DYNAMIC_LIB))
rm -f $(DESTDIR)$(PREFIX)/lib/$(LIB).$(MAJOR).$(MINOR).$(REVISION)
rm -f $(DESTDIR)$(PREFIX)/lib/$(LIB).$(MAJOR).$(MINOR)
rm -f $(DESTDIR)$(PREFIX)/lib/$(LIB)
endif
.PHONY: all test lint clean install
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,20 @@ return `CLI_OK` if the user is to have access and `CLI_ERROR` if they are not.

The library itself will take care of prompting the user for credentials.

In a threaded server, where the callback needs to know which session it is
checking, use `cli_set_auth_callback_ctx(cli, callback)` instead. Its callback
also gets the `cli_def`, so it can reach `cli_get_context()` and print with
`cli_print()`. It returns `CLI_OK` to accept, `CLI_QUIT` to end the session
(e.g. after too many failures), or anything else to deny.
`cli_set_enable_callback_ctx(cli, callback)` does the same for `enable`.
The buffers holding typed passwords are wiped after use.

A command can ask for a password itself, e.g. `username bob secret`, with
`cli_read_password(cli, prompt, buf, size)`. The line is not echoed and never
enters the history; ctrl-c cancels it. It returns `CLI_OK`, `CLI_ERROR`
(cancelled or too long), or `CLI_QUIT` (connection closed or idle timeout),
which the command should return.

Commands are built using a tree-like structure. You define commands with the
`cli_register_command(parent, command, callback, privilege, mode, help)` function.

Expand Down
Loading