From: Thomas Walker Lynch Date: Tue, 2 Apr 2019 18:31:31 +0000 (+0200) Subject: subu-0 lib compiles again X-Git-Url: https://git.reasoningtechnology.com/style/rt_dark_doc.css?a=commitdiff_plain;h=e56bcde3ca12d4c14b9e1b0198e13345d7ec3fee;p=subu subu-0 lib compiles again --- diff --git a/makefile b/makefile index 06d6508..287b43b 100755 --- a/makefile +++ b/makefile @@ -4,23 +4,23 @@ MAKEABLE=\ module/da/test\ module/debug\ module/tranche\ - module/dispatch + module/dispatch\ + module/subu-0 .PHONY: all all: - $(foreach dir, $(MAKEABLE), \ - -make -C $$dir dist-clean dep lib exec share - ) + for dir in $(MAKEABLE); do pushd $$dir; make dist-clean dep lib exec share; popd; done -.PHONY: all +.PHONY: dep +dep: + for dir in $(MAKEABLE); do pushd $$dir; make dep; popd; done + +.PHONY: update update: - $(foreach dir, $(MAKEABLE), \ - -make -C $$dir lib exec share - ) + for dir in $(MAKEABLE); do pushd $$dir; make lib exec share; popd; done .PHONY: info info: - @echo "SRCDIRS:" $(SRCDIRS) @echo "MAKEABLE:" $(MAKEABLE) .PHONY: clean @@ -28,8 +28,7 @@ clean: for dir in $(MAKEABLE); do pushd $$dir; make clean; popd; done .PHONY: dist-clean -dist-clean : - for dir in $(MAKEABLE); do pushd $$dir; make dist-clean; popd; done +dist-clean : clean for i in $(wildcard module/share/lib/*); do rm $$i; done for i in $(wildcard module/share/inc/*); do rm $$i; done for i in $(wildcard module/share/bin/*); do rm $$i; done diff --git a/module/da/include/da.h b/module/da/include/da.h new file mode 100644 index 0000000..8195c4a --- /dev/null +++ b/module/da/include/da.h @@ -0,0 +1,51 @@ +#ifndef DA_LIB_H +#define DA_LIB_H +#include +#include +#include + +typedef struct Da{ + char *base; + char *end; // one byte/one element off the end of the array + size_t size; // size >= (end - base) + 1; + size_t element_size; +} Da; + +#define RETURN(dap, r) \ + { da_free_elements(dap); return r; } + + +void da_alloc(Da *dap, size_t element_size); +void da_free(Da *dap); +void da_rewind(Da *dap); +bool da_emptyq(Da *dap); +size_t da_length(Da *dap); +void da_rebase(Da *dap, char *old_base, void *pta); +char *da_expand(Da *dap); +bool da_boundq(Da *dap); + +char *da_index(Da *dap, size_t i); +char *da_push_alloc(Da *dap); +char *da_push(Da *dap, void *element); +bool da_pop(Da *dap, void *element); + +bool da_endq(Da *dap, void *pt); +void da_map(Da *dap, void f(void *, void *), void *closure); + +void da_free_elements(Da *dap); + +void da_ints_print(Da *dap, char *sep); + +void da_strings_print(Da *dap, char *sep); +bool da_strings_exists(Da *string_arrp, char *test_string); +void da_strings_set_insert(Da *string_arrp, char *proffered_string, void destruct(void *)); +void da_strings_set_union(Da *string_arrp, Da *proffered_string_arrp, void destruct(void *)); + + +char *da_string_input(Da *dap, FILE *file); +void da_string_push(Da *dap0, char *string); + +void da_cat(Da *dap_base, Da *dap_cat); + +#endif + diff --git a/module/da/lib/libda.a b/module/da/lib/libda.a new file mode 100644 index 0000000..28db3cb Binary files /dev/null and b/module/da/lib/libda.a differ diff --git a/module/da/makefile b/module/da/makefile index 80b385d..2a50e4e 100644 --- a/module/da/makefile +++ b/module/da/makefile @@ -16,8 +16,8 @@ dep: .PHONY: lib lib: - $(MAKE) $@ cp $(SRCDIR)/da.lib.h $(INCDIR)/da.h + $(MAKE) $@ .PHONY: exec exec: diff --git a/module/da/makefile-flags b/module/da/makefile-flags index ae5fb48..25ae25d 100644 --- a/module/da/makefile-flags +++ b/module/da/makefile-flags @@ -6,7 +6,7 @@ DOCDIR=doc EXECDIR=exec INCDIR=include LIBDIR=lib -SHAREDIR=../share +SHAREDIR=$(realpath $(PROJECT_SUBU)/module/share) SRCDIR=src TESTDIR=test TMPDIR=tmp @@ -23,9 +23,8 @@ ECHO= echo # compiler and flags C=gcc -CFLAGS=-std=gnu11 -fPIC -I. -ggdb -Werror -DDEBUG -DDEBUGDB -#CFLAGS=-std=gnu11 -fPIC -I. -Werror -LINKFLAGS=-Llib -lda +CFLAGS=-std=gnu11 -fPIC -I$(SRCDIR) -I$(INCDIR) -I$(SHAREDIR)/include -ggdb -Werror -DDEBUG -DDEBUGDB +LINKFLAGS=-L$(LIBDIR) -l$(MODULE) diff --git a/module/da/src/da.lib.c b/module/da/src/da.lib.c index 18abb99..543e95d 100644 --- a/module/da/src/da.lib.c +++ b/module/da/src/da.lib.c @@ -69,10 +69,18 @@ char *da_index(Da *dap, size_t i){ return pt; } -void da_push(Da *dap, void *element){ - if( dap->end >= dap->base + dap->size ) da_expand(dap); - memcpy(dap->end, element, dap->element_size); +// allocate space for a new element at the end of the array +char *da_push_alloc(Da *dap){ + size_t element_off = dap->end - dap->base; dap->end += dap->element_size; + if( dap->end > dap->base + dap->size ) da_expand(dap); + return dap->base + element_off; +} + +char *da_push(Da *dap, void *element){ + char *element_pt = da_push_alloc(dap); + memcpy(element_pt, element, dap->element_size); + return element_pt; } bool da_pop(Da *dap, void *element){ diff --git a/module/da/src/da.lib.h b/module/da/src/da.lib.h index 518e72c..8195c4a 100644 --- a/module/da/src/da.lib.h +++ b/module/da/src/da.lib.h @@ -12,7 +12,7 @@ typedef struct Da{ } Da; #define RETURN(dap, r) \ - { da_map(dap, da_free, NULL); return r; } + { da_free_elements(dap); return r; } void da_alloc(Da *dap, size_t element_size); @@ -25,7 +25,8 @@ char *da_expand(Da *dap); bool da_boundq(Da *dap); char *da_index(Da *dap, size_t i); -void da_push(Da *dap, void *element); +char *da_push_alloc(Da *dap); +char *da_push(Da *dap, void *element); bool da_pop(Da *dap, void *element); bool da_endq(Da *dap, void *pt); diff --git a/module/da/test/exec/test_da b/module/da/test/exec/test_da new file mode 100755 index 0000000..1b5765d Binary files /dev/null and b/module/da/test/exec/test_da differ diff --git a/module/da/test/lib/libtest.a b/module/da/test/lib/libtest.a new file mode 100644 index 0000000..49e4695 Binary files /dev/null and b/module/da/test/lib/libtest.a differ diff --git a/module/da/test/makefile-flags b/module/da/test/makefile-flags index 37ea9c1..686a0f8 100644 --- a/module/da/test/makefile-flags +++ b/module/da/test/makefile-flags @@ -23,7 +23,7 @@ ECHO= echo # compiler and flags C=gcc -CFLAGS=-std=gnu11 -fPIC -I../include -ggdb -Werror -DDEBUG -DDEBUGDB -#CFLAGS=-std=gnu11 -fPIC -I../include -Werror +CFLAGS=-std=gnu11 -fPIC -Iinclude -I../include -ggdb -Werror -DDEBUG -DDEBUGDB +#CFLAGS=-std=gnu11 -fPIC -Iinclude -I../include -Werror LINKFLAGS= -Llib -L../lib -ltest -lda diff --git a/module/debug/include/debug.h b/module/debug/include/debug.h new file mode 100644 index 0000000..f1be3d8 --- /dev/null +++ b/module/debug/include/debug.h @@ -0,0 +1,6 @@ +#ifndef DB_LIB_H +#define DB_LIB_H + +int debug_printf(const char *format, ...); + +#endif diff --git a/module/debug/lib/libda.a b/module/debug/lib/libda.a deleted file mode 100644 index c6e819f..0000000 Binary files a/module/debug/lib/libda.a and /dev/null differ diff --git a/module/debug/lib/libdebug.a b/module/debug/lib/libdebug.a new file mode 100644 index 0000000..df2a6dd Binary files /dev/null and b/module/debug/lib/libdebug.a differ diff --git a/module/debug/makefile b/module/debug/makefile index 181818b..a19b90e 100644 --- a/module/debug/makefile +++ b/module/debug/makefile @@ -16,8 +16,8 @@ dep: .PHONY: lib lib: + cp $(SRCDIR)/debug.lib.h $(INCDIR)/debug.h $(MAKE) $@ - cp $(SRCDIR)/db.lib.h $(INCDIR)/db.h %:: $(MAKE) $@ diff --git a/module/debug/makefile-flags b/module/debug/makefile-flags index 65ef1be..4dfd9bf 100644 --- a/module/debug/makefile-flags +++ b/module/debug/makefile-flags @@ -1,12 +1,12 @@ -MODULE=db +MODULE=debug DEPRDIR=deprecated DOCDIR=doc EXECDIR=exec INCDIR=include LIBDIR=lib -SHAREDIR=../share +SHAREDIR=$(realpath $(PROJECT_SUBU)/module/share) SRCDIR=src TESTDIR=test TMPDIR=tmp @@ -23,9 +23,8 @@ ECHO= echo # compiler and flags C=gcc -CFLAGS=-std=gnu11 -fPIC -I. -ggdb -Werror -DDEBUG -DDEBUGDB -#CFLAGS=-std=gnu11 -fPIC -I. -Werror -LINKFLAGS=-Llib -ldb +CFLAGS=-std=gnu11 -fPIC -I$(SRCDIR) -I$(INCDIR) -I$(SHAREDIR)/include -ggdb -Werror -DDEBUG -DDEBUGDB +LINKFLAGS=-L$(LIBDIR) -l$(MODULE) diff --git a/module/dispatch/include/dispatch.h b/module/dispatch/include/dispatch.h new file mode 100644 index 0000000..8b99d43 --- /dev/null +++ b/module/dispatch/include/dispatch.h @@ -0,0 +1,32 @@ + /* + Runs a command or function as its own process. + + The return status integer from command or function must be greater than ERR_DISPATCH. + In the case of dispatch_exec, we only have a promise from the user to not dispatch + non compliant commands. + + */ + #ifndef DISPATCH_LIB_H + #define DISPATCH_LIB_H + #include + #include + + #define ERR_DISPATCH -1024 + #define ERR_DISPATCH_NEGATIVE_RETURN_STATUS -1024 + #define ERR_DISPATCH_F_FORK -1025 + #define ERR_DISPATCH_F_SETEUID -1026 + #define ERR_DISPATCH_F_SETEGID -1027 + #define ERR_DISPATCH_NULL_EXECUTABLE -1028 + #define ERR_DISPATCH_EXEC -1029 + + // currently both dispatcher and dispatchee strings are statically allocated + struct dispatch_ctx{ + char *dispatcher; // name of the dispatch function ("dispatch_f", "dispatch_f_euid_egid", etc.) + char *dispatchee; // name of the function being dispatched + int err; // error code as listed below, or status returned from dispatchee + }; +void dispatch_f_mess(char *fname, int err, char *dispatchee); +int dispatch_f(char *fname, int (*f)(void *arg), void *f_arg); +int dispatch_f_euid_egid(char *fname, int (*f)(void *arg), void *f_arg, uid_t euid, gid_t egid); +int dispatch_exec(char **argv, char **envp); +#endif diff --git a/module/dispatch/lib/libdispatch.a b/module/dispatch/lib/libdispatch.a new file mode 100644 index 0000000..70d2fff Binary files /dev/null and b/module/dispatch/lib/libdispatch.a differ diff --git a/module/dispatch/makefile b/module/dispatch/makefile index ab3ffe5..add0ff2 100644 --- a/module/dispatch/makefile +++ b/module/dispatch/makefile @@ -34,8 +34,8 @@ dep: .PHONY: lib lib: - $(MAKE) $@ cp $(SRCDIR)/dispatch.lib.h $(INCDIR)/dispatch.h + $(MAKE) $@ %:: $(MAKE) $@ diff --git a/module/dispatch/makefile-flags b/module/dispatch/makefile-flags index 854b84f..a50b71c 100644 --- a/module/dispatch/makefile-flags +++ b/module/dispatch/makefile-flags @@ -24,10 +24,8 @@ ECHO= echo # compiler and flags C=gcc -CFLAGS=-std=gnu11 -fPIC -I. -I../share/include -ggdb -Werror -DDEBUG -DDEBUGDB -#CFLAGS=-std=gnu11 -fPIC -I. -I../share/include -Werror - -LINKFLAGS=-L1_lib -lda +CFLAGS=-std=gnu11 -fPIC -I$(SRCDIR) -I$(INCDIR) -I$(SHAREDIR)/include -ggdb -Werror -DDEBUG -DDEBUGDB +LINKFLAGS=-L$(LIBDIR) -L(SHAREDIR)/lib -ldebug diff --git a/module/dispatch/trc/dispatch.trc.c b/module/dispatch/trc/dispatch.trc.c index c24b0ab..f08602c 100644 --- a/module/dispatch/trc/dispatch.trc.c +++ b/module/dispatch/trc/dispatch.trc.c @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include "dispatch.lib.h" #tranche dispatch.lib.h diff --git a/module/share/include/da.h b/module/share/include/da.h index 518e72c..8195c4a 100644 --- a/module/share/include/da.h +++ b/module/share/include/da.h @@ -12,7 +12,7 @@ typedef struct Da{ } Da; #define RETURN(dap, r) \ - { da_map(dap, da_free, NULL); return r; } + { da_free_elements(dap); return r; } void da_alloc(Da *dap, size_t element_size); @@ -25,7 +25,8 @@ char *da_expand(Da *dap); bool da_boundq(Da *dap); char *da_index(Da *dap, size_t i); -void da_push(Da *dap, void *element); +char *da_push_alloc(Da *dap); +char *da_push(Da *dap, void *element); bool da_pop(Da *dap, void *element); bool da_endq(Da *dap, void *pt); diff --git a/module/share/include/db.h b/module/share/include/db.h deleted file mode 100644 index f1be3d8..0000000 --- a/module/share/include/db.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef DB_LIB_H -#define DB_LIB_H - -int debug_printf(const char *format, ...); - -#endif diff --git a/module/share/include/debug.h b/module/share/include/debug.h new file mode 100644 index 0000000..f1be3d8 --- /dev/null +++ b/module/share/include/debug.h @@ -0,0 +1,6 @@ +#ifndef DB_LIB_H +#define DB_LIB_H + +int debug_printf(const char *format, ...); + +#endif diff --git a/module/subu-0/include/subu.h b/module/subu-0/include/subu.h new file mode 100644 index 0000000..683ddb3 --- /dev/null +++ b/module/subu-0/include/subu.h @@ -0,0 +1,62 @@ + typedef unsigned int uint; + /* + Fedora 29's sss_cache is checking the inherited uid instead of the effective + uid, so setuid root scripts will fail when calling sss_cache. + + Fedora 29's 'useradd' calls sss_cache, and useradd is called by our setuid root + program subu-mk-0. + */ + #define BUG_SSS_CACHE_RUID 1 + // extern char *DB_File; + extern char DB_File[]; + extern uint Subuhome_Perms; + extern uint First_Max_Subunumber; + extern char Subuland_Extension[]; + /* + The db file is maintained in SQLite + + Because linux user names are limited length, subu user names are of a compact + form: _s. A separate table translates the numbers into the subu names. + + Each of these returns SQLITE_OK upon success + */ + #include + int db_begin(sqlite3 *db); + int db_commit(sqlite3 *db); + int db_rollback(sqlite3 *db); + int subudb_schema(sqlite3 *db); + int subudb_number_get(sqlite3 *db, int *n); + int subudb_number_set(sqlite3 *db, int n); + int subudb_Masteru_Subu_put(sqlite3 *db, char *masteru_name, char *subuname, char *subu_username); + int subudb_Masteru_Subu_get_subu_username(sqlite3 *db, char *masteru_name, char *subuname, char **subu_username); + typedef struct{ + char *subuname; // the name that masteru chose for his or her subu + char *subu_username; // the adduser name we gave it, typically of the s + } subudb_subu_element; + int subudb_Masteru_Subu_get_subus(sqlite3 *db, char *masteru_name, Da *subus); + int subudb_Masteru_Subu_rm(sqlite3 *db, char *masteru_name, char *subuname, char *subu_username); + #include + #include + #include + char *useradd_mess(int err); + char *userdel_mess(int err); + #define SUBU_ERR_ARG_CNT 1 + #define SUBU_ERR_SETUID_ROOT 2 + #define SUBU_ERR_MALLOC 3 + #define SUBU_ERR_MKDIR_SUBUHOME 4 + #define SUBU_ERR_RMDIR_SUBUHOME 5 + #define SUBU_ERR_SUBUNAME_MALFORMED 6 + #define SUBU_ERR_HOMELESS 7 + #define SUBU_ERR_DB_FILE 8 + #define SUBU_ERR_SUBUHOME_EXISTS 9 + #define SUBU_ERR_BUG_SSS 10 + #define SUBU_ERR_FAILED_USERADD 11 + #define SUBU_ERR_FAILED_USERDEL 12 + #define SUBU_ERR_SUBU_NOT_FOUND 13 + #define SUBU_ERR_N 14 + #define SUBU_ERR_BIND 15 + void subu_err(char *fname, int err, char *mess); + int subu_mk_0(char **mess, sqlite3 *db, char *subuname); + int subu_rm_0(char **mess, sqlite3 *db, char *subuname); + int subu_bind(char **mess, char *masteru_name, char *subu_username, char *subuhome); + int subu_bind_all(char **mess, sqlite3 *db); diff --git a/module/subu-0/lib/libsubu-0.a b/module/subu-0/lib/libsubu-0.a new file mode 100644 index 0000000..e678762 Binary files /dev/null and b/module/subu-0/lib/libsubu-0.a differ diff --git a/module/subu-0/makefile b/module/subu-0/makefile index ab3ffe5..dacec61 100644 --- a/module/subu-0/makefile +++ b/module/subu-0/makefile @@ -2,17 +2,16 @@ SHELL=/bin/bash MAKE=/usr/bin/make --no-print-directory -f $(PROJECT_SUBU)/tool/lib/makefile-cc -#MAKE=/usr/bin/make -f $(PROJECT_SUBU)/tool/lib/makefile-cc -include makefile-flags - .PHONY: all all: version .PHONY: info info: @echo "TRCDIR: " $(TRCDIR) + @echo "SHAREDIR: " $(SHAREDIR) $(MAKE) $@ .PHONY: setup @@ -23,21 +22,25 @@ setup: .PHONY: dep dep: if [ -e $(DEPFILE) ]; then rm $(DEPFILE); fi - @trcsources=$(wildcard $(TRCDIR)/*.trc.c)$(wildcard $(TRCDIR)/*.trc.cc);\ + trcsources=($(wildcard $(TRCDIR)/*.trc.c)$(wildcard $(TRCDIR)/*.trc.cc));\ if [ ! -z "$$trcsources" ]; then\ - trctargets=$$(tranche-target $$trcsources -sep " " -tdir $(SRCDIR) );\ - $(ECHO) $$trcsources;\ - tranche-make $$trcsources -tdir $(SRCDIR) -mfile $(DEPFILE);\ + trctargets=$$(tranche-target $${trcsources[@]} -sep " " -tdir $(SRCDIR) );\ + $(ECHO) "trcsources: " $${trcsources[@]};\ + $(ECHO) "trctargets: " $$trctargets;\ + tranche-make $${trcsources[@]} -tdir $(SRCDIR) -mfile $(DEPFILE);\ $(MAKE) $$trctargets;\ fi $(MAKE) $@ .PHONY: lib lib: + cp $(SRCDIR)/common.lib.h $(INCDIR)/subu.h + cat $(SRCDIR)/subudb.lib.h >> $(INCDIR)/subu.h + cat $(SRCDIR)/subu.lib.h >> $(INCDIR)/subu.h $(MAKE) $@ - cp $(SRCDIR)/dispatch.lib.h $(INCDIR)/dispatch.h %:: + @echo default target $(MAKE) $@ diff --git a/module/subu-0/makefile-flags b/module/subu-0/makefile-flags index 854b84f..f373601 100644 --- a/module/subu-0/makefile-flags +++ b/module/subu-0/makefile-flags @@ -1,12 +1,12 @@ -MODULE=dispatch +MODULE=subu-0 DEPRDIR=deprecated DOCDIR=doc EXECDIR=exec INCDIR=include LIBDIR=lib -SHAREDIR=../share +SHAREDIR=$(realpath $(PROJECT_SUBU)/module/share) SRCDIR=tmp TESTDIR=test TMPDIR=tmp @@ -24,10 +24,8 @@ ECHO= echo # compiler and flags C=gcc -CFLAGS=-std=gnu11 -fPIC -I. -I../share/include -ggdb -Werror -DDEBUG -DDEBUGDB -#CFLAGS=-std=gnu11 -fPIC -I. -I../share/include -Werror - -LINKFLAGS=-L1_lib -lda +CFLAGS=-std=gnu11 -fPIC -I$(SRCDIR) -I$(INCDIR) -I$(SHAREDIR)/include -ggdb -Werror -DDEBUG -DDEBUGDB +LINKFLAGS=-L$(LIBDIR) -L$(SHAREDIR)/lib/ -l$(MODULE) -lda -ltranche -ldispatch diff --git a/module/subu-0/trc/common.lib.c b/module/subu-0/trc/common.lib.c deleted file mode 100644 index fec4853..0000000 --- a/module/subu-0/trc/common.lib.c +++ /dev/null @@ -1,29 +0,0 @@ -#tranche common.lib.c -#include "common.lib.h" - -#tranche common.lib.h - typedef unsigned int uint; - /* - Fedora 29's sss_cache is checking the inherited uid instead of the effective - uid, so setuid root scripts will fail when calling sss_cache. - - Fedora 29's 'useradd' calls sss_cache, and useradd is called by our setuid root - program subu-mk-0. - */ - #define BUG_SSS_CACHE_RUID 1 -#tranche-end - -#tranche common.lib.h - // extern char *DB_File; - extern char DB_File[]; - extern uint Subuhome_Perms; - extern uint First_Max_Subunumber; - extern char Subuland_Extension[]; -#tranche-end -// char *DB_File = "/etc/subudb"; -char DB_File[] = "subudb"; -uint Subuhome_Perms = 0700; -uint First_Max_Subunumber = 114; -char Subuland_Extension[] = "/subuland/"; - -#tranche-end diff --git a/module/subu-0/trc/common.trc.c b/module/subu-0/trc/common.trc.c new file mode 100644 index 0000000..fec4853 --- /dev/null +++ b/module/subu-0/trc/common.trc.c @@ -0,0 +1,29 @@ +#tranche common.lib.c +#include "common.lib.h" + +#tranche common.lib.h + typedef unsigned int uint; + /* + Fedora 29's sss_cache is checking the inherited uid instead of the effective + uid, so setuid root scripts will fail when calling sss_cache. + + Fedora 29's 'useradd' calls sss_cache, and useradd is called by our setuid root + program subu-mk-0. + */ + #define BUG_SSS_CACHE_RUID 1 +#tranche-end + +#tranche common.lib.h + // extern char *DB_File; + extern char DB_File[]; + extern uint Subuhome_Perms; + extern uint First_Max_Subunumber; + extern char Subuland_Extension[]; +#tranche-end +// char *DB_File = "/etc/subudb"; +char DB_File[] = "subudb"; +uint Subuhome_Perms = 0700; +uint First_Max_Subunumber = 114; +char Subuland_Extension[] = "/subuland/"; + +#tranche-end diff --git a/module/subu-0/trc/db.lib.c b/module/subu-0/trc/db.lib.c deleted file mode 100644 index 17a5419..0000000 --- a/module/subu-0/trc/db.lib.c +++ /dev/null @@ -1,192 +0,0 @@ -/* -The db file is maintained in SQLite - -Because user names of are of limited length, subu user names are always named _s. -A separate table translates the numbers into the subu names. - -The first argument is the biggest subu number in the system, or one minus an -starting point for subu numbering. - -currently a unit converted to base 10 will always fit in a 21 bit buffer. - -Each of these returns SQLITE_OK upon success -*/ -#include "subudb.lib.h" - -#if INTERFACE -#include -#endif - -#include -#include -#include -#include - -//-------------------------------------------------------------------------------- -// sqlite transactions don't nest. There is a way to use save points, but still -// we can't just nest transactions. Instead use these wrappers around the whole -// of something that needs to be in a transaction. -int db_begin(sqlite3 *db){ - return sqlite3_exec(db, "BEGIN TRANSACTION;", NULL, NULL, NULL); -} -int db_commit(sqlite3 *db){ - return sqlite3_exec(db, "COMMIT;", NULL, NULL, NULL); -} -int db_rollback(sqlite3 *db){ - return sqlite3_exec(db, "ROLLBACK;", NULL, NULL, NULL); -} - -//-------------------------------------------------------------------------------- -int subudb_schema(sqlite3 *db){ - int rc; - - { // build tables - char sql[] = - "CREATE TABLE Masteru_Subu(masteru_name TEXT, subuname TEXT, subu_username TEXT);" - "CREATE TABLE Attribute_Int(attribute TEXT, value INT);" - ; - rc = sqlite3_exec(db, sql, NULL, NULL, NULL); - if(rc != SQLITE_OK) return rc; - } - - { // data initialization - char *sql = "INSERT INTO Attribute_Int (attribute, value) VALUES ('Max_Subunumber', ?1);"; - sqlite3_stmt *stmt; - sqlite3_prepare_v2(db, sql, -1, &stmt, NULL); - sqlite3_bind_int(stmt, 1, First_Max_Subunumber); - rc = sqlite3_step(stmt); - sqlite3_finalize(stmt); - if( rc != SQLITE_DONE ) return rc; - } - - return SQLITE_OK; -} - -//-------------------------------------------------------------------------------- -int subudb_number_get(sqlite3 *db, int *n){ - char *sql = "SELECT value FROM Attribute_Int WHERE attribute = 'Max_Subunumber';"; - sqlite3_stmt *stmt; - sqlite3_prepare_v2(db, sql, -1, &stmt, NULL); - int rc = sqlite3_step(stmt); - if( rc == SQLITE_ROW ){ - *n = sqlite3_column_int(stmt,0); - rc = sqlite3_step(stmt); - sqlite3_finalize(stmt); - if( rc != SQLITE_DONE ) return rc; - return SQLITE_OK; - } - // should have a message return, suppose - sqlite3_finalize(stmt); - return SQLITE_NOTFOUND; -} - -int subudb_number_set(sqlite3 *db, int n){ - int rc; - char *sql = "UPDATE Attribute_Int SET value = ?1 WHERE attribute = 'Max_Subunumber';"; - sqlite3_stmt *stmt; - sqlite3_prepare_v2(db, sql, -1, &stmt, NULL); - sqlite3_bind_int(stmt, 1, n); - rc = sqlite3_step(stmt); - sqlite3_finalize(stmt); - if( rc == SQLITE_DONE ) return SQLITE_OK; - return rc; -} - -//-------------------------------------------------------------------------------- -// put relation into Masteru_Subu table -int subudb_Masteru_Subu_put(sqlite3 *db, char *masteru_name, char *subuname, char *subu_username){ - char *sql = "INSERT INTO Masteru_Subu VALUES (?1, ?2, ?3);"; - sqlite3_stmt *stmt; - sqlite3_prepare_v2(db, sql, -1, &stmt, NULL); - sqlite3_bind_text(stmt, 1, masteru_name, -1, SQLITE_STATIC); - sqlite3_bind_text(stmt, 2, subuname, -1, SQLITE_STATIC); - sqlite3_bind_text(stmt, 3, subu_username, -1, SQLITE_STATIC); - int rc = sqlite3_step(stmt); - sqlite3_finalize(stmt); - if( rc == SQLITE_DONE ) return SQLITE_OK; - return rc; -} - -//-------------------------------------------------------------------------------- -int subudb_Masteru_Subu_get_subu_username(sqlite3 *db, char *masteru_name, char *subuname, char **subu_username){ - char *sql = "SELECT subu_username FROM Masteru_Subu WHERE masteru_name = ?1 AND subuname = ?2;"; - size_t sql_len = strlen(sql); - sqlite3_stmt *stmt; - int rc; - rc = sqlite3_prepare_v2(db, sql, sql_len, &stmt, NULL); - if( rc != SQLITE_OK ) return rc; - sqlite3_bind_text(stmt, 1, masteru_name, strlen(masteru_name), SQLITE_STATIC); - sqlite3_bind_text(stmt, 2, subuname, strlen(subuname), SQLITE_STATIC); - rc = sqlite3_step(stmt); - if( rc == SQLITE_ROW ){ - const char *username = sqlite3_column_text(stmt, 0); - *subu_username = strdup(username); - }else{ - sqlite3_finalize(stmt); - return rc; // woops this needs to return an error!, be sure it is not SQLITE_DONE - } - rc = sqlite3_step(stmt); - if( rc == SQLITE_DONE ) return SQLITE_OK; - return rc; -} - -//-------------------------------------------------------------------------------- - -// we return and array of subudb_subu_info -#if INTERFACE -struct subudb_subu_element{ - char *subuname; - char *subu_username; -}; -#endif - -int subudb_Masteru_Subu_get_subus -( - sqlite3 *db, - char *masteru_name, - da *subus -){ - char *sql = "SELECT subuname, subu_username" - " FROM Masteru_Subu" - " WHERE masteru_name = ?1;"; - size_t sql_len = strlen(sql); - sqlite3_stmt *stmt; - int rc; - rc = sqlite3_prepare_v2(db, sql, sql_len, &stmt, NULL); - if( rc != SQLITE_OK ) return rc; - sqlite3_bind_text(stmt, 1, masteru_name, strlen(masteru_name), SQLITE_STATIC); - - da_alloc(subus, sizeof(subudb_subu_element)); - subudb_subu_element *pt = (subudb_subu_element *)subus->base; - rc = sqlite3_step(stmt); - while( rc == SQLITE_ROW ){ - if( da_boundq(subus, pt) ){ - char *old_base = da_expand(subus); - da_rebase(subus, old_base, pt); - } - pt->subuname = strdup(sqlite3_column_text(stmt, 0)); - pt->subu_username = strdup(sqlite3_column_text(stmt, 1)); - rc = sqlite3_step(stmt); - pt++; - } - sqlite3_finalize(stmt); - if( rc != SQLITE_DONE ) return rc; - return SQLITE_OK; -} - -//-------------------------------------------------------------------------------- -int subudb_Masteru_Subu_rm(sqlite3 *db, char *masteru_name, char *subuname, char *subu_username){ - char *sql = "DELETE FROM Masteru_Subu WHERE masteru_name = ?1 AND subuname = ?2 AND subu_username = ?3;"; - size_t sql_len = strlen(sql); - sqlite3_stmt *stmt; - int rc; - rc = sqlite3_prepare_v2(db, sql, sql_len, &stmt, NULL); - if( rc != SQLITE_OK ) return rc; - sqlite3_bind_text(stmt, 1, masteru_name, -1, SQLITE_STATIC); - sqlite3_bind_text(stmt, 2, subuname, -1, SQLITE_STATIC); - sqlite3_bind_text(stmt, 3, subu_username, -1, SQLITE_STATIC); - rc = sqlite3_step(stmt); - sqlite3_finalize(stmt); - if( rc == SQLITE_DONE ) return SQLITE_OK; - return rc; -} diff --git a/module/subu-0/trc/subu-bind-all.cli.c b/module/subu-0/trc/subu-bind-all.cli.c deleted file mode 100644 index e942909..0000000 --- a/module/subu-0/trc/subu-bind-all.cli.c +++ /dev/null @@ -1,31 +0,0 @@ -/* -mount all the subu user directories into master's subuland -uses unmount to undo this - -*/ -#include "subu-bind-all.cli.h" -#include -#include - -int main(int argc, char **argv){ - if( argc != 1){ - fprintf(stderr, "%s does not take arguments\n",argv[0]); - return SUBU_ERR_ARG_CNT; - } - - int rc; - sqlite3 *db; - rc = sqlite3_open_v2(DB_File, &db, SQLITE_OPEN_READWRITE, NULL); - if( rc != SQLITE_OK ){ - fprintf(stderr, "could not open db file \"%s\"\n", DB_File); - return SUBU_ERR_DB_FILE; - } - - char *mess; - rc = subu_bind_all(&mess, db); - if(rc != 0){ - fprintf(stderr, "subu-bind: %s\n", mess); - return rc; - } - return 0; -} diff --git a/module/subu-0/trc/subu-bind-all.trc.c b/module/subu-0/trc/subu-bind-all.trc.c new file mode 100644 index 0000000..7674927 --- /dev/null +++ b/module/subu-0/trc/subu-bind-all.trc.c @@ -0,0 +1,32 @@ +#tranche subu-bind-all.cli.c +/* +mount all the subu user directories into master's subuland +uses unmount to undo this + +*/ +#include +#include + +int main(int argc, char **argv){ + if( argc != 1){ + fprintf(stderr, "%s does not take arguments\n",argv[0]); + return SUBU_ERR_ARG_CNT; + } + + int rc; + sqlite3 *db; + rc = sqlite3_open_v2(DB_File, &db, SQLITE_OPEN_READWRITE, NULL); + if( rc != SQLITE_OK ){ + fprintf(stderr, "could not open db file \"%s\"\n", DB_File); + return SUBU_ERR_DB_FILE; + } + + char *mess; + rc = subu_bind_all(&mess, db); + if(rc != 0){ + fprintf(stderr, "subu-bind: %s\n", mess); + return rc; + } + return 0; +} +#tranche-end diff --git a/module/subu-0/trc/subu-bind.cli.c b/module/subu-0/trc/subu-bind.cli.c deleted file mode 100644 index f315823..0000000 --- a/module/subu-0/trc/subu-bind.cli.c +++ /dev/null @@ -1,25 +0,0 @@ -/* -mount a subu user directory into master's subuland -uses unmount to undo this - -*/ -#include "subu-bind.cli.h" -#include -#include - -int main(int argc, char **argv){ - - if( argc != 4){ - fprintf(stderr, "usage: %s masteru subu_username subuhome\n",argv[0]); - return SUBU_ERR_ARG_CNT; - } - - int rc; - char *mess; - rc = subu_bind(&mess, argv[1], argv[2], argv[3]); - if(rc != 0){ - fprintf(stderr, "subu-bind: %s\n", mess); - return rc; - } - return 0; -} diff --git a/module/subu-0/trc/subu-bind.trc.c b/module/subu-0/trc/subu-bind.trc.c new file mode 100644 index 0000000..0510d55 --- /dev/null +++ b/module/subu-0/trc/subu-bind.trc.c @@ -0,0 +1,26 @@ +#tranche subu-bind.cli.c +/* +mount a subu user directory into master's subuland +uses unmount to undo this + +*/ +#include +#include + +int main(int argc, char **argv){ + + if( argc != 4){ + fprintf(stderr, "usage: %s masteru subu_username subuhome\n",argv[0]); + return SUBU_ERR_ARG_CNT; + } + + int rc; + char *mess; + rc = subu_bind(&mess, argv[1], argv[2], argv[3]); + if(rc != 0){ + fprintf(stderr, "subu-bind: %s\n", mess); + return rc; + } + return 0; +} +#tranche-end diff --git a/module/subu-0/trc/subu-mk-0.cli.c b/module/subu-0/trc/subu-mk-0.cli.c deleted file mode 100644 index af0888b..0000000 --- a/module/subu-0/trc/subu-mk-0.cli.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - subu-mk-0 command - -*/ -#include "subu-mk-0.cli.h" -#include -#include - -int main(int argc, char **argv){ - char *command = argv[0]; - if( argc != 2 ){ - fprintf(stderr, "usage: %s subu", command); - return SUBU_ERR_ARG_CNT; - } - char *subuname = argv[1]; - - int rc; - sqlite3 *db; - rc = sqlite3_open_v2(DB_File, &db, SQLITE_OPEN_READWRITE, NULL); - if( rc != SQLITE_OK ){ - fprintf(stderr, "error when opening db, %s\n", DB_File); - fprintf(stderr, "sqlite3 says: %s\n", sqlite3_errmsg(db)); - sqlite3_close(db); - return SUBU_ERR_DB_FILE; - } - - char *mess; - rc = subu_mk_0(&mess, db, subuname); - if( rc ){ - subu_err("subu_mk_0", rc, mess); - free(mess); - sqlite3_close(db); - return rc; - } - - rc = sqlite3_close(db); - if( rc != SQLITE_OK ){ - fprintf(stderr, "when closing db, %s\n", sqlite3_errmsg(db)); - return SUBU_ERR_DB_FILE; - } - return 0; - -} diff --git a/module/subu-0/trc/subu-mk-0.trc.c b/module/subu-0/trc/subu-mk-0.trc.c new file mode 100644 index 0000000..f0a7b5a --- /dev/null +++ b/module/subu-0/trc/subu-mk-0.trc.c @@ -0,0 +1,44 @@ +#tranche subu-mk-0.cli.c +/* + subu-mk-0 command + +*/ +#include +#include + +int main(int argc, char **argv){ + char *command = argv[0]; + if( argc != 2 ){ + fprintf(stderr, "usage: %s subu", command); + return SUBU_ERR_ARG_CNT; + } + char *subuname = argv[1]; + + int rc; + sqlite3 *db; + rc = sqlite3_open_v2(DB_File, &db, SQLITE_OPEN_READWRITE, NULL); + if( rc != SQLITE_OK ){ + fprintf(stderr, "error when opening db, %s\n", DB_File); + fprintf(stderr, "sqlite3 says: %s\n", sqlite3_errmsg(db)); + sqlite3_close(db); + return SUBU_ERR_DB_FILE; + } + + char *mess; + rc = subu_mk_0(&mess, db, subuname); + if( rc ){ + subu_err("subu_mk_0", rc, mess); + free(mess); + sqlite3_close(db); + return rc; + } + + rc = sqlite3_close(db); + if( rc != SQLITE_OK ){ + fprintf(stderr, "when closing db, %s\n", sqlite3_errmsg(db)); + return SUBU_ERR_DB_FILE; + } + return 0; + +} +#tranche-end diff --git a/module/subu-0/trc/subu-rm-0.cli.c b/module/subu-0/trc/subu-rm-0.cli.c deleted file mode 100644 index a7e5926..0000000 --- a/module/subu-0/trc/subu-rm-0.cli.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - subu-mk-0 command - -*/ -#include "subu-rm-0.cli.h" -#include -#include - -int main(int argc, char **argv){ - char *command = argv[0]; - if( argc != 2 ){ - fprintf(stderr, "usage: %s subu", command); - return SUBU_ERR_ARG_CNT; - } - char *subuname = argv[1]; - - sqlite3 *db; - { - int ret = sqlite3_open_v2(DB_File, &db, SQLITE_OPEN_READWRITE, NULL); - if( ret != SQLITE_OK ){ - fprintf(stderr, "error exit, could not open db file \"%s\"\n", DB_File); - return SUBU_ERR_DB_FILE; - }} - - { - char *mess=0; - int ret = subu_rm_0(&mess, db, subuname); - subu_err("subu_rm_0", ret, mess); - free(mess); - return ret; - } -} diff --git a/module/subu-0/trc/subu-rm-0.trc.c b/module/subu-0/trc/subu-rm-0.trc.c new file mode 100644 index 0000000..e49e611 --- /dev/null +++ b/module/subu-0/trc/subu-rm-0.trc.c @@ -0,0 +1,33 @@ +#tranche subu-rm-0.cli.c +/* + subu-mk-0 command + +*/ +#include +#include + +int main(int argc, char **argv){ + char *command = argv[0]; + if( argc != 2 ){ + fprintf(stderr, "usage: %s subu", command); + return SUBU_ERR_ARG_CNT; + } + char *subuname = argv[1]; + + sqlite3 *db; + { + int ret = sqlite3_open_v2(DB_File, &db, SQLITE_OPEN_READWRITE, NULL); + if( ret != SQLITE_OK ){ + fprintf(stderr, "error exit, could not open db file \"%s\"\n", DB_File); + return SUBU_ERR_DB_FILE; + }} + + { + char *mess=0; + int ret = subu_rm_0(&mess, db, subuname); + subu_err("subu_rm_0", ret, mess); + free(mess); + return ret; + } +} +#tranche-end diff --git a/module/subu-0/trc/subu.lib.c b/module/subu-0/trc/subu.lib.c deleted file mode 100644 index cd6bc2f..0000000 --- a/module/subu-0/trc/subu.lib.c +++ /dev/null @@ -1,713 +0,0 @@ -/* - sqllite3 is used to maintain the db file, which is currently compiled - in as /etc/subu.db, (or just subu.db for testing). - - masteru is the user who ran this script. The masteru name comes from getuid - and /etc/passwd. - - subu is a subservient user. The subuname is passed in as an argument. - - subu-mk-0 synthesizes a new user user name s, calls useradd to creat - the new uswer account, and enters the relationship between masteru, subu, and - s in the db file. It is this relation in the db file that - associates the subuname with the s user. - - subu-rm-0 uses userdel to delete the related s user account. It - then removes the relaton from the db file. - - subu-mk-0 and subu-rm-0 are setuid root scripts. - -*/ -#include "subu.lib.h" - -// without this #define we get the warning: implicit declaration of function ‘seteuid’/‘setegid’ -#define _GNU_SOURCE - -#include -#include -#include -#include -#include -#include -#include -#include - -#if INTERFACE -#include -#include -#include -#endif - -//-------------------------------------------------------------------------------- -// dispatched command errors .. should add mkdir and rmdir ... -// -char *useradd_mess(int err){ - if(err <= 0) return NULL; - char *mess; - switch(err){ - case 1: mess = "can't update password file"; break; - case 2: mess = "invalid command syntax"; break; - case 3: mess = "invalid argument to option"; break; - case 4: mess = "UID already in use (and no -o)"; break; - case 5: mess = "undefined"; break; - case 6: mess = "specified group doesn't exist"; break; - case 7: - case 8: mess = "undefined"; break; - case 9: mess = "username already in use"; break; - case 10: mess = "can't update group file:"; break; - case 11: mess = "undefined"; break; - case 12: mess = "can't create home directory"; break; - case 13: mess = "undefined"; break; - case 14: mess = "can't update SELinux user mapping"; break; - default: mess = "undefined"; break; - } - return strdup(mess); -} -char *userdel_mess(int err){ - if(err <= 0) return NULL; - char *mess; - switch(err){ - case 1: mess = "can't update password file"; break; - case 2: mess = "invalid command syntax"; break; - case 3: - case 4: - case 5: mess = "undefined"; break; - case 6: mess = "specified user doesn't exist"; break; - case 7: - case 8: - case 9: mess = "undefined"; break; - case 10: mess = "can't update group file:"; break; - case 11: mess = "undefined"; break; - case 12: mess = "can't remove home directory"; break; - default: mess = "undefined"; break; - } - return strdup(mess); -} - - -//-------------------------------------------------------------------------------- -// -#if INTERFACE -#define SUBU_ERR_ARG_CNT 1 -#define SUBU_ERR_SETUID_ROOT 2 -#define SUBU_ERR_MALLOC 3 -#define SUBU_ERR_MKDIR_SUBUHOME 4 -#define SUBU_ERR_RMDIR_SUBUHOME 5 -#define SUBU_ERR_SUBUNAME_MALFORMED 6 -#define SUBU_ERR_HOMELESS 7 -#define SUBU_ERR_DB_FILE 8 -#define SUBU_ERR_SUBUHOME_EXISTS 9 -#define SUBU_ERR_BUG_SSS 10 -#define SUBU_ERR_FAILED_USERADD 11 -#define SUBU_ERR_FAILED_USERDEL 12 -#define SUBU_ERR_SUBU_NOT_FOUND 13 -#define SUBU_ERR_N 14 -#define SUBU_ERR_BIND 15 -#endif - -void subu_err(char *fname, int err, char *mess){ - if(!mess) mess = ""; - switch(err){ - case 0: return; - case SUBU_ERR_ARG_CNT: - if(mess[0]) - fprintf(stderr, "Incorrect number of arguments, %s", mess); - else - fprintf(stderr, "Incorrect number of arguments.", mess); - break; - case SUBU_ERR_SETUID_ROOT: - fprintf(stderr, "This program must be run setuid root from a user account."); - break; - case SUBU_ERR_MALLOC: - perror(fname); - break; - case SUBU_ERR_DB_FILE: - fprintf(stderr, "error on %s", DB_File); // DB_File is in common - fprintf(stderr, ": %s", mess); - break; - case SUBU_ERR_HOMELESS: - fprintf(stderr,"Masteru, \"%s\", has no home directory", mess); - break; - case SUBU_ERR_SUBUNAME_MALFORMED: - fprintf(stderr, "subuname, \"%s\" is not in [ _.-a-zA-Z0-9]*", mess); - break; - case SUBU_ERR_SUBUHOME_EXISTS: - fprintf(stderr, "a file system object already exists at subuhome, \"%s\"\n", mess); - break; - case SUBU_ERR_MKDIR_SUBUHOME: - fprintf(stderr, "masteru could not make subuhome, \"%s\"", mess); - break; - case SUBU_ERR_BUG_SSS: - perror(fname); - break; - case SUBU_ERR_FAILED_USERADD: - fprintf(stderr, "%s useradd failed\n", mess); - break; - default: - fprintf(stderr, "unknown error code %d\n", err); - } - fputc('\n', stderr); -} - - -//-------------------------------------------------------------------------------- -// a well formed subuname -// returns the length of the subuname, or -1 -// -static int allowed_subuname(char **mess, char *subuname, size_t *subuname_len){ - char *ch = subuname; - size_t i = 0; - while( - *ch - && - ( *ch >= 'a' && *ch <= 'z' - || - *ch >= 'A' && *ch <= 'Z' - || - *ch >= '0' && *ch <= '9' - || - *ch == '-' - || - *ch == '_' - || - *ch == '.' - || - *ch == ' ' - ) - ){ - ch++; - i++; - } - if( !*ch ){ - *subuname_len = i; - return 0; - }else{ - if(mess) *mess = strdup(subuname); - return SUBU_ERR_SUBUNAME_MALFORMED; - } -} - -//-------------------------------------------------------------------------------- -// dispatched functions -// -static int masteru_mkdir_subuhome(void *arg){ - char *subuhome = (char *) arg; - if( mkdir( subuhome, Subuhome_Perms ) == -1 ){ // find subuhome perms in common - perror("masteru_mkdir_subuhome"); - return SUBU_ERR_MKDIR_SUBUHOME; - } - return 0; -} -static int masteru_rmdir_subuhome(void *arg){ - char *subuhome = (char *) arg; - if( rmdir( subuhome ) == -1 ){ // find subuhome perms in common - perror("masteru_rmdir_subuhome"); - return SUBU_ERR_RMDIR_SUBUHOME; - } - return 0; -} - -//-------------------------------------------------------------------------------- -// build strings -// -static int mk_subu_username(char **mess, sqlite3 *db, char **subu_username){ - int rc,n; - db_begin(db); - if( - (rc = subudb_number_get(db, &n)) - || - (rc = subudb_number_set(db, ++n)) - ){ - db_rollback(db); - return SUBU_ERR_DB_FILE; - } - db_commit(db); - - size_t len = 0; - FILE* name_stream = open_memstream(subu_username, &len); - fprintf(name_stream, "s%d", n); - fclose(name_stream); - return 0; -} - -// man page says that getpwuid strings may not be freed, I don't know how long until they -// are overwritten, so I just make my own copies that can be freed -static int uid_to_name_and_home(uid_t uid, char **name, char **home ){ - struct passwd *pw_record_pt = getpwuid(uid); // reading /etc/passwd - *name = strdup(pw_record_pt->pw_name); - *home = strdup(pw_record_pt->pw_dir); - if( !home || !home[0] || (*home)[0] == '(' ) return SUBU_ERR_HOMELESS; - return 0; -} - -static int username_to_home(char *name, char **home ){ - struct passwd *pw_record_pt = getpwnam(name); // reading /etc/passwd - *home = strdup(pw_record_pt->pw_dir); - if( !home || !home[0] || (*home)[0] == '(' ) return SUBU_ERR_HOMELESS; - return 0; -} - -static int mk_subuland(char *masteru_home, char **subuland){ - size_t masteru_home_len = strlen(masteru_home); - char *Subuland_Extension = "/subuland/"; - size_t Subuland_Extension_len = strlen(Subuland_Extension); - *subuland = (char *)malloc( masteru_home_len + Subuland_Extension_len + 1 ); - if(!*subuland) SUBU_ERR_MALLOC; - strcpy(*subuland, masteru_home); - strcpy(*subuland + masteru_home_len, Subuland_Extension); - return 0; -} - -static int mk_subuhome(char *subuland, char *subuname, char **subuhome){ - size_t subuland_len = strlen(subuland); - size_t subuhome_len = subuland_len + strlen(subuname); // subuland has a trailing '/' - *subuhome = (char *)malloc(subuhome_len + 1); - if(!*subuhome) return SUBU_ERR_MALLOC; - strcpy (*subuhome, subuland); - strcpy (*subuhome + subuland_len, subuname); - return 0; -} - - - -//=============================================================================== -int subu_mk_0(char **mess, sqlite3 *db, char *subuname){ - - int rc; - if(mess)*mess = 0; - da resources; - da_alloc(&resources, sizeof(char *)); - - //-------------------------------------------------------------------------------- - size_t subuname_len; - rc = allowed_subuname(mess, subuname, &subuname_len); - if(rc) return rc; - #ifdef DEBUG - debug_printf("subuname is well formed\n"); - #endif - - //-------------------------------------------------------------------------------- - uid_t masteru_uid; - gid_t masteru_gid; - uid_t set_euid; - gid_t set_egid; - { - masteru_uid = getuid(); - masteru_gid = getgid(); - set_euid = geteuid(); - set_egid = getegid(); - #ifdef DEBUG - debug_printf("masteru_uid %u, masteru_gid %u, set_euid %u set_egid %u\n", masteru_uid, masteru_gid, set_euid, set_egid); - #endif - if( masteru_uid == 0 || set_euid != 0 ) return SUBU_ERR_SETUID_ROOT; - } - - //-------------------------------------------------------------------------------- - char *masteru_name = 0; - char *masteru_home = 0; - char *subu_username = 0; - char *subuland = 0; - char *subuhome = 0; // the name of the directory to put in subuland, not subu_user home dir - da_push(&resources, masteru_name); - da_push(&resources, masteru_home); - da_push(&resources, subu_username); - da_push(&resources, subuland); - da_push(&resources, subuhome); - rc = - uid_to_name_and_home(masteru_uid, &masteru_name, &masteru_home) - || - mk_subu_username(mess, db, &subu_username) - || - mk_subuland(masteru_home, &subuland) - || - mk_subuhome(subuland, subuname, &subuhome) - ; - if(rc) RETURN(&resources, rc); - #ifdef DEBUG - debug_printf("subu_username, subuland, subuhome: \"%s\"\"%s\"\"%s\"\n", subu_username, subuland, subuhome); - #endif - - //-------------------------------------------------------------------------------- - // By having masteru create the subuhome, we know that masteru has rights to - // to access this directory. This will be the mount point for bindfs - { - struct stat st; - if( stat(subuhome, &st) != -1 ){ - if(mess)*mess = strdup(subuhome); - RETURN(&resources, SUBU_ERR_SUBUHOME_EXISTS); - } - int dispatch_err = dispatch_f_euid_egid - ( - "masteru_mkdir_subuhome", - masteru_mkdir_subuhome, - (void *)subuhome, - masteru_uid, - masteru_gid - ); - if( dispatch_err <= ERR_DISPATCH || dispatch_err == SUBU_ERR_MKDIR_SUBUHOME ){ - #ifdef DEBUG - dispatch_f_mess("dispatch_f_euid_egid", dispatch_err, "masteru_mkdir_subuhome"); - #endif - if(mess)*mess = strdup(subuhome); - RETURN(&resources, SUBU_ERR_MKDIR_SUBUHOME); - } - } - #ifdef DEBUG - debug_printf("made directory \"%s\"\n", subuhome); - #endif - - //-------------------------------------------------------------------------------- - // Make the subservient user account, i.e. the subu - { - #ifdef DEBUG - debug_printf("making subu \"%s\" as user \"%s\"\n", subuname, subu_username); - #endif - #if BUG_SSS_CACHE_RUID - #ifdef DEBUG - debug_printf("setting inherited real uid to 0 to accomodate SSS_CACHE UID BUG\n"); - #endif - if( setuid(0) == -1 ) RETURN(&resources, SUBU_ERR_BUG_SSS); - #endif - char *command = "/usr/sbin/useradd"; - char *argv[3]; - argv[0] = command; - argv[1] = subu_username; - argv[2] = (char *) NULL; - char *envp[1]; - envp[0] = (char *) NULL; - int dispatch_err = dispatch_exec(argv, envp); - if( dispatch_err != 0 ){ - #ifdef DEBUG - dispatch_f_mess("dispatch_exec", dispatch_err, command); - #endif - // go back and remove the directory we made in subuland - int dispatch_err_rmdir = dispatch_f_euid_egid - ( - "masteru_rmdir_subuhome", - masteru_rmdir_subuhome, - (void *)subuhome, - masteru_uid, - masteru_gid - ); - #ifdef DEBUG - dispatch_f_mess("dispatch_f_euid_egid", dispatch_err_rmdir, "masteru_rmdir_subuhome"); - #endif - if(mess)*mess = useradd_mess(dispatch_err); - RETURN(&resources, SUBU_ERR_FAILED_USERADD); - } - #ifdef DEBUG - debug_printf("added user \"%s\"\n", subu_username); - #endif - } - - //-------------------------------------------------------------------------------- - #ifdef DEBUG - debug_printf("setting the masteru_name, subuname, subu_username relation\n"); - #endif - { - int rc = subudb_Masteru_Subu_put(db, masteru_name, subuname, subu_username); - if( rc != SQLITE_OK ){ - if(mess)*mess = strdup("insert of masteru subu relation failed"); - RETURN(&resources, SUBU_ERR_DB_FILE); - } - } - #ifdef DEBUG - debug_printf("finished subu-mk-0(%s)\n", subuname); - #endif - RETURN(&resources, 0); -} - -//================================================================================ -int subu_rm_0(char **mess, sqlite3 *db, char *subuname){ - - int rc; - if(mess)*mess = 0; - da resources; - da_alloc(&resources, sizeof(char *)); - - //-------------------------------------------------------------------------------- - size_t subuname_len; - rc = allowed_subuname(mess, subuname, &subuname_len); - if(rc) return rc; - #ifdef DEBUG - debug_printf("subuname is well formed\n"); - #endif - - //-------------------------------------------------------------------------------- - uid_t masteru_uid; - gid_t masteru_gid; - uid_t set_euid; - gid_t set_egid; - { - masteru_uid = getuid(); - masteru_gid = getgid(); - set_euid = geteuid(); - set_egid = getegid(); - #ifdef DEBUG - debug_printf("masteru_uid %u, masteru_gid %u, set_euid %u set_egid %u\n", masteru_uid, masteru_gid, set_euid, set_egid); - #endif - if( masteru_uid == 0 || set_euid != 0 ) return SUBU_ERR_SETUID_ROOT; - } - - //-------------------------------------------------------------------------------- - // various strings that we will need - char *masteru_name = 0; - char *masteru_home = 0; - char *subuland = 0; - char *subuhome = 0; // the name of the directory to put in subuland, not subu_user home dir - da_push(&resources, masteru_name); - da_push(&resources, masteru_home); - da_push(&resources, subuland); - da_push(&resources, subuhome); - rc = - uid_to_name_and_home(masteru_uid, &masteru_name, &masteru_home) - || - mk_subuland(masteru_home, &subuland) - || - mk_subuhome(subuland, subuname, &subuhome) - ; - if(rc) RETURN(&resources, rc); - #ifdef DEBUG - debug_printf("masteru_home, subuhome: \"%s\", \"%s\"\n", masteru_home, subuhome); - #endif - - //-------------------------------------------------------------------------------- - // removal from db - char *subu_username = 0; - da_push(&resources, subu_username); - - db_begin(db); - - rc = subudb_Masteru_Subu_get_subu_username(db, masteru_name, subuname, &subu_username); - if( rc != SQLITE_OK ){ - if(mess) *mess = strdup("subu requested for removal not found under this masteru in db file"); - rc = SUBU_ERR_SUBU_NOT_FOUND; - db_rollback(db); - RETURN(&resources, rc); - } - #ifdef DEBUG - printf("subu_username: \"%s\"\n", subu_username); - #endif - - rc = subudb_Masteru_Subu_rm(db, masteru_name, subuname, subu_username); - if( rc != SQLITE_OK ){ - if(mess)*mess = strdup("removal of masteru subu relation failed"); - db_rollback(db); - RETURN(&resources, SUBU_ERR_DB_FILE); - } - #ifdef DEBUG - debug_printf("removed the masteru_name, subuname, subu_username relation\n"); - #endif - - rc = db_commit(db); - if( rc != SQLITE_OK ){ - if(mess)*mess = strdup("removal of masteru subu relation in unknown state, exiting"); - RETURN(&resources, SUBU_ERR_DB_FILE); - } - - // even after removing the last masteru subu relation, we still do not remove - // the max subu count. Hence, a masteru will keep such for a life time. - - - //-------------------------------------------------------------------------------- - // Only masteru can remove directories from masteru/subuland, so we switch to - // masteru's uid to perform the rmdir. - // - { - #ifdef DEBUG - debug_printf("as masteru, removing the directory \"%s\"\n", subuhome); - #endif - int dispatch_err = dispatch_f_euid_egid - ( - "masteru_rmdir_subuhome", - masteru_rmdir_subuhome, - (void *)subuhome, - masteru_uid, - masteru_gid - ); - if( dispatch_err <= ERR_DISPATCH || dispatch_err == SUBU_ERR_RMDIR_SUBUHOME ){ - #ifdef DEBUG - dispatch_f_mess("dispatch_f_euid_egid", dispatch_err, "masteru_rmdir_subuhome"); - #endif - if(mess)*mess = strdup(subuhome); - RETURN(&resources, SUBU_ERR_RMDIR_SUBUHOME); - } - } - - //-------------------------------------------------------------------------------- - // Delete the subservient user account - { - #ifdef DEBUG - debug_printf("deleting user \"%s\"\n", subu_username); - #endif - #if BUG_SSS_CACHE_RUID - #ifdef DEBUG - debug_printf("setting inherited real uid to 0 to accomodate SSS_CACHE UID BUG\n"); - #endif - if( setuid(0) == -1 ){ - RETURN(&resources, SUBU_ERR_BUG_SSS); - } - #endif - char *command = "/usr/sbin/userdel"; - char *argv[4]; - argv[0] = command; - argv[1] = subu_username; - argv[2] = "-r"; - argv[3] = (char *) NULL; - char *envp[1]; - envp[0] = (char *) NULL; - int dispatch_err = dispatch_exec(argv, envp); - if( dispatch_err != 0 ){ - #ifdef DEBUG - dispatch_f_mess("dispatch_exec", dispatch_err, command); - #endif - if(mess)*mess = userdel_mess(dispatch_err); - RETURN(&resources, SUBU_ERR_FAILED_USERDEL); - } - #ifdef DEBUG - debug_printf("deleted user \"%s\"\n", subu_username); - #endif - } - - #ifdef DEBUG - debug_printf("finished subu-rm-0(%s)\n", subuname); - #endif - RETURN(&resources, 0); -} - -//================================================================================ -// identifies masteru, the bindfs maps each subu_user's home to its mount point -// in subuland. -int subu_bind(char **mess, char *masteru_name, char *subu_username, char *subuhome){ - - int rc; - if(mess)*mess = 0; - da resources; - da_alloc(&resources, sizeof(char *)); - - // lookup the subu_user_home - char *subu_user_home = 0; - da_push(&resources, subu_user_home); - - rc = username_to_home(subu_username, &subu_user_home); - if( rc ){ - if(mess) *mess = strdup("in subu_bind, subu user home directory lookup in /etc/passwd failed."); - RETURN(&resources, rc); - } - - size_t len = 0; - char *map = 0; - da_push(&resources, map); - - FILE* map_stream = open_memstream(&map, &len); - fprintf(map_stream, "--map=%s/%s:@%s/@%s", subu_username, masteru_name, subu_username, masteru_name); - fclose(map_stream); - - char *command = "/usr/bin/bindfs"; - char *argv[5]; - argv[0] = command; - argv[1] = map; - argv[2] = subu_user_home; - argv[3] = subuhome; - argv[4] = (char *) NULL; - char *envp[1]; - envp[0] = (char *) NULL; - int dispatch_err = dispatch_exec(argv, envp); - if( dispatch_err != 0 ){ - #ifdef DEBUG - dispatch_f_mess(command, dispatch_err, "dispatch_exec"); - #endif - if(mess)*mess = strdup("bind failed"); - RETURN(&resources, SUBU_ERR_BIND); - } - #ifdef DEBUG - debug_printf("mapped \"%s\" as \"%s\"\n", subu_user_home, subuhome); - #endif - RETURN(&resources, 0); -} - -int subu_bind_all(char **mess, sqlite3 *db){ - - int rc; - if(mess)*mess = 0; - da resources; - da_alloc(&resources, sizeof(char *)); - - //-------------------------------------------------------------------------------- - uid_t masteru_uid; - gid_t masteru_gid; - uid_t set_euid; - gid_t set_egid; - { - masteru_uid = getuid(); - masteru_gid = getgid(); - set_euid = geteuid(); - set_egid = getegid(); - #ifdef DEBUG - debug_printf("masteru_uid %u, masteru_gid %u, set_euid %u set_egid %u\n", masteru_uid, masteru_gid, set_euid, set_egid); - #endif - if( masteru_uid == 0 || set_euid != 0 ) return SUBU_ERR_SETUID_ROOT; - } - - //-------------------------------------------------------------------------------- - // various strings that we will need - char *masteru_name = 0; - char *masteru_home = 0; - char *subuland = 0; - da_push(&resources, masteru_name); - da_push(&resources, masteru_home); - da_push(&resources, subuland); - rc = - uid_to_name_and_home(masteru_uid, &masteru_name, &masteru_home) - || - mk_subuland(masteru_home, &subuland) - ; - if(rc) RETURN(&resources, rc); - #ifdef DEBUG - if(masteru_name) - debug_printf("masteru_name: \"%s\"", masteru_name); - else - debug_printf("masteru_name unknown"); - if(subuland) - debug_printf("subuland: \"%s\"", subuland); - else - debug_printf("subuland unknown"); - debug_printf("\n"); - #endif - - //-------------------------------------------------------------------------------- - da subus; - rc = subudb_Masteru_Subu_get_subus(db, masteru_name, &subus); - if( rc != SQLITE_OK ){ - if(mess)*mess = strdup("db access failed when fetching a list of subus"); - return rc; - } - // a limitation of our error reporting approach is that we can only - // return one error, but here is a loop that might generate many - rc = 0; - char *subuhome = 0; // the name of the directory to put in subuland, not subu_user home dir - uint err_cnt = 0; - subudb_subu_element *pt = (subudb_subu_element *)(subus.base); - while( !da_endq(&subus,pt) ){ - rc = mk_subuhome(subuland, pt->subuname, &subuhome); - #ifdef DEBUG - if(subuhome) - debug_printf("subuhome: \"%s\"\n", subuhome); - else - debug_printf("subuhome unknown \n"); - #endif - if(!rc) rc = subu_bind(NULL, masteru_name, pt->subu_username, subuhome); - if(rc) err_cnt++; - free(subuhome); - subuhome=0; - pt++; - } - if(err_cnt==1){ - RETURN(&resources, rc); - } - if(err_cnt > 1){ - *mess = strdup("multiple errors occured while binding subus"); - RETURN(&resources, SUBU_ERR_BIND); - } - RETURN(&resources, 0); -} diff --git a/module/subu-0/trc/subu.trc.c b/module/subu-0/trc/subu.trc.c new file mode 100644 index 0000000..6ce4625 --- /dev/null +++ b/module/subu-0/trc/subu.trc.c @@ -0,0 +1,742 @@ +#tranche subu.lib.c +/* + sqllite3 is used to maintain the db file, which is currently compiled + in as /etc/subu.db, (or just subu.db for testing). + + masteru is the user who ran this script. The masteru name comes from getuid + and /etc/passwd. + + subu is a subservient user. The subuname is passed in as an argument. + + subu-mk-0 synthesizes a new user user name s, calls useradd to creat + the new uswer account, and enters the relationship between masteru, subu, and + s in the db file. It is this relation in the db file that + associates the subuname with the s user. + + subu-rm-0 uses userdel to delete the related s user account. It + then removes the relaton from the db file. + + subu-mk-0 and subu-rm-0 are setuid root scripts. + +*/ +#include +#include +#include +#include "common.lib.h" +#include "subudb.lib.h" +#include "subu.lib.h" + +// without this #define we get the warning: implicit declaration of function ‘seteuid’/‘setegid’ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include + +#tranche subu.lib.h + #include + #include + #include +#tranche-end + +//-------------------------------------------------------------------------------- +// dispatched command errors .. should add mkdir and rmdir ... +// +#tranche subu.lib.h + char *useradd_mess(int err); +#tranche-end +char *useradd_mess(int err){ + if(err <= 0) return NULL; + char *mess; + switch(err){ + case 1: mess = "can't update password file"; break; + case 2: mess = "invalid command syntax"; break; + case 3: mess = "invalid argument to option"; break; + case 4: mess = "UID already in use (and no -o)"; break; + case 5: mess = "undefined"; break; + case 6: mess = "specified group doesn't exist"; break; + case 7: + case 8: mess = "undefined"; break; + case 9: mess = "username already in use"; break; + case 10: mess = "can't update group file:"; break; + case 11: mess = "undefined"; break; + case 12: mess = "can't create home directory"; break; + case 13: mess = "undefined"; break; + case 14: mess = "can't update SELinux user mapping"; break; + default: mess = "undefined"; break; + } + return strdup(mess); +} +#tranche subu.lib.h + char *userdel_mess(int err); +#tranche-end +char *userdel_mess(int err){ + if(err <= 0) return NULL; + char *mess; + switch(err){ + case 1: mess = "can't update password file"; break; + case 2: mess = "invalid command syntax"; break; + case 3: + case 4: + case 5: mess = "undefined"; break; + case 6: mess = "specified user doesn't exist"; break; + case 7: + case 8: + case 9: mess = "undefined"; break; + case 10: mess = "can't update group file:"; break; + case 11: mess = "undefined"; break; + case 12: mess = "can't remove home directory"; break; + default: mess = "undefined"; break; + } + return strdup(mess); +} + + +//-------------------------------------------------------------------------------- +// +#tranche subu.lib.h + #define SUBU_ERR_ARG_CNT 1 + #define SUBU_ERR_SETUID_ROOT 2 + #define SUBU_ERR_MALLOC 3 + #define SUBU_ERR_MKDIR_SUBUHOME 4 + #define SUBU_ERR_RMDIR_SUBUHOME 5 + #define SUBU_ERR_SUBUNAME_MALFORMED 6 + #define SUBU_ERR_HOMELESS 7 + #define SUBU_ERR_DB_FILE 8 + #define SUBU_ERR_SUBUHOME_EXISTS 9 + #define SUBU_ERR_BUG_SSS 10 + #define SUBU_ERR_FAILED_USERADD 11 + #define SUBU_ERR_FAILED_USERDEL 12 + #define SUBU_ERR_SUBU_NOT_FOUND 13 + #define SUBU_ERR_N 14 + #define SUBU_ERR_BIND 15 +#tranche-end +#tranche subu.lib.h + void subu_err(char *fname, int err, char *mess); +#tranche-end +void subu_err(char *fname, int err, char *mess){ + if(!mess) mess = ""; + switch(err){ + case 0: return; + case SUBU_ERR_ARG_CNT: + if(mess[0]) + fprintf(stderr, "Incorrect number of arguments, %s", mess); + else + fprintf(stderr, "Incorrect number of arguments.", mess); + break; + case SUBU_ERR_SETUID_ROOT: + fprintf(stderr, "This program must be run setuid root from a user account."); + break; + case SUBU_ERR_MALLOC: + perror(fname); + break; + case SUBU_ERR_DB_FILE: + fprintf(stderr, "error on %s", DB_File); // DB_File is in common + fprintf(stderr, ": %s", mess); + break; + case SUBU_ERR_HOMELESS: + fprintf(stderr,"Masteru, \"%s\", has no home directory", mess); + break; + case SUBU_ERR_SUBUNAME_MALFORMED: + fprintf(stderr, "subuname, \"%s\" is not in [ _.-a-zA-Z0-9]*", mess); + break; + case SUBU_ERR_SUBUHOME_EXISTS: + fprintf(stderr, "a file system object already exists at subuhome, \"%s\"\n", mess); + break; + case SUBU_ERR_MKDIR_SUBUHOME: + fprintf(stderr, "masteru could not make subuhome, \"%s\"", mess); + break; + case SUBU_ERR_BUG_SSS: + perror(fname); + break; + case SUBU_ERR_FAILED_USERADD: + fprintf(stderr, "%s useradd failed\n", mess); + break; + default: + fprintf(stderr, "unknown error code %d\n", err); + } + fputc('\n', stderr); +} + + +//-------------------------------------------------------------------------------- +// a well formed subuname +// returns the length of the subuname, or -1 +// +static int allowed_subuname(char **mess, char *subuname, size_t *subuname_len){ + char *ch = subuname; + size_t i = 0; + while( + *ch + && + ( *ch >= 'a' && *ch <= 'z' + || + *ch >= 'A' && *ch <= 'Z' + || + *ch >= '0' && *ch <= '9' + || + *ch == '-' + || + *ch == '_' + || + *ch == '.' + || + *ch == ' ' + ) + ){ + ch++; + i++; + } + if( !*ch ){ + *subuname_len = i; + return 0; + }else{ + if(mess) *mess = strdup(subuname); + return SUBU_ERR_SUBUNAME_MALFORMED; + } +} + +//-------------------------------------------------------------------------------- +// dispatched functions +// +static int masteru_mkdir_subuhome(void *arg){ + char *subuhome = (char *) arg; + if( mkdir( subuhome, Subuhome_Perms ) == -1 ){ // find subuhome perms in common + perror("masteru_mkdir_subuhome"); + return SUBU_ERR_MKDIR_SUBUHOME; + } + return 0; +} +static int masteru_rmdir_subuhome(void *arg){ + char *subuhome = (char *) arg; + if( rmdir( subuhome ) == -1 ){ // find subuhome perms in common + perror("masteru_rmdir_subuhome"); + return SUBU_ERR_RMDIR_SUBUHOME; + } + return 0; +} + +//-------------------------------------------------------------------------------- +// build strings +// +static int mk_subu_username(char **mess, sqlite3 *db, char **subu_username){ + int rc,n; + db_begin(db); + if( + (rc = subudb_number_get(db, &n)) + || + (rc = subudb_number_set(db, ++n)) + ){ + db_rollback(db); + return SUBU_ERR_DB_FILE; + } + db_commit(db); + + size_t len = 0; + FILE* name_stream = open_memstream(subu_username, &len); + fprintf(name_stream, "s%d", n); + fclose(name_stream); + return 0; +} + +// man page says that getpwuid strings may not be freed, I don't know how long until they +// are overwritten, so I just make my own copies that can be freed +static int uid_to_name_and_home(uid_t uid, char **name, char **home ){ + struct passwd *pw_record_pt = getpwuid(uid); // reading /etc/passwd + *name = strdup(pw_record_pt->pw_name); + *home = strdup(pw_record_pt->pw_dir); + if( !home || !home[0] || (*home)[0] == '(' ) return SUBU_ERR_HOMELESS; + return 0; +} + +static int username_to_home(char *name, char **home ){ + struct passwd *pw_record_pt = getpwnam(name); // reading /etc/passwd + *home = strdup(pw_record_pt->pw_dir); + if( !home || !home[0] || (*home)[0] == '(' ) return SUBU_ERR_HOMELESS; + return 0; +} + +static int mk_subuland(char *masteru_home, char **subuland){ + size_t masteru_home_len = strlen(masteru_home); + char *Subuland_Extension = "/subuland/"; + size_t Subuland_Extension_len = strlen(Subuland_Extension); + *subuland = (char *)malloc( masteru_home_len + Subuland_Extension_len + 1 ); + if(!*subuland) SUBU_ERR_MALLOC; + strcpy(*subuland, masteru_home); + strcpy(*subuland + masteru_home_len, Subuland_Extension); + return 0; +} + +static int mk_subuhome(char *subuland, char *subuname, char **subuhome){ + size_t subuland_len = strlen(subuland); + size_t subuhome_len = subuland_len + strlen(subuname); // subuland has a trailing '/' + *subuhome = (char *)malloc(subuhome_len + 1); + if(!*subuhome) return SUBU_ERR_MALLOC; + strcpy (*subuhome, subuland); + strcpy (*subuhome + subuland_len, subuname); + return 0; +} + + + +//=============================================================================== +#tranche subu.lib.h + int subu_mk_0(char **mess, sqlite3 *db, char *subuname); +#tranche-end +int subu_mk_0(char **mess, sqlite3 *db, char *subuname){ + + int rc; + if(mess)*mess = 0; + Da resources; + da_alloc(&resources, sizeof(char *)); + + //-------------------------------------------------------------------------------- + size_t subuname_len; + rc = allowed_subuname(mess, subuname, &subuname_len); + if(rc) return rc; + #ifdef DEBUG + debug_printf("subuname is well formed\n"); + #endif + + //-------------------------------------------------------------------------------- + uid_t masteru_uid; + gid_t masteru_gid; + uid_t set_euid; + gid_t set_egid; + { + masteru_uid = getuid(); + masteru_gid = getgid(); + set_euid = geteuid(); + set_egid = getegid(); + #ifdef DEBUG + debug_printf("masteru_uid %u, masteru_gid %u, set_euid %u set_egid %u\n", masteru_uid, masteru_gid, set_euid, set_egid); + #endif + if( masteru_uid == 0 || set_euid != 0 ) return SUBU_ERR_SETUID_ROOT; + } + + //-------------------------------------------------------------------------------- + char *masteru_name = 0; + char *masteru_home = 0; + char *subu_username = 0; + char *subuland = 0; + char *subuhome = 0; // the name of the directory to put in subuland, not subu_user home dir + da_push(&resources, masteru_name); + da_push(&resources, masteru_home); + da_push(&resources, subu_username); + da_push(&resources, subuland); + da_push(&resources, subuhome); + rc = + uid_to_name_and_home(masteru_uid, &masteru_name, &masteru_home) + || + mk_subu_username(mess, db, &subu_username) + || + mk_subuland(masteru_home, &subuland) + || + mk_subuhome(subuland, subuname, &subuhome) + ; + if(rc) RETURN(&resources, rc); + #ifdef DEBUG + debug_printf("subu_username, subuland, subuhome: \"%s\"\"%s\"\"%s\"\n", subu_username, subuland, subuhome); + #endif + + //-------------------------------------------------------------------------------- + // By having masteru create the subuhome, we know that masteru has rights to + // to access this directory. This will be the mount point for bindfs + { + struct stat st; + if( stat(subuhome, &st) != -1 ){ + if(mess)*mess = strdup(subuhome); + RETURN(&resources, SUBU_ERR_SUBUHOME_EXISTS); + } + int dispatch_err = dispatch_f_euid_egid + ( + "masteru_mkdir_subuhome", + masteru_mkdir_subuhome, + (void *)subuhome, + masteru_uid, + masteru_gid + ); + if( dispatch_err <= ERR_DISPATCH || dispatch_err == SUBU_ERR_MKDIR_SUBUHOME ){ + #ifdef DEBUG + dispatch_f_mess("dispatch_f_euid_egid", dispatch_err, "masteru_mkdir_subuhome"); + #endif + if(mess)*mess = strdup(subuhome); + RETURN(&resources, SUBU_ERR_MKDIR_SUBUHOME); + } + } + #ifdef DEBUG + debug_printf("made directory \"%s\"\n", subuhome); + #endif + + //-------------------------------------------------------------------------------- + // Make the subservient user account, i.e. the subu + { + #ifdef DEBUG + debug_printf("making subu \"%s\" as user \"%s\"\n", subuname, subu_username); + #endif + #if BUG_SSS_CACHE_RUID + #ifdef DEBUG + debug_printf("setting inherited real uid to 0 to accomodate SSS_CACHE UID BUG\n"); + #endif + if( setuid(0) == -1 ) RETURN(&resources, SUBU_ERR_BUG_SSS); + #endif + char *command = "/usr/sbin/useradd"; + char *argv[3]; + argv[0] = command; + argv[1] = subu_username; + argv[2] = (char *) NULL; + char *envp[1]; + envp[0] = (char *) NULL; + int dispatch_err = dispatch_exec(argv, envp); + if( dispatch_err != 0 ){ + #ifdef DEBUG + dispatch_f_mess("dispatch_exec", dispatch_err, command); + #endif + // go back and remove the directory we made in subuland + int dispatch_err_rmdir = dispatch_f_euid_egid + ( + "masteru_rmdir_subuhome", + masteru_rmdir_subuhome, + (void *)subuhome, + masteru_uid, + masteru_gid + ); + #ifdef DEBUG + dispatch_f_mess("dispatch_f_euid_egid", dispatch_err_rmdir, "masteru_rmdir_subuhome"); + #endif + if(mess)*mess = useradd_mess(dispatch_err); + RETURN(&resources, SUBU_ERR_FAILED_USERADD); + } + #ifdef DEBUG + debug_printf("added user \"%s\"\n", subu_username); + #endif + } + + //-------------------------------------------------------------------------------- + #ifdef DEBUG + debug_printf("setting the masteru_name, subuname, subu_username relation\n"); + #endif + { + int rc = subudb_Masteru_Subu_put(db, masteru_name, subuname, subu_username); + if( rc != SQLITE_OK ){ + if(mess)*mess = strdup("insert of masteru subu relation failed"); + RETURN(&resources, SUBU_ERR_DB_FILE); + } + } + #ifdef DEBUG + debug_printf("finished subu-mk-0(%s)\n", subuname); + #endif + RETURN(&resources, 0); +} + +//================================================================================ +#tranche subu.lib.h + int subu_rm_0(char **mess, sqlite3 *db, char *subuname); +#tranche-end +int subu_rm_0(char **mess, sqlite3 *db, char *subuname){ + + int rc; + if(mess)*mess = 0; + Da resources; + da_alloc(&resources, sizeof(char *)); + + //-------------------------------------------------------------------------------- + size_t subuname_len; + rc = allowed_subuname(mess, subuname, &subuname_len); + if(rc) return rc; + #ifdef DEBUG + debug_printf("subuname is well formed\n"); + #endif + + //-------------------------------------------------------------------------------- + uid_t masteru_uid; + gid_t masteru_gid; + uid_t set_euid; + gid_t set_egid; + { + masteru_uid = getuid(); + masteru_gid = getgid(); + set_euid = geteuid(); + set_egid = getegid(); + #ifdef DEBUG + debug_printf("masteru_uid %u, masteru_gid %u, set_euid %u set_egid %u\n", masteru_uid, masteru_gid, set_euid, set_egid); + #endif + if( masteru_uid == 0 || set_euid != 0 ) return SUBU_ERR_SETUID_ROOT; + } + + //-------------------------------------------------------------------------------- + // various strings that we will need + char *masteru_name = 0; + char *masteru_home = 0; + char *subuland = 0; + char *subuhome = 0; // the name of the directory to put in subuland, not subu_user home dir + da_push(&resources, masteru_name); + da_push(&resources, masteru_home); + da_push(&resources, subuland); + da_push(&resources, subuhome); + rc = + uid_to_name_and_home(masteru_uid, &masteru_name, &masteru_home) + || + mk_subuland(masteru_home, &subuland) + || + mk_subuhome(subuland, subuname, &subuhome) + ; + if(rc) RETURN(&resources, rc); + #ifdef DEBUG + debug_printf("masteru_home, subuhome: \"%s\", \"%s\"\n", masteru_home, subuhome); + #endif + + //-------------------------------------------------------------------------------- + // removal from db + char *subu_username = 0; + da_push(&resources, subu_username); + + db_begin(db); + + rc = subudb_Masteru_Subu_get_subu_username(db, masteru_name, subuname, &subu_username); + if( rc != SQLITE_OK ){ + if(mess) *mess = strdup("subu requested for removal not found under this masteru in db file"); + rc = SUBU_ERR_SUBU_NOT_FOUND; + db_rollback(db); + RETURN(&resources, rc); + } + #ifdef DEBUG + printf("subu_username: \"%s\"\n", subu_username); + #endif + + rc = subudb_Masteru_Subu_rm(db, masteru_name, subuname, subu_username); + if( rc != SQLITE_OK ){ + if(mess)*mess = strdup("removal of masteru subu relation failed"); + db_rollback(db); + RETURN(&resources, SUBU_ERR_DB_FILE); + } + #ifdef DEBUG + debug_printf("removed the masteru_name, subuname, subu_username relation\n"); + #endif + + rc = db_commit(db); + if( rc != SQLITE_OK ){ + if(mess)*mess = strdup("removal of masteru subu relation in unknown state, exiting"); + RETURN(&resources, SUBU_ERR_DB_FILE); + } + + // even after removing the last masteru subu relation, we still do not remove + // the max subu count. Hence, a masteru will keep such for a life time. + + + //-------------------------------------------------------------------------------- + // Only masteru can remove directories from masteru/subuland, so we switch to + // masteru's uid to perform the rmdir. + // + { + #ifdef DEBUG + debug_printf("as masteru, removing the directory \"%s\"\n", subuhome); + #endif + int dispatch_err = dispatch_f_euid_egid + ( + "masteru_rmdir_subuhome", + masteru_rmdir_subuhome, + (void *)subuhome, + masteru_uid, + masteru_gid + ); + if( dispatch_err <= ERR_DISPATCH || dispatch_err == SUBU_ERR_RMDIR_SUBUHOME ){ + #ifdef DEBUG + dispatch_f_mess("dispatch_f_euid_egid", dispatch_err, "masteru_rmdir_subuhome"); + #endif + if(mess)*mess = strdup(subuhome); + RETURN(&resources, SUBU_ERR_RMDIR_SUBUHOME); + } + } + + //-------------------------------------------------------------------------------- + // Delete the subservient user account + { + #ifdef DEBUG + debug_printf("deleting user \"%s\"\n", subu_username); + #endif + #if BUG_SSS_CACHE_RUID + #ifdef DEBUG + debug_printf("setting inherited real uid to 0 to accomodate SSS_CACHE UID BUG\n"); + #endif + if( setuid(0) == -1 ){ + RETURN(&resources, SUBU_ERR_BUG_SSS); + } + #endif + char *command = "/usr/sbin/userdel"; + char *argv[4]; + argv[0] = command; + argv[1] = subu_username; + argv[2] = "-r"; + argv[3] = (char *) NULL; + char *envp[1]; + envp[0] = (char *) NULL; + int dispatch_err = dispatch_exec(argv, envp); + if( dispatch_err != 0 ){ + #ifdef DEBUG + dispatch_f_mess("dispatch_exec", dispatch_err, command); + #endif + if(mess)*mess = userdel_mess(dispatch_err); + RETURN(&resources, SUBU_ERR_FAILED_USERDEL); + } + #ifdef DEBUG + debug_printf("deleted user \"%s\"\n", subu_username); + #endif + } + + #ifdef DEBUG + debug_printf("finished subu-rm-0(%s)\n", subuname); + #endif + RETURN(&resources, 0); +} + +//================================================================================ +// identifies masteru, the bindfs maps each subu_user's home to its mount point +// in subuland. +#tranche subu.lib.h + int subu_bind(char **mess, char *masteru_name, char *subu_username, char *subuhome); +#tranche-end +int subu_bind(char **mess, char *masteru_name, char *subu_username, char *subuhome){ + + int rc; + if(mess)*mess = 0; + Da resources; + da_alloc(&resources, sizeof(char *)); + + // lookup the subu_user_home + char *subu_user_home = 0; + da_push(&resources, subu_user_home); + + rc = username_to_home(subu_username, &subu_user_home); + if( rc ){ + if(mess) *mess = strdup("in subu_bind, subu user home directory lookup in /etc/passwd failed."); + RETURN(&resources, rc); + } + + size_t len = 0; + char *map = 0; + da_push(&resources, map); + + FILE* map_stream = open_memstream(&map, &len); + fprintf(map_stream, "--map=%s/%s:@%s/@%s", subu_username, masteru_name, subu_username, masteru_name); + fclose(map_stream); + + char *command = "/usr/bin/bindfs"; + char *argv[5]; + argv[0] = command; + argv[1] = map; + argv[2] = subu_user_home; + argv[3] = subuhome; + argv[4] = (char *) NULL; + char *envp[1]; + envp[0] = (char *) NULL; + int dispatch_err = dispatch_exec(argv, envp); + if( dispatch_err != 0 ){ + #ifdef DEBUG + dispatch_f_mess(command, dispatch_err, "dispatch_exec"); + #endif + if(mess)*mess = strdup("bind failed"); + RETURN(&resources, SUBU_ERR_BIND); + } + #ifdef DEBUG + debug_printf("mapped \"%s\" as \"%s\"\n", subu_user_home, subuhome); + #endif + RETURN(&resources, 0); +} + +#tranche subu.lib.h + int subu_bind_all(char **mess, sqlite3 *db); +#tranche-end +int subu_bind_all(char **mess, sqlite3 *db){ + + int rc; + if(mess)*mess = 0; + Da resources; + da_alloc(&resources, sizeof(char *)); + + //-------------------------------------------------------------------------------- + uid_t masteru_uid; + gid_t masteru_gid; + uid_t set_euid; + gid_t set_egid; + { + masteru_uid = getuid(); + masteru_gid = getgid(); + set_euid = geteuid(); + set_egid = getegid(); + #ifdef DEBUG + debug_printf("masteru_uid %u, masteru_gid %u, set_euid %u set_egid %u\n", masteru_uid, masteru_gid, set_euid, set_egid); + #endif + if( masteru_uid == 0 || set_euid != 0 ) return SUBU_ERR_SETUID_ROOT; + } + + //-------------------------------------------------------------------------------- + // various strings that we will need + char *masteru_name = 0; + char *masteru_home = 0; + char *subuland = 0; + da_push(&resources, masteru_name); + da_push(&resources, masteru_home); + da_push(&resources, subuland); + rc = + uid_to_name_and_home(masteru_uid, &masteru_name, &masteru_home) + || + mk_subuland(masteru_home, &subuland) + ; + if(rc) RETURN(&resources, rc); + #ifdef DEBUG + if(masteru_name) + debug_printf("masteru_name: \"%s\"", masteru_name); + else + debug_printf("masteru_name unknown"); + if(subuland) + debug_printf("subuland: \"%s\"", subuland); + else + debug_printf("subuland unknown"); + debug_printf("\n"); + #endif + + //-------------------------------------------------------------------------------- + Da subus; + Da *subusp = &subus; + da_alloc(subusp, sizeof(subudb_subu_element)); + rc = subudb_Masteru_Subu_get_subus(db, masteru_name, subusp); + if( rc != SQLITE_OK ){ + if(mess)*mess = strdup("db access failed when fetching a list of subus"); + return rc; + } + // a limitation of our error reporting approach is that we can only + // return one error, but here is a loop that might generate many + rc = 0; + char *subuhome = 0; // the name of the directory to put in subuland, not subu_user home dir + uint err_cnt = 0; + subudb_subu_element *pt = (subudb_subu_element *)(subusp->base); + while( !da_endq(subusp,pt) ){ + rc = mk_subuhome(subuland, pt->subuname, &subuhome); + #ifdef DEBUG + if(subuhome) + debug_printf("subuhome: \"%s\"\n", subuhome); + else + debug_printf("subuhome unknown \n"); + #endif + if(!rc) rc = subu_bind(NULL, masteru_name, pt->subu_username, subuhome); + if(rc) err_cnt++; + free(subuhome); + subuhome=0; + pt++; + } + if(err_cnt==1){ + RETURN(&resources, rc); + } + if(err_cnt > 1){ + *mess = strdup("multiple errors occured while binding subus"); + RETURN(&resources, SUBU_ERR_BIND); + } + RETURN(&resources, 0); +} +#tranche-end diff --git a/module/subu-0/trc/subudb-init.cli.c b/module/subu-0/trc/subudb-init.cli.c deleted file mode 100644 index 714c7e4..0000000 --- a/module/subu-0/trc/subudb-init.cli.c +++ /dev/null @@ -1,26 +0,0 @@ -/* -This command initializes the db file. - -*/ -#include "subudb-init.cli.h" -#include - -int main(){ - sqlite3 *db; - if( sqlite3_open(DB_File, &db) != SQLITE_OK ){ - fprintf(stderr, "error exit, could not open db file \"%s\"\n", DB_File); - return SUBU_ERR_DB_FILE; - } - db_begin(db); - if( subudb_schema(db) != SQLITE_OK ){ - db_rollback(db); - fprintf(stderr, "error exit, opened db file but could not build schema\n"); - return SUBU_ERR_DB_FILE; - } - db_commit(db); - if( sqlite3_close(db) != SQLITE_OK ){ - fprintf(stderr, "error exit, could not close the db\n"); - return SUBU_ERR_DB_FILE; - } - return 0; -} diff --git a/module/subu-0/trc/subudb-init.trc.c b/module/subu-0/trc/subudb-init.trc.c new file mode 100644 index 0000000..794644d --- /dev/null +++ b/module/subu-0/trc/subudb-init.trc.c @@ -0,0 +1,27 @@ +#tranche subudb-init.cli.c +/* +This command initializes the db file. + +*/ +#include + +int main(){ + sqlite3 *db; + if( sqlite3_open(DB_File, &db) != SQLITE_OK ){ + fprintf(stderr, "error exit, could not open db file \"%s\"\n", DB_File); + return SUBU_ERR_DB_FILE; + } + db_begin(db); + if( subudb_schema(db) != SQLITE_OK ){ + db_rollback(db); + fprintf(stderr, "error exit, opened db file but could not build schema\n"); + return SUBU_ERR_DB_FILE; + } + db_commit(db); + if( sqlite3_close(db) != SQLITE_OK ){ + fprintf(stderr, "error exit, could not close the db\n"); + return SUBU_ERR_DB_FILE; + } + return 0; +} +#tranche-end diff --git a/module/subu-0/trc/subudb-number.cli.c b/module/subu-0/trc/subudb-number.cli.c deleted file mode 100644 index 60304e3..0000000 --- a/module/subu-0/trc/subudb-number.cli.c +++ /dev/null @@ -1,63 +0,0 @@ -/* -Set or get a new maximum subu number. Currently doesn't do the setting part. - -*/ -#include "subudb-number.cli.h" -#include -#include -#include - -int main(int argc, char **argv){ - - if( argc < 1 || argc > 2){ - fprintf(stderr, "usage: %s [n]\n",argv[0]); - return SUBU_ERR_ARG_CNT; - } - - int rc; - sqlite3 *db; - rc = sqlite3_open_v2(DB_File, &db, SQLITE_OPEN_READWRITE, NULL); - if( rc != SQLITE_OK ){ - fprintf(stderr, "error exit, could not open db file\n"); - sqlite3_close(db); - return SUBU_ERR_DB_FILE; - } - - // then arg[1] holds a number to set the max to - if(argc == 2){ - long int i = strtol(argv[1], NULL, 10); - if( i < 0 ){ - fprintf(stderr, "n must be positive\n"); - sqlite3_close(db); - return SUBU_ERR_N; - } - if( i > INT_MAX ){ - fprintf(stderr, "n is too big, max supported by this program is %d\n", INT_MAX); - sqlite3_close(db); - return SUBU_ERR_N; - } - rc = subudb_number_set(db, i); - if( rc != SQLITE_OK ){ - fprintf(stderr, "couldn't set Max_Subunumber: %s\n", sqlite3_errmsg(db)); - return SUBU_ERR_N; - } - } - - // read and print the current max - int n; - rc = subudb_number_get(db, &n); - if( rc == SQLITE_OK ){ - printf("%d\n", n); - }else{ - fprintf(stderr, "couldn't get Max_Subunumber: %s\n", sqlite3_errmsg(db)); - sqlite3_close(db); - return SUBU_ERR_DB_FILE; - } - rc = sqlite3_close(db); - if( rc != SQLITE_OK ){ - fprintf(stderr, "when closing db, %s\n", sqlite3_errmsg(db)); - return SUBU_ERR_DB_FILE; - } - return 0; - -} diff --git a/module/subu-0/trc/subudb-number.trc.c b/module/subu-0/trc/subudb-number.trc.c new file mode 100644 index 0000000..183aec0 --- /dev/null +++ b/module/subu-0/trc/subudb-number.trc.c @@ -0,0 +1,64 @@ +#tranche subudb-number.cli.c +/* +Set or get a new maximum subu number. Currently doesn't do the setting part. + +*/ +#include +#include +#include + +int main(int argc, char **argv){ + + if( argc < 1 || argc > 2){ + fprintf(stderr, "usage: %s [n]\n",argv[0]); + return SUBU_ERR_ARG_CNT; + } + + int rc; + sqlite3 *db; + rc = sqlite3_open_v2(DB_File, &db, SQLITE_OPEN_READWRITE, NULL); + if( rc != SQLITE_OK ){ + fprintf(stderr, "error exit, could not open db file\n"); + sqlite3_close(db); + return SUBU_ERR_DB_FILE; + } + + // then arg[1] holds a number to set the max to + if(argc == 2){ + long int i = strtol(argv[1], NULL, 10); + if( i < 0 ){ + fprintf(stderr, "n must be positive\n"); + sqlite3_close(db); + return SUBU_ERR_N; + } + if( i > INT_MAX ){ + fprintf(stderr, "n is too big, max supported by this program is %d\n", INT_MAX); + sqlite3_close(db); + return SUBU_ERR_N; + } + rc = subudb_number_set(db, i); + if( rc != SQLITE_OK ){ + fprintf(stderr, "couldn't set Max_Subunumber: %s\n", sqlite3_errmsg(db)); + return SUBU_ERR_N; + } + } + + // read and print the current max + int n; + rc = subudb_number_get(db, &n); + if( rc == SQLITE_OK ){ + printf("%d\n", n); + }else{ + fprintf(stderr, "couldn't get Max_Subunumber: %s\n", sqlite3_errmsg(db)); + sqlite3_close(db); + return SUBU_ERR_DB_FILE; + } + rc = sqlite3_close(db); + if( rc != SQLITE_OK ){ + fprintf(stderr, "when closing db, %s\n", sqlite3_errmsg(db)); + return SUBU_ERR_DB_FILE; + } + return 0; + +} +#tranche-end diff --git a/module/subu-0/trc/subudb-rel-get.cli.c b/module/subu-0/trc/subudb-rel-get.cli.c deleted file mode 100644 index 9828b15..0000000 --- a/module/subu-0/trc/subudb-rel-get.cli.c +++ /dev/null @@ -1,42 +0,0 @@ -/* -get the username from the db file -for testing subudb_Masteru_Subu_get_subu_username - -*/ -#include "subudb-rel-get.cli.h" -#include -#include - -int main(int argc, char **argv){ - - if(argc != 3){ - fprintf(stderr, "usage: %s masteru_name subuname\n", argv[0]); - return SUBU_ERR_ARG_CNT; - } - - int rc; - sqlite3 *db; - rc = sqlite3_open_v2(DB_File, &db, SQLITE_OPEN_READWRITE, NULL); - if( rc != SQLITE_OK ){ - fprintf(stderr, "could not open db file \"%s\"\n", DB_File); - return SUBU_ERR_DB_FILE; - } - - char *masteru_name = argv[1]; - char *subuname = argv[2]; - char *subu_username; - - int ret = subudb_Masteru_Subu_get_subu_username(db, masteru_name, subuname, &subu_username); - if( ret != SQLITE_DONE ){ - fprintf(stderr, "subudb_Masteru_Subu_get_subu_username indicates failure by returning %d\n",ret); - fprintf(stderr, "sqlite3 issues message, %s\n", sqlite3_errmsg(db)); - return SUBU_ERR_DB_FILE; - } - ret = sqlite3_close(db); - if( ret != SQLITE_OK ){ - fprintf(stderr, "sqlite3_close(db) indicates failure by returning %d\n",ret); - fprintf(stderr, "sqlite3 issues message: %s\n", sqlite3_errmsg(db)); - return SUBU_ERR_DB_FILE; - } - return 0; -} diff --git a/module/subu-0/trc/subudb-rel-get.trc.c b/module/subu-0/trc/subudb-rel-get.trc.c new file mode 100644 index 0000000..e64331a --- /dev/null +++ b/module/subu-0/trc/subudb-rel-get.trc.c @@ -0,0 +1,43 @@ +#tranche subudb-rel-get.cli.c +/* +get the username from the db file +for testing subudb_Masteru_Subu_get_subu_username + +*/ +#include +#include + +int main(int argc, char **argv){ + + if(argc != 3){ + fprintf(stderr, "usage: %s masteru_name subuname\n", argv[0]); + return SUBU_ERR_ARG_CNT; + } + + int rc; + sqlite3 *db; + rc = sqlite3_open_v2(DB_File, &db, SQLITE_OPEN_READWRITE, NULL); + if( rc != SQLITE_OK ){ + fprintf(stderr, "could not open db file \"%s\"\n", DB_File); + return SUBU_ERR_DB_FILE; + } + + char *masteru_name = argv[1]; + char *subuname = argv[2]; + char *subu_username; + + int ret = subudb_Masteru_Subu_get_subu_username(db, masteru_name, subuname, &subu_username); + if( ret != SQLITE_DONE ){ + fprintf(stderr, "subudb_Masteru_Subu_get_subu_username indicates failure by returning %d\n",ret); + fprintf(stderr, "sqlite3 issues message, %s\n", sqlite3_errmsg(db)); + return SUBU_ERR_DB_FILE; + } + ret = sqlite3_close(db); + if( ret != SQLITE_OK ){ + fprintf(stderr, "sqlite3_close(db) indicates failure by returning %d\n",ret); + fprintf(stderr, "sqlite3 issues message: %s\n", sqlite3_errmsg(db)); + return SUBU_ERR_DB_FILE; + } + return 0; +} +#tranche-end diff --git a/module/subu-0/trc/subudb-rel-put.cli.c b/module/subu-0/trc/subudb-rel-put.cli.c deleted file mode 100644 index b19896e..0000000 --- a/module/subu-0/trc/subudb-rel-put.cli.c +++ /dev/null @@ -1,40 +0,0 @@ -/* -puts a relation in the masteru/subu table - -*/ -#include "subudb-rel-put.cli.h" -#include -#include - -int main(int argc, char **argv){ - - if(argc != 4){ - fprintf(stderr, "expected: %s masteru_name subuname subu_username\n", argv[0]); - return 1; - } - char *masteru_name = argv[1]; - char *subuname = argv[2]; - char *subu_username = argv[3]; - - sqlite3 *db; - { - int ret = sqlite3_open_v2(DB_File, &db, SQLITE_OPEN_READWRITE, NULL); - if( ret != SQLITE_OK ){ - fprintf(stderr, "could not open db file \"%s\"\n", DB_File); - return SUBU_ERR_DB_FILE; - }} - - int ret = subudb_Masteru_Subu_put(db, masteru_name, subuname, subu_username); - if( ret != SQLITE_OK ){ - fprintf(stderr, "subudb_Masteru_Subu_put indicates failure by returning %d\n",ret); - fprintf(stderr, "sqlite3 issues message, %s\n", sqlite3_errmsg(db)); - return SUBU_ERR_DB_FILE; - } - ret = sqlite3_close(db); - if( ret != SQLITE_OK ){ - fprintf(stderr, "sqlite3_close(db) indicates failure by returning %d\n",ret); - fprintf(stderr, "sqlite3 issues message: %s\n", sqlite3_errmsg(db)); - return SUBU_ERR_DB_FILE; - } - return 0; -} diff --git a/module/subu-0/trc/subudb-rel-put.trc.c b/module/subu-0/trc/subudb-rel-put.trc.c new file mode 100644 index 0000000..5352700 --- /dev/null +++ b/module/subu-0/trc/subudb-rel-put.trc.c @@ -0,0 +1,41 @@ +#tranche subudb-rel-put.cli.c +/* +puts a relation in the masteru/subu table + +*/ +#include +#include + +int main(int argc, char **argv){ + + if(argc != 4){ + fprintf(stderr, "expected: %s masteru_name subuname subu_username\n", argv[0]); + return 1; + } + char *masteru_name = argv[1]; + char *subuname = argv[2]; + char *subu_username = argv[3]; + + sqlite3 *db; + { + int ret = sqlite3_open_v2(DB_File, &db, SQLITE_OPEN_READWRITE, NULL); + if( ret != SQLITE_OK ){ + fprintf(stderr, "could not open db file \"%s\"\n", DB_File); + return SUBU_ERR_DB_FILE; + }} + + int ret = subudb_Masteru_Subu_put(db, masteru_name, subuname, subu_username); + if( ret != SQLITE_OK ){ + fprintf(stderr, "subudb_Masteru_Subu_put indicates failure by returning %d\n",ret); + fprintf(stderr, "sqlite3 issues message, %s\n", sqlite3_errmsg(db)); + return SUBU_ERR_DB_FILE; + } + ret = sqlite3_close(db); + if( ret != SQLITE_OK ){ + fprintf(stderr, "sqlite3_close(db) indicates failure by returning %d\n",ret); + fprintf(stderr, "sqlite3 issues message: %s\n", sqlite3_errmsg(db)); + return SUBU_ERR_DB_FILE; + } + return 0; +} +#tranche-end diff --git a/module/subu-0/trc/subudb-rel-rm.cli.c b/module/subu-0/trc/subudb-rel-rm.cli.c deleted file mode 100644 index 3d15ca9..0000000 --- a/module/subu-0/trc/subudb-rel-rm.cli.c +++ /dev/null @@ -1,41 +0,0 @@ -/* -puts a relation in the masteru/subu table - -*/ -#include "subudb-rel-rm.cli.h" -#include -#include - -int main(int argc, char **argv){ - - if(argc != 4){ - fprintf(stderr, "expected: %s masteru_name subuname subu_username\n", argv[0]); - return 1; - } - char *masteru_name = argv[1]; - char *subuname = argv[2]; - char *subu_username = argv[3]; - - sqlite3 *db; - { - int ret = sqlite3_open_v2(DB_File, &db, SQLITE_OPEN_READWRITE, NULL); - if( ret != SQLITE_OK ){ - fprintf(stderr, "could not open db file \"%s\"\n", DB_File); - return SUBU_ERR_DB_FILE; - }} - - int ret = subudb_Masteru_Subu_rm(db, masteru_name, subuname, subu_username); - if( ret != SQLITE_DONE ){ - fprintf(stderr, "subudb_Masteru_Subu_rm indicates failure by returning %d\n",ret); - fprintf(stderr, "sqlite3 issues message, %s\n", sqlite3_errmsg(db)); - printf("put failed\n"); - return 2; - } - ret = sqlite3_close(db); - if( ret != SQLITE_OK ){ - fprintf(stderr, "sqlite3_close(db) indicates failure by returning %d\n",ret); - fprintf(stderr, "sqlite3 issues message: %s\n", sqlite3_errmsg(db)); - return SUBU_ERR_DB_FILE; - } - return 0; -} diff --git a/module/subu-0/trc/subudb-rel-rm.trc.c b/module/subu-0/trc/subudb-rel-rm.trc.c new file mode 100644 index 0000000..6008c70 --- /dev/null +++ b/module/subu-0/trc/subudb-rel-rm.trc.c @@ -0,0 +1,42 @@ +#tranche subudb-rel-rm.cli.c +/* +puts a relation in the masteru/subu table + +*/ +#include +#include + +int main(int argc, char **argv){ + + if(argc != 4){ + fprintf(stderr, "expected: %s masteru_name subuname subu_username\n", argv[0]); + return 1; + } + char *masteru_name = argv[1]; + char *subuname = argv[2]; + char *subu_username = argv[3]; + + sqlite3 *db; + { + int ret = sqlite3_open_v2(DB_File, &db, SQLITE_OPEN_READWRITE, NULL); + if( ret != SQLITE_OK ){ + fprintf(stderr, "could not open db file \"%s\"\n", DB_File); + return SUBU_ERR_DB_FILE; + }} + + int ret = subudb_Masteru_Subu_rm(db, masteru_name, subuname, subu_username); + if( ret != SQLITE_DONE ){ + fprintf(stderr, "subudb_Masteru_Subu_rm indicates failure by returning %d\n",ret); + fprintf(stderr, "sqlite3 issues message, %s\n", sqlite3_errmsg(db)); + printf("put failed\n"); + return 2; + } + ret = sqlite3_close(db); + if( ret != SQLITE_OK ){ + fprintf(stderr, "sqlite3_close(db) indicates failure by returning %d\n",ret); + fprintf(stderr, "sqlite3 issues message: %s\n", sqlite3_errmsg(db)); + return SUBU_ERR_DB_FILE; + } + return 0; +} +#tranche-end diff --git a/module/subu-0/trc/subudb-subus.cli.c b/module/subu-0/trc/subudb-subus.cli.c deleted file mode 100644 index be3af20..0000000 --- a/module/subu-0/trc/subudb-subus.cli.c +++ /dev/null @@ -1,47 +0,0 @@ -/* -Set or get a new maximum subu number. Currently doesn't do the setting part. - -*/ -#include "subudb-subus.cli.h" -#include -#include -#include - -int main(int argc, char **argv){ - - if( argc != 2){ - fprintf(stderr, "usage: %s masteru_name\n",argv[0]); - return SUBU_ERR_ARG_CNT; - } - char *masteru_name = argv[1]; - - int rc; - sqlite3 *db; - rc = sqlite3_open_v2(DB_File, &db, SQLITE_OPEN_READWRITE, NULL); - if( rc != SQLITE_OK ){ - fprintf(stderr, "error exit, could not open db file\n"); - sqlite3_close(db); - return SUBU_ERR_DB_FILE; - } - - subudb_subu_element *sa; - subudb_subu_element *sa_end; - rc = subudb_Masteru_Subu_get_subus(db, masteru_name, &sa, &sa_end); - if( rc == SQLITE_OK ){ - subudb_subu_element *pt = sa; - while( pt != sa_end ){ - printf("%s %s\n", pt->subuname, pt->subu_username); - pt++; - } - rc = sqlite3_close(db); - if( rc != SQLITE_OK ){ - fprintf(stderr, "when closing db, %s\n", sqlite3_errmsg(db)); - return SUBU_ERR_DB_FILE; - } - return 0; - } - fprintf(stderr, "lookup failed %s\n", sqlite3_errmsg(db)); - sqlite3_close(db); - return SUBU_ERR_DB_FILE; - -} diff --git a/module/subu-0/trc/subudb-subus.trc.c b/module/subu-0/trc/subudb-subus.trc.c new file mode 100644 index 0000000..4871967 --- /dev/null +++ b/module/subu-0/trc/subudb-subus.trc.c @@ -0,0 +1,48 @@ +#tranche subudb-subus.cli.c +/* +Set or get a new maximum subu number. Currently doesn't do the setting part. + +*/ +#include +#include +#include + +int main(int argc, char **argv){ + + if( argc != 2){ + fprintf(stderr, "usage: %s masteru_name\n",argv[0]); + return SUBU_ERR_ARG_CNT; + } + char *masteru_name = argv[1]; + + int rc; + sqlite3 *db; + rc = sqlite3_open_v2(DB_File, &db, SQLITE_OPEN_READWRITE, NULL); + if( rc != SQLITE_OK ){ + fprintf(stderr, "error exit, could not open db file\n"); + sqlite3_close(db); + return SUBU_ERR_DB_FILE; + } + + subudb_subu_element *sa; + subudb_subu_element *sa_end; + rc = subudb_Masteru_Subu_get_subus(db, masteru_name, &sa, &sa_end); + if( rc == SQLITE_OK ){ + subudb_subu_element *pt = sa; + while( pt != sa_end ){ + printf("%s %s\n", pt->subuname, pt->subu_username); + pt++; + } + rc = sqlite3_close(db); + if( rc != SQLITE_OK ){ + fprintf(stderr, "when closing db, %s\n", sqlite3_errmsg(db)); + return SUBU_ERR_DB_FILE; + } + return 0; + } + fprintf(stderr, "lookup failed %s\n", sqlite3_errmsg(db)); + sqlite3_close(db); + return SUBU_ERR_DB_FILE; + +} +#tranche-end diff --git a/module/subu-0/trc/subudb.trc.c b/module/subu-0/trc/subudb.trc.c new file mode 100644 index 0000000..27d5639 --- /dev/null +++ b/module/subu-0/trc/subudb.trc.c @@ -0,0 +1,201 @@ +#tranche subudb.lib.c +#tranche subudb.lib.h + /* + The db file is maintained in SQLite + + Because linux user names are limited length, subu user names are of a compact + form: _s. A separate table translates the numbers into the subu names. + + Each of these returns SQLITE_OK upon success + */ + #include +#tranche-end + +#include +#include "common.lib.h" +#include "subudb.lib.h" +#include +#include +#include +#include + +//-------------------------------------------------------------------------------- +// sqlite transactions don't nest. There is a way to use save points, but still +// we can't just nest transactions. Instead use these wrappers around the whole +// of something that needs to be in a transaction. +#tranche subudb.lib.h + int db_begin(sqlite3 *db); + int db_commit(sqlite3 *db); + int db_rollback(sqlite3 *db); +#tranche-end +int db_begin(sqlite3 *db){ + return sqlite3_exec(db, "BEGIN TRANSACTION;", NULL, NULL, NULL); +} +int db_commit(sqlite3 *db){ + return sqlite3_exec(db, "COMMIT;", NULL, NULL, NULL); +} +int db_rollback(sqlite3 *db){ + return sqlite3_exec(db, "ROLLBACK;", NULL, NULL, NULL); +} + +//-------------------------------------------------------------------------------- +#tranche subudb.lib.h + int subudb_schema(sqlite3 *db); +#tranche-end +int subudb_schema(sqlite3 *db){ + int rc; + + { // build tables + char sql[] = + "CREATE TABLE Masteru_Subu(masteru_name TEXT, subuname TEXT, subu_username TEXT);" + "CREATE TABLE Attribute_Int(attribute TEXT, value INT);" + ; + rc = sqlite3_exec(db, sql, NULL, NULL, NULL); + if(rc != SQLITE_OK) return rc; + } + + { // data initialization + char *sql = "INSERT INTO Attribute_Int (attribute, value) VALUES ('Max_Subunumber', ?1);"; + sqlite3_stmt *stmt; + sqlite3_prepare_v2(db, sql, -1, &stmt, NULL); + sqlite3_bind_int(stmt, 1, First_Max_Subunumber); + rc = sqlite3_step(stmt); + sqlite3_finalize(stmt); + if( rc != SQLITE_DONE ) return rc; + } + + return SQLITE_OK; +} + +//-------------------------------------------------------------------------------- +#tranche subudb.lib.h + int subudb_number_get(sqlite3 *db, int *n); +#tranche-end +int subudb_number_get(sqlite3 *db, int *n){ + char *sql = "SELECT value FROM Attribute_Int WHERE attribute = 'Max_Subunumber';"; + sqlite3_stmt *stmt; + sqlite3_prepare_v2(db, sql, -1, &stmt, NULL); + int rc = sqlite3_step(stmt); + if( rc == SQLITE_ROW ){ + *n = sqlite3_column_int(stmt,0); + rc = sqlite3_step(stmt); + sqlite3_finalize(stmt); + if( rc != SQLITE_DONE ) return rc; + return SQLITE_OK; + } + // should have a message return, suppose + sqlite3_finalize(stmt); + return SQLITE_NOTFOUND; +} + +#tranche subudb.lib.h + int subudb_number_set(sqlite3 *db, int n); +#tranche-end +int subudb_number_set(sqlite3 *db, int n){ + int rc; + char *sql = "UPDATE Attribute_Int SET value = ?1 WHERE attribute = 'Max_Subunumber';"; + sqlite3_stmt *stmt; + sqlite3_prepare_v2(db, sql, -1, &stmt, NULL); + sqlite3_bind_int(stmt, 1, n); + rc = sqlite3_step(stmt); + sqlite3_finalize(stmt); + if( rc == SQLITE_DONE ) return SQLITE_OK; + return rc; +} + +//-------------------------------------------------------------------------------- +// put relation into Masteru_Subu table +#tranche subudb.lib.h + int subudb_Masteru_Subu_put(sqlite3 *db, char *masteru_name, char *subuname, char *subu_username); +#tranche-end +int subudb_Masteru_Subu_put(sqlite3 *db, char *masteru_name, char *subuname, char *subu_username){ + char *sql = "INSERT INTO Masteru_Subu VALUES (?1, ?2, ?3);"; + sqlite3_stmt *stmt; + sqlite3_prepare_v2(db, sql, -1, &stmt, NULL); + sqlite3_bind_text(stmt, 1, masteru_name, -1, SQLITE_STATIC); + sqlite3_bind_text(stmt, 2, subuname, -1, SQLITE_STATIC); + sqlite3_bind_text(stmt, 3, subu_username, -1, SQLITE_STATIC); + int rc = sqlite3_step(stmt); + sqlite3_finalize(stmt); + if( rc == SQLITE_DONE ) return SQLITE_OK; + return rc; +} + +//-------------------------------------------------------------------------------- +#tranche subudb.lib.h + int subudb_Masteru_Subu_get_subu_username(sqlite3 *db, char *masteru_name, char *subuname, char **subu_username); +#tranche-end +int subudb_Masteru_Subu_get_subu_username(sqlite3 *db, char *masteru_name, char *subuname, char **subu_username){ + char *sql = "SELECT subu_username FROM Masteru_Subu WHERE masteru_name = ?1 AND subuname = ?2;"; + size_t sql_len = strlen(sql); + sqlite3_stmt *stmt; + int rc; + rc = sqlite3_prepare_v2(db, sql, sql_len, &stmt, NULL); + if( rc != SQLITE_OK ) return rc; + sqlite3_bind_text(stmt, 1, masteru_name, strlen(masteru_name), SQLITE_STATIC); + sqlite3_bind_text(stmt, 2, subuname, strlen(subuname), SQLITE_STATIC); + rc = sqlite3_step(stmt); + if( rc == SQLITE_ROW ){ + const char *username = sqlite3_column_text(stmt, 0); + *subu_username = strdup(username); + }else{ + sqlite3_finalize(stmt); + return rc; // woops this needs to return an error!, be sure it is not SQLITE_DONE + } + rc = sqlite3_step(stmt); + if( rc == SQLITE_DONE ) return SQLITE_OK; + return rc; +} + +//-------------------------------------------------------------------------------- +#tranche subudb.lib.h + typedef struct{ + char *subuname; // the name that masteru chose for his or her subu + char *subu_username; // the adduser name we gave it, typically of the s + } subudb_subu_element; + int subudb_Masteru_Subu_get_subus(sqlite3 *db, char *masteru_name, Da *subus); +#tranche-end +//returns an array of subudb_subu_elements that correspond to the masteru_name +int subudb_Masteru_Subu_get_subus(sqlite3 *db, char *masteru_name, Da *subusp){ + char *sql = "SELECT subuname, subu_username" + " FROM Masteru_Subu" + " WHERE masteru_name = ?1;"; + size_t sql_len = strlen(sql); + sqlite3_stmt *stmt; + int rc; + rc = sqlite3_prepare_v2(db, sql, sql_len, &stmt, NULL); + if( rc != SQLITE_OK ) return rc; + sqlite3_bind_text(stmt, 1, masteru_name, strlen(masteru_name), SQLITE_STATIC); + + subudb_subu_element *pt; + rc = sqlite3_step(stmt); + while( rc == SQLITE_ROW ){ + pt = (subudb_subu_element *)da_push_alloc(subusp); + pt->subuname = strdup(sqlite3_column_text(stmt, 0)); + pt->subu_username = strdup(sqlite3_column_text(stmt, 1)); + rc = sqlite3_step(stmt); + } + sqlite3_finalize(stmt); + if( rc != SQLITE_DONE ) return rc; + return SQLITE_OK; +} + +//-------------------------------------------------------------------------------- +#tranche subudb.lib.h + int subudb_Masteru_Subu_rm(sqlite3 *db, char *masteru_name, char *subuname, char *subu_username); +#tranche-end +int subudb_Masteru_Subu_rm(sqlite3 *db, char *masteru_name, char *subuname, char *subu_username){ + char *sql = "DELETE FROM Masteru_Subu WHERE masteru_name = ?1 AND subuname = ?2 AND subu_username = ?3;"; + size_t sql_len = strlen(sql); + sqlite3_stmt *stmt; + int rc; + rc = sqlite3_prepare_v2(db, sql, sql_len, &stmt, NULL); + if( rc != SQLITE_OK ) return rc; + sqlite3_bind_text(stmt, 1, masteru_name, -1, SQLITE_STATIC); + sqlite3_bind_text(stmt, 2, subuname, -1, SQLITE_STATIC); + sqlite3_bind_text(stmt, 3, subu_username, -1, SQLITE_STATIC); + rc = sqlite3_step(stmt); + sqlite3_finalize(stmt); + if( rc == SQLITE_DONE ) return SQLITE_OK; + return rc; +} diff --git a/module/subu-0/try/makefile b/module/subu-0/try/makefile new file mode 100644 index 0000000..400ec02 --- /dev/null +++ b/module/subu-0/try/makefile @@ -0,0 +1,11 @@ + + +a b c: + echo $@ + +x y z: + echo $@ + +e f g: x y z + echo $^ + diff --git a/module/tranche/exec/tranche b/module/tranche/exec/tranche new file mode 100755 index 0000000..886b915 Binary files /dev/null and b/module/tranche/exec/tranche differ diff --git a/module/tranche/exec/tranche-make b/module/tranche/exec/tranche-make new file mode 100755 index 0000000..d2f5d91 Binary files /dev/null and b/module/tranche/exec/tranche-make differ diff --git a/module/tranche/exec/tranche-target b/module/tranche/exec/tranche-target new file mode 100755 index 0000000..8ef74f3 Binary files /dev/null and b/module/tranche/exec/tranche-target differ diff --git a/module/tranche/include/tranche.h b/module/tranche/include/tranche.h new file mode 100644 index 0000000..575c97f --- /dev/null +++ b/module/tranche/include/tranche.h @@ -0,0 +1,16 @@ +#ifndef TRANCHE_LIB_H +#define TRANCHE_LIB_H + +#define TRANCHE_ERR_ARG_PARSE 1 +#define TRANCHE_ERR_SRC_OPEN 2 +#define TRANCHE_ERR_DST_OPEN 4 +#define TRANCHE_ERR_FCLOSE 8 +#define TRANCHE_ERR_HELP 16 +#define TRANCHE_ERR_SNAME 32 + +void path_trim_slashes(char *path); +int tranche_send(FILE *src, Da *arg_fds, char *tdir); +int tranche_target(FILE *src, Da *targets, char *tdir); +void tranche_make(FILE *src_file, char *src_name, int mfile_fd, char *tdir); + +#endif diff --git a/module/tranche/lib/libtranche.a b/module/tranche/lib/libtranche.a new file mode 100644 index 0000000..407c21b Binary files /dev/null and b/module/tranche/lib/libtranche.a differ diff --git a/module/tranche/makefile b/module/tranche/makefile index 2c21909..e80a0d9 100644 --- a/module/tranche/makefile +++ b/module/tranche/makefile @@ -16,8 +16,8 @@ dep: .PHONY: lib lib: - $(MAKE) $@ cp $(SRCDIR)/tranche.lib.h include/tranche.h + $(MAKE) $@ .PHONY: exec exec: diff --git a/module/tranche/makefile-flags b/module/tranche/makefile-flags index 076600d..46febb1 100644 --- a/module/tranche/makefile-flags +++ b/module/tranche/makefile-flags @@ -5,7 +5,7 @@ DOCDIR=doc EXECDIR=exec INCDIR=include LIBDIR=lib -SHAREDIR=../share +SHAREDIR=$(realpath $(PROJECT_SUBU)/module/share) SRCDIR=src TESTDIR= TMPDIR=tmp @@ -21,7 +21,6 @@ ECHO= echo #ECHO= echo -e C=gcc -CFLAGS=-std=gnu11 -fPIC -I. -I../share/include -ggdb -Werror -DDEBUG -DDEBUGDB -#CFLAGS=-std=gnu11 -fPIC -I. -I../share/include -Werror -LINKFLAGS=-Llib -L../share/lib/ -lda -ltranche +CFLAGS=-std=gnu11 -fPIC -I$(SRCDIR) -I$(INCDIR) -I$(SHAREDIR)/include -ggdb -Werror -DDEBUG -DDEBUGDB +LINKFLAGS=-L$(LIBDIR) -L$(SHAREDIR)/lib/ -l$(MODULE) -lda diff --git a/module/tranche/src/tranche.lib.c b/module/tranche/src/tranche.lib.c index 65e66c1..9c154ce 100644 --- a/module/tranche/src/tranche.lib.c +++ b/module/tranche/src/tranche.lib.c @@ -179,48 +179,60 @@ void path_trim_slashes(char *path){ // write a make file rule for making the tranche targets void tranche_make(FILE *src_file, char *src_name, int mfile_fd, char *tdir){ - // target list - Da ta; - Da *tap=&ta; // target array pointer - da_alloc(tap, sizeof(char *)); - tranche_target(src_file, tap, tdir); + // array of the target file names ----------------------------------------- + Da target_arr; + Da *target_arrp=&target_arr; // target array pointer + da_alloc(target_arrp, sizeof(char *)); + tranche_target(src_file, target_arrp, tdir); + + // a space separated list of the target file names + Da target_arr_as_string; + Da *taasp = &target_arr_as_string; + da_alloc(taasp, sizeof(char)); + char *pt = target_arrp->base; // char * because it points to a byte in the array + if( pt < target_arrp->end ){ + da_string_push(taasp, *(char **)pt); + pt += target_arrp->element_size; + } + while( pt < target_arrp->end ){ + da_push(taasp, &sp); + da_string_push(taasp, *(char **)pt); + pt += target_arrp->element_size; + } + da_free_elements(target_arrp); + da_free(target_arrp); // construct then output the dependency line ---------------------------------------- - Da dla; - Da *dlap=&dla; // dependency line array pointer - da_alloc(dlap, sizeof(char)); - char *pt = tap->base; // char * because it points to a byte in the array - while( pt < tap->end ){ - da_string_push(dlap, *(char **)pt); - da_push(dlap, &sp); - pt += tap->element_size; - } - da_push(dlap, &colon); - da_push(dlap, &sp); - da_string_push(dlap, src_name); - da_push(dlap, &newline); - write(mfile_fd, dlap->base, dlap->end - dlap->base); - da_free_elements(tap); - da_free(tap); + Da make_line_string; + Da *mlsp = &make_line_string; + da_alloc(mlsp, sizeof(char)); + da_cat(mlsp, taasp); + da_push(mlsp, &colon); + da_push(mlsp, &sp); + da_string_push(mlsp, src_name); + da_push(mlsp, &newline); + write(mfile_fd, mlsp->base, mlsp->end - mlsp->base); // output action lines ---------------------------------------- - da_rewind(dlap); // reuse the line buffer - da_push(dlap, &tab); - da_string_push(dlap, "for i in $@; do rm $$i || true; done"); - da_push(dlap, &newline); - write(mfile_fd, dlap->base, dlap->end - dlap->base); - - da_rewind(dlap); // reuse the line buffer - da_push(dlap, &tab); - da_string_push(dlap, "tranche $<"); + da_rewind(mlsp); // reuse make line buffer + da_push(mlsp, &tab); + da_string_push(mlsp, "rm -f "); + da_cat(mlsp, taasp); + da_push(mlsp, &newline); + write(mfile_fd, mlsp->base, mlsp->end - mlsp->base); + + da_rewind(mlsp); // reuse the line buffer + da_push(mlsp, &tab); + da_string_push(mlsp, "tranche $<"); if(tdir){ - da_string_push(dlap, " -tdir "); - da_string_push(dlap, tdir); + da_string_push(mlsp, " -tdir "); + da_string_push(mlsp, tdir); } - da_push(dlap, &newline); - da_push(dlap, &newline); - write(mfile_fd, dlap->base, dlap->end - dlap->base); + da_push(mlsp, &newline); + da_push(mlsp, &newline); + write(mfile_fd, mlsp->base, mlsp->end - mlsp->base); - da_free(dlap); + da_free(taasp); + da_free(mlsp); return; } diff --git a/module/tranche/test/try/test4.out.expected b/module/tranche/test/try/test4.out.expected index e69de29..c7ff184 100644 --- a/module/tranche/test/try/test4.out.expected +++ b/module/tranche/test/try/test4.out.expected @@ -0,0 +1,2 @@ +test2.c +test2.h \ No newline at end of file diff --git a/tool/bin/tranche b/tool/bin/tranche index 31fdc5d..886b915 100755 Binary files a/tool/bin/tranche and b/tool/bin/tranche differ diff --git a/tool/bin/tranche-make b/tool/bin/tranche-make index ae00d98..d2f5d91 100755 Binary files a/tool/bin/tranche-make and b/tool/bin/tranche-make differ diff --git a/tool/bin/tranche-target b/tool/bin/tranche-target index 4415c1a..8ef74f3 100755 Binary files a/tool/bin/tranche-target and b/tool/bin/tranche-target differ diff --git a/tool/lib/makefile-cc b/tool/lib/makefile-cc index 4d548e9..71f1a05 100755 --- a/tool/lib/makefile-cc +++ b/tool/lib/makefile-cc @@ -36,7 +36,7 @@ DOCDIR=doc EXECDIR=exec INCDIR=include LIBDIR=lib -SHAREDIR=../share +SHAREDIR=$(realpath $(PROJECT_SUBU)/module/share) SRCDIR=src TESTDIR=test TMPDIR=tmp @@ -47,7 +47,6 @@ DEPFILE=$(TMPDIR)/makefile-cc.deps LIBFILE=$(LIBDIR)/lib$(MODULE).a INCFILE=$(INCDIR)/$(MODULE).h - # a single space literal, for example if you wanted to subsitute commas to # spaces: $(subst $(space),;,$(string)) blank := @@ -61,7 +60,8 @@ CC= # local customization # user must define things needed by the local makefile, the compiler, and flags --include makefile-flags +include makefile-flags +-include $(DEPFILE) #-------------------------------------------------------------------------------- # targets @@ -183,11 +183,10 @@ dist-clean: clean rm $(LIBFILE) || true # recipes --include $(DEPFILE) - -$(TMPDIR)/%.o : $(SRCDIR)/%.c + $(TMPDIR)/%.o : $(SRCDIR)/%.c $(C) $(CFLAGS) -o $@ -c $< -$(TMPDIR)/%.o : $(SRCDIR)/%.cc + $(TMPDIR)/%.o : $(SRCDIR)/%.cc $(CC) $(CCFLAGS) -o $@ -c $< +