# | grep -v deprecated | grep -v doc | sort -u | sed ':a;N;$!ba;s/\n/ /g' \
#)
-MAKEABLE= module/da module/da/test module/tranche
+MAKEABLE= module/da module/da/test module/tranche module/dispatch
.PHONY: all info clean dist-clean
#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.
+// allocation
void da_alloc(Da *dap, size_t element_size){
dap->element_size = element_size;
return (dap->end - dap->base)/dap->element_size;
}
-
void da_rebase(Da *dap, char *old_base, void *pta){
char **pt = (char **)pta;
size_t offset = *pt - old_base;
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
+// true when end has run off the allocated area
bool da_boundq(Da *dap){
return dap->end >= dap->base + dap->size;
}
+//--------------------------------------------------------------------------------
+// putting/taking items
+
+char *da_index(Da *dap, size_t i){
+ size_t offset = i * dap->element_size;
+ char *pt = dap->base + offset;
+ return pt;
+}
+
void da_push(Da *dap, void *element){
if( dap->end >= dap->base + dap->size ) da_expand(dap);
memcpy(dap->end, element, dap->element_size);
return flag;
}
-void da_cat(Da *dap0, Da *dap1){
- if(dap1->base == dap1->end) return;
- size_t dap0_size = dap0->end - dap0->base;
- size_t dap1_size = dap1->end - dap1->base; // size of the active portion
- dap0->end += dap1_size;
- while( dap0->end >= dap0->base + dap0->size ) da_expand(dap0);
- memcpy(dap0->base + dap0_size, dap1->base, dap1_size);
-}
-
-// If dap0 has had a terminatating zero added, that must be popped off before
-// the call. Similarly if a terminating zero is desired, it should be pushed
-// after the call.
-void da_push_string(Da *dap0, char *string){
- if(!*string) return;
- size_t dap0_size = dap0->end - dap0->base;
- size_t string_size = strlen(string);
- dap0->end += string_size;
- while( dap0->end >= dap0->base + dap0->size ) da_expand(dap0);
- memcpy(dap0->base + dap0_size, string, string_size);
-}
-
+//--------------------------------------------------------------------------------
+// iteration
-char *da_index(Da *dap, size_t i){
- size_t offset = i * dap->element_size;
- char *pt = dap->base + offset;
- return pt;
+// true when pt has run off the end
+bool da_endq(Da *dap, void *pt){
+ return (char *)pt >= dap->end;
}
// passed in f(element_pt, arg_pt)
}
}
-// da_lists are sometimes used as resource managers
+//--------------------------------------------------------------------------------
+// da being used as a resource manager
+
+
+// elements were malloced, now they will all be freed
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);
}
+//--------------------------------------------------------------------------------
+// da is an array of integers
+
+// would like to pass in the printf format to make a general print
+// but can't get *pt on the stack for the printf call .. hmmm
+void da_ints_print(Da *dap, char *sep){
+ char *pt = dap->base; // char * because it points to a byte in the array
+ if( pt < dap->end ){
+ printf("%u", *(int *)pt);
+ pt += dap->element_size;
+ while( pt < dap->end ){
+ printf("%s%u", sep, *(int *)pt);
+ pt += dap->element_size;
+ }}}
+
+
+//--------------------------------------------------------------------------------
+// da is an array of strings
+
// for the case of an array of strings
-void da_strings_puts(Da *dap){
+void da_strings_print(Da *dap, char *sep){
char *pt = dap->base; // char * because it points to a byte in the array
- while( pt < dap->end ){
- puts(*(char **)pt);
- pt += dap->element_size;
+ if( pt < dap->end ){
+ fputs(*(char **)pt, stdout);
+ pt += dap->element_size;
+ while( pt < dap->end ){
+ fputs(sep,stdout);
+ fputs(*(char **)pt,stdout);
+ pt += dap->element_size;
+ }}}
+
+// da is an array of strings, true if the test string is in the array
+// might be better to iterate instead of using a map ...
+typedef struct {
+ char *string;
+ bool found;
+} da_strings_exists_closure;
+static void string_equal(void *sp, void *closure){
+ char *string_element = *(char **)sp;
+ da_strings_exists_closure *ss = (da_strings_exists_closure *)closure;
+ if( ss->found ) return;
+ ss->found = !strcmp(string_element, ss->string);
+ return;
+}
+bool da_strings_exists(Da *string_arrp, char *test_string){
+ da_strings_exists_closure sec;
+ sec.string = test_string;
+ sec.found = false;
+ da_map(string_arrp, string_equal, &sec);
+ return sec.found;
+}
+
+void da_strings_set_insert(Da *string_arrp, char *proffered_string, void destruct(void *)){
+ if( da_strings_exists( string_arrp, proffered_string)){ // then throw it away, we don't need it
+ if(destruct)destruct(proffered_string);
+ return;
}
+ da_push(string_arrp, &proffered_string);
}
-// would like to pass in the printf format to make a general print
-// but can't get *pt on the stack for the printf call .. hmmm
-void da_ints_print(Da *dap){
- char *pt = dap->base;
- while( pt < dap->end ){
- printf("%u\n", *(int *)pt);
- pt += dap->element_size;
+// union
+void da_strings_set_union(Da *string_arrp, Da *proffered_string_arrp, void destruct(void *)){
+ char *pt = proffered_string_arrp->base;
+ while( pt < proffered_string_arrp->end ){
+ da_strings_set_insert(string_arrp, *(char **)pt, destruct);
+ pt += proffered_string_arrp->element_size;
}
+ return;
}
+//--------------------------------------------------------------------------------
+// the da itself is a string
+
// 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 *da_string_input(Da *dap, FILE *file){
char *old_base = dap->base;
int c = fgetc(file);
while( c != EOF && c != '\n' ){
da_push(dap, &terminator);
return old_base;
}
+
+void da_string_push(Da *dap0, char *string){
+ if(!*string) return;
+ size_t dap0_size = dap0->end - dap0->base;
+ size_t string_size = strlen(string);
+ dap0->end += string_size;
+ while( dap0->end >= dap0->base + dap0->size ) da_expand(dap0);
+ memcpy(dap0->base + dap0_size, string, string_size);
+}
+
+
+//--------------------------------------------------------------------------------
+// list operations
+
+// If dap0 has had a terminatating zero added, that must be popped off before
+// the call. Similarly if a terminating zero is desired, it should be pushed
+// after the call.
+
+// appends contents of dap1 onto dap0
+void da_cat(Da *dap0, Da *dap1){
+ if(dap1->base == dap1->end) return;
+ size_t dap0_size = dap0->end - dap0->base;
+ size_t dap1_size = dap1->end - dap1->base; // size of the active portion
+ dap0->end += dap1_size;
+ while( dap0->end >= dap0->base + dap0->size ) da_expand(dap0);
+ memcpy(dap0->base + dap0_size, dap1->base, dap1_size);
+}
+
+
#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);
bool da_emptyq(Da *dap);
size_t da_length(Da *dap);
-char *da_expand(Da *dap);
void da_rebase(Da *dap, char *old_base, void *pta);
-bool da_endq(Da *dap, void *pt);
+char *da_expand(Da *dap);
bool da_boundq(Da *dap);
+
+char *da_index(Da *dap, size_t i);
void da_push(Da *dap, void *element);
bool da_pop(Da *dap, void *element);
-void da_cat(Da *dap_base, Da *dap_cat);
-void da_push_string(Da *dap0, char *string);
-char *da_index(Da *dap, size_t i);
+
+bool da_endq(Da *dap, void *pt);
void da_map(Da *dap, void f(void *, void *), void *closure);
+
void da_free_elements(Da *dap);
-void da_strings_puts(Da *dap);
-void da_ints_print(Da *dap);
-char *da_fgets(Da *dap, FILE *fd);
+
+void da_ints_print(Da *dap, char *sep);
+
+void da_strings_print(Da *dap, char *sep);
+bool da_strings_exists(Da *string_arrp, char *test_string);
+void da_strings_set_insert(Da *string_arrp, char *proffered_string, void destruct(void *));
+void da_strings_set_union(Da *string_arrp, Da *proffered_string_arrp, void destruct(void *));
+
+
+char *da_string_input(Da *dap, FILE *file);
+void da_string_push(Da *dap0, char *string);
+
+void da_cat(Da *dap_base, Da *dap_cat);
#endif
+++ /dev/null
-passed all 4 tests
Da da;
da_alloc(&da, sizeof(char));
- da_fgets(&da, file);
+ da_string_input(&da, file);
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,file);
+ old_base = da_string_input(&da,file);
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,file);
+ old_base = da_string_input(&da,file);
da_rebase(&da, old_base, &s2);
bool f2 = !strcmp(s2, "(setq mode-require-final-newline nil)");
--- /dev/null
+2019-03-31T20:08:48Z
+morpheus@manorhouse§~/subu_land/subu/module/da/test/exec§
+> ./test_da
+passed all 5 tests
+
+++ /dev/null
-# 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) $@
-
-
-
-
+++ /dev/null
-
-# 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 shared
-#$(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
-
+++ /dev/null
-
-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.
+++ /dev/null
-
-#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;
-}
--- /dev/null
+#ifndef DB_LIB_H
+#define DB_LIB_H
+
+int dbprintf(const char *format, ...);
+
+#endif
--- /dev/null
+# da/makefile
+
+
+SHELL=/bin/bash
+MAKE=/usr/bin/make --no-print-directory -f $(PROJECT_SUBU)/tool/lib/makefile-cc
+#MAKE=/usr/bin/make -f $(PROJECT_SUBU)/tool/lib/makefile-cc
+
+-include makefile-flags
+
+.PHONY: all
+all: version dep lib exec
+
+.PHONY: lib
+lib:
+ $(MAKE) $@
+ cp src/db.lib.h include/db.h
+
+%::
+ $(MAKE) $@
+
+
+
+
--- /dev/null
+
+MODULE=db
+
+# 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=-Llib -ldb
+
+
+
--- /dev/null
+
+#include "db.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;
+}
--- /dev/null
+#ifndef DB_LIB_H
+#define DB_LIB_H
+
+int dbprintf(const char *format, ...);
+
+#endif
+MODULE=dispatch
+
# 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
LINKFLAGS=-L1_lib -lda
-MODULE=dispatch
+SRCDIR=tmp
+TRCDIR=trc
-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
+MAKE=/usr/bin/make --no-print-directory -f $(PROJECT_SUBU)/tool/lib/makefile-cc
+#MAKE=/usr/bin/make -f $(PROJECT_SUBU)/tool/lib/makefile-cc
+++ /dev/null
-#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
--- /dev/null
+#tranche dispatch.lib.c
+
+#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.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
#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);
bool da_emptyq(Da *dap);
size_t da_length(Da *dap);
-char *da_expand(Da *dap);
void da_rebase(Da *dap, char *old_base, void *pta);
-bool da_endq(Da *dap, void *pt);
+char *da_expand(Da *dap);
bool da_boundq(Da *dap);
+
+char *da_index(Da *dap, size_t i);
void da_push(Da *dap, void *element);
bool da_pop(Da *dap, void *element);
-void da_cat(Da *dap_base, Da *dap_cat);
-void da_push_string(Da *dap0, char *string);
-char *da_index(Da *dap, size_t i);
+
+bool da_endq(Da *dap, void *pt);
void da_map(Da *dap, void f(void *, void *), void *closure);
+
void da_free_elements(Da *dap);
-void da_strings_puts(Da *dap);
-void da_ints_print(Da *dap);
-char *da_fgets(Da *dap, FILE *fd);
+
+void da_ints_print(Da *dap, char *sep);
+
+void da_strings_print(Da *dap, char *sep);
+bool da_strings_exists(Da *string_arrp, char *test_string);
+void da_strings_set_insert(Da *string_arrp, char *proffered_string, void destruct(void *));
+void da_strings_set_union(Da *string_arrp, Da *proffered_string_arrp, void destruct(void *));
+
+
+char *da_string_input(Da *dap, FILE *file);
+void da_string_push(Da *dap0, char *string);
+
+void da_cat(Da *dap_base, Da *dap_cat);
#endif
$(MAKE) $@
share:
- if [ ! -z "$(wildcard $(EXECDIR)/*)" ]; then cp $(EXECDIR)/* $(PROJECT_SUBU)/tool/bin; fi
+ if [ -d $(EXECDIR) ]; then if [ ! -z "$(wildcard $(EXECDIR)/*)" ]; then cp $(EXECDIR)/* $(PROJECT_SUBU)/tool/bin; fi; fi
%::
$(MAKE) $@
# directories used by this makefile, these could all be set to dot for
# the simplest source directory structure
+EXECDIR=exec
C=gcc
CFLAGS=-std=gnu11 -fPIC -I. -I../share/include -ggdb -Werror -DDEBUG -DDEBUGDB
int main(int argc, char **argv, char **envp){
- char *src_file_path = 0;
+ int err = 0;
char *sname = 0;
char *tdir = 0;
char *mfile_path = 0;
-
+ Da args; // we will queue the non option args here
+ Da *argsp = &args; // collection of the non-option non-option-value args
+ da_alloc(argsp, sizeof(char *));
{ // argument parse
- Da args; // we will queue the non option args here
- Da *argsp = &args;
- da_alloc(argsp, sizeof(char *));
-
- int err_cnt = 0;
- char **pt = argv;
+ char **pt = argv + 1; // skip the command name
char *option;
char *value; // currently all our tranche options have exactly one value
while(*pt){
if( **pt == '-' ){
option = *pt + 1;
+
+ // options that take no values:
if(!*option){
fprintf(stderr, "Currently there is no lone '-' option.\n");
- err_cnt++;
+ err |= TRANCHE_ERR_ARG_PARSE;
goto endif;
}
+ if( !strcmp(option, "h") || !strcmp(option, "help") ){
+ err |= TRANCHE_ERR_HELP; // this will force the usage message, though it will also return an error
+ goto endif;
+ }
+
+ // options that take one value:
pt++; if(!*pt || **pt == '-'){
fprintf(stderr, "Missing value for option %s.\n", option);
- err_cnt++;
+ err |= TRANCHE_ERR_ARG_PARSE;
if(!*pt) break; // then nothing more to parse
goto endif;
}
}
if( !strcmp(option, "tdir") ){
tdir = value;
+ path_trim_slashes(tdir);
goto endif;
}
if( !strcmp(option, "sname") ){
goto endif;
}
fprintf(stderr, "Unrecognized option %s.", option);
- err_cnt++;
+ err |= TRANCHE_ERR_ARG_PARSE;
goto endif;
}
// else clause
da_push(argsp, pt);
endif:
- pt++;
+ pt++;
}
- int args_cnt = da_length(argsp);
- if(args_cnt > 1) src_file_path = *(char **)da_index(argsp, 1);
-
- // arg contracts
- if(args_cnt > 2){
- fprintf(stderr, "too many args\n");
- err_cnt++;
- }
- if(!src_file_path && !sname){
- fprintf(stderr, "must specify at least one of a src_file_path or an sname\n");
- err_cnt++;
+ if(da_emptyq(argsp) && !sname){
+ fprintf(stderr, "Must be given at least one source name argument or an sname option\n");
+ err |= TRANCHE_ERR_SNAME;
}
- if(err_cnt > 0){
- fprintf(stderr, "usage: %s [<src_file_path>] [-sname <sname>] [-tdir <dir>] [-mfile <mfile_path>]\n", argv[0]);
- return TRANCHE_ERR_ARG_PARSE;
+ if(err){
+ fprintf(stderr, "usage: %s [<src_file_path>].. [-sname <sname>] [-tdir <dir>]\n", argv[0]);
+ return err;
}
- da_free(argsp); // this only frees the array itself, not the things it points to
-
}// end of argument parse
- FILE *src_file;
+ // open the output file
int mfile_fd;
- { //source and mfile open
- if(!src_file_path)
- src_file = stdin;
- else
- src_file = fopen(src_file_path, "r");
-
+ {
if(mfile_path)
mfile_fd = open(mfile_path, O_WRONLY | O_APPEND | O_CREAT, 0666);
else
mfile_fd = STDOUT_FILENO;
- int err = 0;
- if(!src_file){
- fprintf(stderr,"could not open tranche source file %s\n", src_file_path);
- err+= TRANCHE_ERR_SRC_OPEN;
- }
if(mfile_fd == -1){
fprintf(stderr, "Could not open the dep file %s\n", mfile_path);
- err+= TRANCHE_ERR_DST_OPEN;
+ err |= TRANCHE_ERR_DST_OPEN;
}
- if(err) return err;
}
- if(sname)src_file_path = sname;
- path_trim_slashes(tdir);
- tranche_make(src_file, src_file_path, mfile_fd, tdir);
+ // The arguments are source file paths, but we process each one only once.
+ Da src_arr;
+ Da *src_arrp = &src_arr;
+ da_alloc(src_arrp, sizeof(char *));
+ da_strings_set_union(src_arrp, argsp, NULL); // NULL destructor
+ da_free(argsp);
- { // deallocate resources instead of just existing, so as to catch any errors
- int err_cnt = 0;
- if(src_file != stdin)
- if( fclose(src_file) ){perror(NULL); err_cnt++;}
- if(mfile_fd != STDOUT_FILENO)
- if( close(mfile_fd) == -1 ){perror(NULL); err_cnt++;}
- if( err_cnt )
- return TRANCHE_ERR_FCLOSE;
- else
- return 0;
+ char *src_file_path;
+ FILE *src_file;
+ if(da_emptyq(src_arrp))
+ tranche_make(stdin, sname, mfile_fd, tdir);
+ else{
+ char *pt = src_arrp->base;
+ while( pt < src_arrp->end ){
+ src_file_path = *(char **)pt;
+ src_file = fopen(src_file_path, "r");
+ if(!src_file){
+ fprintf(stderr,"Could not open source file %s.\n", src_file_path);
+ err |= TRANCHE_ERR_SRC_OPEN;
+ }else{
+ tranche_make(src_file, src_file_path, mfile_fd, tdir);
+ if( fclose(src_file) == -1 ){perror(NULL); err |= TRANCHE_ERR_FCLOSE;}
+ }
+ pt += src_arrp->element_size;
+ }
+ }
+ da_free(src_arrp);
+
+ if(mfile_fd != STDOUT_FILENO && close(mfile_fd) == -1 ){
+ perror(NULL);
+ err |= TRANCHE_ERR_FCLOSE;
}
+ return err;
}
#include <stdio.h>
#include <unistd.h>
+#include <string.h>
#include <da.h>
#include "tranche.lib.h"
int main(int argc, char **argv, char **envp){
- if(argc != 2){
- fprintf(stderr, "usage: %s <source>\n",argv[0]);
- return ERR_ARGC;
- }
- char *src_file_name = argv[1];
-
- int dep_fd;
- FILE *src_file = fopen(src_file_name, "r");
- unsigned int err = 0;
- if(!src_file){
- fprintf(stderr,"could not open tranche source file %s\n", src_file_name);
- err+= ERR_SRC_OPEN;
- }
- if(err) return err;
+ int err = 0;
+ char *sep = 0;
+ Da args; // we will queue the non option args here
+ Da *argsp = &args; // collection of the non-option non-option-value args
+ da_alloc(argsp, sizeof(char *));
+ { // argument parse
+ char **pt = argv + 1; // skip the command name
+ char *option;
+ char *value; // currently all our tranche options have exactly one value
+ while(*pt){
+ if( **pt == '-' ){
+ option = *pt + 1;
+
+ // options that take no values:
+ if(!*option){
+ fprintf(stderr, "Currently there is no lone '-' option.\n");
+ err |= TRANCHE_ERR_ARG_PARSE;
+ goto endif;
+ }
+ if( !strcmp(option, "h") || !strcmp(option, "help") ){
+ err |= TRANCHE_ERR_HELP; // this will force the usage message, though it will also return an error
+ goto endif;
+ }
+
+ // options that take one value:
+ pt++; if(!*pt || **pt == '-'){
+ fprintf(stderr, "Missing value for option %s.\n", option);
+ err |= TRANCHE_ERR_ARG_PARSE;
+ if(!*pt) break; // then nothing more to parse
+ goto endif;
+ }
+ value = *pt;
+ if( !strcmp(option, "sep") ){
+ sep = value;
+ goto endif;
+ }
+ fprintf(stderr, "Unrecognized option %s.", option);
+ err |= TRANCHE_ERR_ARG_PARSE;
+ goto endif;
+ }
+ // else clause
+ da_push(argsp, pt);
+ endif:
+ pt++;
+ }
+ if(!sep)sep = "\n";
+ if(err){
+ fprintf(stderr, "usage: %s [<src_file_path>].. [-sep <sep>]\n", argv[0]);
+ return err;
+ }
+ }// end of argument parse
+
+ // The arguments are source file paths, but we process each one only once.
+ Da src_arr;
+ Da *src_arrp = &src_arr;
+ da_alloc(src_arrp, sizeof(char *));
+ da_strings_set_union(src_arrp, argsp, NULL); // NULL destructor
+ da_free(argsp);
+
+ // a list of unique targets
Da target_arr;
Da *target_arrp = &target_arr;
da_alloc(target_arrp, sizeof(char *));
- tranche_target(src_file, target_arrp);
- da_strings_puts(target_arrp);
+
+ uint err_cnt = 0;
+ char *src_file_path;
+ FILE *src_file;
+ if(da_emptyq(src_arrp))
+ tranche_target(stdin, target_arrp);
+ else{
+ char *pt = src_arrp->base;
+ while( pt < src_arrp->end ){
+ src_file_path = *(char **)pt;
+ src_file = fopen(src_file_path, "r");
+ if(!src_file){
+ fprintf(stderr,"Could not open source file %s.\n", src_file_path);
+ err |= TRANCHE_ERR_SRC_OPEN;
+ }else{
+ tranche_target(src_file, target_arrp);
+ if( fclose(src_file) == -1 ){perror(NULL); err |= TRANCHE_ERR_FCLOSE;}
+ }
+ pt += src_arrp->element_size;
+ }
+ }
+ da_free(src_arrp);
+ da_strings_print(target_arrp, sep);
da_free_elements(target_arrp);
- fclose(src_file);
- return 0;
+ da_free(target_arrp);
+ return err;
}
.. currently tranche_send will probably mess up if the user nests a tranche to
the same file as one already open in the containing tranche ..
-.. should allow multiple source file args
*/
#include <stdio.h>
#include "tranche.lib.h"
int main(int argc, char **argv, char **envp){
- char *src_file_path = 0;
- char *tdir = 0;
+ int err = 0;
+ char *tdir = 0;
+ Da args; // we will queue the non option args here
+ Da *argsp = &args; // collection of the non-option non-option-value args
+ da_alloc(argsp, sizeof(char *));
{ // argument parse
- Da args; // we will queue the non option args here
- Da *argsp = &args;
- da_alloc(argsp, sizeof(char *));
-
- int err_cnt = 0;
- char **pt = argv;
+ char **pt = argv + 1; // skip the command name
char *option;
char *value; // currently all our tranche options have exactly one value
while(*pt){
if( **pt == '-' ){
option = *pt + 1;
+
+ // options that take no values:
if(!*option){
fprintf(stderr, "Currently there is no lone '-' option.\n");
- err_cnt++;
+ err |= TRANCHE_ERR_ARG_PARSE;
+ goto endif;
+ }
+ if( !strcmp(option, "h") || !strcmp(option, "help") ){
+ err |= TRANCHE_ERR_HELP; // this will force the usage message, though it will also return an error
goto endif;
}
+
+ // options that take one value:
pt++; if(!*pt || **pt == '-'){
fprintf(stderr, "Missing value for option %s.\n", option);
- err_cnt++;
+ err |= TRANCHE_ERR_ARG_PARSE;
if(!*pt) break; // then nothing more to parse
goto endif;
}
goto endif;
}
fprintf(stderr, "Unrecognized option %s.", option);
- err_cnt++;
+ err |= TRANCHE_ERR_ARG_PARSE;
goto endif;
}
// else clause
endif:
pt++;
}
- int args_cnt = da_length(argsp);
- if(args_cnt > 1) src_file_path = *(char **)da_index(argsp, 1);
-
- // arg contracts
- if(args_cnt > 2){
- fprintf(stderr, "too many arguments\n");
- err_cnt++;
- }
- if(err_cnt > 0){
- fprintf(stderr, "usage: %s [<src_file_path>] [-tdir <dir>]\n", argv[0]);
- return TRANCHE_ERR_ARG_PARSE;
+ if(err){
+ fprintf(stderr, "usage: %s [<src_file_path>].. [-tdir <dir>]\n", argv[0]);
+ return err;
}
- da_free(argsp); // this only frees the array itself, not the things it points to
-
}// end of argument parse
- FILE *src_file;
- { //source and mfile open
- if(!src_file_path)
- src_file = stdin;
- else
- src_file = fopen(src_file_path, "r");
-
- int err = 0;
- if(!src_file){
- fprintf(stderr,"could not open tranche source file %s\n", src_file_path);
- err+= TRANCHE_ERR_SRC_OPEN;
- }
- if(err) return err;
- }
-
Da targets;
- da_alloc(&targets, sizeof(int));
+ Da *target_arrp = &targets;
+ da_alloc(target_arrp, sizeof(int));
int fd = STDOUT_FILENO;
- da_push(&targets, &fd);
+ da_push(target_arrp, &fd);
if(tdir)chdir(tdir);
- tranche_send(src_file, &targets);
+ Da src_arr;
+ Da *src_arrp = &src_arr;
+ da_alloc(src_arrp, sizeof(char *));
+ da_strings_set_union(src_arrp, argsp, NULL);
+ da_free(argsp);
+
+ char *src_file_path;
+ FILE *src_file;
+ if(da_emptyq(src_arrp))
+ tranche_send(stdin, target_arrp);
+ else{
+ char *pt = src_arrp->base;
+ while( pt < src_arrp->end ){
+ src_file_path = *(char **)pt;
+ src_file = fopen(src_file_path, "r");
+ if(!src_file){
+ fprintf(stderr,"Could not open source file %s.\n", src_file_path);
+ err |= TRANCHE_ERR_SRC_OPEN;
+ }else{
+ tranche_send(src_file, target_arrp);
+ if( fclose(src_file) == -1 ){perror(NULL); err |= TRANCHE_ERR_FCLOSE;}
+ }
+ pt += src_arrp->element_size;
+ }
+ }
- da_free(&targets);
- fclose(src_file);
- return 0;
+ da_free(target_arrp);
+ da_free(src_arrp);
+ return err;
}
da_alloc(&fda, sizeof(int));
while( !feof(src) ){
- da_fgets(&line, src);
+ da_string_input(&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
//--------------------------------------------------------------------------------
// returns a list of unique target file names from a tranche source
-
-// return true if proffered test string is already in the strings array
-typedef struct {
- char *string;
- bool found;
-} string_state;
-static void string_equal(void *sp, void *closure){
- char *string_element = *(char **)sp;
- string_state *ss = (string_state *)closure;
- if( ss->found ) return;
- ss->found = !strcmp(string_element, ss->string);
- return;
-}
-static bool exists(Da *string_arrp, char *test_string){
- string_state ss;
- ss.string = test_string;
- ss.found = false;
- da_map(string_arrp, string_equal, &ss);
- return ss.found;
-}
-
-// only inserts the string if it is not already in the array
-static void insert_if_unique(Da *string_arrp, char *proffered_string){
- if( exists( string_arrp, proffered_string)){ // then throw it away, we don't need it
- free(proffered_string);
- return;
- }
- da_push(string_arrp, &proffered_string);
-}
-
-// dissolves proffered array into the existing array
-static void combine_one(void *psp, void *closure){
- char *proffered_string = *(char **)psp;
- Da *string_arrp = (Da *)closure;
- insert_if_unique(string_arrp, proffered_string);
-}
-static void combine(Da *string_arrp, Da *proffered_string_arrp){
- da_map(proffered_string_arrp, combine_one, string_arrp);
- return;
-}
-
// make a list of the unique tranche target files found in src
int tranche_target(FILE *src, Da *target_arrp){
char *pt;
da_alloc(&line, sizeof(char));
da_alloc(&file_name_arr, sizeof(char *));
while( !feof(src) ){
- da_fgets(&line, src);
+ da_string_input(&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);
- combine(target_arrp, &file_name_arr); // frees strings that are not inserted
+ da_strings_set_union(target_arrp, &file_name_arr, free);
da_rewind(&file_name_arr);
tranche_target(src, target_arrp);
}
char *pt = tap->base; // char * because it points to a byte in the array
while( pt < tap->end ){
if(tdir){
- da_push_string(dlap, tdir);
+ da_string_push(dlap, tdir);
da_push(dlap, &slash);
}
- da_push_string(dlap, *(char **)pt);
+ da_string_push(dlap, *(char **)pt);
da_push(dlap, &sp);
pt += tap->element_size;
}
da_push(dlap, &colon);
da_push(dlap, &sp);
- da_push_string(dlap, src_name);
+ da_string_push(dlap, src_name);
da_push(dlap, &newline);
write(mfile_fd, dlap->base, dlap->end - dlap->base);
da_free_elements(tap);
// output acction line ----------------------------------------
da_rewind(dlap); // reuse the line buffer
da_push(dlap, &tab);
- da_push_string(dlap, "tranche $<");
+ da_string_push(dlap, "tranche $<");
if(tdir){
- da_push_string(dlap, " -tdir ");
- da_push_string(dlap, tdir);
+ da_string_push(dlap, " -tdir ");
+ da_string_push(dlap, tdir);
}
da_push(dlap, &newline);
da_push(dlap, &newline);
#define TRANCHE_ERR_SRC_OPEN 2
#define TRANCHE_ERR_DST_OPEN 4
#define TRANCHE_ERR_FCLOSE 8
+#define TRANCHE_ERR_HELP 16
+#define TRANCHE_ERR_SNAME 32
void path_trim_slashes(char *path);
int tranche_send(FILE *src, Da *arg_fds);
diff -q test2.c test2.c.expected
diff -q test2.h test2.h.expected
diff -q test2stdout.dat test2stdout.dat.expected
-rm test2.c test2.h
+rm test2.c test2.h test2stdout.dat.expected
--- /dev/null
+./tranche test1.dat test2.trc.c
+
+diff -q test11.dat test11.dat.expected
+diff -q test12.dat test12.dat.expected
+diff -q test13.dat test13.dat.expected
+diff -q test14.dat test14.dat.expected
+diff -q test15.dat test15.dat.expected
+
+diff -q test2.c test2.c.expected
+diff -q test2.h test2.h.expected
+
+rm test11.dat test12.dat test13.dat test14.dat test15.dat
+rm test2.c test2.h
# executables are made from CLI sources
EXEC= $(patsubst %, $(EXECDIR)/%, $(C_BASE_CLI) $(CC_BASE_CLI))
+# default directory seteup
+# For TRC projects define TRDIR (even if it is just '.'), and typically set SRCDIR to tmp
+#
+
DEPRDIR=deprecated
DOCDIR=doc
EXECDIR=exec
TESTDIR=test
TMPDIR=tmp
TOOLDIR=$(realpath $(PROJECT_SUBU)/tool)
+TRCDIR=
TRYDIR=try
+
# a single space literal, for example if you wanted to subsitute commas to
# spaces: $(subst $(space),;,$(string))
blank :=
LIBFILE=$(LIBDIR)/lib$(MODULE).a
INCFILE=$(INCDIR)/$(MODULE).h
+#--------------------------------------------------------------------------------
+# when local customizations set a TRCDIR, then these are the actual sources
+
+ifneq ($TRCDIR,)
+ TRCFILES= $(wildcard $(TRCDIR)/*.trc.c) $(wildcard $(TRCDIR)/*.trc.cc)
+else
+ TRCFILES=
+endif
+
+
#--------------------------------------------------------------------------------
# targets
.PHONY: all
-all: version dep lib exec
+all: version
.PHONY: version
version:
- @echo makefile version 4.0
+ @echo makefile version 5.0
@echo "PWD: " $(PWD)
@echo "MAKEFILE_LIST: " $(MAKEFILE_LIST)
@echo "C: " $(C)
@echo "TESTDIR: " $(TESTDIR)
@echo "TMPDIR: " $(TMPDIR)
@echo "TOOLDIR: " $(TOOLDIR)
+ @echo "TRCDIR: " $(TRCDIR)
@echo "TRYDIR: " $(TRYDIR)
@echo "DEPFILE: " $(DEPFILE)
@echo "LIBFILE: " $(LIBFILE)
@echo "INCFILE: " $(INCFILE)
+ @echo "TRCFILES: " $(TRCFILES)
+ @echo "C_SOURCE_LIB: " $(C_SOURCE_LIB)
@echo "C_SOURCE_LIB: " $(C_SOURCE_LIB)
@echo "C_SOURCE_CLI: " $(C_SOURCE_CLI)
@echo "CC_SOURCE_LIB: " $(CC_SOURCE_LIB)
@echo "EXEC: " $(EXEC)
# should be safe to run this in an already setup or partially setup directory
+# gee looks like a candidate for a makefile function ..
.PHONY: setup
setup:
- [ ! -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
+ [ ! -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 $(TRCDIR) ] && mkdir $(TRCDIR) || true
+ [ ! -e $(TRYDIR) ] && mkdir $(TRYDIR) || true
+
+# gee this script could be better, particlarly in gathering the targets
+# it would be simplified if the tranche commands took multiple source arguments
+# if [ -e $(DEPFILE) ]; then rm $(DEPFILE); fi
+# if [ ! -z "$(TRCFILES)" ]; then\
+# targets="";\
+# for i in $(TRCFILES); do\
+# tranche-make $$i -tdir $(SRCDIR) -mfile $(DEPFILE);\
+# targets+=$$(tranche-target $$i);\
+# targets+=" ";\
+# done;\
+# echo $$targets;\
+# fi
+
+
.PHONY: dep
-dep:
- @if [ -z "$(CC)" ]; then\
+dep:
+ if [ -e $(DEPFILE) ]; then rm $(DEPFILE); fi
+ if [ ! -z "$(TRCFILES)" ]; then\
+ tranche-make $(TRCFILES) -mfile $(DEPFILE);\
+ $(MAKE) $(shell tranche-targets $(TRCFILES) -sep " ");\
+ fi
+ if [ -z "$(CC)" ]; then\
if [ -z "$C()" ]; then\
echo "No compiler specified";\
exit 1;\
else\
echo "C compiler only deps" ;\
- $(C) $(CFLAGS) -MM $(C_SOURCE_LIB) $(C_SOURCE_CLI) | sed 's|^.*\.o|$(TMPDIR)/&|' > $(DEPFILE);\
+ $(C) $(CFLAGS) -MM $(C_SOURCE_LIB) $(C_SOURCE_CLI) | sed 's|^.*\.o|$(TMPDIR)/&|' >> $(DEPFILE);\
echo "deps for C linking";\
- for i in $(C_BASE_CLI) ; do\
+ 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_SOURCE_LIB) $(CC_SOURCE_CLI) | sed 's|^.*\.o|$(TMPDIR)/&|' > $(DEPFILE);\
+ $(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_SOURCE_LIB) $(C_SOURCE_CLI) | sed 's|^.*\.o|$(TMPDIR)/&|' > $(DEPFILE);\
+ $(C) $(CFLAGS) -MM $(C_SOURCE_LIB) $(C_SOURCE_CLI) | sed 's|^.*\.o|$(TMPDIR)/&|' >> $(DEPFILE);\
fi;\
echo "deps for CC linking";\
for i in $(CC_BASE_CLI) $(C_BASE_CLI) ; do\
+++ /dev/null
-
-# This makefile is usually called through a local makefile rather than directly.
-# The purpose of this makefile is to expand out the tranched C/CC sources, and
-# otherwise to fall through to makefile_cc.
-
-SHELL=/bin/bash
-
-TRCDIR=trc
-
-# these are the sources edited by the programmer
-TRC_FILE= $(wildcard $(TRCDIR)/*.trc.c) $(wildcard $(TRCDIR)/*.trc.cc)
-
--include makefile-flags
-
-MAKE=/usr/bin/make --no-print-directory -f $(PROJECT_SUBU)/tool/lib/makefile-cc
-#MAKE=/usr/bin/make -f $(PROJECT_SUBU)/tool/lib/makefile-cc
-
-DEPFILE=$(TMPDIR)/makefile-trc.deps
-
-all: version deps lib execs
-
-.PHONY: all version deps lib exec
-all: version deps lib exec
-
-lib:
- $(MAKE) $@
-
-exec:
- $(MAKE) $@
-
-share:
- if [ ! -z "$(wildcard $(EXECDIR)/*)" ]; then cp $(EXECDIR)/* $(PROJECT_SUBU)/tool/bin; fi
-
-%::
- $(MAKE) $@
-
-dep:
\ No newline at end of file