new structure in prep for using tranche
authorThomas Walker Lynch <thomas.lynch@reasoningtechnology.com>
Thu, 28 Mar 2019 01:11:15 +0000 (02:11 +0100)
committerThomas Walker Lynch <thomas.lynch@reasoningtechnology.com>
Thu, 28 Mar 2019 01:11:15 +0000 (02:11 +0100)
180 files changed:
da/makefile [new file with mode: 0644]
da/makefile-flags [new file with mode: 0644]
da/src/da.lib.c [new file with mode: 0644]
da/src/da.lib.h [new file with mode: 0644]
da/test/makefile [new file with mode: 0644]
da/test/makefile-dep [new file with mode: 0644]
da/test/makefile-flags [new file with mode: 0644]
da/test/results [new file with mode: 0644]
da/test/test.dat [new file with mode: 0644]
da/test/test_da.cli.c [new file with mode: 0644]
da/test/test_da.cli.o [new file with mode: 0644]
da/test/test_da.lib.c [new file with mode: 0644]
da/test/test_da.lib.h [new file with mode: 0644]
da/test/test_da.lib.o [new file with mode: 0644]
db/0_makefile [new file with mode: 0644]
db/0_makefile-flags [new file with mode: 0644]
db/1_doc/return-from-transaction.txt [new file with mode: 0644]
db/dbprintf.lib.c [new file with mode: 0644]
dispatch/makefile [new file with mode: 0644]
dispatch/makefile-flags [new file with mode: 0644]
dispatch/src/dispatch.lib.c [new file with mode: 0644]
doc/dir-structure.txt
makefile
src-0/0_makefile [deleted file]
src-0/0_makefile-flags [deleted file]
src-0/1_deprecated/dispatch_exec.lib.c [deleted file]
src-0/1_deprecated/dispatch_f.lib.c [deleted file]
src-0/1_deprecated/dispatch_useradd.lib.c [deleted file]
src-0/1_deprecated/subu-rm-0.lib.c [deleted file]
src-0/1_deprecated/subudb-number-next.cli.c [deleted file]
src-0/1_doc/to_do.txt [deleted file]
src-0/1_tests/0_makefile [deleted file]
src-0/1_tests/0_makefile_flags [deleted file]
src-0/1_tests/1_tmp/makefile_deps [deleted file]
src-0/1_tests/da.cli.c [deleted file]
src-0/1_tests/libtests.a [deleted file]
src-0/1_tmp/da.lib.h [deleted file]
src-0/1_tmp/dbprintf.lib.h [deleted file]
src-0/1_tmp/dispatch.lib.h [deleted file]
src-0/1_tmp/subu-bind-all.cli.h [deleted file]
src-0/1_tmp/subu-bind.cli.h [deleted file]
src-0/1_tmp/subu-common.lib.h [deleted file]
src-0/1_tmp/subu-mk-0.cli.h [deleted file]
src-0/1_tmp/subu-rm-0.cli.h [deleted file]
src-0/1_tmp/subu.lib.h [deleted file]
src-0/1_tmp/subudb-init.cli.h [deleted file]
src-0/1_tmp/subudb-number.cli.h [deleted file]
src-0/1_tmp/subudb-rel-get.cli.h [deleted file]
src-0/1_tmp/subudb-rel-put.cli.h [deleted file]
src-0/1_tmp/subudb-rel-rm.cli.h [deleted file]
src-0/1_tmp/subudb-subus.cli.h [deleted file]
src-0/1_tmp/subudb.lib.h [deleted file]
src-0/1_try/split.c [deleted file]
src-0/1_try/split_arg.c [deleted file]
src-0/1_try/subudb [deleted file]
src-0/1_try/voidptr.c [deleted file]
src-0/common.lib.c [deleted file]
src-0/db.lib.c [deleted file]
src-0/subu-bind-all.cli.c [deleted file]
src-0/subu-bind.cli.c [deleted file]
src-0/subu-mk-0.cli.c [deleted file]
src-0/subu-rm-0.cli.c [deleted file]
src-0/subu.lib.c [deleted file]
src-0/subudb-init.cli.c [deleted file]
src-0/subudb-number.cli.c [deleted file]
src-0/subudb-rel-get.cli.c [deleted file]
src-0/subudb-rel-put.cli.c [deleted file]
src-0/subudb-rel-rm.cli.c [deleted file]
src-0/subudb-subus.cli.c [deleted file]
src-da/0_makefile [deleted file]
src-da/0_makefile-flags [deleted file]
src-da/1_include/da.h [deleted file]
src-da/1_tests/0_makefile [deleted file]
src-da/1_tests/0_makefile-flags [deleted file]
src-da/1_tests/results [deleted file]
src-da/1_tests/test.dat [deleted file]
src-da/1_tests/test_da.cli.c [deleted file]
src-da/1_tests/test_da.lib.c [deleted file]
src-da/1_tests/test_da.lib.h [deleted file]
src-da/da.lib.c [deleted file]
src-da/da.lib.h [deleted file]
src-db/0_makefile [deleted file]
src-db/0_makefile-flags [deleted file]
src-db/1_doc/return-from-transaction.txt [deleted file]
src-db/dbprintf.lib.c [deleted file]
src-dispatch/0_makefile [deleted file]
src-dispatch/0_makefile-flags [deleted file]
src-dispatch/dispatch.src.c [deleted file]
src-py/subu-mk.py [deleted file]
src-tranche/0_makefile [deleted file]
src-tranche/0_makefile-flags [deleted file]
src-tranche/1_deprecated/0_makefile [deleted file]
src-tranche/1_deprecated/0_makefile-flags [deleted file]
src-tranche/1_doc/todo.txt [deleted file]
src-tranche/1_include/tranche.h [deleted file]
src-tranche/1_tests/0_makefile [deleted file]
src-tranche/1_tests/0_makefile-flags [deleted file]
src-tranche/1_tests/test1.dat [deleted file]
src-tranche/1_tests/test1.sh [deleted file]
src-tranche/1_tests/test11.dat.expected [deleted file]
src-tranche/1_tests/test12.dat.expected [deleted file]
src-tranche/1_tests/test13.dat.expected [deleted file]
src-tranche/1_tests/test14.dat.expected [deleted file]
src-tranche/1_tests/test15.dat.expected [deleted file]
src-tranche/1_tests/test1stdout.dat.expected [deleted file]
src-tranche/1_tests/tranche [deleted symlink]
src-tranche/tranche.cli.c [deleted file]
src-tranche/tranche.lib.c [deleted file]
src-tranche/tranche.lib.h [deleted file]
subu-0/0_makefile [new file with mode: 0644]
subu-0/0_makefile-flags [new file with mode: 0644]
subu-0/1_deprecated/dispatch_exec.lib.c [new file with mode: 0644]
subu-0/1_deprecated/dispatch_f.lib.c [new file with mode: 0644]
subu-0/1_deprecated/dispatch_useradd.lib.c [new file with mode: 0644]
subu-0/1_deprecated/subu-rm-0.lib.c [new file with mode: 0644]
subu-0/1_deprecated/subudb-number-next.cli.c [new file with mode: 0644]
subu-0/1_doc/to_do.txt [new file with mode: 0644]
subu-0/1_tests/0_makefile [new file with mode: 0644]
subu-0/1_tests/0_makefile_flags [new file with mode: 0644]
subu-0/1_tests/1_tmp/makefile_deps [new file with mode: 0644]
subu-0/1_tests/da.cli.c [new file with mode: 0644]
subu-0/1_tests/libtests.a [new file with mode: 0644]
subu-0/1_tmp/da.lib.h [new file with mode: 0644]
subu-0/1_tmp/dbprintf.lib.h [new file with mode: 0644]
subu-0/1_tmp/dispatch.lib.h [new file with mode: 0644]
subu-0/1_tmp/subu-bind-all.cli.h [new file with mode: 0644]
subu-0/1_tmp/subu-bind.cli.h [new file with mode: 0644]
subu-0/1_tmp/subu-common.lib.h [new file with mode: 0644]
subu-0/1_tmp/subu-mk-0.cli.h [new file with mode: 0644]
subu-0/1_tmp/subu-rm-0.cli.h [new file with mode: 0644]
subu-0/1_tmp/subu.lib.h [new file with mode: 0644]
subu-0/1_tmp/subudb-init.cli.h [new file with mode: 0644]
subu-0/1_tmp/subudb-number.cli.h [new file with mode: 0644]
subu-0/1_tmp/subudb-rel-get.cli.h [new file with mode: 0644]
subu-0/1_tmp/subudb-rel-put.cli.h [new file with mode: 0644]
subu-0/1_tmp/subudb-rel-rm.cli.h [new file with mode: 0644]
subu-0/1_tmp/subudb-subus.cli.h [new file with mode: 0644]
subu-0/1_tmp/subudb.lib.h [new file with mode: 0644]
subu-0/1_try/split.c [new file with mode: 0644]
subu-0/1_try/split_arg.c [new file with mode: 0644]
subu-0/1_try/subudb [new file with mode: 0644]
subu-0/1_try/voidptr.c [new file with mode: 0644]
subu-0/common.lib.c [new file with mode: 0644]
subu-0/db.lib.c [new file with mode: 0644]
subu-0/subu-bind-all.cli.c [new file with mode: 0644]
subu-0/subu-bind.cli.c [new file with mode: 0644]
subu-0/subu-mk-0.cli.c [new file with mode: 0644]
subu-0/subu-rm-0.cli.c [new file with mode: 0644]
subu-0/subu.lib.c [new file with mode: 0644]
subu-0/subudb-init.cli.c [new file with mode: 0644]
subu-0/subudb-number.cli.c [new file with mode: 0644]
subu-0/subudb-rel-get.cli.c [new file with mode: 0644]
subu-0/subudb-rel-put.cli.c [new file with mode: 0644]
subu-0/subudb-rel-rm.cli.c [new file with mode: 0644]
subu-0/subudb-subus.cli.c [new file with mode: 0644]
subu-1/subu-mk.py [new file with mode: 0644]
tools/bin/make [deleted file]
tools/bin/tranche [new file with mode: 0755]
tools/lib/makefile_cc
tools/lib/makefile_trc [new file with mode: 0644]
tranche/deprecated/0_makefile [new file with mode: 0644]
tranche/deprecated/0_makefile-flags [new file with mode: 0644]
tranche/doc/todo.txt [new file with mode: 0644]
tranche/makefile [new file with mode: 0644]
tranche/makefile-flags [new file with mode: 0644]
tranche/src/tranche.cli.c [new file with mode: 0644]
tranche/src/tranche.lib.c [new file with mode: 0644]
tranche/src/tranche.lib.h [new file with mode: 0644]
tranche/test/test1.dat [new file with mode: 0644]
tranche/test/test1.sh [new file with mode: 0644]
tranche/test/test11.dat.expected [new file with mode: 0644]
tranche/test/test12.dat.expected [new file with mode: 0644]
tranche/test/test13.dat.expected [new file with mode: 0644]
tranche/test/test14.dat.expected [new file with mode: 0644]
tranche/test/test15.dat.expected [new file with mode: 0644]
tranche/test/test1stdout.dat.expected [new file with mode: 0644]
tranche/test/test2.c.expected [new file with mode: 0644]
tranche/test/test2.h.expected [new file with mode: 0644]
tranche/test/test2.trc.c [new file with mode: 0644]
tranche/test/tranche [new symlink]

