/* Jimsh - An interactive shell for Jim * Copyright 2005 Salvatore Sanfilippo * Copyright 2009 Steve Bennett * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * A copy of the license is also included in the source distribution * of Jim, as a TXT file name called LICENSE. * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include "jim.h" /* JimGetExePath try to get the absolute path of the directory * of the jim binary, in order to add this path to the library path. * Likely shipped libraries are in the same path too. */ #ifndef JIM_ANSIC /* A bit complex on POSIX */ #include static Jim_Obj *JimGetExePath(Jim_Interp *interp, const char *argv0) { char *p; /* Check if the executable was called with an absolute pathname */ if (argv0[0] == '/') { p = strrchr(argv0, '/'); return Jim_NewStringObj(interp, argv0, (p == argv0) ? 1 : p - argv0); } else { int l; char *path = Jim_Alloc(JIM_PATH_LEN + 1); if (getcwd(path, JIM_PATH_LEN) == NULL) { default_path: Jim_Free(path); return Jim_NewStringObj(interp, "/usr/local/lib/jim/", -1); } /* Need to add the directory component of argv0 to pwd (path) */ /* Strip any leading "./" off argv0 for cleanliness */ while (argv0[0] == '.' && argv0[1] == '/') { argv0 += 2; } l = strlen(path); /* Strip the last component from argv0 */ p = strrchr(argv0, '/'); if (p) { int argv0len = p - argv0; /* Need a trailing / on pwd */ if (l > 0 && path[l - 1] != '/') path[l++] = '/'; /* And append it to 'path' */ if (l + argv0len > JIM_PATH_LEN) { /* It won't fit. Don't both trying to realloc. */ goto default_path; } memcpy(path + l, argv0, argv0len); l += argv0len; path[l] = '\0'; } return Jim_NewStringObjNoAlloc(interp, path, l); } } #else /* JIM_ANSIC */ /* ... and impossible with just ANSI C */ static Jim_Obj *JimGetExePath(Jim_Interp *interp, const char *argv0) { JIM_NOTUSED(argv0); return Jim_NewStringObj(interp, "/usr/local/lib/jim/", -1); } #endif /* JIM_ANSIC */ static void JimLoadJimRc(Jim_Interp *interp) { const char *home; /* XXX: Move off stack */ char buf[JIM_PATH_LEN + 1]; const char *names[] = { ".jimrc", "jimrc.tcl", NULL }; int i; FILE *fp; if ((home = getenv("HOME")) == NULL) return; for (i = 0; names[i] != NULL; i++) { if (strlen(home) + strlen(names[i]) + 1 > JIM_PATH_LEN) continue; sprintf(buf, "%s/%s", home, names[i]); if ((fp = fopen(buf, "r")) != NULL) { fclose(fp); if (Jim_EvalFile(interp, buf) != JIM_OK) { Jim_PrintErrorMessage(interp); } return; } } } static void JimSetArgv(Jim_Interp *interp, int argc, char *const argv[]) { int n; Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); /* Populate argv global var */ for (n = 0; n < argc; n++) { Jim_Obj *obj = Jim_NewStringObj(interp, argv[n], -1); Jim_ListAppendElement(interp, listObj, obj); } Jim_SetVariableStr(interp, "argv", listObj); } int main(int argc, char *const argv[]) { int retcode; Jim_Interp *interp; Jim_Obj *listObj; /* Create and initialize the interpreter */ interp = Jim_CreateInterp(); Jim_RegisterCoreCommands(interp); /* Register static extensions */ if (Jim_InitStaticExtensions(interp) != JIM_OK) { Jim_PrintErrorMessage(interp); } /* Append the path where the executed Jim binary is contained * in the jim_libpath list. */ listObj = Jim_GetVariableStr(interp, JIM_LIBPATH, JIM_NONE); if (Jim_IsShared(listObj)) listObj = Jim_DuplicateObj(interp, listObj); Jim_ListAppendElement(interp, listObj, JimGetExePath(interp, argv[0])); Jim_SetVariableStr(interp, JIM_LIBPATH, listObj); Jim_SetVariableStrWithStr(interp, "jim_argv0", argv[0]); if (argc == 1) { Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1"); JimSetArgv(interp, 0, NULL); JimLoadJimRc(interp); retcode = Jim_InteractivePrompt(interp); } else { Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "0"); if (argc > 2 && strcmp(argv[1], "-e") == 0) { JimSetArgv(interp, argc - 3, argv + 3); retcode = Jim_Eval(interp, argv[2]); } else { Jim_SetVariableStr(interp, "argv0", Jim_NewStringObj(interp, argv[1], -1)); JimSetArgv(interp, argc - 2, argv + 2); retcode = Jim_EvalFile(interp, argv[1]); } if (retcode == JIM_ERR) { Jim_PrintErrorMessage(interp); } } if (retcode == JIM_OK) { retcode = 0; } else if (retcode == JIM_EXIT) { retcode = interp->exitCode; } else { retcode = 1; } Jim_FreeInterp(interp); return retcode; }