Diff

Differences From Artifact [c5ca9c2598]:

To Artifact [ade95f924e]:


    80     80   		} symlink;
    81     81   	} typeinfo;
    82     82   };
    83     83   
    84     84   /*
    85     85    * Create a new Tcl interpreter and completely initialize it
    86     86    */
    87         -static Tcl_Interp *appfs_create_TclInterp(void) {
           87  +static Tcl_Interp *appfs_create_TclInterp(char **error_string) {
    88     88   	Tcl_Interp *interp;
    89     89   	int tcl_ret;
    90     90   
    91     91   	APPFS_DEBUG("Creating new Tcl interpreter for TID = 0x%llx", (unsigned long long) pthread_self());
    92     92   
    93     93   	interp = Tcl_CreateInterp();
    94     94   	if (interp == NULL) {
    95     95   		fprintf(stderr, "Unable to create Tcl Interpreter.  Aborting.\n");
           96  +
           97  +		if (error_string) {
           98  +			*error_string = strdup("Unable to create Tcl interpreter.");
           99  +		}
    96    100   
    97    101   		return(NULL);
    98    102   	}
    99    103   
   100    104   	tcl_ret = Tcl_Init(interp);
   101    105   	if (tcl_ret != TCL_OK) {
   102    106   		fprintf(stderr, "Unable to initialize Tcl.  Aborting.\n");
   103    107   		fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
          108  +
          109  +		if (error_string) {
          110  +			*error_string = strdup(Tcl_GetStringResult(interp));
          111  +		}
   104    112   
   105    113   		Tcl_DeleteInterp(interp);
   106    114   
   107    115   		return(NULL);
   108    116   	}
   109    117   
   110    118   	tcl_ret = Tcl_Eval(interp, "package ifneeded sha1 1.0 [list load {} sha1]");
   111    119   	if (tcl_ret != TCL_OK) {
   112    120   		fprintf(stderr, "Unable to initialize Tcl SHA1.  Aborting.\n");
   113    121   		fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
          122  +
          123  +		if (error_string) {
          124  +			*error_string = strdup(Tcl_GetStringResult(interp));
          125  +		}
   114    126   
   115    127   		Tcl_DeleteInterp(interp);
   116    128   
   117    129   		return(NULL);
   118    130   	}
   119    131   
   120    132   	tcl_ret = Tcl_Eval(interp, "package ifneeded appfsd 1.0 [list load {} appfsd]");
   121    133   	if (tcl_ret != TCL_OK) {
   122    134   		fprintf(stderr, "Unable to initialize Tcl AppFS Package.  Aborting.\n");
   123    135   		fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
          136  +
          137  +		if (error_string) {
          138  +			*error_string = strdup(Tcl_GetStringResult(interp));
          139  +		}
   124    140   
   125    141   		Tcl_DeleteInterp(interp);
   126    142   
   127    143   		return(NULL);
   128    144   	}
   129    145   
   130    146   	/*
................................................................................
   134    150   	 */
   135    151   	tcl_ret = Tcl_Eval(interp, ""
   136    152   #include "appfsd.tcl.h"
   137    153   	"");
   138    154   	if (tcl_ret != TCL_OK) {
   139    155   		fprintf(stderr, "Unable to initialize Tcl AppFS script.  Aborting.\n");
   140    156   		fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
          157  +
          158  +		if (error_string) {
          159  +			*error_string = strdup(Tcl_GetStringResult(interp));
          160  +		}
   141    161   
   142    162   		Tcl_DeleteInterp(interp);
   143    163   
   144    164   		return(NULL);
   145    165   	}
   146    166   
   147    167   	/*
   148    168   	 * Set global variables from C to Tcl
   149    169   	 */
   150    170   	if (Tcl_SetVar(interp, "::appfs::cachedir", appfs_cachedir, TCL_GLOBAL_ONLY) == NULL) {
   151    171   		fprintf(stderr, "Unable to set cache directory.  This should never fail.\n");
          172  +
          173  +		if (error_string) {
          174  +			*error_string = strdup(Tcl_GetStringResult(interp));
          175  +		}
   152    176   
   153    177   		Tcl_DeleteInterp(interp);
   154    178   
   155    179   		return(NULL);
   156    180   	}
   157    181   
   158    182   	/*
................................................................................
   159    183   	 * Initialize the "appfsd.tcl" environment, which must be done after
   160    184   	 * global variables are set.
   161    185   	 */
   162    186   	tcl_ret = Tcl_Eval(interp, "::appfs::init");
   163    187   	if (tcl_ret != TCL_OK) {
   164    188   		fprintf(stderr, "Unable to initialize Tcl AppFS script (::appfs::init).  Aborting.\n");
   165    189   		fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
          190  +
          191  +		if (error_string) {
          192  +			*error_string = strdup(Tcl_GetStringResult(interp));
          193  +		}
   166    194   
   167    195   		Tcl_DeleteInterp(interp);
   168    196   
   169    197   		return(NULL);
   170    198   	}
   171    199   
   172    200   	/*
................................................................................
   187    215    */
   188    216   static Tcl_Interp *appfs_TclInterp(void) {
   189    217   	Tcl_Interp *interp;
   190    218   	int pthread_ret;
   191    219   
   192    220   	interp = pthread_getspecific(interpKey);
   193    221   	if (interp == NULL) {
   194         -		interp = appfs_create_TclInterp();
          222  +		interp = appfs_create_TclInterp(NULL);
   195    223   
   196    224   		if (interp == NULL) {
   197    225   			return(NULL);
   198    226   		}
   199    227   
   200    228   		pthread_ret = pthread_setspecific(interpKey, interp);
   201    229   		if (pthread_ret != 0) {
................................................................................
   730    758    * SQLite3 mode: Execute raw SQL and return success or failure
   731    759    */
   732    760   static int appfs_sqlite3(const char *sql) {
   733    761   	Tcl_Interp *interp;
   734    762   	const char *sql_ret;
   735    763   	int tcl_ret;
   736    764   
   737         -	interp = appfs_create_TclInterp();
          765  +	interp = appfs_create_TclInterp(NULL);
   738    766   	if (interp == NULL) {
   739    767   		fprintf(stderr, "Unable to create a Tcl interpreter.  Aborting.\n");
   740    768   
   741    769   		return(1);
   742    770   	}
   743    771   
   744    772   	tcl_ret = appfs_Tcl_Eval(interp, 5, "::appfs::db", "eval", sql, "row", "unset -nocomplain row(*); parray row; puts \"----\"");
................................................................................
   761    789    * Tcl mode: Execute raw Tcl and return success or failure
   762    790    */
   763    791   static int appfs_tcl(const char *tcl) {
   764    792   	Tcl_Interp *interp;
   765    793   	const char *tcl_result;
   766    794   	int tcl_ret;
   767    795   
   768         -	interp = appfs_create_TclInterp();
          796  +	interp = appfs_create_TclInterp(NULL);
   769    797   	if (interp == NULL) {
   770    798   		fprintf(stderr, "Unable to create a Tcl interpreter.  Aborting.\n");
   771    799   
   772    800   		return(1);
   773    801   	}
   774    802   
   775    803   	tcl_ret = Tcl_Eval(interp, tcl);
................................................................................
   837    865   	return(1);
   838    866   }
   839    867   
   840    868   /*
   841    869    * Entry point into this program.
   842    870    */
   843    871   int main(int argc, char **argv) {
          872  +	Tcl_Interp *test_interp;
          873  +	char *test_interp_error;
   844    874   	struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
   845    875   	int pthread_ret;
   846    876   
   847    877   	/*
   848    878   	 * Skip passed program name
   849    879   	 */
   850    880   	if (argc == 0 || argv == NULL) {
................................................................................
   920    950   	fuse_opt_add_arg(&args, "-odefault_permissions,fsname=appfs,subtype=appfsd,use_ino,kernel_cache,entry_timeout=60,attr_timeout=3600,intr,big_writes");
   921    951   
   922    952   	if (getuid() == 0) {
   923    953   		fuse_opt_parse(&args, NULL, NULL, NULL);
   924    954   		fuse_opt_add_arg(&args, "-oallow_other");
   925    955   	}
   926    956   
          957  +	/*
          958  +	 * Create a Tcl interpreter just to verify that things are in working 
          959  +	 * order before we become a daemon.
          960  +	 */
          961  +	test_interp = appfs_create_TclInterp(&test_interp_error);
          962  +	if (test_interp == NULL) {
          963  +		if (test_interp_error == NULL) {
          964  +			test_interp_error = "Unknown error";
          965  +		}
          966  +
          967  +		fprintf(stderr, "Unable to initialize Tcl interpreter for AppFSd:\n");
          968  +		fprintf(stderr, "%s", test_interp_error);
          969  +
          970  +		return(1);
          971  +	}
          972  +	Tcl_DeleteInterp(test_interp);
          973  +
   927    974   	/*
   928    975   	 * Enter the FUSE main loop -- this will process any arguments
   929    976   	 * and start servicing requests.
   930    977   	 */
   931    978   	appfs_fuse_started = 1;
   932    979   	return(fuse_main(args.argc, args.argv, &appfs_operations, NULL));
   933    980   }
   934    981