--- /dev/null
+/*
+ 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;
+ }
+}
--- /dev/null
+/*
+ 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;
+ }
+}
+
+
--- /dev/null
+/*
+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;
+ }}}
+
--- /dev/null
+/* \aThis file was automatically generated. Do not edit! */
+#undef INTERFACE
+#include <sys/types.h>
+#include <unistd.h>
+typedef struct dispatch_ctx dispatch_ctx;
+dispatch_ctx *dispatch_exec(char **argv,char **envp);
+dispatch_ctx *dispatch_f_euid_egid(char *fname,int(*f)(void *arg),void *f_arg,uid_t euid,gid_t egid);
+int dbprintf(const char *format,...);
+dispatch_ctx *dispatch_f(char *fname,int(*f)(void *arg),void *f_arg);
+void dispatch_f_mess(struct dispatch_ctx *ctxp);
+void dispatch_ctx_free(dispatch_ctx *ctxp);
+dispatch_ctx *dispatch_ctx_mk(char *dispatcher,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
+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
#include <sqlite3.h>
int subu_put_masteru_subu(sqlite3 *db,char *masteru_name,char *subuname,char *subu_username);
#include <sys/types.h>
-#include <pwd.h>
-typedef struct dispatch_useradd_ret_t dispatch_useradd_ret_t;
-typedef unsigned int uint;
-struct dispatch_useradd_ret_t {
- uint error;
- struct passwd *pw_record;
-};
-struct dispatch_useradd_ret_t dispatch_useradd(char **argv,char **envp);
-#define BUG_SSS_CACHE_RUID 1
#include <unistd.h>
-typedef struct dispatch_f_ctx dispatch_f_ctx;
-dispatch_f_ctx *dispatch_f_euid_egid(char *fname,int(*f)(void *arg),void *f_arg,uid_t euid,gid_t egid);
-struct dispatch_f_ctx {
- char *dispatcher; // name of the dispatch function (currently "dispatch_f" or "dispatch_f_euid_egid")
+typedef struct dispatch_ctx dispatch_ctx;
+dispatch_ctx *dispatch_exec(char **argv,char **envp);
+#define BUG_SSS_CACHE_RUID 1
+void dispatch_f_mess(struct dispatch_ctx *ctxp);
+#define ERR_DISPATCH -1024
+dispatch_ctx *dispatch_f_euid_egid(char *fname,int(*f)(void *arg),void *f_arg,uid_t euid,gid_t egid);
+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;
- int status; // return value from the function
+ int err; // error code as listed below, or status returned from dispatchee
};
int subu_number_get(sqlite3 *db,char **nsp,char **errmsg);
int dbprintf(const char *format,...);
#include <errno.h>
typedef struct subu_mk_0_ctx subu_mk_0_ctx;
struct subu_mk_0_ctx *subu_mk_0(sqlite3 *db,char *subuname);
+typedef unsigned int uint;
extern uint subuhome_perms;
void subu_mk_0_mess(struct subu_mk_0_ctx *ctxp);
void subu_mk_0_ctx_free(struct subu_mk_0_ctx *ctxp);
--- /dev/null
+/*
+ Runs a command or function as its own process.
+
+ For the return status 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.
+
+ Interesting it isn't possible to have a kernel dispatch that calls fork, and then
+ others that call this kernel. The reason being is because of collision in return
+ status values between the function in the kernel, and with each wrapper. The
+ TTCA with the passed in error processing functions would not have this problem.
+
+*/
+#define _GNU_SOURCE
+
+#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>
+
+#if INTERFACE
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+//--------------------------------------------------------------------------------
+// dispatch returns an instance of this class.
+//
+#if INTERFACE
+// 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
+};
+#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
+#endif
+dispatch_ctx *dispatch_ctx_mk(char *dispatcher, char *dispatchee){
+ dispatch_ctx *ctxp = malloc(sizeof(dispatch_ctx));
+ ctxp->dispatcher = dispatcher;
+ ctxp->dispatchee = dispatchee;
+ ctxp->err = 0;
+ return ctxp;
+}
+void dispatch_ctx_free(dispatch_ctx *ctxp){
+ // currently no dynamic variables to be freed in ctx
+ free(ctxp);
+}
+void dispatch_f_mess(struct dispatch_ctx *ctxp){
+ if(ctxp->err > ERR_DISPATCH) return;
+ fprintf(stderr, "%s", ctxp->dispatcher); // if fprintf gets an error, errno will be overwritten
+ switch(ctxp->err){
+ case ERR_DISPATCH_NEGATIVE_RETURN_STATUS:
+ fprintf(stderr, " dispatchee \"%s\" returned a negative status.", ctxp->dispatchee);
+ break;
+ case ERR_DISPATCH_F_FORK:
+ case ERR_DISPATCH_F_SETEUID:
+ case ERR_DISPATCH_F_SETEGID:
+ fputc(' ', stderr);
+ perror(ctxp->dispatcher);
+ break;
+ case ERR_DISPATCH_NULL_EXECUTABLE:
+ fprintf(stderr, " executable was not specified");
+ break;
+ case ERR_DISPATCH_EXEC:
+ // exec is in another process when it fails, so we can't see the errno value it set
+ fprintf(stderr, " exec of \"%s\" failed", ctxp->dispatchee);
+ break;
+ default:
+ fprintf(stderr, " returned undefined status");
+ }
+ fputc('\n', stderr);
+}
+
+//--------------------------------------------------------------------------------
+// interface call point, dispatch a function
+dispatch_ctx *dispatch_f(char *fname, int (*f)(void *arg), void *f_arg){
+ dispatch_ctx *ctxp = dispatch_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; // something went wrong and 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 < ERR_DISPATCH ) status = ERR_DISPATCH_NEGATIVE_RETURN_STATUS;
+ exit(status);
+ }else{ // we are the parent
+ waitpid(pid, &(ctxp->err), 0);
+ return ctxp;
+ }
+}
+
+//--------------------------------------------------------------------------------
+// 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
+dispatch_ctx *dispatch_f_euid_egid(char *fname, int (*f)(void *arg), void *f_arg, uid_t euid, gid_t egid){
+ dispatch_ctx *ctxp = dispatch_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 <= ERR_DISPATCH ) status = ERR_DISPATCH_NEGATIVE_RETURN_STATUS;
+ exit(status);
+ }
+ }else{ // we are the parent
+ waitpid(pid, &(ctxp->err), 0);
+ return ctxp;
+ }
+}
+
+//--------------------------------------------------------------------------------
+// interface call point, dispatch a executable
+dispatch_ctx *dispatch_exec(char **argv, char **envp){
+ dispatch_ctx *ctxp;
+ char *command;
+ {
+ if( !argv || !argv[0] ){
+ ctxp = dispatch_ctx_mk("dispatch_exec", "NULL");
+ ctxp->err = ERR_DISPATCH_NULL_EXECUTABLE;
+ return ctxp;
+ }
+ #ifdef DEBUG
+ dbprintf("dispatch_exec:");
+ char **apt = argv;
+ while( *apt ){
+ dbprintf(" %s",*apt);
+ apt++;
+ }
+ dbprintf("\n");
+ #endif
+ command = argv[0];
+ ctxp = dispatch_ctx_mk("dispatch_exec", command);
+ }
+ pid_t pid = fork();
+ if( pid == -1 ){
+ ctxp->err = ERR_DISPATCH_F_FORK; // something went wrong and we are still in the parent process
+ return ctxp;
+ }
+ if( pid == 0 ){ // we are the child
+ execvpe(command, argv, envp); // exec will only return if it has an error
+ perror("dispatch_exec"); // our only chance to print this message, as this is the child process
+ exit(ERR_DISPATCH_EXEC);
+ }else{ // we are the parent
+ waitpid(pid, &(ctxp->err), 0);
+ return ctxp;
+ }
+}
+
+
+++ /dev/null
-/*
- 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;
- }
-}
+++ /dev/null
-/*
- 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;
- }
-}
-
-
+++ /dev/null
-/*
-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;
- }}}
-
ctxp->err = ERR_SUBU_MK_0_SUBUHOME_EXISTS;
return ctxp;
}
- struct dispatch_f_ctx *dfr = dispatch_f_euid_egid
+ dispatch_ctx *dfr = dispatch_f_euid_egid
(
"masteru_makes_subuhome",
masteru_makes_subuhome,
masteru_uid,
masteru_gid
);
- if( dfr->err < 0 || dfr->err == ERR_SUBU_MK_0_MKDIR_SUBUHOME ){
+ if( dfr->err <= ERR_DISPATCH || dfr->err == ERR_SUBU_MK_0_MKDIR_SUBUHOME ){
+ #ifdef DEBUG
+ if( dfr->err == ERR_SUBU_MK_0_MKDIR_SUBUHOME )
+ perror("mkdir");
+ else
+ dispatch_f_mess(dfr);
+ #endif
ctxp->err = ERR_SUBU_MK_0_MKDIR_SUBUHOME;
return ctxp;
}
argv[2] = (char *) NULL;
char *envp[1];
envp[0] = (char *) NULL;
- struct dispatch_useradd_ret_t ret;
- ret = dispatch_useradd(argv, envp);
- if(ret.error){
+ 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
ctxp->err = ERR_SUBU_MK_0_FAILED_USERADD;
return ctxp;
}