diff --git a/da/makefile b/da/makefile
new file mode 100644 (file)
index 0000000..67fbdb9
--- /dev/null
@@ -0,0 +1,21 @@
+# da/makefile
+
+SHELL=/bin/bash
+MAKE=
+
+-include makefile-flags
+
+.PHONY: all
+all: version dep lib exec
+
+.PHONY: lib
+lib:
+       $(MAKE) $@
+       cp src/da.lib.h include/da.h
+
+%::
+       $(MAKE) $@
+
+
+
+
diff --git a/da/makefile-flags b/da/makefile-flags
new file mode 100644 (file)
index 0000000..d732652
--- /dev/null
@@ -0,0 +1,35 @@
+
+MODULE=da
+
+# some versions of Linux need a -e option others complain if there is a -e .. and it isn't the binary for echo ..
+ECHO= echo
+#ECHO= echo -e
+
+# directories used by this makefile, these could all be set to dot for
+# the simplest source directory structure
+
+#LIDBIR, EXECDIR, INCDIR hold the make results that might later be staged
+#$(PWD) is the directory that make was called from, this is already build in
+#set to dot to use the same directory as the source code
+#leave blank to ommit
+DEPRDIR=deprecated
+DOCDIR=doc
+EXECDIR=exec
+INCDIR=include
+LIBDIR=lib
+SRCDIR=src
+TESTDIR=test
+TMPDIR=tmp
+TOOLSDIR=$(realpath $(PROJECT_SUBU)/tools)
+TRYDIR=try
+
+# compiler and flags
+C=gcc
+CFLAGS=-std=gnu11 -fPIC -I. -ggdb -Werror -DDEBUG -DDEBUGDB 
+#CFLAGS=-std=gnu11 -fPIC -I. -Werror
+LINKFLAGS=-Llib -lda 
+
+MAKE=/usr/bin/make --no-print-directory -f $(PROJECT_SUBU)/tools/lib/makefile_cc
+#MAKE=/usr/bin/make -f $(PROJECT_SUBU)/tools/lib/makefile_cc
+
+
diff --git a/da/src/da.lib.c b/da/src/da.lib.c
new file mode 100644 (file)
index 0000000..0956d7e
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+Dynamic Array
+
+*/
+
+#include "da.lib.h"
+
+#include<stdlib.h>
+#include<stdbool.h>
+#include<string.h>
+
+//--------------------------------------------------------------------------------
+// generic
+// We manipulate pointers to a smallest addressable unit. The sizeof operator
+// returns counts in these addressable units. Sizeof(char) is defined to be 1.
+
+void da_alloc(Da *dap, size_t element_size){
+  dap->element_size = element_size;
+  dap->size = 4 * element_size;
+  dap->base = malloc(dap->size);
+  dap->end = dap->base;
+}
+void da_free(Da *dap){
+  free(dap->base);
+  dap->size = 0;
+}
+void da_rewind(Da *dap){
+  dap->end = dap->base;
+}
+
+bool da_empty(Da *dap){
+  return dap->end == dap->base;
+}
+
+void da_rebase(Da *dap, char *old_base, void *pta){
+  char **pt = (char **)pta;
+  size_t offset = *pt - old_base;
+  *pt = dap->base + offset;
+}
+
+// Doubles size of of da.  Returns old base, so that existing pointers into the
+// array can be moved to the new array
+char *da_expand(Da *dap){
+  char *old_base = dap->base;
+  size_t end_offset = dap->end - old_base;
+  size_t new_size = dap->size << 1;
+  char *new_base = malloc( new_size );
+  memcpy( new_base, old_base, end_offset + dap->element_size);
+  free(old_base);
+  dap->base = new_base;
+  dap->end = new_base + end_offset;
+  dap->size = new_size;
+  return old_base;
+}
+
+// true when pt has run off the end of the area currently allocated for the array
+bool da_endq(Da *dap, void *pt){
+  return (char *)pt >= dap->end;
+}
+
+// true when pt has run off the end of the area allocated for the array
+bool da_boundq(Da *dap){
+  return dap->end >= dap->base + dap->size;
+}
+
+void da_push(Da *dap, void *element){
+  if( dap->end >= dap->base + dap->size ) da_expand(dap);
+  memcpy(dap->end, element, dap->element_size);
+  dap->end += dap->element_size;
+}
+
+bool da_pop(Da *dap, void *element){
+  bool flag = dap->end >= dap->base + dap->element_size;
+  if( flag ){
+    dap->end -= dap->element_size;
+    if(element) memcpy(element, dap->end, dap->element_size);
+  }
+  return flag;
+}
+
+char *da_index(Da *dap, size_t i){
+  size_t offset = i * dap->element_size;
+  char *pt = dap->base + offset;
+  return pt;
+}
+
+// passed in f(element_pt, arg_pt)
+// We have no language support closures, so we pass in an argument for it.
+// The closure may be set to NULL if it is not needed.
+void da_map(Da *dap, void f(void *, void *), void *closure){
+  char *pt = dap->base;
+  while( pt != dap->end ){
+    f(pt, closure);
+  pt += dap->element_size;
+  }
+}
+
+// da_lists are sometimes used as resource managers
+static void da_free_element(void *pt, void *closure){
+  free(*(char **)pt); // free does not care about the pointer type
+}
+
+void da_free_elements(Da *dap){
+  da_map(dap, da_free_element, NULL);
+  da_rewind(dap);
+}
+
+// for the case of an array of strings
+void da_strings_puts(Da *dap){
+  char *pt = dap->base;
+  while( pt != dap->end ){
+    puts(*(char **)pt);
+  pt += dap->element_size;
+  }
+}
+
+
+// Puts text from a line into buffer *dap. Does not push EOF or '\n' into the
+// buffer.  Returns the old_base so that external pointers can be rebased.
+// It is possible that the the base hasn't changed. Use feof(FILE *stream) to
+// test for EOF;
+char *da_fgets(Da *dap, FILE *file){
+  char *old_base = dap->base;
+  int c = fgetc(file);
+  while( c != EOF && c != '\n' ){
+    da_push(dap, &c);
+  c = fgetc(file);
+  }
+  int terminator = 0;
+  da_push(dap, &terminator);
+  return old_base;
+}
diff --git a/da/src/da.lib.h b/da/src/da.lib.h
new file mode 100644 (file)
index 0000000..6d3c43b
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef DA_LIB_H
+#define DA_LIB_H
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdio.h>
+
+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_map(dap, da_free, NULL); return r; }
+
+void da_alloc(Da *dap, size_t element_size);
+void da_free(Da *dap);
+void da_rewind(Da *dap);
+char *da_expand(Da *dap);
+void da_rebase(Da *dap, char *old_base, void *pta);
+bool da_endq(Da *dap, void *pt);
+bool da_boundq(Da *dap);
+void da_push(Da *dap, void *element);
+bool da_pop(Da *dap, void *element);
+char *da_index(Da *dap, size_t i);
+void da_map(Da *dap, void f(void *, void *), void *closure);
+void da_free_elements(Da *dap);
+void da_strings_puts(Da *dap);
+char *da_fgets(Da *dap, FILE *fd);
+
+#endif
+
diff --git a/da/test/makefile b/da/test/makefile
new file mode 100644 (file)
index 0000000..dbd6be0
--- /dev/null
@@ -0,0 +1,15 @@
+# da/test
+
+SHELL=/bin/bash
+
+-include makefile-flags
+
+.PHONY: all
+all: version deps lib exec
+
+%::
+       $(MAKE) $@
+
+
+
+
diff --git a/da/test/makefile-dep b/da/test/makefile-dep
new file mode 100644 (file)
index 0000000..cf61fb9
--- /dev/null
@@ -0,0 +1,5 @@
+./test_da.lib.o: test_da.lib.c ../include/da.h test_da.lib.h
+./test_da.cli.o: test_da.cli.c test_da.lib.h
+
+./test_da : ./test_da.cli.o ./libtest.a
+       gcc -o ./test_da ./test_da.cli.o -L. -L../lib -ltest -lda
diff --git a/da/test/makefile-flags b/da/test/makefile-flags
new file mode 100644 (file)
index 0000000..d916748
--- /dev/null
@@ -0,0 +1,33 @@
+
+MODULE=test
+
+# some versions of Linux need a -e option others complain if there is a -e .. and it isn't the binary for echo ..
+ECHO= echo
+#ECHO= echo -e
+
+# directories used by this makefile, these could all be set to dot for
+# the simplest source directory structure
+
+#LIDBIR, EXECSDIR, HDIR hold the make results that might later be staged
+#$(PWD) is the directory that make was called from, this is already build in
+#set to dot to use the same directory as the source code
+#leave blank to ommit
+DEPRDIR=
+DOCDIR=
+EXECDIR=.
+INCDIR=.
+LIBDIR=.
+SRCDIR=.
+TESTDIR=
+TMPDIR=.
+TOOLSDIR=$(realpath $(PROJECT_SUBU)/tools)
+TRYDIR=
+
+# compiler and flags
+C=gcc
+CFLAGS=-std=gnu11 -fPIC -I../include -ggdb -Werror -DDEBUG -DDEBUGDB 
+#CFLAGS=-std=gnu11 -fPIC -I../include -Werror
+LINKFLAGS=-L. -L../lib -ltest -lda
+
+MAKE=/usr/bin/make --no-print-directory -f $(PROJECT_SUBU)/tools/lib/makefile_cc
+#MAKE=/usr/bin/make -f $(PROJECT_SUBU)/tools/lib/makefile_cc
diff --git a/da/test/results b/da/test/results
new file mode 100644 (file)
index 0000000..9e59b33
--- /dev/null
@@ -0,0 +1 @@
+passed all 4 tests
diff --git a/da/test/test.dat b/da/test/test.dat
new file mode 100644 (file)
index 0000000..6b4b5bd
--- /dev/null
@@ -0,0 +1,3 @@
+this is a test
+ends without a newline
+(setq mode-require-final-newline nil)
\ No newline at end of file
diff --git a/da/test/test_da.cli.c b/da/test/test_da.cli.c
new file mode 100644 (file)
index 0000000..bee5a6c
--- /dev/null
@@ -0,0 +1,46 @@
+
+#include <stdio.h>
+#include <stdbool.h>
+#include "test_da.lib.h"
+
+int main(){
+  bool da_0_passed = test_da_0();
+
+  unsigned int passed = 0;
+  unsigned int failed = 0;
+
+  // enumeration of tests
+  typedef bool (*test_fun)();
+  test_fun tests[] = {test_da_0, test_da_1, test_da_2, test_da_3, NULL};
+  char *test_names[] = {"test_da_0", "test_da_1", "test_da_2", "test_da_3", NULL};
+
+  // call tests
+  test_fun *tfp = tests;
+  char **tnp = test_names;
+  while(*tfp){
+    if( !(*tfp)() ){
+      failed++;
+      if(*tnp)
+        printf("%s failed\n", *tnp);
+      else
+        fprintf(stderr, "internal error, no test_names[] entry for test\n");
+    }else
+      passed++;
+  tfp++;
+  tnp++;
+  }
+
+  // summarize results
+
+  if( passed == 0 && failed == 0)
+    printf("no tests ran\n");
+  else if( passed == 0 )
+    printf("failed all %u tests\n", failed);
+  else if( failed == 0 )
+    printf("passed all %u tests\n", passed);
+  else
+    printf("failed %u of %u tests\n", failed, passed + failed);
+
+  if( passed == 0 || failed != 0 ) return 1;
+  return 0;
+}
diff --git a/da/test/test_da.cli.o b/da/test/test_da.cli.o
new file mode 100644 (file)
index 0000000..d28221c
Binary files /dev/null and b/da/test/test_da.cli.o differ
diff --git a/da/test/test_da.lib.c b/da/test/test_da.lib.c
new file mode 100644 (file)
index 0000000..88a94c7
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+Tests for Da.
+
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+#include <da.h>
+
+#include "test_da.lib.h"
+
+// tests push
+bool test_da_0(){
+  Da da;
+  da_alloc(&da, sizeof(int)); // leaves room for 4 ints
+  int i = 0;
+  int *pt = (int *)da.base;
+  // will double, 4 -> 8, then double 8 -> 16
+  while( i < 10 ){
+    da_push(&da, &i);
+  i++;
+  pt++;
+  }
+
+  bool f0 = da.size == sizeof(int) * 16;
+  bool f1 = 10 == (da.end - da.base) / sizeof(int);
+  bool f2 = true;
+  pt = (int *)da.base;
+  i = 0;
+  while( i < 10 ){
+    f2 = f2 && *pt == i && !da_endq(&da, pt);
+  i++;
+  pt++;
+  }
+  bool f3 = da_endq(&da, pt);
+
+  return f0 && f1 && f2 && f3;
+}
+
+// tests manual expansion
+bool test_da_1(){
+  Da da;
+  da_alloc(&da, sizeof(int)); // leaves room for 4 ints
+  int i = 0;
+  int *pt = (int *)da.base;
+  // will double, 4 -> 8, then double 8 -> 16
+  while( i < 10 ){
+    da.end += da.element_size;
+    if( da_boundq(&da) ){
+      char *old_base = da_expand(&da);
+      da_rebase(&da, old_base, &pt);
+    }
+    *pt = i;
+  i++;
+  pt++;
+  }
+
+  bool f0 = da.size == sizeof(int) * 16;
+  bool f1 = 10 == (da.end - da.base) / sizeof(int);
+  bool f2 = true;
+  pt = (int *)da.base;
+  i = 0;
+  while( i < 10 ){
+    f2 = f2 && *pt == i && !da_endq(&da, pt);
+  i++;
+  pt++;
+  }
+  bool f3 = da_endq(&da, pt);
+
+  return f0 && f1 && f2 && f3;
+}
+
+// da_fgets
+bool test_da_2(){
+
+  FILE *fd = fopen("test.dat","r");
+
+  Da da;
+  da_alloc(&da, sizeof(char));
+
+  da_fgets(&da, fd);
+  bool f0 = !strcmp(da.base, "this is a test");
+
+  char *old_base;
+  da_pop(&da, NULL); // pop the prior null terminator
+  char *s1 = da.end;
+  old_base = da_fgets(&da,fd);
+  da_rebase(&da, old_base, &s1);
+  bool f1 = !strcmp(s1, "ends without a newline");
+  
+  da_pop(&da, NULL); // pop the prior null terminator
+  char *s2 = da.end;
+  old_base = da_fgets(&da,fd);
+  da_rebase(&da, old_base, &s2);
+  bool f2 = !strcmp(s2, "(setq mode-require-final-newline nil)");
+
+  bool f3 = !strcmp(da.base, "this is a testends without a newline(setq mode-require-final-newline nil)");
+
+  fclose(fd);
+  return f0 && f1 && f2 && f3;
+}
+
+// da_fgets
+bool test_da_3(){
+
+  FILE *fd = fopen("test.dat","r");
+
+  Da da;
+  da_alloc(&da, sizeof(int));
+
+  int i = 5;
+  da_push(&da, &i);
+  i++;
+  da_push(&da, &i);
+  i++;
+  da_push(&da, &i);
+
+  int j;
+  bool f0 = da_pop(&da, &j) && j == 7;
+  bool f1 = da_pop(&da, &j) && j == 6;
+  bool f2 = da_pop(&da, NULL);
+  bool f3 = !da_pop(&da, &j);
+
+  return f0 && f1 && f2 && f3;
+}
+
+
+
+
diff --git a/da/test/test_da.lib.h b/da/test/test_da.lib.h
new file mode 100644 (file)
index 0000000..686b0d0
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef DA_LIB_H
+#define DA_LIB_H
+
+bool test_da_0();
+bool test_da_1();
+bool test_da_2();
+bool test_da_3();
+
+#endif
diff --git a/da/test/test_da.lib.o b/da/test/test_da.lib.o
new file mode 100644 (file)
index 0000000..2a03683
Binary files /dev/null and b/da/test/test_da.lib.o differ
diff --git a/db/0_makefile b/db/0_makefile
new file mode 100644 (file)
index 0000000..b8c7b9d
--- /dev/null
@@ -0,0 +1,40 @@
+# src/0_makefile
+
+SHELL=/bin/bash
+
+-include 0_makefile_flags
+
+SUID_TOOL=$(TOOLSDIR)/bin/setuid_root.sh
+MAKE=/usr/bin/make -f $(PROJECT_SUBU)/tools/lib/makefile_cc
+
+SOURCES=$(wildcard *.c)
+HFILES=$(wildcard *.h)
+
+all: version deps lib execs
+
+version:
+       $(MAKE) $@
+       @echo "SUID_TOOL: " $(SUID_TOOL)
+
+deps:
+       makeheaders $(SOURCES) $(HFILES)
+       sed -i '/^ *int *main *(.*)/d' *.h
+       $(MAKE) $@
+
+execs:
+       $(MAKE) $@
+       @echo "-> $(SUID_TOOL) $(EXECSDIR)/subu-mk-0 $(EXECSDIR)/subu-rm-0 $(EXECSDIR)/subu-bind-all"
+       cat $(SUID_TOOL)
+       @echo -n "Are you sure? [y/N] " && read ans && [ $${ans:-N} == y ]
+       sudo $(SUID_TOOL) $(EXECSDIR)/subu-mk-0 $(EXECSDIR)/subu-rm-0 $(EXECSDIR)/subu-bind-all
+
+clean:
+       $(MAKE) $@
+       for i in $(HFILES); do rm $$i; done
+
+%::
+       $(MAKE) $@
+
+
+
+
diff --git a/db/0_makefile-flags b/db/0_makefile-flags
new file mode 100644 (file)
index 0000000..0da8b61
--- /dev/null
@@ -0,0 +1,31 @@
+
+# some versions of Linux need a -e option others complain if there is a -e .. and it isn't the binary for echo ..
+ECHO= echo
+#ECHO= echo -e
+
+# directories used by this makefile, these could all be set to dot for
+# the simplest source directory structure
+
+#LIDBIR, EXECSDIR, HDIR hold the make results that might later be staged
+#$(PWD) is the directory that make was called from, this is already build in
+#set to dot to use the same directory as the source code
+#leave blank to ommit
+DEPRDIR=1_deprecated
+DOCDIR=1_doc
+EXECSDIR=1_execs
+HDIR=1_headers
+LIBDIR=1_lib
+TESTDIR=1_tests
+TMPDIR=1_tmp
+TOOLSDIR=$(realpath $(PROJECT_SUBU)/tools)
+TRYDIR=1_try
+
+
+# compiler and flags
+CC=gcc
+CFLAGS=-std=gnu11 -fPIC -I. -ggdb -Werror -DDEBUG -DDEBUGDB 
+#CFLAGS=-std=gnu11 -fPIC -I. -Werror
+LINKFLAGS=-L1_lib -lsubu -lsqlite3
+
+LIBFILE=$(LIBDIR)/libsubu.a
+
diff --git a/db/1_doc/return-from-transaction.txt b/db/1_doc/return-from-transaction.txt
new file mode 100644 (file)
index 0000000..b7f8cbb
--- /dev/null
@@ -0,0 +1,15 @@
+
+1.
+  This sql:
+
+    char *sql = 
+      "BEGIN TRANSACTION;"
+      "UPDATE Key_Int SET value = value + 1 WHERE key = 'max_subu_number';"
+      "SELECT value FROM Key_Int WHERE key = 'max_subu_number';"
+      "COMMIT;"
+      ;
+
+  with sqlite_exec, the call back is called with the data from the select.
+
+  with sqlite_prepare_v2, sqlite_step just returns SQLITE_DONE, and we never
+  get to see our data from the select.
diff --git a/db/dbprintf.lib.c b/db/dbprintf.lib.c
new file mode 100644 (file)
index 0000000..d9d236b
--- /dev/null
@@ -0,0 +1,14 @@
+
+#include "dbprintf.lib.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+
+int dbprintf(const char *format, ...){
+  va_list args;
+  va_start(args,format);  
+  int ret = vfprintf(stdout, format, args);
+  fflush(stdout);
+  va_end(args);
+  return ret;
+}
diff --git a/dispatch/makefile b/dispatch/makefile
new file mode 100644 (file)
index 0000000..175b683
--- /dev/null
@@ -0,0 +1,14 @@
+# src-dispatch/makefile
+
+SHELL=/bin/bash
+
+-include makefile-flags
+
+all: version dep lib
+
+%::
+       $(MAKE) $@
+
+
+
+
diff --git a/dispatch/makefile-flags b/dispatch/makefile-flags
new file mode 100644 (file)
index 0000000..48cadc2
--- /dev/null
@@ -0,0 +1,20 @@
+
+# some versions of Linux need a -e option others complain if there is a -e .. and it isn't the binary for echo ..
+ECHO= echo
+#ECHO= echo -e
+
+# directories used by this makefile, these could all be set to dot for
+# the simplest source directory structure
+
+# compiler and flags
+C=gcc
+CFLAGS=-std=gnu11 -fPIC -I. -ggdb -Werror -DDEBUG -DDEBUGDB 
+#CFLAGS=-std=gnu11 -fPIC -I. -Werror
+
+LINKFLAGS=-L1_lib -lda 
+
+MODULE=dispatch
+
+MAKE=/usr/bin/make --no-print-directory -f $(PROJECT_SUBU)/tools/lib/makefile_trc
+#MAKE=/usr/bin/make -f $(PROJECT_SUBU)/tools/lib/makefile_trc
+
diff --git a/dispatch/src/dispatch.lib.c b/dispatch/src/dispatch.lib.c
new file mode 100644 (file)
index 0000000..e34d020
--- /dev/null
@@ -0,0 +1,166 @@
+#tranche tmp/dispatch.trc.c
+
+#tranche include/dispatch.h
+/*
+  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 <sys/types.h>
+#include <unistd.h>
+
+#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
+};
+#tranche-end
+
+#include "dispatch.h"
+
+// we need the declaration for uid_t etc.
+// without this #define execvpe is undefined
+#define _GNU_SOURCE   
+
+#include <wait.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+#tranche include/dispatch.h
+void dispatch_f_mess(char *fname, int err, char *dispatchee);
+#tranche-end
+void dispatch_f_mess(char *fname, int err, char *dispatchee){
+  if(err == 0) return;
+  fprintf(stderr, "%s: ", fname); // if fprintf gets an error, errno will be overwritten
+  if(err > ERR_DISPATCH){
+    fprintf(stderr, "dispatchee \"%s\" returned the error %d\n", dispatchee, err);
+    return;
+  }
+  switch(err){
+  case ERR_DISPATCH_NEGATIVE_RETURN_STATUS:
+    fprintf(stderr, " dispatchee \"%s\" returned a negative status.", dispatchee);
+    break;
+  case ERR_DISPATCH_F_FORK:
+  case ERR_DISPATCH_F_SETEUID:
+  case ERR_DISPATCH_F_SETEGID:
+    fputc(' ', stderr);
+    perror(dispatchee);
+    break;
+  case ERR_DISPATCH_NULL_EXECUTABLE:
+    fprintf(stderr, " executable was not specified");
+    break;
+  case ERR_DISPATCH_EXEC:
+    // exec is running in another process when it fails, so we can't see the errno value it set
+    fprintf(stderr, " exec of \"%s\" failed", dispatchee);
+    break;
+  default:
+    fprintf(stderr, " returned undefined status when dispatching \"%s\"", dispatchee);
+  }
+  fputc('\n', stderr);
+}
+
+//--------------------------------------------------------------------------------
+// interface call point, dispatch a function
+#tranche include/dispatch.h
+int dispatch_f(char *fname, int (*f)(void *arg), void *f_arg);
+#tranche-end
+int dispatch_f(char *fname, int (*f)(void *arg), void *f_arg){
+  #ifdef DEBUG
+  dbprintf("%s %s\n", "dispatch_f", fname);
+  #endif
+  pid_t pid = fork();
+  if( pid == -1 ) return ERR_DISPATCH_F_FORK; // something went wrong and we are still in the parent process
+  if( pid == 0 ){ // we are the child
+    int status = (*f)(f_arg); // we require that f return a zero or positive value
+    if( status < ERR_DISPATCH ) status = ERR_DISPATCH_NEGATIVE_RETURN_STATUS;
+    exit(status);
+  }else{ // we are the parent
+    int err;
+    waitpid(pid, &err, 0);
+    return err;
+  }
+}
+
+//--------------------------------------------------------------------------------
+// interface call point, dispatch a function with a given euid/egid
+// of course this will only work if our euid is root in the first place
+#tranche include/dispatch.h
+int dispatch_f_euid_egid(char *fname, int (*f)(void *arg), void *f_arg, uid_t euid, gid_t egid);
+#tranche-end
+int dispatch_f_euid_egid(char *fname, int (*f)(void *arg), void *f_arg, uid_t euid, gid_t egid){
+  #ifdef DEBUG
+  dbprintf("%s %s as euid:%u egid:%u\n", "dispatch_f_euid_egid", fname, euid, egid);
+  #endif
+  pid_t pid = fork();
+  if( pid == -1 ) return ERR_DISPATCH_F_FORK;
+  if( pid == 0 ){ // we are the child
+    int status;
+    if( seteuid(euid) == -1 )
+      status = ERR_DISPATCH_F_SETEUID;
+    else if( setegid(egid) == -1 )
+      status = ERR_DISPATCH_F_SETEGID;
+    else{
+      status = (*f)(f_arg);
+      if( status <= ERR_DISPATCH ) status = ERR_DISPATCH_NEGATIVE_RETURN_STATUS;
+      exit(status);
+    }
+  }else{ // we are the parent
+    uint err;
+    waitpid(pid, &err, 0);
+    return err;
+  }
+}
+
+//--------------------------------------------------------------------------------
+// interface call point, dispatch a executable
+#tranche include/dispatch.h
+int dispatch_exec(char **argv, char **envp);
+#tranche-end
+int dispatch_exec(char **argv, char **envp){
+  char *command;
+  {
+    if( !argv || !argv[0] ) return ERR_DISPATCH_NULL_EXECUTABLE;
+    #ifdef DEBUG
+      dbprintf("dispatch_exec:");
+      char **apt = argv;
+      while( *apt ){
+        dbprintf(" %s",*apt);
+        apt++;
+      }
+      dbprintf("\n");
+    #endif
+    command = argv[0];
+  }
+  pid_t pid = fork();
+  if( pid == -1 ) return ERR_DISPATCH_F_FORK; // something went wrong and we are still in the parent process
+  if( pid == 0 ){ // we are the child
+    execvpe(command, argv, envp); // exec will only return if it has an error
+    #ifdef DEBUG
+    dbprintf("dispatch_exec: exec returned, perror message:");
+    perror("dispatch_exec"); // our only chance to print this message, as this is the child process
+    #endif
+    fflush(stdout);
+    exit(ERR_DISPATCH_EXEC); 
+  }else{ // we are the parent
+    int err;
+    waitpid(pid, &err, 0);
+    return err;
+  }
+}
+
+#tranche-end
index 668b909..b385074 100644 (file)
@@ -1,6 +1,9 @@
 
 ~ is the project directory
 
+--------------------------------------------------------------------------------
+most subdirectories are source modules
+
 
 --------------------------------------------------------------------------------
 ~/tools
@@ -27,29 +30,7 @@ Typically the install target copies material in the staging area to
 system locations.
 
 --------------------------------------------------------------------------------
-~/src
-
-The prefixed numbered directories are overhead for building the src code.
-
-src/1_tests  these are programs that typically must pass before the compiled
-code may be staged.  Tests typically make use of the library in 2_lib and
-the header files in 2_include.
-
-src/1_try a free area for the programmer to try things out. For example when
-learning a language. Programs and code left in this directory might be interesting
-to newcomers.
-
-src/2_bin these are cli executables that have been created by the makefile
-and will be staged after testing
-
-src/2_include  interface header files to be released with the lib. These might
-be different from the build header files found in the src dir.
-
-src/2_lib holds libraries being tested. Currently each src directory only
-builds one library.
-
-3_documents  these are for developers working on src. A user manual might
-be under development.
+~/<module>
 
 
 
index c8d9a4e..ddad312 100755 (executable)
--- a/makefile
+++ b/makefile
@@ -1,13 +1,15 @@
-SRCDIRS= $(wildcard src-*)
-MAKEABLE=$(shell \
-    find src-*\
-       -mindepth 1  \
-       \( -name '?_makefile' -o -name 'makefile' -o -name 'Makefile' \)\
-       -printf "%h\n"\
-    | grep -v deprecated | grep -v doc | sort -u | sed ':a;N;$!ba;s/\n/ /g' \
-)
-
-all :
+#MAKEABLE=$(shell \
+#    find .\
+#      \( -name 'makefile' -o -name 'Makefile' \)\
+#      -printf "%h\n"\
+#    | grep -v deprecated | grep -v doc | sort -u | sed ':a;N;$!ba;s/\n/ /g' \
+#)
+
+MAKEABLE= da da/test tranche
+
+.PHONY: all info clean dist-clean
+
+all:
        $(foreach dir, $(MAKEABLE), \
          make -C $$dir
          -make -C $$dir stage
@@ -17,10 +19,11 @@ info:
        @echo "SRCDIRS:" $(SRCDIRS)
        @echo "MAKEABLE:" $(MAKEABLE)
 
-clean :
+clean:
        for dir in $(MAKEABLE); do pushd $$dir; make clean; popd; done
 
-dist-clean : clean
+dist-clean : 
+       for dir in $(MAKEABLE); do pushd $$dir; make dist-clean; popd; done
        for i in $(wildcard stage/lib/*); do rm $$i; done
        for i in $(wildcard stage/inc/*); do rm $$i; done
        for i in $(wildcard stage/bin/*); do rm $$i; done
diff --git a/src-0/0_makefile b/src-0/0_makefile
deleted file mode 100644 (file)
index b8c7b9d..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-# src/0_makefile
-
-SHELL=/bin/bash
-
--include 0_makefile_flags
-
-SUID_TOOL=$(TOOLSDIR)/bin/setuid_root.sh
-MAKE=/usr/bin/make -f $(PROJECT_SUBU)/tools/lib/makefile_cc
-
-SOURCES=$(wildcard *.c)
-HFILES=$(wildcard *.h)
-
-all: version deps lib execs
-
-version:
-       $(MAKE) $@
-       @echo "SUID_TOOL: " $(SUID_TOOL)
-
-deps:
-       makeheaders $(SOURCES) $(HFILES)
-       sed -i '/^ *int *main *(.*)/d' *.h
-       $(MAKE) $@
-
-execs:
-       $(MAKE) $@
-       @echo "-> $(SUID_TOOL) $(EXECSDIR)/subu-mk-0 $(EXECSDIR)/subu-rm-0 $(EXECSDIR)/subu-bind-all"
-       cat $(SUID_TOOL)
-       @echo -n "Are you sure? [y/N] " && read ans && [ $${ans:-N} == y ]
-       sudo $(SUID_TOOL) $(EXECSDIR)/subu-mk-0 $(EXECSDIR)/subu-rm-0 $(EXECSDIR)/subu-bind-all
-
-clean:
-       $(MAKE) $@
-       for i in $(HFILES); do rm $$i; done
-
-%::
-       $(MAKE) $@
-
-
-
-
diff --git a/src-0/0_makefile-flags b/src-0/0_makefile-flags
deleted file mode 100644 (file)
index 0da8b61..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-
-# some versions of Linux need a -e option others complain if there is a -e .. and it isn't the binary for echo ..
-ECHO= echo
-#ECHO= echo -e
-
-# directories used by this makefile, these could all be set to dot for
-# the simplest source directory structure
-
-#LIDBIR, EXECSDIR, HDIR hold the make results that might later be staged
-#$(PWD) is the directory that make was called from, this is already build in
-#set to dot to use the same directory as the source code
-#leave blank to ommit
-DEPRDIR=1_deprecated
-DOCDIR=1_doc
-EXECSDIR=1_execs
-HDIR=1_headers
-LIBDIR=1_lib
-TESTDIR=1_tests
-TMPDIR=1_tmp
-TOOLSDIR=$(realpath $(PROJECT_SUBU)/tools)
-TRYDIR=1_try
-
-
-# compiler and flags
-CC=gcc
-CFLAGS=-std=gnu11 -fPIC -I. -ggdb -Werror -DDEBUG -DDEBUGDB 
-#CFLAGS=-std=gnu11 -fPIC -I. -Werror
-LINKFLAGS=-L1_lib -lsubu -lsqlite3
-
-LIBFILE=$(LIBDIR)/libsubu.a
-
diff --git a/src-0/1_deprecated/dispatch_exec.lib.c b/src-0/1_deprecated/dispatch_exec.lib.c
deleted file mode 100644 (file)
index 024bff8..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- fork/execs/wait the command passed in argv[0];
- Returns -1 upon failure.
-
- The wstatus returned from wait() might be either the error returned by exec
- when it failed, or the return value from the command.  An arbitary command is
- passed in, so we don't know what its return values might be. Consquently, we
- have no way of multiplexing a unique exec error code with the command return
- value within wstatus.  If the prorgrammer knows the return values of the
- command passed in, and wants better behavior, he or she can spin a special
- version of dispatch for that command.
-*/
-#include "dispatch_exec.lib.h"
-
-// without this #define execvpe is undefined
-#define _GNU_SOURCE   
-
-#include <sys/types.h>
-#include <unistd.h>
-#include <wait.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-
-
-
-int dispatch_exec(char **argv, char **envp){
-  if( !argv || !argv[0] ){
-    fprintf(stderr, "argv[0] null. Null command passed into dispatch().\n");
-    return -1;
-  }
-  #ifdef DEBUG
-    dbprintf("dispatching exec, args follow:\n");
-    char **apt = argv;
-    while( *apt ){
-      dbprintf("\t%s",*apt);
-    apt++;
-    }
-    dbprintf("\n");
-  #endif
-  char *command = argv[0];
-  pid_t pid = fork();
-  if( pid == -1 ){
-    fprintf(stderr, "fork() failed in dispatch().\n");
-    return -1;
-  }
-  if( pid == 0 ){ // we are the child
-    execvpe(command, argv, envp);
-    // exec will only return if it has an error ..
-    perror(command);
-    return -1;
-  }else{ // we are the parent
-    int wstatus;
-    waitpid(pid, &wstatus, 0);
-    if(wstatus)
-      return -1;
-    else
-      return 0;
-  }
-}
diff --git a/src-0/1_deprecated/dispatch_f.lib.c b/src-0/1_deprecated/dispatch_f.lib.c
deleted file mode 100644 (file)
index 5c199f5..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
-  Forks a new process and runs the a function in that new process.  I.e. it 'spawns' a function.
-
-  f must have the specified prototype. I.e. it accepts one void pointer and
-  returns a positive integer. (Negative integers are used for dispatch error codes.)
-
-  dispatch_f_euid_egid changes to the new euid and egid before running the function.
-
-  If the change to in euid/egid fails, the forked process exits with a negative status.
-  If the function has an error, it returns a positive status.  A status of zero means
-  that all went well.
-
-  Because f is running in a separate process, the return status is the only means
-  of communication going back to the calling process.
-
-
-*/
-#define _GNU_SOURCE
-
-#include "dispatch_f.lib.h"
-// we need the declaration for uid_t etc.
-// without this #define execvpe is undefined
-#define _GNU_SOURCE   
-
-#include <wait.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-
-#if INTERFACE
-#include <sys/types.h>
-#include <unistd.h>
-#endif
-
-//--------------------------------------------------------------------------------
-// dispatch_f_ctx class
-//
-#if INTERFACE
-#define ERR_NEGATIVE_RETURN_STATUS -1
-#define ERR_DISPATCH_F_FORK -2
-#define ERR_DISPATCH_F_SETEUID -3
-#define ERR_DISPATCH_F_SETEGID -4
-
-// both name and fname are static allocations
-struct dispatch_f_ctx{
-  char *dispatcher; // name of the dispatch function (currently "dispatch_f" or "dispatch_f_euid_egid")
-  char *dispatchee; // name of the function being dispatched
-  int err;
-  int status; // return value from the function
-};
-#endif
-dispatch_f_ctx *dispatch_f_ctx_mk(char *name, char *fname){
-  dispatch_f_ctx *ctxp = malloc(sizeof(dispatch_f_ctx));
-  ctxp->dispatcher = name;
-  ctxp->dispatchee = fname;
-  ctxp->err = 0;
-  return ctxp;
-}
-void dispatch_f_ctx_free(dispatch_f_ctx *ctxp){
-   // no dynamic variables to be freed in ctx
-  free(ctxp); 
-}
-void dispatch_f_mess(struct dispatch_f_ctx *ctxp){
-  if(ctxp->err == 0) return;
-  switch(ctxp->err){
-  case ERR_NEGATIVE_RETURN_STATUS:
-    fprintf(stderr, "%s, function \"%s\" broke contract with a negative return value.", ctxp->dispatcher, ctxp->dispatchee);
-    break;
-  case ERR_DISPATCH_F_FORK:
-  case ERR_DISPATCH_F_SETEUID:
-  case ERR_DISPATCH_F_SETEGID:
-    fprintf(stderr, "%s, ", ctxp->dispatcher);
-    perror(ctxp->dispatcher);
-    break;
-  }
-  fputc('\n', stderr);
-}
-
-//--------------------------------------------------------------------------------
-// interface call point
-dispatch_f_ctx *dispatch_f(char *fname, int (*f)(void *arg), void *f_arg){
-  dispatch_f_ctx *ctxp = dispatch_f_ctx_mk("dispatch_f", fname);
-  #ifdef DEBUG
-  dbprintf("%s %s\n", ctxp->dispatcher, ctxp->dispatchee);
-  #endif
-  pid_t pid = fork();
-  if( pid == -1 ){
-    ctxp->err = ERR_DISPATCH_F_FORK; // we are still in the parent process
-    return ctxp;
-  }
-  if( pid == 0 ){ // we are the child
-    int status = (*f)(f_arg); // we require that f return a zero or positive value
-    if( status < 0 ) status = ERR_NEGATIVE_RETURN_STATUS;
-    exit(status);
-  }else{ // we are the parent
-    waitpid(pid, &(ctxp->status), 0);
-    return ctxp;
-  }
-}
-
-//--------------------------------------------------------------------------------
-// interface call point
-dispatch_f_ctx *dispatch_f_euid_egid(char *fname, int (*f)(void *arg), void *f_arg, uid_t euid, gid_t egid){
-  dispatch_f_ctx *ctxp = dispatch_f_ctx_mk("dispatch_f_euid_egid", fname);
-  #ifdef DEBUG
-  dbprintf("%s %s as euid:%u egid:%u\n", ctxp->dispatcher, ctxp->dispatchee, euid, egid);
-  #endif
-  pid_t pid = fork();
-  if( pid == -1 ){
-    ctxp->err = ERR_DISPATCH_F_FORK;
-    return ctxp;
-  }
-  if( pid == 0 ){ // we are the child
-    int status;
-    if( seteuid(euid) == -1 )
-      status = ERR_DISPATCH_F_SETEUID;
-    else if( setegid(egid) == -1 )
-      status = ERR_DISPATCH_F_SETEGID;
-    else{
-      status = (*f)(f_arg);
-      if( status < 0 ) status = ERR_NEGATIVE_RETURN_STATUS;
-      exit(status);
-    }
-  }else{ // we are the parent
-    waitpid(pid, &(ctxp->status), 0);
-    return ctxp;
-  }
-}
-
-
diff --git a/src-0/1_deprecated/dispatch_useradd.lib.c b/src-0/1_deprecated/dispatch_useradd.lib.c
deleted file mode 100644 (file)
index 7b75291..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
-There is no C library interface to useradd(8), but if there were, this function
-would be found there instead.
-
-*/
-#include "dispatch_useradd.lib.h"
-
-#include <sys/types.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <errno.h>
-
-#if INTERFACE
-#include <sys/types.h>
-#include <pwd.h>
-#define ERR_DISPATCH_USERADD_ARGC 1
-#define ERR_DISPATCH_USERADD_DISPATCH 2
-#define ERR_DISPATCH_USERADD_PWREC 3
-struct dispatch_useradd_ret_t{
-  uint error;
-  struct passwd *pw_record;  
-};
-#endif
-
-
-// we have a contract with the caller that argv[1] is always the subuname
-struct dispatch_useradd_ret_t dispatch_useradd(char **argv, char **envp){
-  struct dispatch_useradd_ret_t ret;
-  {
-    if( !argv || !argv[0] || !argv[1]){
-      fprintf(stderr,"useradd() needs a first argument as the name of the user to be made");
-      ret.error = ERR_DISPATCH_USERADD_ARGC;
-      ret.pw_record = NULL;
-      return ret;
-    }
-
-    char *subu_name;
-    {
-      subu_name = argv[1];
-      if( dispatch_exec(argv, envp) == -1 ){
-        fprintf(stderr,"%s failed\n", argv[0]);
-        ret.error = ERR_DISPATCH_USERADD_DISPATCH;
-        ret.pw_record = NULL;
-        return ret;
-      }}
-
-    {
-      struct passwd *pw_record = getpwnam(subu_name);
-      uint count = 1;
-      while( !pw_record && count <= 3 ){
-        #ifdef DEBUG
-          printf("try %u, getpwnam failed, trying again\n", count);
-        #endif
-        sleep(1);
-        pw_record = getpwnam(subu_name);
-        count++;
-      }
-      if( !pw_record ){
-        ret.error = ERR_DISPATCH_USERADD_PWREC;
-        ret.pw_record = NULL;
-        return ret;
-      }
-      ret.error = 0;
-      ret.pw_record = pw_record;
-      return ret;
-    }}}
-
diff --git a/src-0/1_deprecated/subu-rm-0.lib.c b/src-0/1_deprecated/subu-rm-0.lib.c
deleted file mode 100644 (file)
index ccad437..0000000
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
-  subu-rm-0 subuname
-
-  1. get our uid and lookup masteru_name in /etc/passwd
-  2. lookup masteru_name/subuname in config file, which gives us subu_username
-  3. unmount subuland/subuname
-  4. userdel subu_username
-  5. rmdir subuland/subuname
-
-  Note, as per the man page, we are not allowed to free the memory allocated by getpwid().
-
-*/
-#include "subu-mk-0.lib.h"
-
-// without this #define we get the warning: implicit declaration of function â€˜seteuid’/‘setegid’
-#define _GNU_SOURCE   
-
-#include <sys/types.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <pwd.h>
-#include <string.h>
-#include <sys/stat.h>
-
-#if INTERFACE
-#include <stdbool.h>
-#include <errno.h>
-#include <sqlite3.h>
-#endif
-
-//--------------------------------------------------------------------------------
-// an instance is subu_rm_0_ctx is returned by subu_rm_0
-//
-#if INTERFACE
-#define ERR_SUBU_RM_0_MKDIR_SUBUHOME 1
-#define ERR_SUBU_RM_0_RMDIR_SUBUHOME 2
-#define ERR_SUBU_RM_0_SUBUNAME_MALFORMED 3
-#define ERR_SUBU_RM_0_SETUID_ROOT 4
-#define ERR_SUBU_RM_0_MASTERU_HOMELESS 5
-#define ERR_SUBU_RM_0_MALLOC 6
-#define ERR_SUBU_RM_0_CONFIG_FILE 7
-#define ERR_SUBU_RM_0_SUBUHOME_EXISTS 8
-#define ERR_SUBU_RM_0_BUG_SSS 9
-#define ERR_SUBU_RM_0_FAILED_USERADD 10
-
-struct subu_rm_0_ctx{
-  char *name;
-  char *subuland;
-  char *subuhome;
-  char *subu_username;
-  bool free_aux;
-  char *aux;
-  uint err;
-};
-#endif
-struct subu_rm_0_ctx *subu_rm_0_ctx_mk(){
-  struct subu_rm_0_ctx *ctxp = malloc(sizeof(struct subu_rm_0_ctx));
-  ctxp->name = "subu_rm_0";
-  ctxp->subuland = 0;
-  ctxp->subuhome = 0;
-  ctxp->subu_username = 0;
-  ctxp->free_aux = false;
-  ctxp->aux = 0;
-}
-void subu_rm_0_ctx_free(struct subu_rm_0_ctx *ctxp){
-  free(ctxp->subuland);
-  free(ctxp->subuhome);
-  free(ctxp->subu_username);
-  if(ctxp->free_aux) free(ctxp->aux);
-  free(ctxp);
-}
-// must be called before any system calls, otherwise perror() will be messed up
-void subu_rm_0_mess(struct subu_rm_0_ctx *ctxp){
-  switch(ctxp->err){
-  case 0: return;
-  case ERR_SUBU_RM_0_MKDIR_SUBUHOME:
-    fprintf(stderr, "masteru could not make subuhome, \"%s\"", ctxp->subuhome);
-    break;
-  case ERR_SUBU_RM_0_SUBUNAME_MALFORMED:
-    fprintf(stderr, "subuname, \"%s\" is not in [ _.-a-zA-Z0-9]*", ctxp->aux);
-    break;
-  case ERR_SUBU_RM_0_SETUID_ROOT:
-    fprintf(stderr, "This program must be run setuid root from a user account.");
-    break;
-  case ERR_SUBU_RM_0_MASTERU_HOMELESS:
-    fprintf(stderr,"Masteru, \"%s\", has no home directory", ctxp->aux);
-    break;
-  case ERR_SUBU_RM_0_MALLOC:
-    perror(ctxp->name);
-  break;
-  case ERR_SUBU_RM_0_CONFIG_FILE:
-    fprintf(stderr, "config file error: %s", ctxp->aux);
-  break;
-  case ERR_SUBU_RM_0_SUBUHOME_EXISTS:
-    fprintf(stderr, "a file system object already exists at subuhome, \"%s\"\n", ctxp->subuhome);
-  break;
-  case ERR_SUBU_RM_0_BUG_SSS:
-    perror(ctxp->name);
-  break;
-  case ERR_SUBU_RM_0_FAILED_USERADD:
-    fprintf(stderr, "%u useradd failed\n", ctxp->subu_username);
-  break;
-  default:
-    fprintf(stderr, "unknown error code %d\n", ctxp->err);
-  }
-  fputc('\n', stderr);
-}
-
-//--------------------------------------------------------------------------------
-// dispatched functions
-//
-// the making of subuhome is dispatched to its own process so as to give it its own uid/gid
-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 ERR_SUBU_RM_0_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 ERR_SUBU_RM_0_RMDIR_SUBUHOME;
-  }
-  return 0;
-}
-
-//--------------------------------------------------------------------------------
-//  the public call point
-struct subu_rm_0_ctx *subu_rm_0(sqlite3 *db, char *subuname){
-
-  struct subu_rm_0_ctx *ctxp = subu_rm_0_ctx_mk();
-
-  //--------------------------------------------------------------------------------
-  #ifdef DEBUG
-  dbprintf("Checking that subuname is well formed and finding its length\n");
-  #endif
-  size_t subuname_len;
-  {
-    int ret = allowed_subuname(subuname, &subuname_len);
-    if( ret == -1 ){
-      ctxp->err = ERR_SUBU_RM_0_SUBUNAME_MALFORMED;
-      ctxp->aux = subuname;
-      return ctxp;
-    }}
-  
-  //--------------------------------------------------------------------------------
-  #ifdef DEBUG
-  dbprintf("Checking that we are running from a user and are setuid root.\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
-    dbprintf("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 ){
-      ctxp->err = ERR_SUBU_RM_0_SETUID_ROOT;
-      return ctxp;
-    }
-  }
-
-  //--------------------------------------------------------------------------------
-  #ifdef DEBUG
-  dbprintf("strings masteru_name and masteru_home\n");
-  #endif
-
-  char *masteru_name;
-  size_t masteru_name_len;
-  char *masteru_home;
-  size_t masteru_home_len;
-  size_t subuland_len;
-  {
-    struct passwd *masteru_pw_record_pt = getpwuid(masteru_uid); // reading /etc/passwd
-    masteru_name = masteru_pw_record_pt->pw_name;
-    masteru_name_len = strlen(masteru_name);
-    #ifdef DEBUG
-    dbprintf("masteru_name \"%s\" %zu\n", masteru_name, masteru_name_len);
-    #endif
-    masteru_home = masteru_pw_record_pt->pw_dir;
-    masteru_home_len = strlen(masteru_home);
-    #ifdef DEBUG
-    dbprintf("masteru_home \"%s\" %zu\n", masteru_home, masteru_home_len);
-    #endif
-    masteru_home_len = strlen(masteru_home);
-    if( masteru_home_len == 0 || masteru_home[0] == '(' ){
-      ctxp->err = ERR_SUBU_RM_0_MASTERU_HOMELESS;
-      ctxp->aux = masteru_name;  // we can not free a passwd struct, or its fields.  I assume then it isn't re-entrant safe.
-      return ctxp;
-    }
-    // char *subuland_extension = "/subuland/"; // moved to common.lib.c
-    size_t subuland_extension_len = strlen(subuland_extension);
-    ctxp->subuland = (char *)malloc( masteru_home_len + subuland_extension_len + 1 );
-    if(!ctxp->subuland){
-      ctxp->err = ERR_SUBU_RM_0_MALLOC;
-      return ctxp;
-    }
-    strcpy(ctxp->subuland, masteru_home);
-    strcpy(ctxp->subuland + masteru_home_len, subuland_extension);
-    subuland_len = masteru_home_len + subuland_extension_len;
-    #ifdef DEBUG
-    dbprintf("subuland \"%s\" %zu\n", ctxp->subuland, subuland_len);
-    #endif
-  }
-
-  //--------------------------------------------------------------------------------
-  #ifdef DEBUG
-  dbprintf("lookup subu_username from masteru_name/subuname in config file\n");
-  #endif
-  char *subu_username; // this is part of ctx and must be freed
-  {
-    int ret = subu_get_masteru_subu(db, masteru_name, subuname, &subu_username);
-    if( ret != SQLITE_DONE ){
-      printf("get failed\n");
-      return 2;
-    }
-    #ifdef DEBUG
-    printf("subu_username: %s\n", subu_username);  
-    #endif
-    
-  }
-
-  //--------------------------------------------------------------------------------
-  #ifdef DEBUG
-  dbprintf("strings subu_username and subuhome\n");
-  #endif
-  size_t subu_username_len;
-  size_t subuhome_len;
-  {
-    char *ns=0; // 'ns'  Number as String
-    char *mess=0;
-    if( subu_number_get( db, &ns, &mess ) != SQLITE_OK ){
-      ctxp->err = ERR_SUBU_RM_0_CONFIG_FILE;
-      ctxp->aux = mess;
-      ctxp->free_aux = true;
-      return ctxp;
-    }
-    size_t ns_len = strlen(ns);
-    ctxp->subu_username = malloc(1 + ns_len + 1);
-    if( !ctxp->subu_username ){
-      ctxp->err = ERR_SUBU_RM_0_MALLOC;
-      return ctxp;
-    }
-    strcpy(ctxp->subu_username, "s");
-    strcpy(ctxp->subu_username + 1, ns);
-    subu_username_len = ns_len + 1;
-    #ifdef DEBUG
-    dbprintf("subu_username \"%s\" %zu\n", ctxp->subu_username, subu_username_len);
-    #endif
-
-    subuhome_len = subuland_len + subuname_len; 
-    ctxp->subuhome = (char *)malloc(subuhome_len + 1);
-    if( !ctxp->subuhome ){
-      ctxp->err = ERR_SUBU_RM_0_MALLOC;
-      return ctxp;
-    }
-    strcpy (ctxp->subuhome, ctxp->subuland);
-    strcpy (ctxp->subuhome + subuland_len, subuname);
-    #ifdef DEBUG
-    dbprintf("subuhome \"%s\" %zu\n", ctxp->subuhome, subuhome_len);
-    #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
-  {
-    #ifdef DEBUG
-    dbprintf("as masteru, making the directory \"%s\"\n", ctxp->subuhome);
-    #endif
-    struct stat st;
-    if( stat(ctxp->subuhome, &st) != -1 ){
-      ctxp->err = ERR_SUBU_RM_0_SUBUHOME_EXISTS;
-      return ctxp;
-    }
-    dispatch_ctx *dfr = dispatch_f_euid_egid
-      (
-       "masteru_mkdir_subuhome", 
-       masteru_mkdir_subuhome, 
-       (void *)ctxp->subuhome,
-       masteru_uid, 
-       masteru_gid
-       );
-    if( dfr->err <= ERR_DISPATCH || dfr->err == ERR_SUBU_RM_0_MKDIR_SUBUHOME ){
-      #ifdef DEBUG
-      if( dfr->err == ERR_SUBU_RM_0_MKDIR_SUBUHOME )
-        perror("mkdir");
-      else
-        dispatch_f_mess(dfr);
-      #endif
-      ctxp->err = ERR_SUBU_RM_0_MKDIR_SUBUHOME;
-      return ctxp;
-    }
-  }
-  #ifdef DEBUG
-  dbprintf("masteru made directory \"%s\"\n", ctxp->subuhome);
-  #endif
-
-  //--------------------------------------------------------------------------------
-  //  Make the subservient user account, i.e. the subu
-  {
-    #ifdef DEBUG
-      dbprintf("making subu \"%s\" as user \"%s\"\n", subuname, ctxp->subu_username);
-    #endif
-    #if BUG_SSS_CACHE_RUID
-      #ifdef DEBUG
-        dbprintf("setting inherited real uid to 0 to accomodate SSS_CACHE UID BUG\n");
-      #endif
-      if( setuid(0) == -1 ){
-        ctxp->err = ERR_SUBU_RM_0_BUG_SSS;
-        return ctxp;
-      }
-    #endif
-    char *command = "/usr/sbin/useradd";
-    char *argv[3];
-    argv[0] = command;
-    argv[1] = ctxp->subu_username;
-    argv[2] = (char *) NULL;
-    char *envp[1];
-    envp[0] = (char *) NULL;
-    dispatch_ctx *dfr = dispatch_exec(argv, envp);
-    if( dfr->err != 0 ){
-      #ifdef DEBUG 
-      if( dfr->err <= ERR_DISPATCH )
-        dispatch_f_mess(dfr);
-      else
-        perror("useradd");
-      #endif
-      // go back and remove the directory we made in subuland
-      dispatch_ctx *dfr = dispatch_f_euid_egid
-        (
-         "masteru_rmdir_subuhome", 
-         masteru_rmdir_subuhome, 
-         (void *)ctxp->subuhome,
-         masteru_uid, 
-         masteru_gid
-         );
-      #ifdef DEBUG
-        if( dfr->err <= ERR_DISPATCH || dfr->err == ERR_SUBU_RM_0_RMDIR_SUBUHOME )
-          if( dfr->err == ERR_SUBU_RM_0_RMDIR_SUBUHOME )
-            perror("rmdir");
-          else
-            dispatch_f_mess(dfr);
-      #endif
-      ctxp->err = ERR_SUBU_RM_0_FAILED_USERADD;
-      return ctxp;
-    }
-    #ifdef DEBUG
-    dbprintf("added user \"%s\"\n", ctxp->subu_username);
-    #endif
-  }  
-  
-  //--------------------------------------------------------------------------------
-  #ifdef DEBUG
-  dbprintf("setting the masteru_name, subuname, subu_username relation\n");
-  #endif
-  {
-    int ret = subu_put_masteru_subu(db, masteru_name, subuname, ctxp->subu_username);
-    if( ret != SQLITE_DONE ){
-      ctxp->err = ERR_SUBU_RM_0_CONFIG_FILE;
-      ctxp->aux = "insert of masteru subu relation failed";
-      return ctxp;
-    }
-  }
-
-  #ifdef DEBUG
-  dbprintf("finished subu-mk-0(%s)\n", subuname);
-  #endif
-  ctxp->err = 0;
-  return ctxp;
-}
diff --git a/src-0/1_deprecated/subudb-number-next.cli.c b/src-0/1_deprecated/subudb-number-next.cli.c
deleted file mode 100644 (file)
index 3373173..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
-Set or get a new maximum subu number. Currently doesn't do the setting part.
-
-*/
-#include "subudb-number-next.cli.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <limits.h>
-
-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 ){
-    sqlite3_close(db);
-    fprintf(stderr, "error exit, could not open db file\n");
-    return SUBU_ERR_DB_FILE;
-  }
-
-  // read and print the current max
-  char *mess;
-  int n;
-  rc = subudb_number_next(db, masteru_name, &n, &mess);
-  if( rc == SQLITE_DONE ){
-    printf("%d\n", n);
-  }else{
-    fprintf(stderr, "subudb_number_next indicates failure by returning %d\n",rc);
-    fprintf(stderr, "and issues message, %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/src-0/1_doc/to_do.txt b/src-0/1_doc/to_do.txt
deleted file mode 100644 (file)
index 0b989cc..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-2019-02-05T23:14:40Z
-  error can cause subu-mk-0 to leave the creating of a subu in an intermediate
-  state.  Rather than bailing on some of the errors we need to clean up instead.
-  Perhaps the yet to be written subu-rm program will be resilent enough to do
-  more general cleanup.
-
-2019-02-23T18:56:31Z
-  need to modify subu-init to take a configuration file name argument instead of
-  using a global variabel value.  might want to add arguments to other subu
-  commands also
-
-2019-03-11T13:48:03Z
-  in subu.lib.c append cascading rmdir failure mess to useradd failure mess
-
-2019-03-11T13:48:03Z
-  want to add subu-type to masteru_subu(),  I imagine there will be static,
-  permanent, and temporary subu types.
-
-2019-03-12T18:35:06Z
-  the masteru subu relation should contain the uid of the masteru as
-  well as the backup type for the subu:  git, rdiff, rsync, none.
-  and the persisitance fo the subu: indefinite, session.
-  seems that operations need to be logged, in case the db is lost
-  the transcript can be played back.  It should also be possible
-  to co-opt an existing user as a subu, though, would require
-  sudo privs.
-
-  need to add messages for subu errors I've added to the end of
-  the list in subu.lib.c
-  
-2019-03-14T10:43:50Z
-
-   should mod all to he subudb routines to return a message, probably
-   strdup(sqlite_errmsg(db)), then the callers to these routines can just pass
-   mess in rather than making up new ones for each situation. The error code
-   probably already carries the contexts specific message.  Or perhaps add
-   a string cat function for message strings, that would run through a stream
-   and free the originals.
diff --git a/src-0/1_tests/0_makefile b/src-0/1_tests/0_makefile
deleted file mode 100644 (file)
index 67cea25..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-# src/1_tests/0_makefile
-
-SHELL=/bin/bash
-
--include 0_makefile_flags
-
-MAKE=/usr/bin/make -f $(PROJECT_SUBU)/tools/lib/makefile_cc
-
-SOURCES=$(wildcard *.c)
-HFILES=$(wildcard *.h)
-
-all: version deps lib execs
-
-deps:
-       makeheaders $(SOURCES) $(HFILES)
-       sed -i '/^ *int *main *(.*)/d' *.h
-       $(MAKE) $@
-
-clean:
-       $(MAKE) $@
-       for i in $(HFILES); do rm $$i; done
-
-dist-clean:
-       $(MAKE) $@
-       if [ -f subudb ]; then rm subudb; fi
-
-%::
-       $(MAKE) $@
-
-
-
-
diff --git a/src-0/1_tests/0_makefile_flags b/src-0/1_tests/0_makefile_flags
deleted file mode 100644 (file)
index 8818691..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-
-# some versions of Linux need a -e option others complain if there is a -e .. and it isn't the binary for echo ..
-ECHO= echo
-#ECHO= echo -e
-
-# directories used by this makefile, these could all be set to dot for
-# the simplest source directory structure
-
-#LIDBIR, EXECSDIR, HDIR hold the make results that might later be staged
-#$(PWD) is the directory that make was called from, this is already build in
-#set to dot to use the same directory as the source code
-#leave blank to ommit
-DEPRDIR=
-DOCDIR=
-EXECSDIR=.
-HDIR=.
-LIBDIR=.
-TESTDIR=.
-TMPDIR=1_tmp
-TOOLSDIR=$(realpath $(PROJECT_SUBU)/tools)
-TRYDIR=
-
-
-# compiler and flags
-CC=gcc
-CFLAGS=-std=gnu11 -fPIC -I. -ggdb -Werror -DDEBUG -DDEBUGDB 
-#CFLAGS=-std=gnu11 -fPIC -I. -Werror
-LINKFLAGS=-L$(PROJECT_SUBU)/src/$(LIBDIR) -L. -lsubu -lsqlite3 -lsubutests
-
-LIBFILE=$(LIBDIR)/libtests.a
-
diff --git a/src-0/1_tests/1_tmp/makefile_deps b/src-0/1_tests/1_tmp/makefile_deps
deleted file mode 100644 (file)
index 9486ae8..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-da.cli.o: da.cli.c da.cli.h
-
-./da : da.cli.o ./libtests.a
-       gcc -o ./da da.cli.o -L/home/morpheus/subu_land/subu/src/. -L. -lsubu -lsqlite3 -lsubutests
diff --git a/src-0/1_tests/da.cli.c b/src-0/1_tests/da.cli.c
deleted file mode 100644 (file)
index 910a15e..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
-Tests for da.
-
-*/
-
-#include <da.cli.h>
-#include <stdbool.h>
-
-int test_da_0(){
-  da da0;
-  da_alloc(&da0, sizeof(int)); // leaves room for 4 ints
-  int i = 0;
-  int *pt = da0->base;
-  // will double, 4 -> 8, then double 8 -> 16
-  while( i < 10 ){
-    if(da_boundq(&da0, pt)){
-      char *old_base = da_expand(&da);
-      da_rebase(&da, old_base, pt);
-    }
-    *pt = i;
-  i++;
-  pt++;
-  }
-
-  bool f0 = da.size == sizof(int) * 16;
-  bool f1 = 10 == (da.end - da.base) / sizeof(int);
-  bool f2 = true;
-  pt = da0->base;
-  while( i < 10 ){
-    f2 = f2 && *pt == i && !da_endq(&da, pt);
-  i++;
-  pt++;
-  }
-  bool f3 = da_endq(&da, pt);
-
-  return f0 && f1 && f2 && f3;
-}
-
-
-int main(){
-
-  bool da_0_passed = test_da_0();
-  if( da_0_passed ){
-    printf("da_0_passed");
-    return 0;
-  }
-  printf("da_0_failed");
-  return 1;
-
-}
diff --git a/src-0/1_tests/libtests.a b/src-0/1_tests/libtests.a
deleted file mode 100644 (file)
index 8b277f0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-!<arch>
diff --git a/src-0/1_tmp/da.lib.h b/src-0/1_tmp/da.lib.h
deleted file mode 100644 (file)
index 4702189..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* \aThis file was automatically generated.  Do not edit! */
-#undef INTERFACE
-#include <stdlib.h>
-#include <stdbool.h>
-void daps_map(char **base,char **end_pt,void f(void *));
-#define RETURN(rc) \
-  { daps_map(mrs, mrs_end, free); return rc; }
-void daps_alloc(char ***base,size_t *s);
-#define MK_MRS \
-  char **mrs;  \
-  char **mrs_end; \
-  size_t mrs_size; \
-  daps_alloc(&mrs, &mrs_size);\
-  mrs_end = mrs;
-void daps_push(char ***base,char ***pt,size_t *s,char *item);
-bool daps_bound(char **base,char **pt,size_t s);
-void daps_expand(char ***base,char ***pt,size_t *s);
-void da_map(void *base,void *end_pt,void f(void *),size_t item_size);
-void da_push(void **base,void **pt,size_t *s,void *item,size_t item_size);
-bool da_bound(void *base,void *pt,size_t s);
-void da_expand(void **base,void **pt,size_t *s);
-void da_alloc(void **base,size_t *s,size_t item_size);
-#define INTERFACE 0
diff --git a/src-0/1_tmp/dbprintf.lib.h b/src-0/1_tmp/dbprintf.lib.h
deleted file mode 100644 (file)
index 3056cf6..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-/* \aThis file was automatically generated.  Do not edit! */
-#undef INTERFACE
-int dbprintf(const char *format,...);
diff --git a/src-0/1_tmp/dispatch.lib.h b/src-0/1_tmp/dispatch.lib.h
deleted file mode 100644 (file)
index 07e2271..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/* \aThis file was automatically generated.  Do not edit! */
-#undef INTERFACE
-#include <sys/types.h>
-#include <unistd.h>
-int dispatch_exec(char **argv,char **envp);
-typedef unsigned int uint;
-int dispatch_f_euid_egid(char *fname,int(*f)(void *arg),void *f_arg,uid_t euid,gid_t egid);
-int dbprintf(const char *format,...);
-int dispatch_f(char *fname,int(*f)(void *arg),void *f_arg);
-void dispatch_f_mess(char *fname,int err,char *dispatchee);
-#define ERR_DISPATCH_EXEC -1029
-#define ERR_DISPATCH_NULL_EXECUTABLE -1028
-#define ERR_DISPATCH_F_SETEGID -1027
-#define ERR_DISPATCH_F_SETEUID -1026
-#define ERR_DISPATCH_F_FORK -1025
-#define ERR_DISPATCH_NEGATIVE_RETURN_STATUS -1024
-#define ERR_DISPATCH -1024
-typedef struct dispatch_ctx dispatch_ctx;
-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
-};
-#define INTERFACE 0
diff --git a/src-0/1_tmp/subu-bind-all.cli.h b/src-0/1_tmp/subu-bind-all.cli.h
deleted file mode 100644 (file)
index 7e52675..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-/* \aThis file was automatically generated.  Do not edit! */
-#undef INTERFACE
-#include <stdbool.h>
-#include <errno.h>
-#include <sqlite3.h>
-int subu_bind_all(char **mess,sqlite3 *db);
-#define SUBU_ERR_DB_FILE 8
-extern char DB_File[];
-#define SUBU_ERR_ARG_CNT 1
diff --git a/src-0/1_tmp/subu-bind.cli.h b/src-0/1_tmp/subu-bind.cli.h
deleted file mode 100644 (file)
index af12d61..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-/* \aThis file was automatically generated.  Do not edit! */
-#undef INTERFACE
-#include <stdbool.h>
-#include <errno.h>
-#include <sqlite3.h>
-int subu_bind(char **mess,char *masteru_name,char *subu_username,char *subuhome);
-#define SUBU_ERR_ARG_CNT 1
diff --git a/src-0/1_tmp/subu-common.lib.h b/src-0/1_tmp/subu-common.lib.h
deleted file mode 100644 (file)
index cfdc520..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-/* \aThis file was automatically generated.  Do not edit! */
-#undef INTERFACE
-extern char Subuland_Extension[];
-typedef unsigned int uint;
-extern uint First_Max_Subunumber;
-extern uint Subuhome_Perms;
-extern char DB_File[];
-#define BUG_SSS_CACHE_RUID 1
-#define INTERFACE 0
diff --git a/src-0/1_tmp/subu-mk-0.cli.h b/src-0/1_tmp/subu-mk-0.cli.h
deleted file mode 100644 (file)
index 487b509..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-/* \aThis file was automatically generated.  Do not edit! */
-#undef INTERFACE
-#include <stdbool.h>
-#include <errno.h>
-#include <sqlite3.h>
-void subu_err(char *fname,int err,char *mess);
-int subu_mk_0(char **mess,sqlite3 *db,char *subuname);
-#define SUBU_ERR_DB_FILE 8
-extern char DB_File[];
-#define SUBU_ERR_ARG_CNT 1
diff --git a/src-0/1_tmp/subu-rm-0.cli.h b/src-0/1_tmp/subu-rm-0.cli.h
deleted file mode 100644 (file)
index 070bfe8..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-/* \aThis file was automatically generated.  Do not edit! */
-#undef INTERFACE
-#include <stdbool.h>
-#include <errno.h>
-#include <sqlite3.h>
-void subu_err(char *fname,int err,char *mess);
-int subu_rm_0(char **mess,sqlite3 *db,char *subuname);
-#define SUBU_ERR_DB_FILE 8
-extern char DB_File[];
-#define SUBU_ERR_ARG_CNT 1
diff --git a/src-0/1_tmp/subu.lib.h b/src-0/1_tmp/subu.lib.h
deleted file mode 100644 (file)
index 69c5da7..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/* \aThis file was automatically generated.  Do not edit! */
-#undef INTERFACE
-typedef unsigned int uint;
-#include <sqlite3.h>
-typedef struct subudb_subu_element subudb_subu_element;
-int subudb_Masteru_Subu_get_subus(sqlite3 *db,char *masteru_name,subudb_subu_element **sa_pt,subudb_subu_element **sa_end_pt);
-struct subudb_subu_element {
-  char *subuname;
-  char *subu_username;
-};
-#include <stdbool.h>
-#include <errno.h>
-int subu_bind_all(char **mess,sqlite3 *db);
-int subu_bind(char **mess,char *masteru_name,char *subu_username,char *subuhome);
-int subudb_Masteru_Subu_rm(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);
-int subu_rm_0(char **mess,sqlite3 *db,char *subuname);
-int subudb_Masteru_Subu_put(sqlite3 *db,char *masteru_name,char *subuname,char *subu_username);
-#include <sys/types.h>
-#include <unistd.h>
-int dispatch_exec(char **argv,char **envp);
-#define BUG_SSS_CACHE_RUID 1
-void dispatch_f_mess(char *fname,int err,char *dispatchee);
-#define ERR_DISPATCH -1024
-int dispatch_f_euid_egid(char *fname,int(*f)(void *arg),void *f_arg,uid_t euid,gid_t egid);
-#include <stdlib.h>
-void daps_map(char **base,char **end_pt,void f(void *));
-#define RETURN(rc) \
-  { daps_map(mrs, mrs_end, free); return rc; }
-void daps_push(char ***base,char ***pt,size_t *s,char *item);
-int dbprintf(const char *format,...);
-void daps_alloc(char ***base,size_t *s);
-#define MK_MRS \
-  char **mrs;  \
-  char **mrs_end; \
-  size_t mrs_size; \
-  daps_alloc(&mrs, &mrs_size);\
-  mrs_end = mrs;
-int subu_mk_0(char **mess,sqlite3 *db,char *subuname);
-extern char Subuland_Extension[];
-int db_commit(sqlite3 *db);
-int db_rollback(sqlite3 *db);
-int subudb_number_set(sqlite3 *db,int n);
-int subudb_number_get(sqlite3 *db,int *n);
-int db_begin(sqlite3 *db);
-extern uint Subuhome_Perms;
-extern char DB_File[];
-void subu_err(char *fname,int err,char *mess);
-#define SUBU_ERR_BIND 15
-#define SUBU_ERR_N 14
-#define SUBU_ERR_SUBU_NOT_FOUND 13
-#define SUBU_ERR_FAILED_USERDEL 12
-#define SUBU_ERR_FAILED_USERADD 11
-#define SUBU_ERR_BUG_SSS 10
-#define SUBU_ERR_SUBUHOME_EXISTS 9
-#define SUBU_ERR_DB_FILE 8
-#define SUBU_ERR_HOMELESS 7
-#define SUBU_ERR_SUBUNAME_MALFORMED 6
-#define SUBU_ERR_RMDIR_SUBUHOME 5
-#define SUBU_ERR_MKDIR_SUBUHOME 4
-#define SUBU_ERR_MALLOC 3
-#define SUBU_ERR_SETUID_ROOT 2
-#define SUBU_ERR_ARG_CNT 1
-char *userdel_mess(int err);
-char *useradd_mess(int err);
-#define INTERFACE 0
diff --git a/src-0/1_tmp/subudb-init.cli.h b/src-0/1_tmp/subudb-init.cli.h
deleted file mode 100644 (file)
index 4435103..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-/* \aThis file was automatically generated.  Do not edit! */
-#undef INTERFACE
-#include <sqlite3.h>
-int db_commit(sqlite3 *db);
-int db_rollback(sqlite3 *db);
-int subudb_schema(sqlite3 *db);
-int db_begin(sqlite3 *db);
-#include <stdbool.h>
-#include <errno.h>
-#define SUBU_ERR_DB_FILE 8
-extern char DB_File[];
diff --git a/src-0/1_tmp/subudb-number.cli.h b/src-0/1_tmp/subudb-number.cli.h
deleted file mode 100644 (file)
index c130fbb..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-/* \aThis file was automatically generated.  Do not edit! */
-#undef INTERFACE
-#include <sqlite3.h>
-int subudb_number_get(sqlite3 *db,int *n);
-int subudb_number_set(sqlite3 *db,int n);
-#include <stdbool.h>
-#include <errno.h>
-#define SUBU_ERR_N 14
-#define SUBU_ERR_DB_FILE 8
-extern char DB_File[];
-#define SUBU_ERR_ARG_CNT 1
diff --git a/src-0/1_tmp/subudb-rel-get.cli.h b/src-0/1_tmp/subudb-rel-get.cli.h
deleted file mode 100644 (file)
index 4f335be..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-/* \aThis file was automatically generated.  Do not edit! */
-#undef INTERFACE
-#include <sqlite3.h>
-int subudb_Masteru_Subu_get_subu_username(sqlite3 *db,char *masteru_name,char *subuname,char **subu_username);
-#include <stdbool.h>
-#include <errno.h>
-#define SUBU_ERR_DB_FILE 8
-extern char DB_File[];
-#define SUBU_ERR_ARG_CNT 1
diff --git a/src-0/1_tmp/subudb-rel-put.cli.h b/src-0/1_tmp/subudb-rel-put.cli.h
deleted file mode 100644 (file)
index 243b3a9..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-/* \aThis file was automatically generated.  Do not edit! */
-#undef INTERFACE
-#include <sqlite3.h>
-int subudb_Masteru_Subu_put(sqlite3 *db,char *masteru_name,char *subuname,char *subu_username);
-#include <stdbool.h>
-#include <errno.h>
-#define SUBU_ERR_DB_FILE 8
-extern char DB_File[];
diff --git a/src-0/1_tmp/subudb-rel-rm.cli.h b/src-0/1_tmp/subudb-rel-rm.cli.h
deleted file mode 100644 (file)
index 595427f..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-/* \aThis file was automatically generated.  Do not edit! */
-#undef INTERFACE
-#include <sqlite3.h>
-int subudb_Masteru_Subu_rm(sqlite3 *db,char *masteru_name,char *subuname,char *subu_username);
-#include <stdbool.h>
-#include <errno.h>
-#define SUBU_ERR_DB_FILE 8
-extern char DB_File[];
diff --git a/src-0/1_tmp/subudb-subus.cli.h b/src-0/1_tmp/subudb-subus.cli.h
deleted file mode 100644 (file)
index 16310b7..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/* \aThis file was automatically generated.  Do not edit! */
-#undef INTERFACE
-#include <sqlite3.h>
-typedef struct subudb_subu_element subudb_subu_element;
-int subudb_Masteru_Subu_get_subus(sqlite3 *db,char *masteru_name,subudb_subu_element **sa_pt,subudb_subu_element **sa_end_pt);
-struct subudb_subu_element {
-  char *subuname;
-  char *subu_username;
-};
-#include <stdbool.h>
-#include <errno.h>
-#define SUBU_ERR_DB_FILE 8
-extern char DB_File[];
-#define SUBU_ERR_ARG_CNT 1
diff --git a/src-0/1_tmp/subudb.lib.h b/src-0/1_tmp/subudb.lib.h
deleted file mode 100644 (file)
index be73823..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/* \aThis file was automatically generated.  Do not edit! */
-#undef INTERFACE
-#include <sqlite3.h>
-int subudb_Masteru_Subu_rm(sqlite3 *db,char *masteru_name,char *subuname,char *subu_username);
-#include <stdlib.h>
-#include <stdbool.h>
-void da_expand(void **base,void **pt,size_t *s);
-bool da_bound(void *base,void *pt,size_t s);
-typedef struct subudb_subu_element subudb_subu_element;
-int subudb_Masteru_Subu_get_subus(sqlite3 *db,char *masteru_name,subudb_subu_element **sa_pt,subudb_subu_element **sa_end_pt);
-void subu_element_free(subudb_subu_element *base,subudb_subu_element *end_pt);
-void da_alloc(void **base,size_t *s,size_t item_size);
-struct subudb_subu_element {
-  char *subuname;
-  char *subu_username;
-};
-int subudb_Masteru_Subu_get_subu_username(sqlite3 *db,char *masteru_name,char *subuname,char **subu_username);
-int subudb_Masteru_Subu_put(sqlite3 *db,char *masteru_name,char *subuname,char *subu_username);
-int subudb_number_set(sqlite3 *db,int n);
-int subudb_number_get(sqlite3 *db,int *n);
-typedef unsigned int uint;
-extern uint First_Max_Subunumber;
-int subudb_schema(sqlite3 *db);
-int db_rollback(sqlite3 *db);
-int db_commit(sqlite3 *db);
-int db_begin(sqlite3 *db);
-#define INTERFACE 0
diff --git a/src-0/1_try/split.c b/src-0/1_try/split.c
deleted file mode 100644 (file)
index 6d4c6ac..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
-Using preprocessor to make header file?
-
-gcc -E split.c -DPROTOTYPE
-
-Outputs source code source comment lines starting with a hash. Resolves all macro commands,
-hence the resulting header can not have macro commands.
-
- */
-
-#if PROTOTYPE
-##define GREATNESS 21
-int f(int x);
-#endif
-
-#if IMPLEMENTATION
-int f(int x){
-  return x;
-}
-#endif
diff --git a/src-0/1_try/split_arg.c b/src-0/1_try/split_arg.c
deleted file mode 100644 (file)
index 6d4c6ac..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
-Using preprocessor to make header file?
-
-gcc -E split.c -DPROTOTYPE
-
-Outputs source code source comment lines starting with a hash. Resolves all macro commands,
-hence the resulting header can not have macro commands.
-
- */
-
-#if PROTOTYPE
-##define GREATNESS 21
-int f(int x);
-#endif
-
-#if IMPLEMENTATION
-int f(int x){
-  return x;
-}
-#endif
diff --git a/src-0/1_try/subudb b/src-0/1_try/subudb
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/src-0/1_try/voidptr.c b/src-0/1_try/voidptr.c
deleted file mode 100644 (file)
index bd9c3e5..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
-They say a cast is not required passing a typed pointer to a void * argument,
-but What about void **?
-
-gcc -std=gnu11 -o voidptr voidptr.c
-voidptr.c: In function â€˜main’:
-voidptr.c:28:5: warning: passing argument 1 of â€˜g’ from incompatible pointer type [-Wincompatible-pointer-types]
-   g(&pt, y);
-     ^~~
-voidptr.c:13:15: note: expected â€˜void **’ but argument is of type â€˜int **’
- void g(void **pt0, void *pt1){
-        ~~~~~~~^~~
-
-*/
-#include <stdio.h>
-
-int f(void *pt){
-  return *(int *)pt;
-}
-
-/* fails
-void g(void **pt0, int *pt1){
-  *pt0 = pt1;
-}
-*/
-
-// passes
-void g(void *pt0, int *pt1){
-  *(int **)pt0 = pt1;
-}
-
-int main(){
-  int x = 5;
-  int *xp = &x;
-  printf("%d\n",f(xp));
-
-  int y[3];
-  y[0] = 10;
-  y[1] = 11;
-  y[2] = 12;
-
-  int *pt;
-  g(&pt, y);
-  printf("%d\n",*pt);
-
-  printf("that's all folks\n");
-  return 0;
-}
diff --git a/src-0/common.lib.c b/src-0/common.lib.c
deleted file mode 100644 (file)
index 9ce5a27..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-
-#include "subu-common.lib.h"
-
-#if INTERFACE
-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
-#endif
-
-//  char *DB_File = "/etc/subudb";
-char DB_File[] = "subudb";
-uint Subuhome_Perms = 0700;
-uint First_Max_Subunumber = 114;
-char Subuland_Extension[] = "/subuland/";
diff --git a/src-0/db.lib.c b/src-0/db.lib.c
deleted file mode 100644 (file)
index 17a5419..0000000
+++ /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<number>.
-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 <sqlite3.h>
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdbool.h>
-
-//--------------------------------------------------------------------------------
-// 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/src-0/subu-bind-all.cli.c b/src-0/subu-bind-all.cli.c
deleted file mode 100644 (file)
index e942909..0000000
+++ /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 <stdio.h>
-#include <stdlib.h>
-
-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/src-0/subu-bind.cli.c b/src-0/subu-bind.cli.c
deleted file mode 100644 (file)
index f315823..0000000
+++ /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 <stdio.h>
-#include <stdlib.h>
-
-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/src-0/subu-mk-0.cli.c b/src-0/subu-mk-0.cli.c
deleted file mode 100644 (file)
index af0888b..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
-  subu-mk-0 command
-
-*/
-#include "subu-mk-0.cli.h"
-#include <stdio.h>
-#include <stdlib.h>
-
-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/src-0/subu-rm-0.cli.c b/src-0/subu-rm-0.cli.c
deleted file mode 100644 (file)
index a7e5926..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
-  subu-mk-0 command
-
-*/
-#include "subu-rm-0.cli.h"
-#include <stdio.h>
-#include <stdlib.h>
-
-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/src-0/subu.lib.c b/src-0/subu.lib.c
deleted file mode 100644 (file)
index 988bd28..0000000
+++ /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<number>, calls useradd to creat
-  the new uswer account, and enters the relationship between masteru, subu, and
-  s<number> in the db file.  It is this relation in the db file that
-  associates the subuname with the s<number> user.
-
-  subu-rm-0 uses userdel to delete the related s<number> 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 <sys/types.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <pwd.h>
-#include <string.h>
-#include <sys/stat.h>
-
-#if INTERFACE
-#include <stdbool.h>
-#include <errno.h>
-#include <sqlite3.h>
-#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
-  dbprintf("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
-    dbprintf("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
-  dbprintf("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
-  dbprintf("made directory \"%s\"\n", subuhome);
-  #endif
-
-  //--------------------------------------------------------------------------------
-  //  Make the subservient user account, i.e. the subu
-  {
-    #ifdef DEBUG
-      dbprintf("making subu \"%s\" as user \"%s\"\n", subuname, subu_username);
-    #endif
-    #if BUG_SSS_CACHE_RUID
-      #ifdef DEBUG
-        dbprintf("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
-    dbprintf("added user \"%s\"\n", subu_username);
-    #endif
-  }  
-  
-  //--------------------------------------------------------------------------------
-  #ifdef DEBUG
-  dbprintf("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
-  dbprintf("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
-  dbprintf("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
-    dbprintf("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
-  dbprintf("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
-  dbprintf("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
-    dbprintf("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
-    dbprintf("deleting user \"%s\"\n", subu_username);
-    #endif
-    #if BUG_SSS_CACHE_RUID
-      #ifdef DEBUG
-        dbprintf("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
-    dbprintf("deleted user \"%s\"\n", subu_username);
-    #endif
-  }  
-
-  #ifdef DEBUG
-  dbprintf("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
-  dbprintf("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
-    dbprintf("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)  
-    dbprintf("masteru_name: \"%s\"", masteru_name);
-  else
-    dbprintf("masteru_name unknown");
-  if(subuland)
-    dbprintf("subuland: \"%s\"", subuland);
-  else
-    dbprintf("subuland unknown");
-  dbprintf("\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)
-      dbprintf("subuhome: \"%s\"\n", subuhome);
-    else
-      dbprintf("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/src-0/subudb-init.cli.c b/src-0/subudb-init.cli.c
deleted file mode 100644 (file)
index 714c7e4..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
-This command initializes the db file.
-
-*/
-#include "subudb-init.cli.h"
-#include <stdio.h>
-
-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/src-0/subudb-number.cli.c b/src-0/subudb-number.cli.c
deleted file mode 100644 (file)
index 60304e3..0000000
+++ /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 <stdio.h>
-#include <stdlib.h>
-#include <limits.h>
-
-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/src-0/subudb-rel-get.cli.c b/src-0/subudb-rel-get.cli.c
deleted file mode 100644 (file)
index 9828b15..0000000
+++ /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 <stdio.h>
-#include <stdlib.h>
-
-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/src-0/subudb-rel-put.cli.c b/src-0/subudb-rel-put.cli.c
deleted file mode 100644 (file)
index b19896e..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
-puts a relation in the masteru/subu table
-
-*/
-#include "subudb-rel-put.cli.h"
-#include <stdio.h>
-#include <stdlib.h>
-
-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/src-0/subudb-rel-rm.cli.c b/src-0/subudb-rel-rm.cli.c
deleted file mode 100644 (file)
index 3d15ca9..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
-puts a relation in the masteru/subu table
-
-*/
-#include "subudb-rel-rm.cli.h"
-#include <stdio.h>
-#include <stdlib.h>
-
-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/src-0/subudb-subus.cli.c b/src-0/subudb-subus.cli.c
deleted file mode 100644 (file)
index be3af20..0000000
+++ /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 <stdio.h>
-#include <stdlib.h>
-#include <limits.h>
-
-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/src-da/0_makefile b/src-da/0_makefile
deleted file mode 100644 (file)
index 9835402..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-# src-da/0_makefile
-
-SHELL=/bin/bash
-
--include 0_makefile-flags
-
-all: version deps lib execs
-
-lib:
-       $(MAKE) $@
-       cp da.lib.h 1_include/da.h
-
-%::
-       $(MAKE) $@
-
-
-
-
diff --git a/src-da/0_makefile-flags b/src-da/0_makefile-flags
deleted file mode 100644 (file)
index 6860d2f..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-
-# some versions of Linux need a -e option others complain if there is a -e .. and it isn't the binary for echo ..
-ECHO= echo
-#ECHO= echo -e
-
-# directories used by this makefile, these could all be set to dot for
-# the simplest source directory structure
-
-#LIDBIR, EXECSDIR, HDIR hold the make results that might later be staged
-#$(PWD) is the directory that make was called from, this is already build in
-#set to dot to use the same directory as the source code
-#leave blank to ommit
-DEPRDIR=1_deprecated
-DOCDIR=1_doc
-EXECSDIR=1_execs
-INCDIR=1_include
-LIBDIR=1_lib
-TESTDIR=1_tests
-TMPDIR=1_tmp
-TOOLSDIR=$(realpath $(PROJECT_SUBU)/tools)
-TRYDIR=1_try
-
-# compiler and flags
-C=gcc
-CFLAGS=-std=gnu11 -fPIC -I. -ggdb -Werror -DDEBUG -DDEBUGDB 
-#CFLAGS=-std=gnu11 -fPIC -I. -Werror
-LINKFLAGS=-L1_lib -lda 
-
-CC=
-
-LIBFILE=libda.a
-INCFILE=da.h
-
-MAKE=/usr/bin/make --no-print-directory -f $(PROJECT_SUBU)/tools/lib/makefile_cc
-#MAKE=/usr/bin/make -f $(PROJECT_SUBU)/tools/lib/makefile_cc
-
-
diff --git a/src-da/1_include/da.h b/src-da/1_include/da.h
deleted file mode 100644 (file)
index 6d3c43b..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef DA_LIB_H
-#define DA_LIB_H
-#include <stdlib.h>
-#include <stdbool.h>
-#include <stdio.h>
-
-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_map(dap, da_free, NULL); return r; }
-
-void da_alloc(Da *dap, size_t element_size);
-void da_free(Da *dap);
-void da_rewind(Da *dap);
-char *da_expand(Da *dap);
-void da_rebase(Da *dap, char *old_base, void *pta);
-bool da_endq(Da *dap, void *pt);
-bool da_boundq(Da *dap);
-void da_push(Da *dap, void *element);
-bool da_pop(Da *dap, void *element);
-char *da_index(Da *dap, size_t i);
-void da_map(Da *dap, void f(void *, void *), void *closure);
-void da_free_elements(Da *dap);
-void da_strings_puts(Da *dap);
-char *da_fgets(Da *dap, FILE *fd);
-
-#endif
-
diff --git a/src-da/1_tests/0_makefile b/src-da/1_tests/0_makefile
deleted file mode 100644 (file)
index 8b6f67c..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-# src-da/1_tests/0_makefile
-
-SHELL=/bin/bash
-
--include 0_makefile-flags
-
-all: version deps lib execs
-
-%::
-       $(MAKE) $@
-
-
-
-
diff --git a/src-da/1_tests/0_makefile-flags b/src-da/1_tests/0_makefile-flags
deleted file mode 100644 (file)
index 50cc00a..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-
-# some versions of Linux need a -e option others complain if there is a -e .. and it isn't the binary for echo ..
-ECHO= echo
-#ECHO= echo -e
-
-# directories used by this makefile, these could all be set to dot for
-# the simplest source directory structure
-
-#LIDBIR, EXECSDIR, HDIR hold the make results that might later be staged
-#$(PWD) is the directory that make was called from, this is already build in
-#set to dot to use the same directory as the source code
-#leave blank to ommit
-DEPRDIR=
-DOCDIR=
-EXECSDIR=.
-INCDIR=.
-LIBDIR=.
-TESTDIR=.
-TMPDIR=1_tmp
-TOOLSDIR=$(realpath $(PROJECT_SUBU)/tools)
-TRYDIR=
-
-
-# compiler and flags
-C=gcc
-CFLAGS=-std=gnu11 -fPIC -I. -I../1_include -ggdb -Werror -DDEBUG -DDEBUGDB 
-#CFLAGS=-std=gnu11 -fPIC -I. -I../1_include -Werror
-LINKFLAGS=-L. -L../1_lib -ltests -lda
-
-LIBFILE=libtests.a
-
-MAKE=/usr/bin/make --no-print-directory -f $(PROJECT_SUBU)/tools/lib/makefile_cc
-#MAKE=/usr/bin/make -f $(PROJECT_SUBU)/tools/lib/makefile_cc
diff --git a/src-da/1_tests/results b/src-da/1_tests/results
deleted file mode 100644 (file)
index 9e59b33..0000000
+++ /dev/null
@@ -1 +0,0 @@
-passed all 4 tests
diff --git a/src-da/1_tests/test.dat b/src-da/1_tests/test.dat
deleted file mode 100644 (file)
index 6b4b5bd..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-this is a test
-ends without a newline
-(setq mode-require-final-newline nil)
\ No newline at end of file
diff --git a/src-da/1_tests/test_da.cli.c b/src-da/1_tests/test_da.cli.c
deleted file mode 100644 (file)
index bee5a6c..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-
-#include <stdio.h>
-#include <stdbool.h>
-#include "test_da.lib.h"
-
-int main(){
-  bool da_0_passed = test_da_0();
-
-  unsigned int passed = 0;
-  unsigned int failed = 0;
-
-  // enumeration of tests
-  typedef bool (*test_fun)();
-  test_fun tests[] = {test_da_0, test_da_1, test_da_2, test_da_3, NULL};
-  char *test_names[] = {"test_da_0", "test_da_1", "test_da_2", "test_da_3", NULL};
-
-  // call tests
-  test_fun *tfp = tests;
-  char **tnp = test_names;
-  while(*tfp){
-    if( !(*tfp)() ){
-      failed++;
-      if(*tnp)
-        printf("%s failed\n", *tnp);
-      else
-        fprintf(stderr, "internal error, no test_names[] entry for test\n");
-    }else
-      passed++;
-  tfp++;
-  tnp++;
-  }
-
-  // summarize results
-
-  if( passed == 0 && failed == 0)
-    printf("no tests ran\n");
-  else if( passed == 0 )
-    printf("failed all %u tests\n", failed);
-  else if( failed == 0 )
-    printf("passed all %u tests\n", passed);
-  else
-    printf("failed %u of %u tests\n", failed, passed + failed);
-
-  if( passed == 0 || failed != 0 ) return 1;
-  return 0;
-}
diff --git a/src-da/1_tests/test_da.lib.c b/src-da/1_tests/test_da.lib.c
deleted file mode 100644 (file)
index 88a94c7..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
-Tests for Da.
-
-*/
-
-#include <stdio.h>
-#include <string.h>
-#include <stdbool.h>
-#include <da.h>
-
-#include "test_da.lib.h"
-
-// tests push
-bool test_da_0(){
-  Da da;
-  da_alloc(&da, sizeof(int)); // leaves room for 4 ints
-  int i = 0;
-  int *pt = (int *)da.base;
-  // will double, 4 -> 8, then double 8 -> 16
-  while( i < 10 ){
-    da_push(&da, &i);
-  i++;
-  pt++;
-  }
-
-  bool f0 = da.size == sizeof(int) * 16;
-  bool f1 = 10 == (da.end - da.base) / sizeof(int);
-  bool f2 = true;
-  pt = (int *)da.base;
-  i = 0;
-  while( i < 10 ){
-    f2 = f2 && *pt == i && !da_endq(&da, pt);
-  i++;
-  pt++;
-  }
-  bool f3 = da_endq(&da, pt);
-
-  return f0 && f1 && f2 && f3;
-}
-
-// tests manual expansion
-bool test_da_1(){
-  Da da;
-  da_alloc(&da, sizeof(int)); // leaves room for 4 ints
-  int i = 0;
-  int *pt = (int *)da.base;
-  // will double, 4 -> 8, then double 8 -> 16
-  while( i < 10 ){
-    da.end += da.element_size;
-    if( da_boundq(&da) ){
-      char *old_base = da_expand(&da);
-      da_rebase(&da, old_base, &pt);
-    }
-    *pt = i;
-  i++;
-  pt++;
-  }
-
-  bool f0 = da.size == sizeof(int) * 16;
-  bool f1 = 10 == (da.end - da.base) / sizeof(int);
-  bool f2 = true;
-  pt = (int *)da.base;
-  i = 0;
-  while( i < 10 ){
-    f2 = f2 && *pt == i && !da_endq(&da, pt);
-  i++;
-  pt++;
-  }
-  bool f3 = da_endq(&da, pt);
-
-  return f0 && f1 && f2 && f3;
-}
-
-// da_fgets
-bool test_da_2(){
-
-  FILE *fd = fopen("test.dat","r");
-
-  Da da;
-  da_alloc(&da, sizeof(char));
-
-  da_fgets(&da, fd);
-  bool f0 = !strcmp(da.base, "this is a test");
-
-  char *old_base;
-  da_pop(&da, NULL); // pop the prior null terminator
-  char *s1 = da.end;
-  old_base = da_fgets(&da,fd);
-  da_rebase(&da, old_base, &s1);
-  bool f1 = !strcmp(s1, "ends without a newline");
-  
-  da_pop(&da, NULL); // pop the prior null terminator
-  char *s2 = da.end;
-  old_base = da_fgets(&da,fd);
-  da_rebase(&da, old_base, &s2);
-  bool f2 = !strcmp(s2, "(setq mode-require-final-newline nil)");
-
-  bool f3 = !strcmp(da.base, "this is a testends without a newline(setq mode-require-final-newline nil)");
-
-  fclose(fd);
-  return f0 && f1 && f2 && f3;
-}
-
-// da_fgets
-bool test_da_3(){
-
-  FILE *fd = fopen("test.dat","r");
-
-  Da da;
-  da_alloc(&da, sizeof(int));
-
-  int i = 5;
-  da_push(&da, &i);
-  i++;
-  da_push(&da, &i);
-  i++;
-  da_push(&da, &i);
-
-  int j;
-  bool f0 = da_pop(&da, &j) && j == 7;
-  bool f1 = da_pop(&da, &j) && j == 6;
-  bool f2 = da_pop(&da, NULL);
-  bool f3 = !da_pop(&da, &j);
-
-  return f0 && f1 && f2 && f3;
-}
-
-
-
-
diff --git a/src-da/1_tests/test_da.lib.h b/src-da/1_tests/test_da.lib.h
deleted file mode 100644 (file)
index 686b0d0..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef DA_LIB_H
-#define DA_LIB_H
-
-bool test_da_0();
-bool test_da_1();
-bool test_da_2();
-bool test_da_3();
-
-#endif
diff --git a/src-da/da.lib.c b/src-da/da.lib.c
deleted file mode 100644 (file)
index 0956d7e..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
-Dynamic Array
-
-*/
-
-#include "da.lib.h"
-
-#include<stdlib.h>
-#include<stdbool.h>
-#include<string.h>
-
-//--------------------------------------------------------------------------------
-// generic
-// We manipulate pointers to a smallest addressable unit. The sizeof operator
-// returns counts in these addressable units. Sizeof(char) is defined to be 1.
-
-void da_alloc(Da *dap, size_t element_size){
-  dap->element_size = element_size;
-  dap->size = 4 * element_size;
-  dap->base = malloc(dap->size);
-  dap->end = dap->base;
-}
-void da_free(Da *dap){
-  free(dap->base);
-  dap->size = 0;
-}
-void da_rewind(Da *dap){
-  dap->end = dap->base;
-}
-
-bool da_empty(Da *dap){
-  return dap->end == dap->base;
-}
-
-void da_rebase(Da *dap, char *old_base, void *pta){
-  char **pt = (char **)pta;
-  size_t offset = *pt - old_base;
-  *pt = dap->base + offset;
-}
-
-// Doubles size of of da.  Returns old base, so that existing pointers into the
-// array can be moved to the new array
-char *da_expand(Da *dap){
-  char *old_base = dap->base;
-  size_t end_offset = dap->end - old_base;
-  size_t new_size = dap->size << 1;
-  char *new_base = malloc( new_size );
-  memcpy( new_base, old_base, end_offset + dap->element_size);
-  free(old_base);
-  dap->base = new_base;
-  dap->end = new_base + end_offset;
-  dap->size = new_size;
-  return old_base;
-}
-
-// true when pt has run off the end of the area currently allocated for the array
-bool da_endq(Da *dap, void *pt){
-  return (char *)pt >= dap->end;
-}
-
-// true when pt has run off the end of the area allocated for the array
-bool da_boundq(Da *dap){
-  return dap->end >= dap->base + dap->size;
-}
-
-void da_push(Da *dap, void *element){
-  if( dap->end >= dap->base + dap->size ) da_expand(dap);
-  memcpy(dap->end, element, dap->element_size);
-  dap->end += dap->element_size;
-}
-
-bool da_pop(Da *dap, void *element){
-  bool flag = dap->end >= dap->base + dap->element_size;
-  if( flag ){
-    dap->end -= dap->element_size;
-    if(element) memcpy(element, dap->end, dap->element_size);
-  }
-  return flag;
-}
-
-char *da_index(Da *dap, size_t i){
-  size_t offset = i * dap->element_size;
-  char *pt = dap->base + offset;
-  return pt;
-}
-
-// passed in f(element_pt, arg_pt)
-// We have no language support closures, so we pass in an argument for it.
-// The closure may be set to NULL if it is not needed.
-void da_map(Da *dap, void f(void *, void *), void *closure){
-  char *pt = dap->base;
-  while( pt != dap->end ){
-    f(pt, closure);
-  pt += dap->element_size;
-  }
-}
-
-// da_lists are sometimes used as resource managers
-static void da_free_element(void *pt, void *closure){
-  free(*(char **)pt); // free does not care about the pointer type
-}
-
-void da_free_elements(Da *dap){
-  da_map(dap, da_free_element, NULL);
-  da_rewind(dap);
-}
-
-// for the case of an array of strings
-void da_strings_puts(Da *dap){
-  char *pt = dap->base;
-  while( pt != dap->end ){
-    puts(*(char **)pt);
-  pt += dap->element_size;
-  }
-}
-
-
-// Puts text from a line into buffer *dap. Does not push EOF or '\n' into the
-// buffer.  Returns the old_base so that external pointers can be rebased.
-// It is possible that the the base hasn't changed. Use feof(FILE *stream) to
-// test for EOF;
-char *da_fgets(Da *dap, FILE *file){
-  char *old_base = dap->base;
-  int c = fgetc(file);
-  while( c != EOF && c != '\n' ){
-    da_push(dap, &c);
-  c = fgetc(file);
-  }
-  int terminator = 0;
-  da_push(dap, &terminator);
-  return old_base;
-}
diff --git a/src-da/da.lib.h b/src-da/da.lib.h
deleted file mode 100644 (file)
index 6d3c43b..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef DA_LIB_H
-#define DA_LIB_H
-#include <stdlib.h>
-#include <stdbool.h>
-#include <stdio.h>
-
-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_map(dap, da_free, NULL); return r; }
-
-void da_alloc(Da *dap, size_t element_size);
-void da_free(Da *dap);
-void da_rewind(Da *dap);
-char *da_expand(Da *dap);
-void da_rebase(Da *dap, char *old_base, void *pta);
-bool da_endq(Da *dap, void *pt);
-bool da_boundq(Da *dap);
-void da_push(Da *dap, void *element);
-bool da_pop(Da *dap, void *element);
-char *da_index(Da *dap, size_t i);
-void da_map(Da *dap, void f(void *, void *), void *closure);
-void da_free_elements(Da *dap);
-void da_strings_puts(Da *dap);
-char *da_fgets(Da *dap, FILE *fd);
-
-#endif
-
diff --git a/src-db/0_makefile b/src-db/0_makefile
deleted file mode 100644 (file)
index b8c7b9d..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-# src/0_makefile
-
-SHELL=/bin/bash
-
--include 0_makefile_flags
-
-SUID_TOOL=$(TOOLSDIR)/bin/setuid_root.sh
-MAKE=/usr/bin/make -f $(PROJECT_SUBU)/tools/lib/makefile_cc
-
-SOURCES=$(wildcard *.c)
-HFILES=$(wildcard *.h)
-
-all: version deps lib execs
-
-version:
-       $(MAKE) $@
-       @echo "SUID_TOOL: " $(SUID_TOOL)
-
-deps:
-       makeheaders $(SOURCES) $(HFILES)
-       sed -i '/^ *int *main *(.*)/d' *.h
-       $(MAKE) $@
-
-execs:
-       $(MAKE) $@
-       @echo "-> $(SUID_TOOL) $(EXECSDIR)/subu-mk-0 $(EXECSDIR)/subu-rm-0 $(EXECSDIR)/subu-bind-all"
-       cat $(SUID_TOOL)
-       @echo -n "Are you sure? [y/N] " && read ans && [ $${ans:-N} == y ]
-       sudo $(SUID_TOOL) $(EXECSDIR)/subu-mk-0 $(EXECSDIR)/subu-rm-0 $(EXECSDIR)/subu-bind-all
-
-clean:
-       $(MAKE) $@
-       for i in $(HFILES); do rm $$i; done
-
-%::
-       $(MAKE) $@
-
-
-
-
diff --git a/src-db/0_makefile-flags b/src-db/0_makefile-flags
deleted file mode 100644 (file)
index 0da8b61..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-
-# some versions of Linux need a -e option others complain if there is a -e .. and it isn't the binary for echo ..
-ECHO= echo
-#ECHO= echo -e
-
-# directories used by this makefile, these could all be set to dot for
-# the simplest source directory structure
-
-#LIDBIR, EXECSDIR, HDIR hold the make results that might later be staged
-#$(PWD) is the directory that make was called from, this is already build in
-#set to dot to use the same directory as the source code
-#leave blank to ommit
-DEPRDIR=1_deprecated
-DOCDIR=1_doc
-EXECSDIR=1_execs
-HDIR=1_headers
-LIBDIR=1_lib
-TESTDIR=1_tests
-TMPDIR=1_tmp
-TOOLSDIR=$(realpath $(PROJECT_SUBU)/tools)
-TRYDIR=1_try
-
-
-# compiler and flags
-CC=gcc
-CFLAGS=-std=gnu11 -fPIC -I. -ggdb -Werror -DDEBUG -DDEBUGDB 
-#CFLAGS=-std=gnu11 -fPIC -I. -Werror
-LINKFLAGS=-L1_lib -lsubu -lsqlite3
-
-LIBFILE=$(LIBDIR)/libsubu.a
-
diff --git a/src-db/1_doc/return-from-transaction.txt b/src-db/1_doc/return-from-transaction.txt
deleted file mode 100644 (file)
index b7f8cbb..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-
-1.
-  This sql:
-
-    char *sql = 
-      "BEGIN TRANSACTION;"
-      "UPDATE Key_Int SET value = value + 1 WHERE key = 'max_subu_number';"
-      "SELECT value FROM Key_Int WHERE key = 'max_subu_number';"
-      "COMMIT;"
-      ;
-
-  with sqlite_exec, the call back is called with the data from the select.
-
-  with sqlite_prepare_v2, sqlite_step just returns SQLITE_DONE, and we never
-  get to see our data from the select.
diff --git a/src-db/dbprintf.lib.c b/src-db/dbprintf.lib.c
deleted file mode 100644 (file)
index d9d236b..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-
-#include "dbprintf.lib.h"
-
-#include <stdarg.h>
-#include <stdio.h>
-
-int dbprintf(const char *format, ...){
-  va_list args;
-  va_start(args,format);  
-  int ret = vfprintf(stdout, format, args);
-  fflush(stdout);
-  va_end(args);
-  return ret;
-}
diff --git a/src-dispatch/0_makefile b/src-dispatch/0_makefile
deleted file mode 100644 (file)
index 9835402..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-# src-da/0_makefile
-
-SHELL=/bin/bash
-
--include 0_makefile-flags
-
-all: version deps lib execs
-
-lib:
-       $(MAKE) $@
-       cp da.lib.h 1_include/da.h
-
-%::
-       $(MAKE) $@
-
-
-
-
diff --git a/src-dispatch/0_makefile-flags b/src-dispatch/0_makefile-flags
deleted file mode 100644 (file)
index 6641e4a..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-
-# some versions of Linux need a -e option others complain if there is a -e .. and it isn't the binary for echo ..
-ECHO= echo
-#ECHO= echo -e
-
-# directories used by this makefile, these could all be set to dot for
-# the simplest source directory structure
-
-#LIDBIR, EXECSDIR, HDIR hold the make results that might later be staged
-#$(PWD) is the directory that make was called from, this is already build in
-#set to dot to use the same directory as the source code
-#leave blank to ommit
-DEPRDIR=1_deprecated
-DOCDIR=1_doc
-EXECSDIR=1_execs
-INCDIR=1_include
-LIBDIR=1_lib
-TESTDIR=1_tests
-TMPDIR=1_tmp
-TOOLSDIR=$(realpath $(PROJECT_SUBU)/tools)
-TRYDIR=1_try
-
-# compiler and flags
-C=gcc
-CFLAGS=-std=gnu11 -fPIC -I. -ggdb -Werror -DDEBUG -DDEBUGDB 
-#CFLAGS=-std=gnu11 -fPIC -I. -Werror
-
-LINKFLAGS=-L1_lib -lda 
-
-LIBFILE=libdispatch.a
-INCFILE=dispatch.h
-
-MAKE=/usr/bin/make --no-print-directory -f $(PROJECT_SUBU)/tools/lib/makefile_cc
-#MAKE=/usr/bin/make -f $(PROJECT_SUBU)/tools/lib/makefile_cc
-
diff --git a/src-dispatch/dispatch.src.c b/src-dispatch/dispatch.src.c
deleted file mode 100644 (file)
index 632ae51..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-#tranche dispatch.lib.cc
-
-#tranche dispatch.lib.h
-/*
-  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 <sys/types.h>
-#include <unistd.h>
-
-#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
-};
-#tranche-end
-
-#include "dispatch.lib.h"
-
-// we need the declaration for uid_t etc.
-// without this #define execvpe is undefined
-#define _GNU_SOURCE   
-
-#include <wait.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-
-#tranche dispatch.lib.h
-void dispatch_f_mess(char *fname, int err, char *dispatchee);
-#tranche-end
-void dispatch_f_mess(char *fname, int err, char *dispatchee){
-  if(err == 0) return;
-  fprintf(stderr, "%s: ", fname); // if fprintf gets an error, errno will be overwritten
-  if(err > ERR_DISPATCH){
-    fprintf(stderr, "dispatchee \"%s\" returned the error %d\n", dispatchee, err);
-    return;
-  }
-  switch(err){
-  case ERR_DISPATCH_NEGATIVE_RETURN_STATUS:
-    fprintf(stderr, " dispatchee \"%s\" returned a negative status.", dispatchee);
-    break;
-  case ERR_DISPATCH_F_FORK:
-  case ERR_DISPATCH_F_SETEUID:
-  case ERR_DISPATCH_F_SETEGID:
-    fputc(' ', stderr);
-    perror(dispatchee);
-    break;
-  case ERR_DISPATCH_NULL_EXECUTABLE:
-    fprintf(stderr, " executable was not specified");
-    break;
-  case ERR_DISPATCH_EXEC:
-    // exec is running in another process when it fails, so we can't see the errno value it set
-    fprintf(stderr, " exec of \"%s\" failed", dispatchee);
-    break;
-  default:
-    fprintf(stderr, " returned undefined status when dispatching \"%s\"", dispatchee);
-  }
-  fputc('\n', stderr);
-}
-
-//--------------------------------------------------------------------------------
-// interface call point, dispatch a function
-#tranche dispatch.lib.h
-int dispatch_f(char *fname, int (*f)(void *arg), void *f_arg);
-#tranche-end
-int dispatch_f(char *fname, int (*f)(void *arg), void *f_arg){
-  #ifdef DEBUG
-  dbprintf("%s %s\n", "dispatch_f", fname);
-  #endif
-  pid_t pid = fork();
-  if( pid == -1 ) return ERR_DISPATCH_F_FORK; // something went wrong and we are still in the parent process
-  if( pid == 0 ){ // we are the child
-    int status = (*f)(f_arg); // we require that f return a zero or positive value
-    if( status < ERR_DISPATCH ) status = ERR_DISPATCH_NEGATIVE_RETURN_STATUS;
-    exit(status);
-  }else{ // we are the parent
-    int err;
-    waitpid(pid, &err, 0);
-    return err;
-  }
-}
-
-//--------------------------------------------------------------------------------
-// interface call point, dispatch a function with a given euid/egid
-// of course this will only work if our euid is root in the first place
-#tranche dispatch.lib.h
-int dispatch_f_euid_egid(char *fname, int (*f)(void *arg), void *f_arg, uid_t euid, gid_t egid);
-#tranche-end
-int dispatch_f_euid_egid(char *fname, int (*f)(void *arg), void *f_arg, uid_t euid, gid_t egid){
-  #ifdef DEBUG
-  dbprintf("%s %s as euid:%u egid:%u\n", "dispatch_f_euid_egid", fname, euid, egid);
-  #endif
-  pid_t pid = fork();
-  if( pid == -1 ) return ERR_DISPATCH_F_FORK;
-  if( pid == 0 ){ // we are the child
-    int status;
-    if( seteuid(euid) == -1 )
-      status = ERR_DISPATCH_F_SETEUID;
-    else if( setegid(egid) == -1 )
-      status = ERR_DISPATCH_F_SETEGID;
-    else{
-      status = (*f)(f_arg);
-      if( status <= ERR_DISPATCH ) status = ERR_DISPATCH_NEGATIVE_RETURN_STATUS;
-      exit(status);
-    }
-  }else{ // we are the parent
-    uint err;
-    waitpid(pid, &err, 0);
-    return err;
-  }
-}
-
-//--------------------------------------------------------------------------------
-// interface call point, dispatch a executable
-#tranche dispatch.lib.h
-int dispatch_exec(char **argv, char **envp);
-#tranche-end
-int dispatch_exec(char **argv, char **envp){
-  char *command;
-  {
-    if( !argv || !argv[0] ) return ERR_DISPATCH_NULL_EXECUTABLE;
-    #ifdef DEBUG
-      dbprintf("dispatch_exec:");
-      char **apt = argv;
-      while( *apt ){
-        dbprintf(" %s",*apt);
-        apt++;
-      }
-      dbprintf("\n");
-    #endif
-    command = argv[0];
-  }
-  pid_t pid = fork();
-  if( pid == -1 ) return ERR_DISPATCH_F_FORK; // something went wrong and we are still in the parent process
-  if( pid == 0 ){ // we are the child
-    execvpe(command, argv, envp); // exec will only return if it has an error
-    #ifdef DEBUG
-    dbprintf("dispatch_exec: exec returned, perror message:");
-    perror("dispatch_exec"); // our only chance to print this message, as this is the child process
-    #endif
-    fflush(stdout);
-    exit(ERR_DISPATCH_EXEC); 
-  }else{ // we are the parent
-    int err;
-    waitpid(pid, &err, 0);
-    return err;
-  }
-}
-
-#tranche-end
diff --git a/src-py/subu-mk.py b/src-py/subu-mk.py
deleted file mode 100644 (file)
index 203fab4..0000000
+++ /dev/null
@@ -1,299 +0,0 @@
-#!/usr/bin/python
-# see the help option for syntax
-# this script must be run from root or sudo
-#
-# on Fedora 29 os.getresuid returned all zeros for a script run from sudo.
-# Hence, I am using the environment variable SUDO_USER
-
-import getpass
-import os
-import sys
-import libuser
-from __future__ import print_function
-
-command = os.path.base(argv[0])
-
-#--------------------------------------------------------------------------------
-# utilities
-#
-def prn(str):
-  print(str,end='')
-
-#--------------------------------------------------------------------------------
-# help
-#
-def help():
-  print( command +
-""" [=help] [=version] [shell=<shell>][owner=<owner-username>] [subu=]<subu-username>
-Makes a subservient user.
-If no arguments are given, or if =help is given, this message is printed.
-When this command is invoked through sudo, $SUDO_USER is taken as the owner's username.
-Otherwise, when invoked directly from root, the owner= option must be provided.
-The subu-username argument is the username for the new subservient user
-The the new subu home directory is created in /home/owner/subu/.
-Facls are set to give the owner access to the new subu's home directory.
-The shell option is not implemented yet.  Probably need a number of other options also.
-"""
-  )
-
-def version():
-  print(" version 0")
-
-#--------------------------------------------------------------------------------
-# a manager for handling error messages
-#
-class class_err:
-"""
-An error record has the form [flag, message, args] 
-  class is fatal, warning, info  [currently not implemented]
-  flag is true if an error has occured [need to change this to a count]
-  args is an array of strings to be given after the error message is printed.
-
-The dict holds named error records.
-
-register() is used to name and place error records in the dict. register() is
-typically called multiple times to initialize and error instance.
-
-tattle() is used by the program at run time in order to signal errors.
-
-has_error() returns true if tattle was ever called
-
-report() prints an error report.  When errors have occured this 
-
-vector() [unimplemented] returns a bit vector with one bit per fatal error
-record, in the order they appear in the dictionary. The bit is set if the error
-ever occured.
-
-We check for as many errors as is convenient to do so rather than stopping on
-the first error.
-"""
-
-  # field offsets into the error record
-  flag_dex = 0;
-  message_dex = 1;
-  args_dex = 2;
-
-  def __init__(self):
-    self.total_cnt = 0
-    self.dict = {}
-
-  def register(name, message):
-    self.dict[name] = [False, message, []]
-
-  def tattle(name, *args):
-    self.total_cnt += 1
-    if name in self.dict:
-      self.dict[name][0] = True
-      self.dict[name][2].extend(args)
-
-  def report():
-    if self.total_cnt:
-      for k,v in self.dict.items():
-        if v[self.flag_dex]:
-          print(v[self.message_dex],end='')
-          args = v[self.args_dex]
-          if length(args) :
-            print(args[0],end='')
-            for arg in args[1:]:
-              print( " " + arg, end='')
-          print()
-
-#--------------------------------------------------------------------------------
-# parse the command line
-#
-err.register(
-  'impossible_split',
-  "It is not possible, yet this token split into other than one or two pieces: "
-  )
-err.register(
-  'lone_delim',
-  "No spaces should appear around the '=' delimiter."
-  )
-
-args = sys.argv[1:]
-if len(args) == 0 :
-  version()
-  help()
-  exit(1)
-#create a dictionary based on the command line arguments
-arg_dict = {}
-subu_cnt = 0
-delim = '='
-for token in args:
-  token_pair = split(token, delim);
-  if len(token_pair) == 1 : #means there was no '=' in the token
-    arg_dict['subu'] = token_pair
-    subu_cnt++
-  elif len(token_pair) == 2 :
-    if token_pair[0] == '' and token_pair[1] == '' :
-      err.tattle('lone_delim')
-    elif token_pair[1] == '' : # then has trailing delim, will treat the same as a leading delim
-      arg_dict[token_pair[0]] = None
-    elif token_pair[0] == '' : # then has leading delim
-      arg_dict[token_pair[1]] = None
-    else:
-      arg_dict[token_pair[0]] = token_pair[1]
-  else:
-    err.tattle('impossible_split', token)
-
-if not arg_dict or arg_dict.get('help'):
-  help()
-  err.report()
-  exit(1)
-
-if arg_dict.get('version'):
-  version()
-
-#--------------------------------------------------------------------------------
-# check that the command line arguments are well formed. 
-#
-err.register(
-  'too_many_args',
-  command + " takes at most one non-option argument, but we counted: "
-  )
-err.register(
-  'no_subu'
-  command + " missing subservient username."
-  )
-err.register(
-  'bad_username'
-  "Usernames match ^[a-z_]([a-z0-9_-]{0,31}|[a-z0-9_-]{0,30}\$)$, but found: "
-  )
-err.register(
-  'unknown_option'
-  command + " doesn't implement option: "
-  )
-
-subu = arg_dict.get('subu')
-if subu_cnt > 1:
-  err.tattle('too_many_args')
-elif not subu
-  err.tattle('no_subu')
-elif not re.match("^[a-z_]([a-z0-9_-]{0,31}|[a-z0-9_-]{0,30}\$)$", subu)
-  err.tattle('bad_username', subu)
-
-for k in arg_dict:
-  if k not in ['help', 'version', 'shell', 'owner', 'subu'] :
-    err.tattle('unkown_option', k)
-
-if arg_dict.get('shell') :
-  print "shell option aint implemented yet"
-
-
-
-#--------------------------------------------------------------------------------
-# check that we have root privilege
-#
-err.register(
-  'not_root'
-  command + "requires root privilege"
-  )
-
-uid = os.getuid()
-if uid != 0 :
-  err.tattle('not root')
-
-username = getpass.getuser()
-sudo_caller_username = os.environ.get('SUDO_USER')
-
-if !sudo_caller_username
-  if username not == "root":
-    err.tattle('not_root')
-  elif:
-    owner
-    
-
-  def has_error(*errs):
-    return self.cnt > 0
-
-
-
-#-----
-
-
-
-
-#--------------------------------------------------------------------------------
-#  pull out the owner_dir and subu_dir
-#
-admin= libuser.admin()
-
-err_arg_form = class_err()
-err_arg_form.register('too_many', "too many semicolon delineated parts in")
-
-owner_parts = args[0].split(":")
-subu_parts = args[1].split(":") 
-
-owner_user_name = owner_parts[0]
-if not owner_user_name:
-  err_arg_form.tattle('owner_user_name_missing', args[0])
-else:
-  owner_user = admin.lookupUserByName(owner_user_name)
-  if owner_user == None:
-    err_arg_form.tattle('no_such_user_name', owner_user_name)
-  else:
-    
-
-subu_user_name = subu_parts[0]
-
-
-if length(owner_parts) > 2:
-  err_arg_form.tattle('too_many', args[0])
-elif length(owner_parts) == 2:
-  owner_dir = owner_parts[1]
-else # get the home directory
-    
-  
-
-
-#--------------------------------------------------------------------------------
-# set the home directory
-#
-if len(args) > args_dir_index:
-  dir = args[args_dir_index]
-else:
-  dir = os.getcwd()
-
-home = dir + "/" + name
-home_flag = not os.path.exists(home)
-
-#--------------------------------------------------------------------------------
-# create the user, setfacls
-#
-err_cnt = 0
-name_available_flag = False
-
-if name_flag:
-  admin = libuser.admin()
-  name_available_flag = name not in admin.enumeratedUsers()
-
-if owner_flag and name_flag and name_available_flag and home_flag :
-  user = admin.initUser(name)
-  user[libuser.HOMEDIRECTORY] = home
-  if opt_shell : user[libuser.SHELL] = opt_shell
-  admin.addUser(user)
-  #setfacl -m d:u:plato:rwx,u:plato:rwx directory
-  setfacl = "setfacl -m d:u:" + name + ":rwx,u:" + name + ":rwx " + home
-  exit(0)
-
-#--------------------------------------------------------------------------------
-# error return
-#  .. need to grab the return code from setfacl above and delete the user if it fails
-#
-err_flags = 0
-if not owner_flag :
-  err_flags |= 2**2
-  print "missing owning username argument"
-if not name_flag :
-  err_flags |= 2**3
-  print name + "missing subservient username argument"
-if not name_available_flag :
-  err_flags |= 2**4
-  print name + "specified subservient username already exists"
-if not home_flag :
-  err_flags |= 2**5
-  print "user home directory already exists"
-
-exit(err_flags)
diff --git a/src-tranche/0_makefile b/src-tranche/0_makefile
deleted file mode 100644 (file)
index 107d319..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-# src-da/0_makefile
-
-SHELL=/bin/bash
-
--include 0_makefile-flags
-
-all: version deps lib execs
-
-lib:
-       $(MAKE) $@
-       cp tranche.lib.h 1_include/tranche.h
-
-%::
-       $(MAKE) $@
-
-
-
-
diff --git a/src-tranche/0_makefile-flags b/src-tranche/0_makefile-flags
deleted file mode 100644 (file)
index e37767f..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-
-# some versions of Linux need a -e option others complain if there is a -e .. and it isn't the binary for echo ..
-ECHO= echo
-#ECHO= echo -e
-
-# directories used by this makefile, these could all be set to dot for
-# the simplest source directory structure
-
-#LIDBIR, EXECSDIR, HDIR hold the make results that might later be staged
-#$(PWD) is the directory that make was called from, this is already build in
-#set to dot to use the same directory as the source code
-#leave blank to ommit
-DEPRDIR=1_deprecated
-DOCDIR=1_doc
-EXECSDIR=1_execs
-INCDIR=1_include
-LIBDIR=1_lib
-TESTDIR=1_tests
-TMPDIR=1_tmp
-TOOLSDIR=$(realpath $(PROJECT_SUBU)/tools)
-TRYDIR=1_try
-
-# compiler and flags
-CC=gcc
-CFLAGS=-std=gnu11 -fPIC -I. -I$(PROJECT_SUBU)/stage/include -ggdb -Werror -DDEBUG -DDEBUGDB 
-#CFLAGS=-std=gnu11 -fPIC -I. -Werror
-LINKFLAGS=-L1_lib -L$(PROJECT_SUBU)/stage/lib -lda -ltranche
-
-LIBFILE=libtranche.a
-INCFILE=tranche.h
-
-MAKE=/usr/bin/make --no-print-directory -f $(PROJECT_SUBU)/tools/lib/makefile_cc
-
-# files used by the compiler
-SOURCES_LIB= $(wildcard *.lib.c)
-SOURCES_CLI= $(wildcard *.cli.c)
-SOURCES= $(SOURCES_LIB) $(SOURCES_CLI)
-
-HFILES = $(wildcard *.lib.h) $(wildcard *.cli.h)
-
-OBJECTS_LIB= $(patsubst %.c, %.o, $(SOURCES_LIB))
-OBJECTS_CLI= $(patsubst %.c, %.o, $(SOURCES_CLI))
-OBJECTS= $(OBJECTS_LIB) $(OBJECTS_CLI)
-
-EXECS= $(sort $(patsubst %.cli.c,  %, $(wildcard *.cli.c)))
diff --git a/src-tranche/1_deprecated/0_makefile b/src-tranche/1_deprecated/0_makefile
deleted file mode 100644 (file)
index b8c7b9d..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-# src/0_makefile
-
-SHELL=/bin/bash
-
--include 0_makefile_flags
-
-SUID_TOOL=$(TOOLSDIR)/bin/setuid_root.sh
-MAKE=/usr/bin/make -f $(PROJECT_SUBU)/tools/lib/makefile_cc
-
-SOURCES=$(wildcard *.c)
-HFILES=$(wildcard *.h)
-
-all: version deps lib execs
-
-version:
-       $(MAKE) $@
-       @echo "SUID_TOOL: " $(SUID_TOOL)
-
-deps:
-       makeheaders $(SOURCES) $(HFILES)
-       sed -i '/^ *int *main *(.*)/d' *.h
-       $(MAKE) $@
-
-execs:
-       $(MAKE) $@
-       @echo "-> $(SUID_TOOL) $(EXECSDIR)/subu-mk-0 $(EXECSDIR)/subu-rm-0 $(EXECSDIR)/subu-bind-all"
-       cat $(SUID_TOOL)
-       @echo -n "Are you sure? [y/N] " && read ans && [ $${ans:-N} == y ]
-       sudo $(SUID_TOOL) $(EXECSDIR)/subu-mk-0 $(EXECSDIR)/subu-rm-0 $(EXECSDIR)/subu-bind-all
-
-clean:
-       $(MAKE) $@
-       for i in $(HFILES); do rm $$i; done
-
-%::
-       $(MAKE) $@
-
-
-
-
diff --git a/src-tranche/1_deprecated/0_makefile-flags b/src-tranche/1_deprecated/0_makefile-flags
deleted file mode 100644 (file)
index 0da8b61..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-
-# some versions of Linux need a -e option others complain if there is a -e .. and it isn't the binary for echo ..
-ECHO= echo
-#ECHO= echo -e
-
-# directories used by this makefile, these could all be set to dot for
-# the simplest source directory structure
-
-#LIDBIR, EXECSDIR, HDIR hold the make results that might later be staged
-#$(PWD) is the directory that make was called from, this is already build in
-#set to dot to use the same directory as the source code
-#leave blank to ommit
-DEPRDIR=1_deprecated
-DOCDIR=1_doc
-EXECSDIR=1_execs
-HDIR=1_headers
-LIBDIR=1_lib
-TESTDIR=1_tests
-TMPDIR=1_tmp
-TOOLSDIR=$(realpath $(PROJECT_SUBU)/tools)
-TRYDIR=1_try
-
-
-# compiler and flags
-CC=gcc
-CFLAGS=-std=gnu11 -fPIC -I. -ggdb -Werror -DDEBUG -DDEBUGDB 
-#CFLAGS=-std=gnu11 -fPIC -I. -Werror
-LINKFLAGS=-L1_lib -lsubu -lsqlite3
-
-LIBFILE=$(LIBDIR)/libsubu.a
-
diff --git a/src-tranche/1_doc/todo.txt b/src-tranche/1_doc/todo.txt
deleted file mode 100644 (file)
index 1494e66..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-
-2019-03-22T13:37:23Z
-1. indentation
-
-   the first non blank line after the #tranche keyword sets the indentation
-   level for the following text.  When echoing to the output file 
-   remove that many leading spaces.
-
-   Hmm,  or allow options among the tranche parameters,  -indent 3 or
-   -indent '  '.
-   
diff --git a/src-tranche/1_include/tranche.h b/src-tranche/1_include/tranche.h
deleted file mode 100644 (file)
index 27990a6..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef TRANCHE_LIB_H
-#define TRANCHE_LIB_H
-
-int tranche_send(FILE *src, Da *arg_fds);
-
-
-
-#endif
diff --git a/src-tranche/1_tests/0_makefile b/src-tranche/1_tests/0_makefile
deleted file mode 100644 (file)
index 8b6f67c..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-# src-da/1_tests/0_makefile
-
-SHELL=/bin/bash
-
--include 0_makefile-flags
-
-all: version deps lib execs
-
-%::
-       $(MAKE) $@
-
-
-
-
diff --git a/src-tranche/1_tests/0_makefile-flags b/src-tranche/1_tests/0_makefile-flags
deleted file mode 100644 (file)
index c990581..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-
-# some versions of Linux need a -e option others complain if there is a -e .. and it isn't the binary for echo ..
-ECHO= echo
-#ECHO= echo -e
-
-# directories used by this makefile, these could all be set to dot for
-# the simplest source directory structure
-
-#LIDBIR, EXECSDIR, HDIR hold the make results that might later be staged
-#$(PWD) is the directory that make was called from, this is already build in
-#set to dot to use the same directory as the source code
-#leave blank to ommit
-DEPRDIR=
-DOCDIR=
-EXECSDIR=.
-INCDIR=.
-LIBDIR=.
-TESTDIR=.
-TMPDIR=1_tmp
-TOOLSDIR=$(realpath $(PROJECT_SUBU)/tools)
-TRYDIR=
-
-
-# compiler and flags
-CC=gcc
-CFLAGS=-std=gnu11 -fPIC -I. -I../1_include -ggdb -Werror -DDEBUG -DDEBUGDB 
-#CFLAGS=-std=gnu11 -fPIC -I. -I../1_include -Werror
-LINKFLAGS=-L. -L../1_lib -ltests -lda
-
-LIBFILE=libtranche.a
-MAKE=/usr/bin/make --no-print-directory -f $(PROJECT_SUBU)/tools/lib/makefile_cc
-
-
diff --git a/src-tranche/1_tests/test1.dat b/src-tranche/1_tests/test1.dat
deleted file mode 100644 (file)
index b03df3f..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-
-#tranche test11.dat test12.dat
-The little red hen said to Mick, no thank you not today sir.
-And then all the barnes animals shouted out in glee.
-No more misery!
-#tranche test13.dat
-apple banana pear
-kiwi
-#tranche-end
-cows
-and cats
-#tranche-end
-
-the between space
-
-#tranche test14.dat
-int float if while
-do
-function
-#tranche-end
-
-#tranche test15.dat
-#tranche-end
\ No newline at end of file
diff --git a/src-tranche/1_tests/test1.sh b/src-tranche/1_tests/test1.sh
deleted file mode 100644 (file)
index c1140ca..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/bash -x
-./tranche test1.dat >test1stdout.dat
-diff test11.dat test11.dat.expected
-diff test12.dat test12.dat.expected
-diff test13.dat test13.dat.expected
-diff test14.dat test14.dat.expected
-diff test15.dat test15.dat.expected
-diff test1stdout.dat test1stdout.dat.expected
-rm test11.dat test12.dat test13.dat test14.dat test15.dat test1stdout.dat
-
diff --git a/src-tranche/1_tests/test11.dat.expected b/src-tranche/1_tests/test11.dat.expected
deleted file mode 100644 (file)
index 2c2904a..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-The little red hen said to Mick, no thank you not today sir.
-And then all the barnes animals shouted out in glee.
-No more misery!
-cows
-and cats
diff --git a/src-tranche/1_tests/test12.dat.expected b/src-tranche/1_tests/test12.dat.expected
deleted file mode 100644 (file)
index 2c2904a..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-The little red hen said to Mick, no thank you not today sir.
-And then all the barnes animals shouted out in glee.
-No more misery!
-cows
-and cats
diff --git a/src-tranche/1_tests/test13.dat.expected b/src-tranche/1_tests/test13.dat.expected
deleted file mode 100644 (file)
index 81fb20c..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-apple banana pear
-kiwi
diff --git a/src-tranche/1_tests/test14.dat.expected b/src-tranche/1_tests/test14.dat.expected
deleted file mode 100644 (file)
index 0d8b89b..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-int float if while
-do
-function
diff --git a/src-tranche/1_tests/test15.dat.expected b/src-tranche/1_tests/test15.dat.expected
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/src-tranche/1_tests/test1stdout.dat.expected b/src-tranche/1_tests/test1stdout.dat.expected
deleted file mode 100644 (file)
index 4e519ff..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-the between space
-
-
diff --git a/src-tranche/1_tests/tranche b/src-tranche/1_tests/tranche
deleted file mode 120000 (symlink)
index acf4a6f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../1_execs/tranche
\ No newline at end of file
diff --git a/src-tranche/tranche.cli.c b/src-tranche/tranche.cli.c
deleted file mode 100644 (file)
index 8df4337..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-
-#include <stdio.h>
-#include <unistd.h>
-#include <da.h>
-#include "tranche.lib.h"
-
-int main(int argc, char **argv, char **envp){
-  if(argc != 2){
-    fprintf(stderr, "usage: %s <source-file>\n",argv[0]);
-    return 1;
-  }
-  FILE *file = fopen(argv[1], "r");
-  if(!file){
-    fprintf(stderr,"could not open file %s\n", argv[1]);
-    return 2;
-  }
-  Da targets;
-  da_alloc(&targets, sizeof(int));
-  int fd = STDOUT_FILENO;
-  da_push(&targets, &fd);
-  tranche_send(file, &targets);
-  da_free(&targets);
-  fclose(file);
-  return 0;
-}
diff --git a/src-tranche/tranche.lib.c b/src-tranche/tranche.lib.c
deleted file mode 100644 (file)
index 4679dbe..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
-The purpose of this tools is to facilitate putting prototypes (declarations) next
-to implementations (definitions) in a single source file of a C/C++ programs. 
-
-Splits a single source file into multiple files.  Scans through the single
-source file looking for lines of the form:
-
-  #tranche filename ...
-
-With the # as the first non-space character on the line, and only filename
-following the tag. Upon finding such a line, copies all following lines into the
-listed files, until reaching the end marker:
-
-  #endtranche
-
-A next improvement of this file would be to support variables to be passed in
-for the file names.  As it stands, changing the file name requires editing 
-the source file.
-
-*/
-
-#include <da.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <ctype.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-//--------------------------------------------------------------------------------
-// parsing
-
-char newline = '\n';
-char terminator = 0;
-
-char tranche_begin_tag[] = "#tranche";
-size_t tranche_begin_tag_len = 8;
-
-char tranche_end_tag[] = "#tranche-end";
-size_t tranche_end_tag_len = 12;
-
-// given a line
-// returns beginning of file name list
-static char *is_tranche_begin(char *pt){
-  while( *pt && isspace(*pt) ) pt++;
-  if(!*pt) return NULL;
-  if( strncmp(pt, tranche_begin_tag, tranche_begin_tag_len) ) return NULL;
-  return pt + tranche_begin_tag_len;
-}
-
-static char *is_tranche_end(char *pt){
-  while( *pt && isspace(*pt) ) pt++;
-  if(!*pt) return NULL;
-  if( strncmp(pt, tranche_end_tag, tranche_end_tag_len) ) return NULL;
-  return pt + tranche_end_tag_len;
-}
-
-static bool parse_file_list(Da *file_names, char *pt0){
-  char *pt1;
-  while( *pt0 && isspace(*pt0) ) pt0++;
-  pt1 = pt0;
-  while( *pt0 ){
-    while( *pt1 && !isspace(*pt1) ) pt1++;
-    char *file_name = strndup(pt0, pt1 - pt0);
-    da_push(file_names, &file_name);
-    while( *pt1 && isspace(*pt1) ) pt1++;
-    pt0 = pt1;
-  }
-}
-
-
-
-//--------------------------------------------------------------------------------
-// da_map calls
-
-static void tranche_open_fd(void *fnp, void *closure){
-  char *file_name = *(char **)fnp;
-  Da *fdap = (Da *)closure;
-  int fd = open(file_name, O_CREAT | O_TRUNC | O_WRONLY, 0666);
-  if(fd == -1){
-    fprintf(stderr, "Could not open file %s\n", file_name);
-    return;
-  }
-  da_push(fdap, &fd);  
-  return;
-}
-static void tranche_open_fds(Da *fnap, Da *fdap){
-  da_map(fnap, tranche_open_fd, fdap);
-}
-
-static void tranche_close_fd(void *fdp, void *closure){
-  close(*(int *)fdp);
-}
-static void tranche_close_fds(Da *fdap){
-  da_map(fdap, tranche_close_fd, NULL);
-  da_rewind(fdap);
-}
-
-static void tranche_puts(void *fdp, void *string){
-  write(*(int *)fdp, string, strlen(string));
-}
-static void tranche_puts_all(Da *fdap, char *string){
-  da_map(fdap, tranche_puts, string);
-}
-
-
-
-//--------------------------------------------------------------------------------
-// we have a little problem if the user tries to tranche two things to the same file ..
-int tranche_send(FILE *src, Da *arg_fdap){
-  char *pt;
-  Da line;
-  Da file_name_arr;
-  Da fda;
-  da_alloc(&line, sizeof(char));
-  da_alloc(&file_name_arr, sizeof(char *));
-  da_alloc(&fda, sizeof(int));
-
-  while( !feof(src) ){
-    da_fgets(&line, src);
-    if( is_tranche_end(line.base) ) break;
-    pt = is_tranche_begin(line.base);
-    if(pt){ // then this line is the start of a nested tranche block
-      parse_file_list(&file_name_arr, pt);
-      tranche_open_fds(&file_name_arr, &fda);
-      da_free_elements(&file_name_arr);
-      tranche_send(src, &fda);
-      tranche_close_fds(&fda);
-    }else{
-      da_pop(&line, NULL); // pop the terminating zero
-      da_push(&line, &newline);
-      da_push(&line, &terminator);
-      tranche_puts_all(arg_fdap, line.base);
-    }
-    da_rewind(&line);
-  }
-
-  da_free(&line);
-  da_free(&file_name_arr);
-  da_free(&fda);
-  return 0;
-}
diff --git a/src-tranche/tranche.lib.h b/src-tranche/tranche.lib.h
deleted file mode 100644 (file)
index 27990a6..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef TRANCHE_LIB_H
-#define TRANCHE_LIB_H
-
-int tranche_send(FILE *src, Da *arg_fds);
-
-
-
-#endif
diff --git a/subu-0/0_makefile b/subu-0/0_makefile
new file mode 100644 (file)
index 0000000..b8c7b9d
--- /dev/null
@@ -0,0 +1,40 @@
+# src/0_makefile
+
+SHELL=/bin/bash
+
+-include 0_makefile_flags
+
+SUID_TOOL=$(TOOLSDIR)/bin/setuid_root.sh
+MAKE=/usr/bin/make -f $(PROJECT_SUBU)/tools/lib/makefile_cc
+
+SOURCES=$(wildcard *.c)
+HFILES=$(wildcard *.h)
+
+all: version deps lib execs
+
+version:
+       $(MAKE) $@
+       @echo "SUID_TOOL: " $(SUID_TOOL)
+
+deps:
+       makeheaders $(SOURCES) $(HFILES)
+       sed -i '/^ *int *main *(.*)/d' *.h
+       $(MAKE) $@
+
+execs:
+       $(MAKE) $@
+       @echo "-> $(SUID_TOOL) $(EXECSDIR)/subu-mk-0 $(EXECSDIR)/subu-rm-0 $(EXECSDIR)/subu-bind-all"
+       cat $(SUID_TOOL)
+       @echo -n "Are you sure? [y/N] " && read ans && [ $${ans:-N} == y ]
+       sudo $(SUID_TOOL) $(EXECSDIR)/subu-mk-0 $(EXECSDIR)/subu-rm-0 $(EXECSDIR)/subu-bind-all
+
+clean:
+       $(MAKE) $@
+       for i in $(HFILES); do rm $$i; done
+
+%::
+       $(MAKE) $@
+
+
+
+
diff --git a/subu-0/0_makefile-flags b/subu-0/0_makefile-flags
new file mode 100644 (file)
index 0000000..0da8b61
--- /dev/null
@@ -0,0 +1,31 @@
+
+# some versions of Linux need a -e option others complain if there is a -e .. and it isn't the binary for echo ..
+ECHO= echo
+#ECHO= echo -e
+
+# directories used by this makefile, these could all be set to dot for
+# the simplest source directory structure
+
+#LIDBIR, EXECSDIR, HDIR hold the make results that might later be staged
+#$(PWD) is the directory that make was called from, this is already build in
+#set to dot to use the same directory as the source code
+#leave blank to ommit
+DEPRDIR=1_deprecated
+DOCDIR=1_doc
+EXECSDIR=1_execs
+HDIR=1_headers
+LIBDIR=1_lib
+TESTDIR=1_tests
+TMPDIR=1_tmp
+TOOLSDIR=$(realpath $(PROJECT_SUBU)/tools)
+TRYDIR=1_try
+
+
+# compiler and flags
+CC=gcc
+CFLAGS=-std=gnu11 -fPIC -I. -ggdb -Werror -DDEBUG -DDEBUGDB 
+#CFLAGS=-std=gnu11 -fPIC -I. -Werror
+LINKFLAGS=-L1_lib -lsubu -lsqlite3
+
+LIBFILE=$(LIBDIR)/libsubu.a
+
diff --git a/subu-0/1_deprecated/dispatch_exec.lib.c b/subu-0/1_deprecated/dispatch_exec.lib.c
new file mode 100644 (file)
index 0000000..024bff8
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ fork/execs/wait the command passed in argv[0];
+ Returns -1 upon failure.
+
+ The wstatus returned from wait() might be either the error returned by exec
+ when it failed, or the return value from the command.  An arbitary command is
+ passed in, so we don't know what its return values might be. Consquently, we
+ have no way of multiplexing a unique exec error code with the command return
+ value within wstatus.  If the prorgrammer knows the return values of the
+ command passed in, and wants better behavior, he or she can spin a special
+ version of dispatch for that command.
+*/
+#include "dispatch_exec.lib.h"
+
+// without this #define execvpe is undefined
+#define _GNU_SOURCE   
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <wait.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+
+
+int dispatch_exec(char **argv, char **envp){
+  if( !argv || !argv[0] ){
+    fprintf(stderr, "argv[0] null. Null command passed into dispatch().\n");
+    return -1;
+  }
+  #ifdef DEBUG
+    dbprintf("dispatching exec, args follow:\n");
+    char **apt = argv;
+    while( *apt ){
+      dbprintf("\t%s",*apt);
+    apt++;
+    }
+    dbprintf("\n");
+  #endif
+  char *command = argv[0];
+  pid_t pid = fork();
+  if( pid == -1 ){
+    fprintf(stderr, "fork() failed in dispatch().\n");
+    return -1;
+  }
+  if( pid == 0 ){ // we are the child
+    execvpe(command, argv, envp);
+    // exec will only return if it has an error ..
+    perror(command);
+    return -1;
+  }else{ // we are the parent
+    int wstatus;
+    waitpid(pid, &wstatus, 0);
+    if(wstatus)
+      return -1;
+    else
+      return 0;
+  }
+}
diff --git a/subu-0/1_deprecated/dispatch_f.lib.c b/subu-0/1_deprecated/dispatch_f.lib.c
new file mode 100644 (file)
index 0000000..5c199f5
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+  Forks a new process and runs the a function in that new process.  I.e. it 'spawns' a function.
+
+  f must have the specified prototype. I.e. it accepts one void pointer and
+  returns a positive integer. (Negative integers are used for dispatch error codes.)
+
+  dispatch_f_euid_egid changes to the new euid and egid before running the function.
+
+  If the change to in euid/egid fails, the forked process exits with a negative status.
+  If the function has an error, it returns a positive status.  A status of zero means
+  that all went well.
+
+  Because f is running in a separate process, the return status is the only means
+  of communication going back to the calling process.
+
+
+*/
+#define _GNU_SOURCE
+
+#include "dispatch_f.lib.h"
+// we need the declaration for uid_t etc.
+// without this #define execvpe is undefined
+#define _GNU_SOURCE   
+
+#include <wait.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+#if INTERFACE
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+//--------------------------------------------------------------------------------
+// dispatch_f_ctx class
+//
+#if INTERFACE
+#define ERR_NEGATIVE_RETURN_STATUS -1
+#define ERR_DISPATCH_F_FORK -2
+#define ERR_DISPATCH_F_SETEUID -3
+#define ERR_DISPATCH_F_SETEGID -4
+
+// both name and fname are static allocations
+struct dispatch_f_ctx{
+  char *dispatcher; // name of the dispatch function (currently "dispatch_f" or "dispatch_f_euid_egid")
+  char *dispatchee; // name of the function being dispatched
+  int err;
+  int status; // return value from the function
+};
+#endif
+dispatch_f_ctx *dispatch_f_ctx_mk(char *name, char *fname){
+  dispatch_f_ctx *ctxp = malloc(sizeof(dispatch_f_ctx));
+  ctxp->dispatcher = name;
+  ctxp->dispatchee = fname;
+  ctxp->err = 0;
+  return ctxp;
+}
+void dispatch_f_ctx_free(dispatch_f_ctx *ctxp){
+   // no dynamic variables to be freed in ctx
+  free(ctxp); 
+}
+void dispatch_f_mess(struct dispatch_f_ctx *ctxp){
+  if(ctxp->err == 0) return;
+  switch(ctxp->err){
+  case ERR_NEGATIVE_RETURN_STATUS:
+    fprintf(stderr, "%s, function \"%s\" broke contract with a negative return value.", ctxp->dispatcher, ctxp->dispatchee);
+    break;
+  case ERR_DISPATCH_F_FORK:
+  case ERR_DISPATCH_F_SETEUID:
+  case ERR_DISPATCH_F_SETEGID:
+    fprintf(stderr, "%s, ", ctxp->dispatcher);
+    perror(ctxp->dispatcher);
+    break;
+  }
+  fputc('\n', stderr);
+}
+
+//--------------------------------------------------------------------------------
+// interface call point
+dispatch_f_ctx *dispatch_f(char *fname, int (*f)(void *arg), void *f_arg){
+  dispatch_f_ctx *ctxp = dispatch_f_ctx_mk("dispatch_f", fname);
+  #ifdef DEBUG
+  dbprintf("%s %s\n", ctxp->dispatcher, ctxp->dispatchee);
+  #endif
+  pid_t pid = fork();
+  if( pid == -1 ){
+    ctxp->err = ERR_DISPATCH_F_FORK; // we are still in the parent process
+    return ctxp;
+  }
+  if( pid == 0 ){ // we are the child
+    int status = (*f)(f_arg); // we require that f return a zero or positive value
+    if( status < 0 ) status = ERR_NEGATIVE_RETURN_STATUS;
+    exit(status);
+  }else{ // we are the parent
+    waitpid(pid, &(ctxp->status), 0);
+    return ctxp;
+  }
+}
+
+//--------------------------------------------------------------------------------
+// interface call point
+dispatch_f_ctx *dispatch_f_euid_egid(char *fname, int (*f)(void *arg), void *f_arg, uid_t euid, gid_t egid){
+  dispatch_f_ctx *ctxp = dispatch_f_ctx_mk("dispatch_f_euid_egid", fname);
+  #ifdef DEBUG
+  dbprintf("%s %s as euid:%u egid:%u\n", ctxp->dispatcher, ctxp->dispatchee, euid, egid);
+  #endif
+  pid_t pid = fork();
+  if( pid == -1 ){
+    ctxp->err = ERR_DISPATCH_F_FORK;
+    return ctxp;
+  }
+  if( pid == 0 ){ // we are the child
+    int status;
+    if( seteuid(euid) == -1 )
+      status = ERR_DISPATCH_F_SETEUID;
+    else if( setegid(egid) == -1 )
+      status = ERR_DISPATCH_F_SETEGID;
+    else{
+      status = (*f)(f_arg);
+      if( status < 0 ) status = ERR_NEGATIVE_RETURN_STATUS;
+      exit(status);
+    }
+  }else{ // we are the parent
+    waitpid(pid, &(ctxp->status), 0);
+    return ctxp;
+  }
+}
+
+
diff --git a/subu-0/1_deprecated/dispatch_useradd.lib.c b/subu-0/1_deprecated/dispatch_useradd.lib.c
new file mode 100644 (file)
index 0000000..7b75291
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+There is no C library interface to useradd(8), but if there were, this function
+would be found there instead.
+
+*/
+#include "dispatch_useradd.lib.h"
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+
+#if INTERFACE
+#include <sys/types.h>
+#include <pwd.h>
+#define ERR_DISPATCH_USERADD_ARGC 1
+#define ERR_DISPATCH_USERADD_DISPATCH 2
+#define ERR_DISPATCH_USERADD_PWREC 3
+struct dispatch_useradd_ret_t{
+  uint error;
+  struct passwd *pw_record;  
+};
+#endif
+
+
+// we have a contract with the caller that argv[1] is always the subuname
+struct dispatch_useradd_ret_t dispatch_useradd(char **argv, char **envp){
+  struct dispatch_useradd_ret_t ret;
+  {
+    if( !argv || !argv[0] || !argv[1]){
+      fprintf(stderr,"useradd() needs a first argument as the name of the user to be made");
+      ret.error = ERR_DISPATCH_USERADD_ARGC;
+      ret.pw_record = NULL;
+      return ret;
+    }
+
+    char *subu_name;
+    {
+      subu_name = argv[1];
+      if( dispatch_exec(argv, envp) == -1 ){
+        fprintf(stderr,"%s failed\n", argv[0]);
+        ret.error = ERR_DISPATCH_USERADD_DISPATCH;
+        ret.pw_record = NULL;
+        return ret;
+      }}
+
+    {
+      struct passwd *pw_record = getpwnam(subu_name);
+      uint count = 1;
+      while( !pw_record && count <= 3 ){
+        #ifdef DEBUG
+          printf("try %u, getpwnam failed, trying again\n", count);
+        #endif
+        sleep(1);
+        pw_record = getpwnam(subu_name);
+        count++;
+      }
+      if( !pw_record ){
+        ret.error = ERR_DISPATCH_USERADD_PWREC;
+        ret.pw_record = NULL;
+        return ret;
+      }
+      ret.error = 0;
+      ret.pw_record = pw_record;
+      return ret;
+    }}}
+
diff --git a/subu-0/1_deprecated/subu-rm-0.lib.c b/subu-0/1_deprecated/subu-rm-0.lib.c
new file mode 100644 (file)
index 0000000..ccad437
--- /dev/null
@@ -0,0 +1,381 @@
+/*
+  subu-rm-0 subuname
+
+  1. get our uid and lookup masteru_name in /etc/passwd
+  2. lookup masteru_name/subuname in config file, which gives us subu_username
+  3. unmount subuland/subuname
+  4. userdel subu_username
+  5. rmdir subuland/subuname
+
+  Note, as per the man page, we are not allowed to free the memory allocated by getpwid().
+
+*/
+#include "subu-mk-0.lib.h"
+
+// without this #define we get the warning: implicit declaration of function â€˜seteuid’/‘setegid’
+#define _GNU_SOURCE   
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#if INTERFACE
+#include <stdbool.h>
+#include <errno.h>
+#include <sqlite3.h>
+#endif
+
+//--------------------------------------------------------------------------------
+// an instance is subu_rm_0_ctx is returned by subu_rm_0
+//
+#if INTERFACE
+#define ERR_SUBU_RM_0_MKDIR_SUBUHOME 1
+#define ERR_SUBU_RM_0_RMDIR_SUBUHOME 2
+#define ERR_SUBU_RM_0_SUBUNAME_MALFORMED 3
+#define ERR_SUBU_RM_0_SETUID_ROOT 4
+#define ERR_SUBU_RM_0_MASTERU_HOMELESS 5
+#define ERR_SUBU_RM_0_MALLOC 6
+#define ERR_SUBU_RM_0_CONFIG_FILE 7
+#define ERR_SUBU_RM_0_SUBUHOME_EXISTS 8
+#define ERR_SUBU_RM_0_BUG_SSS 9
+#define ERR_SUBU_RM_0_FAILED_USERADD 10
+
+struct subu_rm_0_ctx{
+  char *name;
+  char *subuland;
+  char *subuhome;
+  char *subu_username;
+  bool free_aux;
+  char *aux;
+  uint err;
+};
+#endif
+struct subu_rm_0_ctx *subu_rm_0_ctx_mk(){
+  struct subu_rm_0_ctx *ctxp = malloc(sizeof(struct subu_rm_0_ctx));
+  ctxp->name = "subu_rm_0";
+  ctxp->subuland = 0;
+  ctxp->subuhome = 0;
+  ctxp->subu_username = 0;
+  ctxp->free_aux = false;
+  ctxp->aux = 0;
+}
+void subu_rm_0_ctx_free(struct subu_rm_0_ctx *ctxp){
+  free(ctxp->subuland);
+  free(ctxp->subuhome);
+  free(ctxp->subu_username);
+  if(ctxp->free_aux) free(ctxp->aux);
+  free(ctxp);
+}
+// must be called before any system calls, otherwise perror() will be messed up
+void subu_rm_0_mess(struct subu_rm_0_ctx *ctxp){
+  switch(ctxp->err){
+  case 0: return;
+  case ERR_SUBU_RM_0_MKDIR_SUBUHOME:
+    fprintf(stderr, "masteru could not make subuhome, \"%s\"", ctxp->subuhome);
+    break;
+  case ERR_SUBU_RM_0_SUBUNAME_MALFORMED:
+    fprintf(stderr, "subuname, \"%s\" is not in [ _.-a-zA-Z0-9]*", ctxp->aux);
+    break;
+  case ERR_SUBU_RM_0_SETUID_ROOT:
+    fprintf(stderr, "This program must be run setuid root from a user account.");
+    break;
+  case ERR_SUBU_RM_0_MASTERU_HOMELESS:
+    fprintf(stderr,"Masteru, \"%s\", has no home directory", ctxp->aux);
+    break;
+  case ERR_SUBU_RM_0_MALLOC:
+    perror(ctxp->name);
+  break;
+  case ERR_SUBU_RM_0_CONFIG_FILE:
+    fprintf(stderr, "config file error: %s", ctxp->aux);
+  break;
+  case ERR_SUBU_RM_0_SUBUHOME_EXISTS:
+    fprintf(stderr, "a file system object already exists at subuhome, \"%s\"\n", ctxp->subuhome);
+  break;
+  case ERR_SUBU_RM_0_BUG_SSS:
+    perror(ctxp->name);
+  break;
+  case ERR_SUBU_RM_0_FAILED_USERADD:
+    fprintf(stderr, "%u useradd failed\n", ctxp->subu_username);
+  break;
+  default:
+    fprintf(stderr, "unknown error code %d\n", ctxp->err);
+  }
+  fputc('\n', stderr);
+}
+
+//--------------------------------------------------------------------------------
+// dispatched functions
+//
+// the making of subuhome is dispatched to its own process so as to give it its own uid/gid
+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 ERR_SUBU_RM_0_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 ERR_SUBU_RM_0_RMDIR_SUBUHOME;
+  }
+  return 0;
+}
+
+//--------------------------------------------------------------------------------
+//  the public call point
+struct subu_rm_0_ctx *subu_rm_0(sqlite3 *db, char *subuname){
+
+  struct subu_rm_0_ctx *ctxp = subu_rm_0_ctx_mk();
+
+  //--------------------------------------------------------------------------------
+  #ifdef DEBUG
+  dbprintf("Checking that subuname is well formed and finding its length\n");
+  #endif
+  size_t subuname_len;
+  {
+    int ret = allowed_subuname(subuname, &subuname_len);
+    if( ret == -1 ){
+      ctxp->err = ERR_SUBU_RM_0_SUBUNAME_MALFORMED;
+      ctxp->aux = subuname;
+      return ctxp;
+    }}
+  
+  //--------------------------------------------------------------------------------
+  #ifdef DEBUG
+  dbprintf("Checking that we are running from a user and are setuid root.\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
+    dbprintf("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 ){
+      ctxp->err = ERR_SUBU_RM_0_SETUID_ROOT;
+      return ctxp;
+    }
+  }
+
+  //--------------------------------------------------------------------------------
+  #ifdef DEBUG
+  dbprintf("strings masteru_name and masteru_home\n");
+  #endif
+
+  char *masteru_name;
+  size_t masteru_name_len;
+  char *masteru_home;
+  size_t masteru_home_len;
+  size_t subuland_len;
+  {
+    struct passwd *masteru_pw_record_pt = getpwuid(masteru_uid); // reading /etc/passwd
+    masteru_name = masteru_pw_record_pt->pw_name;
+    masteru_name_len = strlen(masteru_name);
+    #ifdef DEBUG
+    dbprintf("masteru_name \"%s\" %zu\n", masteru_name, masteru_name_len);
+    #endif
+    masteru_home = masteru_pw_record_pt->pw_dir;
+    masteru_home_len = strlen(masteru_home);
+    #ifdef DEBUG
+    dbprintf("masteru_home \"%s\" %zu\n", masteru_home, masteru_home_len);
+    #endif
+    masteru_home_len = strlen(masteru_home);
+    if( masteru_home_len == 0 || masteru_home[0] == '(' ){
+      ctxp->err = ERR_SUBU_RM_0_MASTERU_HOMELESS;
+      ctxp->aux = masteru_name;  // we can not free a passwd struct, or its fields.  I assume then it isn't re-entrant safe.
+      return ctxp;
+    }
+    // char *subuland_extension = "/subuland/"; // moved to common.lib.c
+    size_t subuland_extension_len = strlen(subuland_extension);
+    ctxp->subuland = (char *)malloc( masteru_home_len + subuland_extension_len + 1 );
+    if(!ctxp->subuland){
+      ctxp->err = ERR_SUBU_RM_0_MALLOC;
+      return ctxp;
+    }
+    strcpy(ctxp->subuland, masteru_home);
+    strcpy(ctxp->subuland + masteru_home_len, subuland_extension);
+    subuland_len = masteru_home_len + subuland_extension_len;
+    #ifdef DEBUG
+    dbprintf("subuland \"%s\" %zu\n", ctxp->subuland, subuland_len);
+    #endif
+  }
+
+  //--------------------------------------------------------------------------------
+  #ifdef DEBUG
+  dbprintf("lookup subu_username from masteru_name/subuname in config file\n");
+  #endif
+  char *subu_username; // this is part of ctx and must be freed
+  {
+    int ret = subu_get_masteru_subu(db, masteru_name, subuname, &subu_username);
+    if( ret != SQLITE_DONE ){
+      printf("get failed\n");
+      return 2;
+    }
+    #ifdef DEBUG
+    printf("subu_username: %s\n", subu_username);  
+    #endif
+    
+  }
+
+  //--------------------------------------------------------------------------------
+  #ifdef DEBUG
+  dbprintf("strings subu_username and subuhome\n");
+  #endif
+  size_t subu_username_len;
+  size_t subuhome_len;
+  {
+    char *ns=0; // 'ns'  Number as String
+    char *mess=0;
+    if( subu_number_get( db, &ns, &mess ) != SQLITE_OK ){
+      ctxp->err = ERR_SUBU_RM_0_CONFIG_FILE;
+      ctxp->aux = mess;
+      ctxp->free_aux = true;
+      return ctxp;
+    }
+    size_t ns_len = strlen(ns);
+    ctxp->subu_username = malloc(1 + ns_len + 1);
+    if( !ctxp->subu_username ){
+      ctxp->err = ERR_SUBU_RM_0_MALLOC;
+      return ctxp;
+    }
+    strcpy(ctxp->subu_username, "s");
+    strcpy(ctxp->subu_username + 1, ns);
+    subu_username_len = ns_len + 1;
+    #ifdef DEBUG
+    dbprintf("subu_username \"%s\" %zu\n", ctxp->subu_username, subu_username_len);
+    #endif
+
+    subuhome_len = subuland_len + subuname_len; 
+    ctxp->subuhome = (char *)malloc(subuhome_len + 1);
+    if( !ctxp->subuhome ){
+      ctxp->err = ERR_SUBU_RM_0_MALLOC;
+      return ctxp;
+    }
+    strcpy (ctxp->subuhome, ctxp->subuland);
+    strcpy (ctxp->subuhome + subuland_len, subuname);
+    #ifdef DEBUG
+    dbprintf("subuhome \"%s\" %zu\n", ctxp->subuhome, subuhome_len);
+    #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
+  {
+    #ifdef DEBUG
+    dbprintf("as masteru, making the directory \"%s\"\n", ctxp->subuhome);
+    #endif
+    struct stat st;
+    if( stat(ctxp->subuhome, &st) != -1 ){
+      ctxp->err = ERR_SUBU_RM_0_SUBUHOME_EXISTS;
+      return ctxp;
+    }
+    dispatch_ctx *dfr = dispatch_f_euid_egid
+      (
+       "masteru_mkdir_subuhome", 
+       masteru_mkdir_subuhome, 
+       (void *)ctxp->subuhome,
+       masteru_uid, 
+       masteru_gid
+       );
+    if( dfr->err <= ERR_DISPATCH || dfr->err == ERR_SUBU_RM_0_MKDIR_SUBUHOME ){
+      #ifdef DEBUG
+      if( dfr->err == ERR_SUBU_RM_0_MKDIR_SUBUHOME )
+        perror("mkdir");
+      else
+        dispatch_f_mess(dfr);
+      #endif
+      ctxp->err = ERR_SUBU_RM_0_MKDIR_SUBUHOME;
+      return ctxp;
+    }
+  }
+  #ifdef DEBUG
+  dbprintf("masteru made directory \"%s\"\n", ctxp->subuhome);
+  #endif
+
+  //--------------------------------------------------------------------------------
+  //  Make the subservient user account, i.e. the subu
+  {
+    #ifdef DEBUG
+      dbprintf("making subu \"%s\" as user \"%s\"\n", subuname, ctxp->subu_username);
+    #endif
+    #if BUG_SSS_CACHE_RUID
+      #ifdef DEBUG
+        dbprintf("setting inherited real uid to 0 to accomodate SSS_CACHE UID BUG\n");
+      #endif
+      if( setuid(0) == -1 ){
+        ctxp->err = ERR_SUBU_RM_0_BUG_SSS;
+        return ctxp;
+      }
+    #endif
+    char *command = "/usr/sbin/useradd";
+    char *argv[3];
+    argv[0] = command;
+    argv[1] = ctxp->subu_username;
+    argv[2] = (char *) NULL;
+    char *envp[1];
+    envp[0] = (char *) NULL;
+    dispatch_ctx *dfr = dispatch_exec(argv, envp);
+    if( dfr->err != 0 ){
+      #ifdef DEBUG 
+      if( dfr->err <= ERR_DISPATCH )
+        dispatch_f_mess(dfr);
+      else
+        perror("useradd");
+      #endif
+      // go back and remove the directory we made in subuland
+      dispatch_ctx *dfr = dispatch_f_euid_egid
+        (
+         "masteru_rmdir_subuhome", 
+         masteru_rmdir_subuhome, 
+         (void *)ctxp->subuhome,
+         masteru_uid, 
+         masteru_gid
+         );
+      #ifdef DEBUG
+        if( dfr->err <= ERR_DISPATCH || dfr->err == ERR_SUBU_RM_0_RMDIR_SUBUHOME )
+          if( dfr->err == ERR_SUBU_RM_0_RMDIR_SUBUHOME )
+            perror("rmdir");
+          else
+            dispatch_f_mess(dfr);
+      #endif
+      ctxp->err = ERR_SUBU_RM_0_FAILED_USERADD;
+      return ctxp;
+    }
+    #ifdef DEBUG
+    dbprintf("added user \"%s\"\n", ctxp->subu_username);
+    #endif
+  }  
+  
+  //--------------------------------------------------------------------------------
+  #ifdef DEBUG
+  dbprintf("setting the masteru_name, subuname, subu_username relation\n");
+  #endif
+  {
+    int ret = subu_put_masteru_subu(db, masteru_name, subuname, ctxp->subu_username);
+    if( ret != SQLITE_DONE ){
+      ctxp->err = ERR_SUBU_RM_0_CONFIG_FILE;
+      ctxp->aux = "insert of masteru subu relation failed";
+      return ctxp;
+    }
+  }
+
+  #ifdef DEBUG
+  dbprintf("finished subu-mk-0(%s)\n", subuname);
+  #endif
+  ctxp->err = 0;
+  return ctxp;
+}
diff --git a/subu-0/1_deprecated/subudb-number-next.cli.c b/subu-0/1_deprecated/subudb-number-next.cli.c
new file mode 100644 (file)
index 0000000..3373173
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+Set or get a new maximum subu number. Currently doesn't do the setting part.
+
+*/
+#include "subudb-number-next.cli.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+
+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 ){
+    sqlite3_close(db);
+    fprintf(stderr, "error exit, could not open db file\n");
+    return SUBU_ERR_DB_FILE;
+  }
+
+  // read and print the current max
+  char *mess;
+  int n;
+  rc = subudb_number_next(db, masteru_name, &n, &mess);
+  if( rc == SQLITE_DONE ){
+    printf("%d\n", n);
+  }else{
+    fprintf(stderr, "subudb_number_next indicates failure by returning %d\n",rc);
+    fprintf(stderr, "and issues message, %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/subu-0/1_doc/to_do.txt b/subu-0/1_doc/to_do.txt
new file mode 100644 (file)
index 0000000..0b989cc
--- /dev/null
@@ -0,0 +1,38 @@
+2019-02-05T23:14:40Z
+  error can cause subu-mk-0 to leave the creating of a subu in an intermediate
+  state.  Rather than bailing on some of the errors we need to clean up instead.
+  Perhaps the yet to be written subu-rm program will be resilent enough to do
+  more general cleanup.
+
+2019-02-23T18:56:31Z
+  need to modify subu-init to take a configuration file name argument instead of
+  using a global variabel value.  might want to add arguments to other subu
+  commands also
+
+2019-03-11T13:48:03Z
+  in subu.lib.c append cascading rmdir failure mess to useradd failure mess
+
+2019-03-11T13:48:03Z
+  want to add subu-type to masteru_subu(),  I imagine there will be static,
+  permanent, and temporary subu types.
+
+2019-03-12T18:35:06Z
+  the masteru subu relation should contain the uid of the masteru as
+  well as the backup type for the subu:  git, rdiff, rsync, none.
+  and the persisitance fo the subu: indefinite, session.
+  seems that operations need to be logged, in case the db is lost
+  the transcript can be played back.  It should also be possible
+  to co-opt an existing user as a subu, though, would require
+  sudo privs.
+
+  need to add messages for subu errors I've added to the end of
+  the list in subu.lib.c
+  
+2019-03-14T10:43:50Z
+
+   should mod all to he subudb routines to return a message, probably
+   strdup(sqlite_errmsg(db)), then the callers to these routines can just pass
+   mess in rather than making up new ones for each situation. The error code
+   probably already carries the contexts specific message.  Or perhaps add
+   a string cat function for message strings, that would run through a stream
+   and free the originals.
diff --git a/subu-0/1_tests/0_makefile b/subu-0/1_tests/0_makefile
new file mode 100644 (file)
index 0000000..67cea25
--- /dev/null
@@ -0,0 +1,32 @@
+# src/1_tests/0_makefile
+
+SHELL=/bin/bash
+
+-include 0_makefile_flags
+
+MAKE=/usr/bin/make -f $(PROJECT_SUBU)/tools/lib/makefile_cc
+
+SOURCES=$(wildcard *.c)
+HFILES=$(wildcard *.h)
+
+all: version deps lib execs
+
+deps:
+       makeheaders $(SOURCES) $(HFILES)
+       sed -i '/^ *int *main *(.*)/d' *.h
+       $(MAKE) $@
+
+clean:
+       $(MAKE) $@
+       for i in $(HFILES); do rm $$i; done
+
+dist-clean:
+       $(MAKE) $@
+       if [ -f subudb ]; then rm subudb; fi
+
+%::
+       $(MAKE) $@
+
+
+
+
diff --git a/subu-0/1_tests/0_makefile_flags b/subu-0/1_tests/0_makefile_flags
new file mode 100644 (file)
index 0000000..8818691
--- /dev/null
@@ -0,0 +1,31 @@
+
+# some versions of Linux need a -e option others complain if there is a -e .. and it isn't the binary for echo ..
+ECHO= echo
+#ECHO= echo -e
+
+# directories used by this makefile, these could all be set to dot for
+# the simplest source directory structure
+
+#LIDBIR, EXECSDIR, HDIR hold the make results that might later be staged
+#$(PWD) is the directory that make was called from, this is already build in
+#set to dot to use the same directory as the source code
+#leave blank to ommit
+DEPRDIR=
+DOCDIR=
+EXECSDIR=.
+HDIR=.
+LIBDIR=.
+TESTDIR=.
+TMPDIR=1_tmp
+TOOLSDIR=$(realpath $(PROJECT_SUBU)/tools)
+TRYDIR=
+
+
+# compiler and flags
+CC=gcc
+CFLAGS=-std=gnu11 -fPIC -I. -ggdb -Werror -DDEBUG -DDEBUGDB 
+#CFLAGS=-std=gnu11 -fPIC -I. -Werror
+LINKFLAGS=-L$(PROJECT_SUBU)/src/$(LIBDIR) -L. -lsubu -lsqlite3 -lsubutests
+
+LIBFILE=$(LIBDIR)/libtests.a
+
diff --git a/subu-0/1_tests/1_tmp/makefile_deps b/subu-0/1_tests/1_tmp/makefile_deps
new file mode 100644 (file)
index 0000000..9486ae8
--- /dev/null
@@ -0,0 +1,4 @@
+da.cli.o: da.cli.c da.cli.h
+
+./da : da.cli.o ./libtests.a
+       gcc -o ./da da.cli.o -L/home/morpheus/subu_land/subu/src/. -L. -lsubu -lsqlite3 -lsubutests
diff --git a/subu-0/1_tests/da.cli.c b/subu-0/1_tests/da.cli.c
new file mode 100644 (file)
index 0000000..910a15e
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+Tests for da.
+
+*/
+
+#include <da.cli.h>
+#include <stdbool.h>
+
+int test_da_0(){
+  da da0;
+  da_alloc(&da0, sizeof(int)); // leaves room for 4 ints
+  int i = 0;
+  int *pt = da0->base;
+  // will double, 4 -> 8, then double 8 -> 16
+  while( i < 10 ){
+    if(da_boundq(&da0, pt)){
+      char *old_base = da_expand(&da);
+      da_rebase(&da, old_base, pt);
+    }
+    *pt = i;
+  i++;
+  pt++;
+  }
+
+  bool f0 = da.size == sizof(int) * 16;
+  bool f1 = 10 == (da.end - da.base) / sizeof(int);
+  bool f2 = true;
+  pt = da0->base;
+  while( i < 10 ){
+    f2 = f2 && *pt == i && !da_endq(&da, pt);
+  i++;
+  pt++;
+  }
+  bool f3 = da_endq(&da, pt);
+
+  return f0 && f1 && f2 && f3;
+}
+
+
+int main(){
+
+  bool da_0_passed = test_da_0();
+  if( da_0_passed ){
+    printf("da_0_passed");
+    return 0;
+  }
+  printf("da_0_failed");
+  return 1;
+
+}
diff --git a/subu-0/1_tests/libtests.a b/subu-0/1_tests/libtests.a
new file mode 100644 (file)
index 0000000..8b277f0
--- /dev/null
@@ -0,0 +1 @@
+!<arch>
diff --git a/subu-0/1_tmp/da.lib.h b/subu-0/1_tmp/da.lib.h
new file mode 100644 (file)
index 0000000..4702189
--- /dev/null
@@ -0,0 +1,23 @@
+/* \aThis file was automatically generated.  Do not edit! */
+#undef INTERFACE
+#include <stdlib.h>
+#include <stdbool.h>
+void daps_map(char **base,char **end_pt,void f(void *));
+#define RETURN(rc) \
+  { daps_map(mrs, mrs_end, free); return rc; }
+void daps_alloc(char ***base,size_t *s);
+#define MK_MRS \
+  char **mrs;  \
+  char **mrs_end; \
+  size_t mrs_size; \
+  daps_alloc(&mrs, &mrs_size);\
+  mrs_end = mrs;
+void daps_push(char ***base,char ***pt,size_t *s,char *item);
+bool daps_bound(char **base,char **pt,size_t s);
+void daps_expand(char ***base,char ***pt,size_t *s);
+void da_map(void *base,void *end_pt,void f(void *),size_t item_size);
+void da_push(void **base,void **pt,size_t *s,void *item,size_t item_size);
+bool da_bound(void *base,void *pt,size_t s);
+void da_expand(void **base,void **pt,size_t *s);
+void da_alloc(void **base,size_t *s,size_t item_size);
+#define INTERFACE 0
diff --git a/subu-0/1_tmp/dbprintf.lib.h b/subu-0/1_tmp/dbprintf.lib.h
new file mode 100644 (file)
index 0000000..3056cf6
--- /dev/null
@@ -0,0 +1,3 @@
+/* \aThis file was automatically generated.  Do not edit! */
+#undef INTERFACE
+int dbprintf(const char *format,...);
diff --git a/subu-0/1_tmp/dispatch.lib.h b/subu-0/1_tmp/dispatch.lib.h
new file mode 100644 (file)
index 0000000..07e2271
--- /dev/null
@@ -0,0 +1,24 @@
+/* \aThis file was automatically generated.  Do not edit! */
+#undef INTERFACE
+#include <sys/types.h>
+#include <unistd.h>
+int dispatch_exec(char **argv,char **envp);
+typedef unsigned int uint;
+int dispatch_f_euid_egid(char *fname,int(*f)(void *arg),void *f_arg,uid_t euid,gid_t egid);
+int dbprintf(const char *format,...);
+int dispatch_f(char *fname,int(*f)(void *arg),void *f_arg);
+void dispatch_f_mess(char *fname,int err,char *dispatchee);
+#define ERR_DISPATCH_EXEC -1029
+#define ERR_DISPATCH_NULL_EXECUTABLE -1028
+#define ERR_DISPATCH_F_SETEGID -1027
+#define ERR_DISPATCH_F_SETEUID -1026
+#define ERR_DISPATCH_F_FORK -1025
+#define ERR_DISPATCH_NEGATIVE_RETURN_STATUS -1024
+#define ERR_DISPATCH -1024
+typedef struct dispatch_ctx dispatch_ctx;
+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
+};
+#define INTERFACE 0
diff --git a/subu-0/1_tmp/subu-bind-all.cli.h b/subu-0/1_tmp/subu-bind-all.cli.h
new file mode 100644 (file)
index 0000000..7e52675
--- /dev/null
@@ -0,0 +1,9 @@
+/* \aThis file was automatically generated.  Do not edit! */
+#undef INTERFACE
+#include <stdbool.h>
+#include <errno.h>
+#include <sqlite3.h>
+int subu_bind_all(char **mess,sqlite3 *db);
+#define SUBU_ERR_DB_FILE 8
+extern char DB_File[];
+#define SUBU_ERR_ARG_CNT 1
diff --git a/subu-0/1_tmp/subu-bind.cli.h b/subu-0/1_tmp/subu-bind.cli.h
new file mode 100644 (file)
index 0000000..af12d61
--- /dev/null
@@ -0,0 +1,7 @@
+/* \aThis file was automatically generated.  Do not edit! */
+#undef INTERFACE
+#include <stdbool.h>
+#include <errno.h>
+#include <sqlite3.h>
+int subu_bind(char **mess,char *masteru_name,char *subu_username,char *subuhome);
+#define SUBU_ERR_ARG_CNT 1
diff --git a/subu-0/1_tmp/subu-common.lib.h b/subu-0/1_tmp/subu-common.lib.h
new file mode 100644 (file)
index 0000000..cfdc520
--- /dev/null
@@ -0,0 +1,9 @@
+/* \aThis file was automatically generated.  Do not edit! */
+#undef INTERFACE
+extern char Subuland_Extension[];
+typedef unsigned int uint;
+extern uint First_Max_Subunumber;
+extern uint Subuhome_Perms;
+extern char DB_File[];
+#define BUG_SSS_CACHE_RUID 1
+#define INTERFACE 0
diff --git a/subu-0/1_tmp/subu-mk-0.cli.h b/subu-0/1_tmp/subu-mk-0.cli.h
new file mode 100644 (file)
index 0000000..487b509
--- /dev/null
@@ -0,0 +1,10 @@
+/* \aThis file was automatically generated.  Do not edit! */
+#undef INTERFACE
+#include <stdbool.h>
+#include <errno.h>
+#include <sqlite3.h>
+void subu_err(char *fname,int err,char *mess);
+int subu_mk_0(char **mess,sqlite3 *db,char *subuname);
+#define SUBU_ERR_DB_FILE 8
+extern char DB_File[];
+#define SUBU_ERR_ARG_CNT 1
diff --git a/subu-0/1_tmp/subu-rm-0.cli.h b/subu-0/1_tmp/subu-rm-0.cli.h
new file mode 100644 (file)
index 0000000..070bfe8
--- /dev/null
@@ -0,0 +1,10 @@
+/* \aThis file was automatically generated.  Do not edit! */
+#undef INTERFACE
+#include <stdbool.h>
+#include <errno.h>
+#include <sqlite3.h>
+void subu_err(char *fname,int err,char *mess);
+int subu_rm_0(char **mess,sqlite3 *db,char *subuname);
+#define SUBU_ERR_DB_FILE 8
+extern char DB_File[];
+#define SUBU_ERR_ARG_CNT 1
diff --git a/subu-0/1_tmp/subu.lib.h b/subu-0/1_tmp/subu.lib.h
new file mode 100644 (file)
index 0000000..69c5da7
--- /dev/null
@@ -0,0 +1,66 @@
+/* \aThis file was automatically generated.  Do not edit! */
+#undef INTERFACE
+typedef unsigned int uint;
+#include <sqlite3.h>
+typedef struct subudb_subu_element subudb_subu_element;
+int subudb_Masteru_Subu_get_subus(sqlite3 *db,char *masteru_name,subudb_subu_element **sa_pt,subudb_subu_element **sa_end_pt);
+struct subudb_subu_element {
+  char *subuname;
+  char *subu_username;
+};
+#include <stdbool.h>
+#include <errno.h>
+int subu_bind_all(char **mess,sqlite3 *db);
+int subu_bind(char **mess,char *masteru_name,char *subu_username,char *subuhome);
+int subudb_Masteru_Subu_rm(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);
+int subu_rm_0(char **mess,sqlite3 *db,char *subuname);
+int subudb_Masteru_Subu_put(sqlite3 *db,char *masteru_name,char *subuname,char *subu_username);
+#include <sys/types.h>
+#include <unistd.h>
+int dispatch_exec(char **argv,char **envp);
+#define BUG_SSS_CACHE_RUID 1
+void dispatch_f_mess(char *fname,int err,char *dispatchee);
+#define ERR_DISPATCH -1024
+int dispatch_f_euid_egid(char *fname,int(*f)(void *arg),void *f_arg,uid_t euid,gid_t egid);
+#include <stdlib.h>
+void daps_map(char **base,char **end_pt,void f(void *));
+#define RETURN(rc) \
+  { daps_map(mrs, mrs_end, free); return rc; }
+void daps_push(char ***base,char ***pt,size_t *s,char *item);
+int dbprintf(const char *format,...);
+void daps_alloc(char ***base,size_t *s);
+#define MK_MRS \
+  char **mrs;  \
+  char **mrs_end; \
+  size_t mrs_size; \
+  daps_alloc(&mrs, &mrs_size);\
+  mrs_end = mrs;
+int subu_mk_0(char **mess,sqlite3 *db,char *subuname);
+extern char Subuland_Extension[];
+int db_commit(sqlite3 *db);
+int db_rollback(sqlite3 *db);
+int subudb_number_set(sqlite3 *db,int n);
+int subudb_number_get(sqlite3 *db,int *n);
+int db_begin(sqlite3 *db);
+extern uint Subuhome_Perms;
+extern char DB_File[];
+void subu_err(char *fname,int err,char *mess);
+#define SUBU_ERR_BIND 15
+#define SUBU_ERR_N 14
+#define SUBU_ERR_SUBU_NOT_FOUND 13
+#define SUBU_ERR_FAILED_USERDEL 12
+#define SUBU_ERR_FAILED_USERADD 11
+#define SUBU_ERR_BUG_SSS 10
+#define SUBU_ERR_SUBUHOME_EXISTS 9
+#define SUBU_ERR_DB_FILE 8
+#define SUBU_ERR_HOMELESS 7
+#define SUBU_ERR_SUBUNAME_MALFORMED 6
+#define SUBU_ERR_RMDIR_SUBUHOME 5
+#define SUBU_ERR_MKDIR_SUBUHOME 4
+#define SUBU_ERR_MALLOC 3
+#define SUBU_ERR_SETUID_ROOT 2
+#define SUBU_ERR_ARG_CNT 1
+char *userdel_mess(int err);
+char *useradd_mess(int err);
+#define INTERFACE 0
diff --git a/subu-0/1_tmp/subudb-init.cli.h b/subu-0/1_tmp/subudb-init.cli.h
new file mode 100644 (file)
index 0000000..4435103
--- /dev/null
@@ -0,0 +1,11 @@
+/* \aThis file was automatically generated.  Do not edit! */
+#undef INTERFACE
+#include <sqlite3.h>
+int db_commit(sqlite3 *db);
+int db_rollback(sqlite3 *db);
+int subudb_schema(sqlite3 *db);
+int db_begin(sqlite3 *db);
+#include <stdbool.h>
+#include <errno.h>
+#define SUBU_ERR_DB_FILE 8
+extern char DB_File[];
diff --git a/subu-0/1_tmp/subudb-number.cli.h b/subu-0/1_tmp/subudb-number.cli.h
new file mode 100644 (file)
index 0000000..c130fbb
--- /dev/null
@@ -0,0 +1,11 @@
+/* \aThis file was automatically generated.  Do not edit! */
+#undef INTERFACE
+#include <sqlite3.h>
+int subudb_number_get(sqlite3 *db,int *n);
+int subudb_number_set(sqlite3 *db,int n);
+#include <stdbool.h>
+#include <errno.h>
+#define SUBU_ERR_N 14
+#define SUBU_ERR_DB_FILE 8
+extern char DB_File[];
+#define SUBU_ERR_ARG_CNT 1
diff --git a/subu-0/1_tmp/subudb-rel-get.cli.h b/subu-0/1_tmp/subudb-rel-get.cli.h
new file mode 100644 (file)
index 0000000..4f335be
--- /dev/null
@@ -0,0 +1,9 @@
+/* \aThis file was automatically generated.  Do not edit! */
+#undef INTERFACE
+#include <sqlite3.h>
+int subudb_Masteru_Subu_get_subu_username(sqlite3 *db,char *masteru_name,char *subuname,char **subu_username);
+#include <stdbool.h>
+#include <errno.h>
+#define SUBU_ERR_DB_FILE 8
+extern char DB_File[];
+#define SUBU_ERR_ARG_CNT 1
diff --git a/subu-0/1_tmp/subudb-rel-put.cli.h b/subu-0/1_tmp/subudb-rel-put.cli.h
new file mode 100644 (file)
index 0000000..243b3a9
--- /dev/null
@@ -0,0 +1,8 @@
+/* \aThis file was automatically generated.  Do not edit! */
+#undef INTERFACE
+#include <sqlite3.h>
+int subudb_Masteru_Subu_put(sqlite3 *db,char *masteru_name,char *subuname,char *subu_username);
+#include <stdbool.h>
+#include <errno.h>
+#define SUBU_ERR_DB_FILE 8
+extern char DB_File[];
diff --git a/subu-0/1_tmp/subudb-rel-rm.cli.h b/subu-0/1_tmp/subudb-rel-rm.cli.h
new file mode 100644 (file)
index 0000000..595427f
--- /dev/null
@@ -0,0 +1,8 @@
+/* \aThis file was automatically generated.  Do not edit! */
+#undef INTERFACE
+#include <sqlite3.h>
+int subudb_Masteru_Subu_rm(sqlite3 *db,char *masteru_name,char *subuname,char *subu_username);
+#include <stdbool.h>
+#include <errno.h>
+#define SUBU_ERR_DB_FILE 8
+extern char DB_File[];
diff --git a/subu-0/1_tmp/subudb-subus.cli.h b/subu-0/1_tmp/subudb-subus.cli.h
new file mode 100644 (file)
index 0000000..16310b7
--- /dev/null
@@ -0,0 +1,14 @@
+/* \aThis file was automatically generated.  Do not edit! */
+#undef INTERFACE
+#include <sqlite3.h>
+typedef struct subudb_subu_element subudb_subu_element;
+int subudb_Masteru_Subu_get_subus(sqlite3 *db,char *masteru_name,subudb_subu_element **sa_pt,subudb_subu_element **sa_end_pt);
+struct subudb_subu_element {
+  char *subuname;
+  char *subu_username;
+};
+#include <stdbool.h>
+#include <errno.h>
+#define SUBU_ERR_DB_FILE 8
+extern char DB_File[];
+#define SUBU_ERR_ARG_CNT 1
diff --git a/subu-0/1_tmp/subudb.lib.h b/subu-0/1_tmp/subudb.lib.h
new file mode 100644 (file)
index 0000000..be73823
--- /dev/null
@@ -0,0 +1,27 @@
+/* \aThis file was automatically generated.  Do not edit! */
+#undef INTERFACE
+#include <sqlite3.h>
+int subudb_Masteru_Subu_rm(sqlite3 *db,char *masteru_name,char *subuname,char *subu_username);
+#include <stdlib.h>
+#include <stdbool.h>
+void da_expand(void **base,void **pt,size_t *s);
+bool da_bound(void *base,void *pt,size_t s);
+typedef struct subudb_subu_element subudb_subu_element;
+int subudb_Masteru_Subu_get_subus(sqlite3 *db,char *masteru_name,subudb_subu_element **sa_pt,subudb_subu_element **sa_end_pt);
+void subu_element_free(subudb_subu_element *base,subudb_subu_element *end_pt);
+void da_alloc(void **base,size_t *s,size_t item_size);
+struct subudb_subu_element {
+  char *subuname;
+  char *subu_username;
+};
+int subudb_Masteru_Subu_get_subu_username(sqlite3 *db,char *masteru_name,char *subuname,char **subu_username);
+int subudb_Masteru_Subu_put(sqlite3 *db,char *masteru_name,char *subuname,char *subu_username);
+int subudb_number_set(sqlite3 *db,int n);
+int subudb_number_get(sqlite3 *db,int *n);
+typedef unsigned int uint;
+extern uint First_Max_Subunumber;
+int subudb_schema(sqlite3 *db);
+int db_rollback(sqlite3 *db);
+int db_commit(sqlite3 *db);
+int db_begin(sqlite3 *db);
+#define INTERFACE 0
diff --git a/subu-0/1_try/split.c b/subu-0/1_try/split.c
new file mode 100644 (file)
index 0000000..6d4c6ac
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+Using preprocessor to make header file?
+
+gcc -E split.c -DPROTOTYPE
+
+Outputs source code source comment lines starting with a hash. Resolves all macro commands,
+hence the resulting header can not have macro commands.
+
+ */
+
+#if PROTOTYPE
+##define GREATNESS 21
+int f(int x);
+#endif
+
+#if IMPLEMENTATION
+int f(int x){
+  return x;
+}
+#endif
diff --git a/subu-0/1_try/split_arg.c b/subu-0/1_try/split_arg.c
new file mode 100644 (file)
index 0000000..6d4c6ac
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+Using preprocessor to make header file?
+
+gcc -E split.c -DPROTOTYPE
+
+Outputs source code source comment lines starting with a hash. Resolves all macro commands,
+hence the resulting header can not have macro commands.
+
+ */
+
+#if PROTOTYPE
+##define GREATNESS 21
+int f(int x);
+#endif
+
+#if IMPLEMENTATION
+int f(int x){
+  return x;
+}
+#endif
diff --git a/subu-0/1_try/subudb b/subu-0/1_try/subudb
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/subu-0/1_try/voidptr.c b/subu-0/1_try/voidptr.c
new file mode 100644 (file)
index 0000000..bd9c3e5
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+They say a cast is not required passing a typed pointer to a void * argument,
+but What about void **?
+
+gcc -std=gnu11 -o voidptr voidptr.c
+voidptr.c: In function â€˜main’:
+voidptr.c:28:5: warning: passing argument 1 of â€˜g’ from incompatible pointer type [-Wincompatible-pointer-types]
+   g(&pt, y);
+     ^~~
+voidptr.c:13:15: note: expected â€˜void **’ but argument is of type â€˜int **’
+ void g(void **pt0, void *pt1){
+        ~~~~~~~^~~
+
+*/
+#include <stdio.h>
+
+int f(void *pt){
+  return *(int *)pt;
+}
+
+/* fails
+void g(void **pt0, int *pt1){
+  *pt0 = pt1;
+}
+*/
+
+// passes
+void g(void *pt0, int *pt1){
+  *(int **)pt0 = pt1;
+}
+
+int main(){
+  int x = 5;
+  int *xp = &x;
+  printf("%d\n",f(xp));
+
+  int y[3];
+  y[0] = 10;
+  y[1] = 11;
+  y[2] = 12;
+
+  int *pt;
+  g(&pt, y);
+  printf("%d\n",*pt);
+
+  printf("that's all folks\n");
+  return 0;
+}
diff --git a/subu-0/common.lib.c b/subu-0/common.lib.c
new file mode 100644 (file)
index 0000000..9ce5a27
--- /dev/null
@@ -0,0 +1,20 @@
+
+#include "subu-common.lib.h"
+
+#if INTERFACE
+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
+#endif
+
+//  char *DB_File = "/etc/subudb";
+char DB_File[] = "subudb";
+uint Subuhome_Perms = 0700;
+uint First_Max_Subunumber = 114;
+char Subuland_Extension[] = "/subuland/";
diff --git a/subu-0/db.lib.c b/subu-0/db.lib.c
new file mode 100644 (file)
index 0000000..17a5419
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+The db file is maintained in SQLite
+
+Because user names of are of limited length, subu user names are always named _s<number>.
+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 <sqlite3.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+//--------------------------------------------------------------------------------
+// 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/subu-0/subu-bind-all.cli.c b/subu-0/subu-bind-all.cli.c
new file mode 100644 (file)
index 0000000..e942909
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+mount all the subu user directories into master's subuland
+uses unmount to undo this
+
+*/
+#include "subu-bind-all.cli.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+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/subu-0/subu-bind.cli.c b/subu-0/subu-bind.cli.c
new file mode 100644 (file)
index 0000000..f315823
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+mount a subu user directory into master's subuland
+uses unmount to undo this
+
+*/
+#include "subu-bind.cli.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+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/subu-0/subu-mk-0.cli.c b/subu-0/subu-mk-0.cli.c
new file mode 100644 (file)
index 0000000..af0888b
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+  subu-mk-0 command
+
+*/
+#include "subu-mk-0.cli.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+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/subu-0/subu-rm-0.cli.c b/subu-0/subu-rm-0.cli.c
new file mode 100644 (file)
index 0000000..a7e5926
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+  subu-mk-0 command
+
+*/
+#include "subu-rm-0.cli.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+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/subu-0/subu.lib.c b/subu-0/subu.lib.c
new file mode 100644 (file)
index 0000000..988bd28
--- /dev/null
@@ -0,0 +1,713 @@
+/*
+  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<number>, calls useradd to creat
+  the new uswer account, and enters the relationship between masteru, subu, and
+  s<number> in the db file.  It is this relation in the db file that
+  associates the subuname with the s<number> user.
+
+  subu-rm-0 uses userdel to delete the related s<number> 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 <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#if INTERFACE
+#include <stdbool.h>
+#include <errno.h>
+#include <sqlite3.h>
+#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
+  dbprintf("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
+    dbprintf("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
+  dbprintf("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
+  dbprintf("made directory \"%s\"\n", subuhome);
+  #endif
+
+  //--------------------------------------------------------------------------------
+  //  Make the subservient user account, i.e. the subu
+  {
+    #ifdef DEBUG
+      dbprintf("making subu \"%s\" as user \"%s\"\n", subuname, subu_username);
+    #endif
+    #if BUG_SSS_CACHE_RUID
+      #ifdef DEBUG
+        dbprintf("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
+    dbprintf("added user \"%s\"\n", subu_username);
+    #endif
+  }  
+  
+  //--------------------------------------------------------------------------------
+  #ifdef DEBUG
+  dbprintf("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
+  dbprintf("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
+  dbprintf("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
+    dbprintf("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
+  dbprintf("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
+  dbprintf("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
+    dbprintf("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
+    dbprintf("deleting user \"%s\"\n", subu_username);
+    #endif
+    #if BUG_SSS_CACHE_RUID
+      #ifdef DEBUG
+        dbprintf("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
+    dbprintf("deleted user \"%s\"\n", subu_username);
+    #endif
+  }  
+
+  #ifdef DEBUG
+  dbprintf("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
+  dbprintf("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
+    dbprintf("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)  
+    dbprintf("masteru_name: \"%s\"", masteru_name);
+  else
+    dbprintf("masteru_name unknown");
+  if(subuland)
+    dbprintf("subuland: \"%s\"", subuland);
+  else
+    dbprintf("subuland unknown");
+  dbprintf("\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)
+      dbprintf("subuhome: \"%s\"\n", subuhome);
+    else
+      dbprintf("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/subu-0/subudb-init.cli.c b/subu-0/subudb-init.cli.c
new file mode 100644 (file)
index 0000000..714c7e4
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+This command initializes the db file.
+
+*/
+#include "subudb-init.cli.h"
+#include <stdio.h>
+
+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/subu-0/subudb-number.cli.c b/subu-0/subudb-number.cli.c
new file mode 100644 (file)
index 0000000..60304e3
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+Set or get a new maximum subu number. Currently doesn't do the setting part.
+
+*/
+#include "subudb-number.cli.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+
+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/subu-0/subudb-rel-get.cli.c b/subu-0/subudb-rel-get.cli.c
new file mode 100644 (file)
index 0000000..9828b15
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+get the username from the db file
+for testing subudb_Masteru_Subu_get_subu_username
+
+*/
+#include "subudb-rel-get.cli.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+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/subu-0/subudb-rel-put.cli.c b/subu-0/subudb-rel-put.cli.c
new file mode 100644 (file)
index 0000000..b19896e
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+puts a relation in the masteru/subu table
+
+*/
+#include "subudb-rel-put.cli.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+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/subu-0/subudb-rel-rm.cli.c b/subu-0/subudb-rel-rm.cli.c
new file mode 100644 (file)
index 0000000..3d15ca9
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+puts a relation in the masteru/subu table
+
+*/
+#include "subudb-rel-rm.cli.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+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/subu-0/subudb-subus.cli.c b/subu-0/subudb-subus.cli.c
new file mode 100644 (file)
index 0000000..be3af20
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+Set or get a new maximum subu number. Currently doesn't do the setting part.
+
+*/
+#include "subudb-subus.cli.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+
+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/subu-1/subu-mk.py b/subu-1/subu-mk.py
new file mode 100644 (file)
index 0000000..203fab4
--- /dev/null
@@ -0,0 +1,299 @@
+#!/usr/bin/python
+# see the help option for syntax
+# this script must be run from root or sudo
+#
+# on Fedora 29 os.getresuid returned all zeros for a script run from sudo.
+# Hence, I am using the environment variable SUDO_USER
+
+import getpass
+import os
+import sys
+import libuser
+from __future__ import print_function
+
+command = os.path.base(argv[0])
+
+#--------------------------------------------------------------------------------
+# utilities
+#
+def prn(str):
+  print(str,end='')
+
+#--------------------------------------------------------------------------------
+# help
+#
+def help():
+  print( command +
+""" [=help] [=version] [shell=<shell>][owner=<owner-username>] [subu=]<subu-username>
+Makes a subservient user.
+If no arguments are given, or if =help is given, this message is printed.
+When this command is invoked through sudo, $SUDO_USER is taken as the owner's username.
+Otherwise, when invoked directly from root, the owner= option must be provided.
+The subu-username argument is the username for the new subservient user
+The the new subu home directory is created in /home/owner/subu/.
+Facls are set to give the owner access to the new subu's home directory.
+The shell option is not implemented yet.  Probably need a number of other options also.
+"""
+  )
+
+def version():
+  print(" version 0")
+
+#--------------------------------------------------------------------------------
+# a manager for handling error messages
+#
+class class_err:
+"""
+An error record has the form [flag, message, args] 
+  class is fatal, warning, info  [currently not implemented]
+  flag is true if an error has occured [need to change this to a count]
+  args is an array of strings to be given after the error message is printed.
+
+The dict holds named error records.
+
+register() is used to name and place error records in the dict. register() is
+typically called multiple times to initialize and error instance.
+
+tattle() is used by the program at run time in order to signal errors.
+
+has_error() returns true if tattle was ever called
+
+report() prints an error report.  When errors have occured this 
+
+vector() [unimplemented] returns a bit vector with one bit per fatal error
+record, in the order they appear in the dictionary. The bit is set if the error
+ever occured.
+
+We check for as many errors as is convenient to do so rather than stopping on
+the first error.
+"""
+
+  # field offsets into the error record
+  flag_dex = 0;
+  message_dex = 1;
+  args_dex = 2;
+
+  def __init__(self):
+    self.total_cnt = 0
+    self.dict = {}
+
+  def register(name, message):
+    self.dict[name] = [False, message, []]
+
+  def tattle(name, *args):
+    self.total_cnt += 1
+    if name in self.dict:
+      self.dict[name][0] = True
+      self.dict[name][2].extend(args)
+
+  def report():
+    if self.total_cnt:
+      for k,v in self.dict.items():
+        if v[self.flag_dex]:
+          print(v[self.message_dex],end='')
+          args = v[self.args_dex]
+          if length(args) :
+            print(args[0],end='')
+            for arg in args[1:]:
+              print( " " + arg, end='')
+          print()
+
+#--------------------------------------------------------------------------------
+# parse the command line
+#
+err.register(
+  'impossible_split',
+  "It is not possible, yet this token split into other than one or two pieces: "
+  )
+err.register(
+  'lone_delim',
+  "No spaces should appear around the '=' delimiter."
+  )
+
+args = sys.argv[1:]
+if len(args) == 0 :
+  version()
+  help()
+  exit(1)
+#create a dictionary based on the command line arguments
+arg_dict = {}
+subu_cnt = 0
+delim = '='
+for token in args:
+  token_pair = split(token, delim);
+  if len(token_pair) == 1 : #means there was no '=' in the token
+    arg_dict['subu'] = token_pair
+    subu_cnt++
+  elif len(token_pair) == 2 :
+    if token_pair[0] == '' and token_pair[1] == '' :
+      err.tattle('lone_delim')
+    elif token_pair[1] == '' : # then has trailing delim, will treat the same as a leading delim
+      arg_dict[token_pair[0]] = None
+    elif token_pair[0] == '' : # then has leading delim
+      arg_dict[token_pair[1]] = None
+    else:
+      arg_dict[token_pair[0]] = token_pair[1]
+  else:
+    err.tattle('impossible_split', token)
+
+if not arg_dict or arg_dict.get('help'):
+  help()
+  err.report()
+  exit(1)
+
+if arg_dict.get('version'):
+  version()
+
+#--------------------------------------------------------------------------------
+# check that the command line arguments are well formed. 
+#
+err.register(
+  'too_many_args',
+  command + " takes at most one non-option argument, but we counted: "
+  )
+err.register(
+  'no_subu'
+  command + " missing subservient username."
+  )
+err.register(
+  'bad_username'
+  "Usernames match ^[a-z_]([a-z0-9_-]{0,31}|[a-z0-9_-]{0,30}\$)$, but found: "
+  )
+err.register(
+  'unknown_option'
+  command + " doesn't implement option: "
+  )
+
+subu = arg_dict.get('subu')
+if subu_cnt > 1:
+  err.tattle('too_many_args')
+elif not subu
+  err.tattle('no_subu')
+elif not re.match("^[a-z_]([a-z0-9_-]{0,31}|[a-z0-9_-]{0,30}\$)$", subu)
+  err.tattle('bad_username', subu)
+
+for k in arg_dict:
+  if k not in ['help', 'version', 'shell', 'owner', 'subu'] :
+    err.tattle('unkown_option', k)
+
+if arg_dict.get('shell') :
+  print "shell option aint implemented yet"
+
+
+
+#--------------------------------------------------------------------------------
+# check that we have root privilege
+#
+err.register(
+  'not_root'
+  command + "requires root privilege"
+  )
+
+uid = os.getuid()
+if uid != 0 :
+  err.tattle('not root')
+
+username = getpass.getuser()
+sudo_caller_username = os.environ.get('SUDO_USER')
+
+if !sudo_caller_username
+  if username not == "root":
+    err.tattle('not_root')
+  elif:
+    owner
+    
+
+  def has_error(*errs):
+    return self.cnt > 0
+
+
+
+#-----
+
+
+
+
+#--------------------------------------------------------------------------------
+#  pull out the owner_dir and subu_dir
+#
+admin= libuser.admin()
+
+err_arg_form = class_err()
+err_arg_form.register('too_many', "too many semicolon delineated parts in")
+
+owner_parts = args[0].split(":")
+subu_parts = args[1].split(":") 
+
+owner_user_name = owner_parts[0]
+if not owner_user_name:
+  err_arg_form.tattle('owner_user_name_missing', args[0])
+else:
+  owner_user = admin.lookupUserByName(owner_user_name)
+  if owner_user == None:
+    err_arg_form.tattle('no_such_user_name', owner_user_name)
+  else:
+    
+
+subu_user_name = subu_parts[0]
+
+
+if length(owner_parts) > 2:
+  err_arg_form.tattle('too_many', args[0])
+elif length(owner_parts) == 2:
+  owner_dir = owner_parts[1]
+else # get the home directory
+    
+  
+
+
+#--------------------------------------------------------------------------------
+# set the home directory
+#
+if len(args) > args_dir_index:
+  dir = args[args_dir_index]
+else:
+  dir = os.getcwd()
+
+home = dir + "/" + name
+home_flag = not os.path.exists(home)
+
+#--------------------------------------------------------------------------------
+# create the user, setfacls
+#
+err_cnt = 0
+name_available_flag = False
+
+if name_flag:
+  admin = libuser.admin()
+  name_available_flag = name not in admin.enumeratedUsers()
+
+if owner_flag and name_flag and name_available_flag and home_flag :
+  user = admin.initUser(name)
+  user[libuser.HOMEDIRECTORY] = home
+  if opt_shell : user[libuser.SHELL] = opt_shell
+  admin.addUser(user)
+  #setfacl -m d:u:plato:rwx,u:plato:rwx directory
+  setfacl = "setfacl -m d:u:" + name + ":rwx,u:" + name + ":rwx " + home
+  exit(0)
+
+#--------------------------------------------------------------------------------
+# error return
+#  .. need to grab the return code from setfacl above and delete the user if it fails
+#
+err_flags = 0
+if not owner_flag :
+  err_flags |= 2**2
+  print "missing owning username argument"
+if not name_flag :
+  err_flags |= 2**3
+  print name + "missing subservient username argument"
+if not name_available_flag :
+  err_flags |= 2**4
+  print name + "specified subservient username already exists"
+if not home_flag :
+  err_flags |= 2**5
+  print "user home directory already exists"
+
+exit(err_flags)
diff --git a/tools/bin/make b/tools/bin/make
deleted file mode 100755 (executable)
index 3345aba..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/bash
-
-mf=( ?_makefile )
-if [ -f "$mf" ]; then
-   /usr/bin/make -f "$mf" "$@"
-else 
-   /usr/bin/make "$@"
-fi
-
-
-       
diff --git a/tools/bin/tranche b/tools/bin/tranche
new file mode 100755 (executable)
index 0000000..eb63c28
Binary files /dev/null and b/tools/bin/tranche differ
index 6bef9cc..bcf2475 100755 (executable)
@@ -1,37 +1,38 @@
 
+#should add test that incdir is not pwd before deleting the include file in
+#dist-clean currently make is looking for module.h while the include file is
+#always module.lib.h so the lib include is not getting clobbered
+
 SHELL=/bin/bash
 
-# files used by the compiler
-C_SOURCES_LIB= $(wildcard *.lib.c)
-C_SOURCES_CLI= $(wildcard *.cli.c)
-C_SOURCES= $(C_SOURCES_LIB) $(C_SOURCES_CLI)
-
-CC_SOURCES_LIB= $(wildcard *.lib.cc)
-CC_SOURCES_CLI= $(wildcard *.cli.cc)
-CC_SOURCES= $(CC_SOURCES_LIB) $(CC_SOURCES_CLI)
-
-OBJECTS_LIB=$(sort\
-        $(patsubst %.c, %.o, $(C_SOURCES_LIB))\
-        $(patsubst %.cc, %.o, $(CC_SOURCES_LIB))\
-        )
-OBJECTS_CLI=$(sort\
-        $(patsubst %.c, %.o, $(C_SOURCES_CLI))\
-        $(patsubst %.cc, %.o, $(CC_SOURCES_CLI))\
-        )
-OBJECTS= $(OBJECTS_LIB) $(OBJECTS_CLI)
-
-EXECS= $(sort \
-         $(patsubst %.cli.c,  %, $(wildcard *.cli.c))\
-         $(patsubst %.cli.cc,  %, $(wildcard *.cli.cc))\
-         )
+# these are the sources edited by the programmer
+C_SOURCE_LIB=  $(wildcard $(SRCDIR)/*.lib.c)
+C_SOURCE_CLI=  $(wildcard $(SRCDIR)/*.cli.c)
+CC_SOURCE_LIB= $(wildcard $(SRCDIR)/*.lib.cc)
+CC_SOURCE_CLI= $(wildcard $(SRCDIR)/*.cli.cc)
+
+#remove the suffix to get base name
+C_BASE_LIB=  $(sort $(patsubst %.lib.c,  %, $(notdir $(C_SOURCE_LIB))))
+C_BASE_CLI=  $(sort $(patsubst %.cli.c,  %, $(notdir $(C_SOURCE_CLI))))
+CC_BASE_LIB= $(sort $(patsubst %.lib.cc, %, $(notdir $(CC_SOURCE_LIB))))
+CC_BASE_CLI= $(sort $(patsubst %.cli.cc, %, $(notdir $(CC_SOURCE_CLI))))
+
+# two sets of object files, one for the lib, and one for the command line interface progs
+OBJECT_LIB= $(patsubst %, $(TMPDIR)/%.lib.o, $(C_BASE_LIB) $(CC_BASE_LIB))
+OBJECT_CLI= $(patsubst %, $(TMPDIR)/%.cli.o, $(C_BASE_CLI) $(CC_BASE_CLI))
+
+# executables are made from CLI sources
+EXEC= $(patsubst %, $(EXECDIR)/%, $(C_BASE_CLI) $(CC_BASE_CLI))
 
 #otherwise make provides default values for these
 C=
 CC=
 
--include 0_makefile-flags
+DEPFILE=$(TMPDIR)/makefile-dep
+LIBFILE=$(LIBDIR)/lib$(MODULE).a
+INCFILE=$(INCDIR)/$(MODULE).h
 
-DEPSFILE=$(TMPDIR)/makefile_deps
+-include makefile-flags
 
 # a single space literal, for example if you wanted to subsitute commas to
 # spaces: $(subst $(space),;,$(string)) we ran into this out of a need to send
@@ -39,11 +40,12 @@ DEPSFILE=$(TMPDIR)/makefile_deps
 blank :=
 space :=$(blank)  $(blank)
 
+.PHONY: all
+all: version dep lib exec
 
-all: version deps lib execs
-
+.PHONY: version
 version:
-       @echo makefile version 3.0
+       @echo makefile version 4.0
        @echo "PWD: " $(PWD)
        @echo "MAKEFILE_LIST: " $(MAKEFILE_LIST)
        @echo "C: " $(C)
@@ -52,103 +54,115 @@ version:
        @echo "CCFLAGS: " $(CCFLAGS)
        @echo "LINKFLAGS: " $(LINKFLAGS)
 
+.PHONY: info
 info:
-       @echo "DEPDIR: " $(DEPDIR)
+       @echo "DEPRDIR: " $(DEPRDIR)
        @echo "DOCDIR: " $(DOCDIR)
-       @echo "EXECSDIR: " $(EXECSDIR)
+       @echo "EXECDIR: " $(EXECDIR)
        @echo "INCDIR: " $(INCDIR)
        @echo "LIBDIR: " $(LIBDIR)
        @echo "TESTDIR: " $(TESTDIR)
        @echo "TMPDIR: " $(TMPDIR)
        @echo "TOOLSDIR: " $(TOOLSDIR)
        @echo "TRYDIR: " $(TRYDIR)
-       @echo "DEPSFILE: " $(DEPSFILE)
+       @echo "DEPFILE: " $(DEPFILE)
        @echo "LIBFILE: " $(LIBFILE)
-       @echo "C_SOURCES_LIB: " $(C_SOURCES_LIB)
-       @echo "C_SOURCES_CLI: " $(C_SOURCES_CLI)
-       @echo "C_SOURCES: " $(C_SOURCES)
-       @echo "CC_SOURCES_LIB: " $(CC_SOURCES_LIB)
-       @echo "CC_SOURCES_CLI: " $(CC_SOURCES_CLI)
-       @echo "CC_SOURCES: " $(CC_SOURCES)
-       @echo "OBJECTS_LIB: " $(OBJECTS_LIB)
-       @echo "OBJECTS_CLI: " $(OBJECTS_CLI)
-       @echo "OBJECTS: " $(OBJECTS)
-       @echo "EXECS: " $(EXECS)
+       @echo "INCFILE: " $(INCFILE)
+       @echo "C_SOURCE_LIB: " $(C_SOURCE_LIB)
+       @echo "C_SOURCE_CLI: " $(C_SOURCE_CLI)
+       @echo "CC_SOURCE_LIB: " $(CC_SOURCE_LIB)
+       @echo "CC_SOURCE_CLI: " $(CC_SOURCE_CLI)
+       @echo "C_BASE_LIB: " $(C_BASE_LIB)
+       @echo "C_BASE_CLI: " $(C_BASE_CLI)
+       @echo "CC_BASE_LIB: " $(CC_BASE_LIB)
+       @echo "CC_BASE_CLI: " $(CC_BASE_CLI)
+       @echo "OBJECT_LIB: " $(OBJECT_LIB)
+       @echo "OBJECT_CLI: " $(OBJECT_CLI)
+       @echo "EXEC: " $(EXEC)
 
 # should be safe to run this in an already setup or partially setup directory
+.PHONY: setup
 setup:
-       if [ ! -e $(DEPRDIR) ]; then mkdir $(DEPRDIR); fi
-       if [ ! -e $(DOCDIR) ]; then mkdir $(DOCDIR); fi
-       if [ ! -e $(EXECSDIR) ]; then mkdir $(EXECSDIR); fi
-       if [ ! -e $(INCDIR) ]; then mkdir $(INCDIR); fi
-       if [ ! -e $(LIBDIR) ]; then mkdir $(LIBDIR); fi
-       if [ ! -e $(TESTDIR) ]; then mkdir $(TESTDIR); fi
-       if [ ! -e $(TMPDIR) ]; then mkdir $(TMPDIR); fi
-       if [ ! -e $(TRYDIR) ]; then mkdir $(TRYDIR); fi
-
-deps:
+       [ ! -e $(DEPRDIR) ] && mkdir $(DEPRDIR) || true
+       [ ! -e $(DOCDIR) ]  && mkdir $(DOCDIR)  || true
+       [ ! -e $(EXECDIR) ] && mkdir $(EXECDIR) || true
+       [ ! -e $(INCDIR) ]  && mkdir $(INCDIR)  || true
+       [ ! -e $(LIBDIR) ]  && mkdir $(LIBDIR)  || true
+       [ ! -e $(SRCDIR) ]  && mkdir $(SRCDIR)  || true
+       [ ! -e $(TESTDIR) ] && mkdir $(TESTDIR) || true
+       [ ! -e $(TMPDIR) ]  && mkdir $(TMPDIR)  || true
+       [ ! -e $(TRYDIR) ]  && mkdir $(TRYDIR)  || true
+
+#better to put the dependency generation into a loop on the source file and specify -MT for the target
+#also should be redirecting only stdout so stderr messages will be displayed >>1 depfile
+.PHONY: dep
+dep: 
        @if [ -z "$(CC)" ]; then\
          if [ -z "$C()" ]; then\
            echo "No compiler specified";\
            exit 1;\
          else\
            echo "C compiler only deps" ;\
-           $(C) $(CFLAGS) -MM  $(C_SOURCES) 1> $(DEPSFILE);\
+           $(C) $(CFLAGS) -MM  $(C_SOURCE_LIB) $(C_SOURCE_CLI) | sed 's|^.*\.o|$(TMPDIR)/&|' > $(DEPFILE);\
            echo "deps for C linking";\
-           for i in $(EXECS) ; do\
-             $(ECHO) >> $(DEPSFILE);\
-             $(ECHO) "$(EXECSDIR)/$$i : $$i.cli.o $(LIBDIR)/$(LIBFILE)" >> $(DEPSFILE);\
-             $(ECHO) " $(C) -o $(EXECSDIR)/$$i $$i.cli.o $(LINKFLAGS)" >> $(DEPSFILE);\
+           for i in $(C_BASE_CLI) ; do\
+             $(ECHO) >> $(DEPFILE);\
+             $(ECHO) "$(EXECDIR)/$$i : $(TMPDIR)/$$i.cli.o $(LIBFILE)" >> $(DEPFILE);\
+             $(ECHO) " $(C) -o $(EXECDIR)/$$i $(TMPDIR)/$$i.cli.o $(LINKFLAGS)" >> $(DEPFILE);\
            done;\
          fi;\
        else\
-         $(CC) $(CCFLAGS) -MM  $(CC_SOURCES) 1> $(DEPSFILE);\
+         $(CC) $(CCFLAGS) -MM  $(CC_SOURCE_LIB) $(CC_SOURCE_CLI) | sed 's|^.*\.o|$(TMPDIR)/&|' > $(DEPFILE);\
          if [ -z "$C()" ]; then\
            echo "CC compiler only deps" ;\
          else\
            echo "CC and C mixed compile deps" ;\
-           $(C) $(CFLAGS) -MM  $(C_SOURCES) 1>> $(DEPSFILE);\
+           $(C) $(CFLAGS) -MM   $(C_SOURCE_LIB) $(C_SOURCE_CLI) | sed 's|^.*\.o|$(TMPDIR)/&|' > $(DEPFILE);\
          fi;\
          echo "deps for CC linking";\
-         for i in $(EXECS) ; do\
-           $(ECHO) >> $(DEPSFILE);\
-           $(ECHO) "$(EXECSDIR)/$$i : $$i.cli.o $(LIBDIR)/$(LIBFILE)" >> $(DEPSFILE);\
-           $(ECHO) "   $(CC) -o $(EXECSDIR)/$$i $$i.cli.o $(LINKFLAGS)" >> $(DEPSFILE);\
+         for i in $(CC_BASE_CLI) $(C_BASE_CLI) ; do\
+           $(ECHO) >> $(DEPFILE);\
+           $(ECHO) "$(EXECDIR)/$$i : $(TMPDIR)/$$i.cli.o $(LIBFILE)" >> $(DEPFILE);\
+           $(ECHO) "   $(CC) -o $(EXECDIR)/$$i $(TMPDIR)/$$i.cli.o $(LINKFLAGS)" >> $(DEPFILE);\
          done;\
        fi
 
-lib: 
-       make $(LIBDIR)/$(LIBFILE)
+.PHONY: lib
+lib: $(LIBFILE)
 
-$(LIBDIR)/$(LIBFILE) : $(OBJECTS_LIB)
-       if [ ! -e $(DEPSFILE) ]; then make deps; fi
-       ar rcs $(LIBDIR)/$(LIBFILE) $(OBJECTS_LIB)
+$(LIBFILE): $(OBJECT_LIB)
+       ar rcs $(LIBFILE) $(OBJECT_LIB)
 
-execs: $(LIBDIR)/$(LIBFILE)
-       make sub_execs
+.PHONY: exec
+exec: $(LIBFILE)
+       make sub_exec
 
-sub_execs: $(patsubst %,  $(EXECSDIR)/%, $(EXECS))
+.PHONY: sub_exec
+sub_exec: $(EXEC)
 
+.PHONY: stage
 stage:
-       if [ -f $(LIBDIR)/$(LIBFILE) ]; then cp $(LIBDIR)/$(LIBFILE) $(PROJECT_SUBU)/stage/lib; fi
-       if [ -f $(INCDIR)/$(INCFILE) ]; then cp $(INCDIR)/$(INCFILE) $(PROJECT_SUBU)/stage/include; fi
-       -cp $(EXECSDIR)/* $(PROJECT_SUBU)/stage/bin
+       [ -f $(LIBFILE) ] && cp $(LIBFILE) $(PROJECT_SUBU)/stage/lib || true
+       [ -f $(INCFILE) ] && cp $(INCFILE) $(PROJECT_SUBU)/stage/include || true
+       [ $(shell ls -A $(EXECDIR)) ] && cp $(EXECDIR)/* $(PROJECT_SUBU)/stage/bin || true
 
+.PHONY: clean
 clean:
-       for i in $(wildcard *~); do mv $$i $(TMPDIR); done
-       for i in $(wildcard *.lib.o) $(wildcard *.cli.o); do rm $$i; done 
-       for i in $(EXECS); do if [ -e $(EXECSDIR)/$$i ]; then rm $(EXECSDIR)/$$i; fi; done 
-       if [ -f $(LIBDIR)/$(LIBFILE) ]; then rm $(LIBDIR)/$(LIBFILE); fi
-       if [ -f $(DEPSFILE) ]; then rm $(DEPSFILE); fi
+       for i in $(wildcard tmp/*); do rm $$i || true; done 
+
+.PHONY: dist-clean
+dist-clean: clean
+       for i in $(EXEC); do [ -e $$i ] && rm $$i || true; done 
+       rm $(INCFILE) || true
+       rm $(LIBFILE) || true
 
--include $(DEPSFILE)
+-include $(DEPFILE)
 
-# recipe for making object files:
-#
-%.o : %.c
-       $(C) $(CFLAGS) -c $<
+# recipes
 
-%.o : %.cc
-       $(CC) $(CCFLAGS) -c $<
+$(TMPDIR)/%.o : $(SRCDIR)/%.c
+       $(C) $(CFLAGS) -o $@ -c $<
 
+$(TMPDIR)/%.o : $(SRCDIR)/%.cc
+       $(CC) $(CCFLAGS) -o $@ -c $<
 
diff --git a/tools/lib/makefile_trc b/tools/lib/makefile_trc
new file mode 100644 (file)
index 0000000..1edc8b3
--- /dev/null
@@ -0,0 +1,188 @@
+
+# We should read the tranche sources and see what files they output, and then
+# build the deps accordingly, but this makefile is more primitive approach.
+# Here the programmer must have one output .c file or .cc file per input tranche
+# file and it must be name <base>.{lib,cli}.{c,cc} and the {.c,.cc} output
+# tranche must be named <base>.trc.{c,cc}
+
+# will re-orgnaize the directory structure .. will name the src-da .. etc. to the
+# name of the module, then have a source dir inside that has only the stuff
+# programmer's edit, then get rid of the numbers
+
+SHELL=/bin/bash
+
+#LIDBIR, EXECDIR, HDIR hold the make results that might later be staged
+#$(PWD) is the directory that make was called from, this is already build in
+#set to dot to use the same directory as the source code
+#leave blank to ommit
+DEPRDIR=deprecated
+DOCDIR=doc
+EXECDIR=exec
+INCDIR=include
+LIBDIR=lib
+SRCDIR=src
+TESTDIR=test
+TMPDIR=tmp
+TOOLSDIR=$(realpath $(PROJECT_SUBU)/tools)
+TRYDIR=try
+
+LIBFILE=$(LIBDIR)/lib$(MODULE).a
+INCFILE=$(MODULE).h
+
+# these are the sources edited by the programmer
+C_SOURCE_LIB=  $(wildcard $(SRCDIR)/*.lib.c)
+C_SOURCE_CLI=  $(wildcard $(SRCDIR)/*.cli.c)
+CC_SOURCE_LIB= $(wildcard $(SRCDIR)/*.lib.cc)
+CC_SOURCE_CLI= $(wildcard $(SRCDIR)/*.cli.cc)
+
+#remove the suffix to get base name
+C_BASE_LIB=  $(sort $(patsubst %.lib.c,  %, $(notdir $(C_SOURCE_LIB))))
+C_BASE_CLI=  $(sort $(patsubst %.cli.c,  %, $(notdir $(C_SOURCE_CLI))))
+CC_BASE_LIB= $(sort $(patsubst %.lib.cc, %, $(notdir $(CC_SOURCE_LIB))))
+CC_BASE_CLI= $(sort $(patsubst %.cli.cc, %, $(notdir $(CC_SOURCE_CLI))))
+
+# the progreammer must name the c and cc tranches accordingly:
+C_TRC_LIB= $(patasubst %, $(TMPDIR)/%.trc.c, C_BASE_LIB)
+C_TRC_CLI= $(patasubst %, $(TMPDIR)/%.trc.c, C_BASE_CLI)
+CC_TRC_LIB= $(patasubst %, $(TMPDIR)/%.trc.cc, CC_BASE_LIB)
+CC_TRC_CLI= $(patasubst %, $(TMPDIR)/%.trc.cc, CC_BASE_CLI)
+
+# two sets of object files, one for the lib, and one for the command line interface progs
+OBJECT_LIB= $(patsubst %, $(TMDIR)/%.o, $(C_BASE_LIB) $(CC_BASE_LIB))
+OBJECT_CLI= $(patsubst %, $(TMDIR)/%.o, $(C_BASE_CLI) $(CC_BASE_CLI))
+
+# executables are made from CLI sources
+EXEC= (patsubst %, $(EXECDIR)/%, $(C_BASE_CLI) $(CC_BASE_CLI))
+
+#otherwise make provides default values for these
+C=
+CC=
+
+-include makefile-flags
+
+DEPFILE=$(TMPDIR)/makefile_dep
+
+# a single space literal, for example if you wanted to subsitute commas to
+# spaces: $(subst $(space),;,$(string)) we ran into this out of a need to send
+# multiple separate command arguments to a shell script from one variable value
+blank :=
+space :=$(blank)  $(blank)
+
+all: version deps lib execs
+
+version:
+       @echo makefile version 3.0
+       @echo "PWD: " $(PWD)
+       @echo "MAKEFILE_LIST: " $(MAKEFILE_LIST)
+       @echo "C: " $(C)
+       @echo "CFLAGS: " $(CFLAGS)
+       @echo "CC: " $(CC)
+       @echo "CCFLAGS: " $(CCFLAGS)
+       @echo "LINKFLAGS: " $(LINKFLAGS)
+
+info:
+       @echo "DEPDIR: " $(DEPDIR)
+       @echo "DOCDIR: " $(DOCDIR)
+       @echo "EXECSDIR: " $(EXECSDIR)
+       @echo "INCDIR: " $(INCDIR)
+       @echo "LIBDIR: " $(LIBDIR)
+       @echo "TESTDIR: " $(TESTDIR)
+       @echo "TMPDIR: " $(TMPDIR)
+       @echo "TOOLSDIR: " $(TOOLSDIR)
+       @echo "TRYDIR: " $(TRYDIR)
+       @echo "DEPSFILE: " $(DEPSFILE)
+       @echo "LIBFILE: " $(LIBFILE)
+        @echo "TRC_TRC: " $(TRC_TRC)
+       @echo "C_BASE_LIB: " $(C_BASE_LIB)
+       @echo "C_BASE_CLI: " $(C_BASE_CLI)
+       @echo "CC_BASE_LIB: " $(CC_BASE_LIB)
+       @echo "CC_BASE_CLI: " $(CC_BASE_CLI)
+
+# should be safe to run this in an already setup or partially setup directory
+setup:
+       if [ ! -e $(DEPRDIR) ]; then mkdir $(DEPRDIR); fi
+       if [ ! -e $(DOCDIR) ]; then mkdir $(DOCDIR); fi
+       if [ ! -e $(EXECSDIR) ]; then mkdir $(EXECSDIR); fi
+       if [ ! -e $(INCDIR) ]; then mkdir $(INCDIR); fi
+       if [ ! -e $(LIBDIR) ]; then mkdir $(LIBDIR); fi
+       if [ ! -e $(SRCDIR) ]; then mkdir $(SRCDIR); fi
+       if [ ! -e $(TESTDIR) ]; then mkdir $(TESTDIR); fi
+       if [ ! -e $(TMPDIR) ]; then mkdir $(TMPDIR); fi
+       if [ ! -e $(TRYDIR) ]; then mkdir $(TRYDIR); fi
+
+dep: $(C_TRC_LIB) $(C_TRC_CLI) $(CC_TRC_LIB) $(CC_TRC_CLI)
+       if [ -z "$(CC)" ]; then\
+         if [ -z "$C()" ]; then\
+           echo "No compiler specified";\
+           exit 1;\
+         else\
+           echo "C compiler only deps" ;\
+           $(C) $(CFLAGS) -MM  $(C_TRC_LIB) $(C_TRC_CLI) 1> $(DEPSFILE);\
+           echo "deps for C linking";\
+           for i in $(EXECS) ; do\
+             $(ECHO) >> $(DEPSFILE);\
+             $(ECHO) "$(EXECSDIR)/$$i : $$i.cli.o $(LIBDIR)/$(LIBFILE)" >> $(DEPSFILE);\
+             $(ECHO) " $(C) -o $(EXECSDIR)/$$i $$i.cli.o $(LINKFLAGS)" >> $(DEPSFILE);\
+           done;\
+         fi;\
+       else\
+         $(CC) $(CCFLAGS) -MM  $(CC_TRC_LIB) $(CC_TRC_CLI) 1> $(DEPSFILE);\
+         if [ -z "$C()" ]; then\
+           echo "CC compiler only deps" ;\
+         else\
+           echo "CC and C mixed compile deps" ;\
+           $(C) $(CFLAGS) -MM   $(C_TRC_LIB) $(C_TRC_CLI) 1>> $(DEPSFILE);\
+         fi;\
+         echo "deps for CC linking";\
+         for i in $(EXECS) ; do\
+           $(ECHO) >> $(DEPSFILE);\
+           $(ECHO) "$(EXECSDIR)/$$i : $$i.cli.o $(LIBDIR)/$(LIBFILE)" >> $(DEPSFILE);\
+           $(ECHO) "   $(CC) -o $(EXECSDIR)/$$i $$i.cli.o $(LINKFLAGS)" >> $(DEPSFILE);\
+         done;\
+       fi
+
+lib: 
+       make $(LIBDIR)/$(LIBFILE)
+
+$(LIBDIR)/$(LIBFILE) : $(OBJECTS_LIB)
+       ar rcs $(LIBDIR)/$(LIBFILE) $(OBJECTS_LIB)
+
+exec: $(LIBDIR)/$(LIBFILE)
+       make sub_exec
+
+sub_exec: $(patsubst %,  $(EXECSDIR)/%, $(EXECS))
+
+stage:
+       if [ -f $(LIBDIR)/$(LIBFILE) ]; then cp $(LIBDIR)/$(LIBFILE) $(PROJECT_SUBU)/stage/lib; fi
+       if [ -f $(INCDIR)/$(INCFILE) ]; then cp $(INCDIR)/$(INCFILE) $(PROJECT_SUBU)/stage/include; fi
+       -cp $(EXECSDIR)/* $(PROJECT_SUBU)/stage/bin
+
+clean:
+       for i in $(wildcard *~); do mv $$i $(TMPDIR); done
+       for i in $(wildcard *.lib.o) $(wildcard *.cli.o); do rm $$i; done 
+       for i in $(EXECS); do if [ -e $(EXECSDIR)/$$i ]; then rm $(EXECSDIR)/$$i; fi; done 
+       if [ -f $(LIBDIR)/$(LIBFILE) ]; then rm $(LIBDIR)/$(LIBFILE); fi
+       if [ -f $(DEPSFILE) ]; then rm $(DEPSFILE); fi
+
+-include $(DEPSFILE)
+
+# recipes
+#
+%.trc.c : %.lib.c
+       $(TRANCHE) $<
+
+%.trc.c : %.cli.c
+       $(TRANCHE) $<
+
+%.trc.cc : %.lib.cc
+       $(TRANCHE) $<
+
+%.trc.cc : %.cli.cc
+       $(TRANCHE) $<
+
+%.o : %.c
+       $(C) $(CFLAGS) -c $<
+
+%.o : %.cc
+       $(CC) $(CCFLAGS) -c $<
+
diff --git a/tranche/deprecated/0_makefile b/tranche/deprecated/0_makefile
new file mode 100644 (file)
index 0000000..b8c7b9d
--- /dev/null
@@ -0,0 +1,40 @@
+# src/0_makefile
+
+SHELL=/bin/bash
+
+-include 0_makefile_flags
+
+SUID_TOOL=$(TOOLSDIR)/bin/setuid_root.sh
+MAKE=/usr/bin/make -f $(PROJECT_SUBU)/tools/lib/makefile_cc
+
+SOURCES=$(wildcard *.c)
+HFILES=$(wildcard *.h)
+
+all: version deps lib execs
+
+version:
+       $(MAKE) $@
+       @echo "SUID_TOOL: " $(SUID_TOOL)
+
+deps:
+       makeheaders $(SOURCES) $(HFILES)
+       sed -i '/^ *int *main *(.*)/d' *.h
+       $(MAKE) $@
+
+execs:
+       $(MAKE) $@
+       @echo "-> $(SUID_TOOL) $(EXECSDIR)/subu-mk-0 $(EXECSDIR)/subu-rm-0 $(EXECSDIR)/subu-bind-all"
+       cat $(SUID_TOOL)
+       @echo -n "Are you sure? [y/N] " && read ans && [ $${ans:-N} == y ]
+       sudo $(SUID_TOOL) $(EXECSDIR)/subu-mk-0 $(EXECSDIR)/subu-rm-0 $(EXECSDIR)/subu-bind-all
+
+clean:
+       $(MAKE) $@
+       for i in $(HFILES); do rm $$i; done
+
+%::
+       $(MAKE) $@
+
+
+
+
diff --git a/tranche/deprecated/0_makefile-flags b/tranche/deprecated/0_makefile-flags
new file mode 100644 (file)
index 0000000..0da8b61
--- /dev/null
@@ -0,0 +1,31 @@
+
+# some versions of Linux need a -e option others complain if there is a -e .. and it isn't the binary for echo ..
+ECHO= echo
+#ECHO= echo -e
+
+# directories used by this makefile, these could all be set to dot for
+# the simplest source directory structure
+
+#LIDBIR, EXECSDIR, HDIR hold the make results that might later be staged
+#$(PWD) is the directory that make was called from, this is already build in
+#set to dot to use the same directory as the source code
+#leave blank to ommit
+DEPRDIR=1_deprecated
+DOCDIR=1_doc
+EXECSDIR=1_execs
+HDIR=1_headers
+LIBDIR=1_lib
+TESTDIR=1_tests
+TMPDIR=1_tmp
+TOOLSDIR=$(realpath $(PROJECT_SUBU)/tools)
+TRYDIR=1_try
+
+
+# compiler and flags
+CC=gcc
+CFLAGS=-std=gnu11 -fPIC -I. -ggdb -Werror -DDEBUG -DDEBUGDB 
+#CFLAGS=-std=gnu11 -fPIC -I. -Werror
+LINKFLAGS=-L1_lib -lsubu -lsqlite3
+
+LIBFILE=$(LIBDIR)/libsubu.a
+
diff --git a/tranche/doc/todo.txt b/tranche/doc/todo.txt
new file mode 100644 (file)
index 0000000..1494e66
--- /dev/null
@@ -0,0 +1,11 @@
+
+2019-03-22T13:37:23Z
+1. indentation
+
+   the first non blank line after the #tranche keyword sets the indentation
+   level for the following text.  When echoing to the output file 
+   remove that many leading spaces.
+
+   Hmm,  or allow options among the tranche parameters,  -indent 3 or
+   -indent '  '.
+   
diff --git a/tranche/makefile b/tranche/makefile
new file mode 100644 (file)
index 0000000..4c20d5e
--- /dev/null
@@ -0,0 +1,22 @@
+# tranche/makefile
+
+SHELL=/bin/bash
+
+-include makefile-flags
+
+.PHONY: all version deps lib exec
+all: version deps lib exec
+
+lib:
+       $(MAKE) $@
+       cp src/tranche.lib.h include/tranche.h
+
+exec:
+       $(MAKE) $@
+
+%::
+       $(MAKE) $@
+
+
+
+
diff --git a/tranche/makefile-flags b/tranche/makefile-flags
new file mode 100644 (file)
index 0000000..68f6296
--- /dev/null
@@ -0,0 +1,31 @@
+MODULE=tranche
+
+# some versions of Linux need a -e option others complain if there is a -e .. and it isn't the binary for echo ..
+ECHO= echo
+#ECHO= echo -e
+
+# directories used by this makefile, these could all be set to dot for
+# the simplest source directory structure
+
+#LIDBIR, EXECDIR, INCDIR hold the make results that might later be staged
+#$(PWD) is the directory that make was called from, this is already build in
+#set to dot to use the same directory as the source code
+#leave blank to ommit
+DEPRDIR=deprecated
+DOCDIR=doc
+EXECDIR=exec
+INCDIR=include
+LIBDIR=lib
+SRCDIR=src
+TESTDIR=test
+TMPDIR=tmp
+TOOLSDIR=$(realpath $(PROJECT_SUBU)/tools)
+TRYDIR=try
+
+C=gcc
+CFLAGS=-std=gnu11 -fPIC -I. -I../stage/include -ggdb -Werror -DDEBUG -DDEBUGDB 
+#CFLAGS=-std=gnu11 -fPIC -I. -Werror
+LINKFLAGS=-Llib -L../stage/lib/ -lda -ltranche
+
+MAKE=/usr/bin/make --no-print-directory -f $(PROJECT_SUBU)/tools/lib/makefile_cc
+#MAKE=/usr/bin/make -f $(PROJECT_SUBU)/tools/lib/makefile_cc
diff --git a/tranche/src/tranche.cli.c b/tranche/src/tranche.cli.c
new file mode 100644 (file)
index 0000000..8df4337
--- /dev/null
@@ -0,0 +1,25 @@
+
+#include <stdio.h>
+#include <unistd.h>
+#include <da.h>
+#include "tranche.lib.h"
+
+int main(int argc, char **argv, char **envp){
+  if(argc != 2){
+    fprintf(stderr, "usage: %s <source-file>\n",argv[0]);
+    return 1;
+  }
+  FILE *file = fopen(argv[1], "r");
+  if(!file){
+    fprintf(stderr,"could not open file %s\n", argv[1]);
+    return 2;
+  }
+  Da targets;
+  da_alloc(&targets, sizeof(int));
+  int fd = STDOUT_FILENO;
+  da_push(&targets, &fd);
+  tranche_send(file, &targets);
+  da_free(&targets);
+  fclose(file);
+  return 0;
+}
diff --git a/tranche/src/tranche.lib.c b/tranche/src/tranche.lib.c
new file mode 100644 (file)
index 0000000..9b824d3
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+The purpose of this tools is to facilitate putting prototypes (declarations) next
+to implementations (definitions) in a single source file of a C/C++ programs. 
+
+Splits a single source file into multiple files.  Scans through the single
+source file looking for lines of the form:
+
+  #tranche-begin filename ...
+
+With the # as the first non-space character on the line, and only filename
+following the tag. Upon finding such a line, copies all following lines into the
+listed files, until reaching the end marker:
+
+  #tranche-end
+
+A next improvement of this file would be to support variables to be passed in
+for the file names.  As it stands, changing the file name requires editing 
+the source file.
+
+Files are opened for create or append, so opening to the same file will append
+to the end.
+
+*/
+
+#include <da.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+//--------------------------------------------------------------------------------
+// parsing
+
+char newline = '\n';
+char terminator = 0;
+
+char tranche_begin_tag[] = "#tranche";
+size_t tranche_begin_tag_len = 8;
+
+char tranche_end_tag[] = "#tranche-end";
+size_t tranche_end_tag_len = 12;
+
+// given a line
+// returns beginning of file name list
+static char *is_tranche_begin(char *pt){
+  while( *pt && isspace(*pt) ) pt++;
+  if(!*pt) return NULL;
+  if( strncmp(pt, tranche_begin_tag, tranche_begin_tag_len) ) return NULL;
+  return pt + tranche_begin_tag_len;
+}
+
+static char *is_tranche_end(char *pt){
+  while( *pt && isspace(*pt) ) pt++;
+  if(!*pt) return NULL;
+  if( strncmp(pt, tranche_end_tag, tranche_end_tag_len) ) return NULL;
+  return pt + tranche_end_tag_len;
+}
+
+static bool parse_file_list(Da *file_names, char *pt0){
+  char *pt1;
+  while( *pt0 && isspace(*pt0) ) pt0++;
+  pt1 = pt0;
+  while( *pt0 ){
+    while( *pt1 && !isspace(*pt1) ) pt1++;
+    char *file_name = strndup(pt0, pt1 - pt0);
+    da_push(file_names, &file_name);
+    while( *pt1 && isspace(*pt1) ) pt1++;
+    pt0 = pt1;
+  }
+}
+
+
+
+//--------------------------------------------------------------------------------
+// da_map calls
+
+static void tranche_open_fd(void *fnp, void *closure){
+  char *file_name = *(char **)fnp;
+  Da *fdap = (Da *)closure;
+  int fd = open(file_name, O_WRONLY | O_APPEND | O_CREAT, 0666);
+  if(fd == -1){
+    fprintf(stderr, "Could not open file %s\n", file_name);
+    return;
+  }
+  da_push(fdap, &fd);  
+  return;
+}
+static void tranche_open_fds(Da *fnap, Da *fdap){
+  da_map(fnap, tranche_open_fd, fdap);
+}
+
+static void tranche_close_fd(void *fdp, void *closure){
+  close(*(int *)fdp);
+}
+static void tranche_close_fds(Da *fdap){
+  da_map(fdap, tranche_close_fd, NULL);
+  da_rewind(fdap);
+}
+
+static void tranche_puts(void *fdp, void *string){
+  write(*(int *)fdp, string, strlen(string));
+}
+static void tranche_puts_all(Da *fdap, char *string){
+  da_map(fdap, tranche_puts, string);
+}
+
+
+
+//--------------------------------------------------------------------------------
+// we have a little problem if the user tries to tranche two things to the same file ..
+int tranche_send(FILE *src, Da *arg_fdap){
+  char *pt;
+  Da line;
+  Da file_name_arr;
+  Da fda;
+  da_alloc(&line, sizeof(char));
+  da_alloc(&file_name_arr, sizeof(char *));
+  da_alloc(&fda, sizeof(int));
+
+  while( !feof(src) ){
+    da_fgets(&line, src);
+    if( is_tranche_end(line.base) ) break;
+    pt = is_tranche_begin(line.base);
+    if(pt){ // then this line is the start of a nested tranche block
+      parse_file_list(&file_name_arr, pt);
+      tranche_open_fds(&file_name_arr, &fda);
+      da_free_elements(&file_name_arr);
+      tranche_send(src, &fda);
+      tranche_close_fds(&fda);
+    }else{
+      da_pop(&line, NULL); // pop the terminating zero
+      da_push(&line, &newline);
+      da_push(&line, &terminator);
+      tranche_puts_all(arg_fdap, line.base);
+    }
+    da_rewind(&line);
+  }
+
+  da_free(&line);
+  da_free(&file_name_arr);
+  da_free(&fda);
+  return 0;
+}
diff --git a/tranche/src/tranche.lib.h b/tranche/src/tranche.lib.h
new file mode 100644 (file)
index 0000000..27990a6
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef TRANCHE_LIB_H
+#define TRANCHE_LIB_H
+
+int tranche_send(FILE *src, Da *arg_fds);
+
+
+
+#endif
diff --git a/tranche/test/test1.dat b/tranche/test/test1.dat
new file mode 100644 (file)
index 0000000..b03df3f
--- /dev/null
@@ -0,0 +1,23 @@
+
+#tranche test11.dat test12.dat
+The little red hen said to Mick, no thank you not today sir.
+And then all the barnes animals shouted out in glee.
+No more misery!
+#tranche test13.dat
+apple banana pear
+kiwi
+#tranche-end
+cows
+and cats
+#tranche-end
+
+the between space
+
+#tranche test14.dat
+int float if while
+do
+function
+#tranche-end
+
+#tranche test15.dat
+#tranche-end
\ No newline at end of file
diff --git a/tranche/test/test1.sh b/tranche/test/test1.sh
new file mode 100644 (file)
index 0000000..c1140ca
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/bash -x
+./tranche test1.dat >test1stdout.dat
+diff test11.dat test11.dat.expected
+diff test12.dat test12.dat.expected
+diff test13.dat test13.dat.expected
+diff test14.dat test14.dat.expected
+diff test15.dat test15.dat.expected
+diff test1stdout.dat test1stdout.dat.expected
+rm test11.dat test12.dat test13.dat test14.dat test15.dat test1stdout.dat
+
diff --git a/tranche/test/test11.dat.expected b/tranche/test/test11.dat.expected
new file mode 100644 (file)
index 0000000..2c2904a
--- /dev/null
@@ -0,0 +1,5 @@
+The little red hen said to Mick, no thank you not today sir.
+And then all the barnes animals shouted out in glee.
+No more misery!
+cows
+and cats
diff --git a/tranche/test/test12.dat.expected b/tranche/test/test12.dat.expected
new file mode 100644 (file)
index 0000000..2c2904a
--- /dev/null
@@ -0,0 +1,5 @@
+The little red hen said to Mick, no thank you not today sir.
+And then all the barnes animals shouted out in glee.
+No more misery!
+cows
+and cats
diff --git a/tranche/test/test13.dat.expected b/tranche/test/test13.dat.expected
new file mode 100644 (file)
index 0000000..81fb20c
--- /dev/null
@@ -0,0 +1,2 @@
+apple banana pear
+kiwi
diff --git a/tranche/test/test14.dat.expected b/tranche/test/test14.dat.expected
new file mode 100644 (file)
index 0000000..0d8b89b
--- /dev/null
@@ -0,0 +1,3 @@
+int float if while
+do
+function
diff --git a/tranche/test/test15.dat.expected b/tranche/test/test15.dat.expected
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tranche/test/test1stdout.dat.expected b/tranche/test/test1stdout.dat.expected
new file mode 100644 (file)
index 0000000..4e519ff
--- /dev/null
@@ -0,0 +1,5 @@
+
+
+the between space
+
+
diff --git a/tranche/test/test2.c.expected b/tranche/test/test2.c.expected
new file mode 100644 (file)
index 0000000..a4876a1
--- /dev/null
@@ -0,0 +1,10 @@
+
+
+#include "test2.h"
+
+
+int f(int x){
+  return x;
+}
+
+
diff --git a/tranche/test/test2.h.expected b/tranche/test/test2.h.expected
new file mode 100644 (file)
index 0000000..fdc4d72
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef TEST2_H
+#define TEST2_H
+int f(int x);
+#endif
diff --git a/tranche/test/test2.trc.c b/tranche/test/test2.trc.c
new file mode 100644 (file)
index 0000000..ff7d696
--- /dev/null
@@ -0,0 +1,23 @@
+
+#tranche test2.c
+
+#tranche test2.h
+#ifndef TEST2_H
+#define TEST2_H
+#tranche-end
+
+#include "test2.h"
+
+#tranche test2.h
+int f(int x);
+#tranche-end
+
+int f(int x){
+  return x;
+}
+
+#tranche test2.h
+#endif
+#tranche-end
+
+#tranche-end
diff --git a/tranche/test/tranche b/tranche/test/tranche
new file mode 120000 (symlink)
index 0000000..acf4a6f
--- /dev/null
@@ -0,0 +1 @@
+../1_execs/tranche
\ No newline at end of file