*** src/backend/commands/define.c.orig Wed Jul 26 11:50:40 2000 --- src/backend/commands/define.c Thu Jul 27 10:50:59 2000 *************** *** 182,194 **** --- 182,204 ---- interpret_AS_clause(const char *languageName, const List *as, char **prosrc_str_p, char **probin_str_p) { + #if 0 struct stat stat_buf; + #endif Assert(as != NIL); if (strcmp(languageName, "C") == 0) { + #if 0 + /* + * It seems like you should be able to use a file that doesn't currently + * exist yet. It only matters if the file exists when it is used. + * Also, if there is an environment variable in the pathname, doing the + * stat early might prevent the path from being inserted. + */ + /* * For "C" language, store the file name in probin and, when * given, the link symbol name in prosrc. But first, stat the *************** *** 197,203 **** if (stat(strVal(lfirst(as)), &stat_buf) == -1) elog(ERROR, "stat failed on file '%s': %m", strVal(lfirst(as))); ! *probin_str_p = strVal(lfirst(as)); if (lnext(as) == NULL) --- 207,213 ---- if (stat(strVal(lfirst(as)), &stat_buf) == -1) elog(ERROR, "stat failed on file '%s': %m", strVal(lfirst(as))); ! #endif *probin_str_p = strVal(lfirst(as)); if (lnext(as) == NULL) *** src/backend/utils/fmgr/dfmgr.c.orig Wed Apr 12 13:15:57 2000 --- src/backend/utils/fmgr/dfmgr.c Thu Jul 27 10:28:49 2000 *************** *** 36,41 **** --- 36,42 ---- static int pronargs_save; static func_ptr user_fn_save = (func_ptr) NULL; static func_ptr handle_load(char *filename, char *funcname); + static int expand_filename(char *orig, char *new, int size); func_ptr fmgr_dynamic(Oid procedureId, int *pronargs) *************** *** 51,56 **** --- 52,59 ---- func_ptr user_fn; Relation rel; bool isnull; + char filebuf[PATH_MAX]; + char *file_p; /* Implement simple one-element cache for function lookups */ if (procedureId == procedureId_save) *************** *** 120,126 **** heap_close(rel, AccessShareLock); ! user_fn = handle_load(probinstring, linksymbol); pfree(probinstring); if (prosrcstring) --- 123,138 ---- heap_close(rel, AccessShareLock); ! /* Expand any environment variables in the file name. */ ! if (strchr(probinstring, '$') != NULL) { ! if (!expand_filename(probinstring, filebuf, sizeof(filebuf))) ! elog(ERROR, "LOAD: could not expand file '%s': %m", probinstring); ! file_p = filebuf; ! } ! else ! file_p = probinstring; ! ! user_fn = handle_load(file_p, linksymbol); pfree(probinstring); if (prosrcstring) *************** *** 252,266 **** { DynamicFileList *file_scanner, *p; struct stat stat_buf; int done = 0; /* * We need to do stat() in order to determine whether this is the same * file as a previously loaded file; it's also handy so as to give a * good error message if bogus file name given. */ ! if (stat(filename, &stat_buf) == -1) elog(ERROR, "LOAD: could not open file '%s': %m", filename); if (file_list != (DynamicFileList *) NULL --- 264,290 ---- { DynamicFileList *file_scanner, *p; + char filebuf[PATH_MAX]; + char *file_p; struct stat stat_buf; int done = 0; + /* Expand any environment variables in the file name. */ + if (strchr(filename, '$') != NULL) { + if (!expand_filename(filename, filebuf, sizeof(filebuf))) + elog(ERROR, "LOAD: could not expand file '%s': %m", filename); + file_p = filebuf; + elog(NOTICE, "Expanded [%s] to [%s]", filename, file_p); + } + else + file_p = filename; + /* * We need to do stat() in order to determine whether this is the same * file as a previously loaded file; it's also handy so as to give a * good error message if bogus file name given. */ ! if (stat(file_p, &stat_buf) == -1) elog(ERROR, "LOAD: could not open file '%s': %m", filename); if (file_list != (DynamicFileList *) NULL *************** *** 292,298 **** free((char *) p); } } ! handle_load(filename, (char *) NULL); } /* Is this used? bjm 1998/10/08 No. tgl 1999/02/07 */ --- 316,322 ---- free((char *) p); } } ! handle_load(file_p, (char *) NULL); } /* Is this used? bjm 1998/10/08 No. tgl 1999/02/07 */ *************** *** 308,310 **** --- 332,411 ---- } #endif + + /* + * The filename has one or more environment variables. Attempt to expand all + * of the environment variables to build an absolute path. + */ + + static int + expand_filename(char *orig, char *new, int size) + { + char *copy; + char *start; + char *env_ptr; + char env_var[MAXPGPATH]; + char *env_setting; + int i; + + /* Clear the 'new' pathname. */ + *new = '\0'; + + /* Copy the string so it can be safely hacked */ + copy = pstrdup(orig); + + /* Walk the path while expanding the environment variables. */ + start = copy; + while (strlen(start) > 0) { + + /* Find the start of the next environment variable in the path. */ + if ((env_ptr = strchr(start, '$')) != NULL) { + *env_ptr = '\0'; + + /* Append everything before the environment variable. */ + if ((strlen(new) + strlen(start) + 1) > size) { + pfree(copy); + return(0); + } + strcat(new, start); + + /* Copy the environment variable to its own string. */ + env_ptr++; + i = 0; + while (*env_ptr != '\0' && *env_ptr != '/') { + env_var[i] = *env_ptr; + env_ptr++; + i++; + } + env_var[i] = '\0'; + start = env_ptr; + + /* Translate the environment variable. */ + if ((env_setting = getenv(env_var)) == NULL) { + pfree(copy); + return(0); + } + + /* Add the environment variable to the path. */ + if ((strlen(new) + strlen(env_setting) + 1) > size) { + pfree(copy); + return(0); + } + strcat(new, env_setting); + } + + /* + * No environment variables left in the path. So append the rest of + * the path and exit the loop. + */ + else { + if ((strlen(new) + strlen(start) + 1) > size) { + pfree(copy); + return(0); + } + strcat(new, start); + break; + } + } + return(1); + } *** doc/src/sgml/dfunc.sgml.orig Thu Jul 27 10:32:36 2000 --- doc/src/sgml/dfunc.sgml Thu Jul 27 10:40:25 2000 *************** *** 96,105 **** ! Paths given to the create function command must be absolute paths (i.e., start with "/") that refer to directories visible on the machine on which the Postgres server is running. --- 96,113 ---- ! Paths given to the create function command must expand to absolute paths (i.e., start with "/") that refer to directories visible on the machine on which the Postgres server is running. + + + Environment variables in the path will be expanded by the + Postgres server. The environment + variables are interpreted in the context of the server, so make + sure the server has the appropriate environment variables set + correctly. + *** doc/src/sgml/ref/create_function.sgml.orig Thu Jul 27 10:40:56 2000 --- doc/src/sgml/ref/create_function.sgml Thu Jul 27 10:49:32 2000 *************** *** 117,123 **** containing the dynamically loadable object, and link_symbol, is the object's link symbol which is the same as the name of the function in the C ! language source code. --- 117,126 ---- containing the dynamically loadable object, and link_symbol, is the object's link symbol which is the same as the name of the function in the C ! language source code. Postgres will ! automatically expand environment variables in obj_file. The expansion is done using ! the Postgres server's environment.