@@ -82,27 +82,35 @@ }; /* * Create a new Tcl interpreter and completely initialize it */ -static Tcl_Interp *appfs_create_TclInterp(void) { +static Tcl_Interp *appfs_create_TclInterp(char **error_string) { Tcl_Interp *interp; int tcl_ret; APPFS_DEBUG("Creating new Tcl interpreter for TID = 0x%llx", (unsigned long long) pthread_self()); interp = Tcl_CreateInterp(); if (interp == NULL) { fprintf(stderr, "Unable to create Tcl Interpreter. Aborting.\n"); + + if (error_string) { + *error_string = strdup("Unable to create Tcl interpreter."); + } return(NULL); } tcl_ret = Tcl_Init(interp); if (tcl_ret != TCL_OK) { fprintf(stderr, "Unable to initialize Tcl. Aborting.\n"); fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); + + if (error_string) { + *error_string = strdup(Tcl_GetStringResult(interp)); + } Tcl_DeleteInterp(interp); return(NULL); } @@ -109,10 +117,14 @@ tcl_ret = Tcl_Eval(interp, "package ifneeded sha1 1.0 [list load {} sha1]"); if (tcl_ret != TCL_OK) { fprintf(stderr, "Unable to initialize Tcl SHA1. Aborting.\n"); fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); + + if (error_string) { + *error_string = strdup(Tcl_GetStringResult(interp)); + } Tcl_DeleteInterp(interp); return(NULL); } @@ -119,10 +131,14 @@ tcl_ret = Tcl_Eval(interp, "package ifneeded appfsd 1.0 [list load {} appfsd]"); if (tcl_ret != TCL_OK) { fprintf(stderr, "Unable to initialize Tcl AppFS Package. Aborting.\n"); fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); + + if (error_string) { + *error_string = strdup(Tcl_GetStringResult(interp)); + } Tcl_DeleteInterp(interp); return(NULL); } @@ -136,10 +152,14 @@ #include "appfsd.tcl.h" ""); if (tcl_ret != TCL_OK) { fprintf(stderr, "Unable to initialize Tcl AppFS script. Aborting.\n"); fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); + + if (error_string) { + *error_string = strdup(Tcl_GetStringResult(interp)); + } Tcl_DeleteInterp(interp); return(NULL); } @@ -147,10 +167,14 @@ /* * Set global variables from C to Tcl */ if (Tcl_SetVar(interp, "::appfs::cachedir", appfs_cachedir, TCL_GLOBAL_ONLY) == NULL) { fprintf(stderr, "Unable to set cache directory. This should never fail.\n"); + + if (error_string) { + *error_string = strdup(Tcl_GetStringResult(interp)); + } Tcl_DeleteInterp(interp); return(NULL); } @@ -161,10 +185,14 @@ */ tcl_ret = Tcl_Eval(interp, "::appfs::init"); if (tcl_ret != TCL_OK) { fprintf(stderr, "Unable to initialize Tcl AppFS script (::appfs::init). Aborting.\n"); fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp)); + + if (error_string) { + *error_string = strdup(Tcl_GetStringResult(interp)); + } Tcl_DeleteInterp(interp); return(NULL); } @@ -189,11 +217,11 @@ Tcl_Interp *interp; int pthread_ret; interp = pthread_getspecific(interpKey); if (interp == NULL) { - interp = appfs_create_TclInterp(); + interp = appfs_create_TclInterp(NULL); if (interp == NULL) { return(NULL); } @@ -732,11 +760,11 @@ static int appfs_sqlite3(const char *sql) { Tcl_Interp *interp; const char *sql_ret; int tcl_ret; - interp = appfs_create_TclInterp(); + interp = appfs_create_TclInterp(NULL); if (interp == NULL) { fprintf(stderr, "Unable to create a Tcl interpreter. Aborting.\n"); return(1); } @@ -763,11 +791,11 @@ static int appfs_tcl(const char *tcl) { Tcl_Interp *interp; const char *tcl_result; int tcl_ret; - interp = appfs_create_TclInterp(); + interp = appfs_create_TclInterp(NULL); if (interp == NULL) { fprintf(stderr, "Unable to create a Tcl interpreter. Aborting.\n"); return(1); } @@ -839,10 +867,12 @@ /* * Entry point into this program. */ int main(int argc, char **argv) { + Tcl_Interp *test_interp; + char *test_interp_error; struct fuse_args args = FUSE_ARGS_INIT(argc, argv); int pthread_ret; /* * Skip passed program name @@ -922,13 +952,30 @@ if (getuid() == 0) { fuse_opt_parse(&args, NULL, NULL, NULL); fuse_opt_add_arg(&args, "-oallow_other"); } + /* + * Create a Tcl interpreter just to verify that things are in working + * order before we become a daemon. + */ + test_interp = appfs_create_TclInterp(&test_interp_error); + if (test_interp == NULL) { + if (test_interp_error == NULL) { + test_interp_error = "Unknown error"; + } + + fprintf(stderr, "Unable to initialize Tcl interpreter for AppFSd:\n"); + fprintf(stderr, "%s", test_interp_error); + + return(1); + } + Tcl_DeleteInterp(test_interp); + /* * Enter the FUSE main loop -- this will process any arguments * and start servicing requests. */ appfs_fuse_started = 1; return(fuse_main(args.argc, args.argv, &appfs_operations, NULL)); }