Oracle FAQ | Your Portal to the Oracle Knowledge Grid |
Home -> Community -> Usenet -> c.d.o.server -> Re: Executing external programs from a database procedure.
hi
you can use external procedures(found $ORACLE_HOME/plsql/demo/ext*)
also u need 2 patch tnsnames.ora, insert following
extproc_connection_data =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = IPC)(KEY = SID))
(CONNECT_DATA = (SID = extproc))
)
and add
(SID_DESC =
(SID_NAME = extproc)
(ORACLE_HOME = /usr/oracle/product/8.0.5)
(PROGRAM = extproc)
)
into SID_LIST_LISTENER 's SID_LIST section
-- Regards MaXX <djsnyder_at_my-deja.com> wrote in message news:91nrk3$rl5$1_at_nnrp1.deja.com... > I've done this by using the UTL_FILE package to write a Unix shell > script on the host system. Then, I have a C program that monitors a > directory for one of these files. When it finds the file it uses the > SYSTEM command to execute it. If your host has a decent scheduling > tool on it, one that can monitor a directory, then you don't need to > write your own C program. > > Here's some sample code. I pulled out a few installation-specific > things, but it should still work OK. At least it might be enough to > get you started. > > > CREATE OR REPLACE PROCEDURE sp_write_script (p_emp_id IN VARCHAR2, > p_command IN VARCHAR2, > p_o_err OUT NUMBER, > p_o_msg OUT VARCHAR2, > p_sql_err OUT NUMBER, > p_sql_msg OUT VARCHAR2) IS > /* This routine creates a shell script file on the Unix server. > The contents > of the file are specified in the second parameter. > The name of the file created is p_emp_id_xxxxxxxxx.req where > xxxxxxxxx is > a unique temporary file name generated by Unix. Thus, if the > employee id passed to this routine is 'billybob', the file created > would be > named something like this: > billybob_baaa13569.req > > Parameters: > 1. Employee ID. Used to help prevent duplicate file IDs. > 2. Unix command(s) to execute. > 3. On return, result of routine. > 0 : No errors. > 1 : Warning. > -1 : An error occurred. > 4. On return, current error or step message. NULL if no > error. > 5. On return, SQLCODE from last SQL statement when there > was an error; otherwise 0. > 6. On return, SQLERRM from last SQL statement when there > was an error; otherwise 0. > */ > v_output_file_handle UTL_FILE.FILE_TYPE; > v_output_directory VARCHAR2 (512) := 'a directory specified by > the initialization parameter utl_file_dir'; > v_output_file VARCHAR2 (512); > e_edit_excep EXCEPTION; > BEGIN /* main */ > IF p_emp_id IS NULL THEN > p_o_msg := 'Required emp_id parameter missing'; > raise e_edit_excep; > END IF; > --sf_tmpname is a call to an external procedure to generate a > unique name using Unix's TMPNAM function. > p_o_msg := 'Building output file name'; > v_output_file := RTRIM (LTRIM (p_emp_id)) || '_' || sf_tmpname > || '.req'; > p_o_msg := 'Opening output file ' || v_output_directory || '/' || > v_output_file; > v_output_file_handle := UTL_FILE.FOPEN (v_output_directory, > v_output_file, 'w'); > p_o_msg := 'Writing to output file ' || v_output_directory || '/' > || v_output_file; > UTL_FILE.PUT_LINE (v_output_file_handle, '#!/usr/bin/sh'); > UTL_FILE.PUT_LINE (v_output_file_handle, p_command); > UTL_FILE.PUT_LINE (v_output_file_handle, 'return 0'); > p_o_msg := 'Closing output file ' || v_output_directory || '/' || > v_output_file; > UTL_FILE.FCLOSE (v_output_file_handle); > p_o_err := 0; > p_o_msg := NULL; > p_sql_err := 0; > p_sql_msg := NULL; > EXCEPTION /* main */ > WHEN OTHERS THEN > IF UTL_FILE.IS_OPEN (v_output_file_handle) = TRUE THEN > UTL_FILE.FCLOSE (v_output_file_handle); > END IF; > p_o_err := -1; > p_sql_err := SQLCODE; > p_sql_msg := SQLERRM; > END; /* main */ > / > > > /* > * script_launcher.c > * > * This program monitors a directory for specific > * file names. > * When such a file is found, this program then > * executes that file. After the execution is complete, > * this program moves the file to the specified > * subdirectory of the directory where the file > * was found. > * Messages are logged to a file with a base name the > * same as this program's executable, an extension of .log, > * located in the $LOG directory. > * > * Parameters: > * > * 1. Directory to monitor for files. Required. > * 2. Characters in the file name to check for. Required. > * 3. Starting position in the file name to > * check for characters. Zero for match at > * end of name. -1 for match anywhere in the > * name. Required. > * 4. Permissions that the file being processed should > * be set to. 777=rwxrwxrwx, 744=rwxr--r--, etc. > Required. > * If we don't care what the permissions are set to, use > * "XXX". > * 5. Subdirectory of parameter 1 that the processed > * files should be moved to. Required. > * 6. Number of seconds to sleep after finding a file to > process. > * This is done because files written by the Oracle > database > * appear in the directory with non-zero sizes before they > * are completely written. Required. > * > * Return values: > * 0 : No errors. > * -1 : An error ocurred. > * > */ > > #include <stdio.h> > #include <string.h> > #include <stdlib.h> > #include <dirent.h> > #include <limits.h> > #include <sys/stat.h> > #include <sys/types.h> > #include <unistd.h> > > /*************************************************************** > ***************************************************************/ > > /* Prototypes */ > > char *match_first_file (char p_directory_to_search[], > char p_characters_to_match[], > int p_starting_position); > int copy_file (char p_source_file[], > char p_dest_file[], > char p_permissions[4]); > int move_file (char p_base_file_name[], > char p_source_dir_name[], > char p_dest_dir_name[]); > int log_message (char p_file[], > char p_message[]); > > /*************************************************************** > ***************************************************************/ > > int main(int argc, char *argv[]) > { > char l_parm0 [MAXNAMLEN], > l_parm1 [PATH_MAX], > l_parm2 [MAXNAMLEN], > l_parm3 [4], > l_parm4 [4], > l_parm5 [PATH_MAX], > l_parm6 [4], > l_full_orig_file_name [MAXNAMLEN], > l_base_file_name [MAXNAMLEN], > l_exec_file_name [MAXNAMLEN], > l_temp_file_name [MAXNAMLEN], > l_sys_cmd [MAXNAMLEN], > l_msg [400]; > > int l_return_value, > l_result_value; > > l_return_value = 0; > > strcpy (l_parm0, argv [0]); > log_message (l_parm0, "Starting script_launcher"); > > if (argc != 7) > { > /* We require all parameters. */ > log_message (l_parm0, "Missing parameters"); > printf ("\nUsage: this_program_name directory_to_monitor > characters_to_match"); > printf ("\n starting_position_to_search (0=at end, - > 1=anywhere)"); > printf ("\n permissions_of_copied_script (XXX=don't > care)"); > printf ("\n subdirectory_for_used_files > sleep_time_after_finding_file"); > l_return_value = -1; > } > else > { > strcpy (l_parm1, argv [1]); > strcpy (l_parm2, argv [2]); > strcpy (l_parm3, argv [3]); > strcpy (l_parm4, argv [4]); > strcpy (l_parm5, argv [5]); > strcpy (l_parm6, argv [6]); > } > > while (l_return_value == 0) > { > /* Find a file to process. */ > strcpy (l_base_file_name, match_first_file (l_parm1, l_parm2, > atoi (l_parm3))); > > if (strncmp (l_base_file_name, "MFF_ERR", 7) == 0) > { > sprintf (l_msg, "Error in match_first_file=%s. parm1=%s > parm2=%s parm3=%s", > l_base_file_name, l_parm1, l_parm2, > l_parm3); > log_message (l_parm0, l_msg); > l_return_value = -1; > break; > } > > if (strcmp (l_base_file_name, NULL) == 0) > { > /* No files found. Wait to make another pass. */ > sleep (10); > /* Insert a break here to have this program make only a > single pass. */ > continue; > } > > /* At this point we know we found a file to process. */ > sleep (atoi (l_parm6)); > > sprintf (l_full_orig_file_name, "%s/%s", l_parm1, > l_base_file_name); > sprintf (l_msg, "Processing file %s", l_full_orig_file_name); > log_message (l_parm0, l_msg); > > /* Copy the file we found as one of our own files since > the execute attribute on the original file might not be enabled > and we might not be able to change it. */ > > strcpy (l_exec_file_name, l_full_orig_file_name); > strcat (l_exec_file_name, ".sh"); > l_result_value = copy_file (l_exec_file_name, > l_full_orig_file_name, l_parm4); > > if (l_result_value != 0) > { > sprintf (l_msg, "Error in copy_file=%d\n", l_result_value); > log_message (l_parm0, l_msg); > l_return_value = -1; > break; > } > > /* Move the original file to the specified directory. */ > sprintf (l_temp_file_name, "%s/%s", l_parm1, l_parm5); > > if (move_file (l_base_file_name, l_parm1, l_temp_file_name) != > 0) > { > log_message (l_parm0, "Error in file rename1"); > l_return_value = -1; > break; > } > > /* Execute our copy of the job. */ > system (l_exec_file_name); > > /* Move our copy of the job to the specified directory. */ > sprintf (l_temp_file_name, "%s/%s", l_parm1, l_parm5); > strcat (l_base_file_name, ".sh"); > > if (move_file (l_base_file_name, l_parm1, l_temp_file_name) != > 0) > { > log_message (l_parm0, "Error in file rename2"); > l_return_value = -1; > break; > } > > /* Insert a break here to have this program process only a > single file. */ > } > > return l_return_value; > > } /* End of main */ > > /*************************************************************** > ***************************************************************/ > > /* > * This routine searches the directory named in its first parameter > * for the first file name with characters that match those specified in > * the second parameter. > * This routine returns a pointer to the character string > containing > * the name of the first file found. If a file was not found, this > routine > * returns NULL. > * > * Parameters: > * 1. Name of directory to search. > * 2. Characters of file name to match. > * 3. Starting position of characters to match name on. Zero > for > * match at end of name. -1 for match anywhere in the > name. > * > * Return values: > * NULL : A file was not found. > * MFF_ERR1 : An error ocurred while opening the > directory. > * MFF_ERR2 : The number of characters requested to match > * on was longer than the longest valid file > name. > * MFF_ERR3 : The directory name requested was longer > than the > * longest valid path name. > * > */ > > char *match_first_file (char p_directory_to_search[], > char p_characters_to_match[], > int p_starting_position) > { > #define MFF_TOO_MANY_CHARACTERS_TO_MATCH "MFF_ERR2" > #define MFF_BAD_DIR_OPEN "MFF_ERR1" > #define MFF_DIR_NAME_TOO_LONG "MFF_ERR3" > #define MFF_FIND_MATCH_ANYWHERE p_starting_position == -1 > #define MFF_FIND_MATCH_AT_END p_starting_position == 0 > > DIR *l_directory_pointer; > struct dirent *l_directory_entry; > struct stat l_file_status; > > int l_number_of_characters_to_match, > l_starting_position, > l_ending_position, > l_filename_position, > l_filename_length, > l_compare_string_position; > > char l_compare_string [MAXNAMLEN]; > char l_found_name [MAXNAMLEN]; > char l_full_path_name [PATH_MAX]; > > /* When p_starting_position is not zero, we want to extract > strlen (p_characters_to_match) characters from the file name > starting at p_starting_position and compare this to > p_characters_to_match. > When p_starting_position is zero, we want to extract > strlen (p_characters_to_match) characters from the file name > starting at strlen (filename) - strlen (p_characters_to_match) */ > > l_number_of_characters_to_match = strlen (p_characters_to_match); > l_starting_position = p_starting_position - 1; > > if (strlen (p_directory_to_search) > PATH_MAX) > { > return MFF_DIR_NAME_TOO_LONG; > } > > if (! MFF_FIND_MATCH_ANYWHERE) > { > if (l_number_of_characters_to_match > MAXNAMLEN) > { > /* If the character string to match is longer than the > longest possible file name. */ > return MFF_TOO_MANY_CHARACTERS_TO_MATCH; > } > > } > > if ((l_directory_pointer = opendir (p_directory_to_search)) == NULL) > { > return MFF_BAD_DIR_OPEN; > } > > while ((l_directory_entry = readdir (l_directory_pointer)) != NULL) > { > strcpy (l_found_name, NULL); > l_filename_length = strlen (l_directory_entry->d_name); > > if (l_filename_length > MAXNAMLEN) > { > /* Don't process any file names that are too long. */ > continue; > } > > if (strlen (p_directory_to_search) + strlen (l_directory_entry- > >d_name) > PATH_MAX) > { > /* Don't process any path/file name combinations that are > too long. */ > continue; > } > > /* Now we need to determine the type of the file we found. */ > strcpy (l_full_path_name, p_directory_to_search); > strcat (l_full_path_name, "/"); > strcat (l_full_path_name, l_directory_entry->d_name); > > stat (l_full_path_name, &l_file_status); > > if ((l_file_status.st_mode & S_IFMT) == S_IFDIR) > { > /* Don't process any directories. */ > continue; > } > > if (MFF_FIND_MATCH_ANYWHERE) > { > /* If we want to match characters anywhere in the file name > we don't need to do much work. */ > if (strstr (l_directory_entry->d_name, > p_characters_to_match)) > { > strcpy (l_found_name, l_directory_entry->d_name); > break; > } > else > { > continue; > } > > } > > if (l_number_of_characters_to_match > l_filename_length) > { > /* If we are requested to match more characters than > there are in the file name, skip the file. */ > continue; > } > > if (MFF_FIND_MATCH_AT_END) > { > /* When the starting position we were given is zero, we > have to > figure out what it really is, based upon the length of > the > file name. */ > l_starting_position = l_filename_length - > l_number_of_characters_to_match; > } > > l_ending_position = l_starting_position + > l_number_of_characters_to_match - 1; > > if (l_ending_position > l_filename_length) > { > /* If we end up with an ending position past the end of the > file name > then skip the file. */ > continue; > } > > l_filename_position = l_starting_position; > l_compare_string_position = 0; > l_compare_string [0] = '\0'; > > /* Now extract the characters from the file name that we will > compare > to the string to search for. */ > while (l_directory_entry->d_name [l_filename_position] != '\0' > && > l_filename_position <= l_ending_position && > l_compare_string_position < MAXNAMLEN && > l_filename_position < MAXNAMLEN) > { > l_compare_string [l_compare_string_position] = > l_directory_entry->d_name [l_filename_position]; > l_filename_position++; > l_compare_string_position++; > } > > l_compare_string [l_compare_string_position] = '\0'; > > if (strcmp (p_characters_to_match, l_compare_string) == 0) > { > strcpy (l_found_name, l_directory_entry->d_name); > break; > } > > } /* while ((l_directory_entry = readdir (l_directory_pointer)) != > NULL) */ > > closedir (l_directory_pointer); > return l_found_name; > > } /* End of match_first_file */ > > /*************************************************************** > ***************************************************************/ > > /* > * This routine copies the file named in the first parameter as > * the file named in the second parameter. The core of this routine > * was copied from Kernighan & Ritchie's filecopy function. The > permissions > * of the destination file are set according to the third parameter if > * the third parameter is not "XXX". > * > * Parameters: > * 1. Name of destination file. > * 2. Name of source file. > * 3. String representing the permissions of the > * new file. 777=rwxrwxrwx, 744=rwxr--r--, etc. > * If this parameter = "XXX" then don't set the > * permissions. > * > * Return values: > * 0 : No errors > * -1 : Error in opening source file. > * -2 : Error in opening destination file. > * -3 : Error in closing source file. > * -4 : Error in closing destination file. > * > */ > > int copy_file (char p_dest_file[], > char p_source_file[], > char p_permissions[4]) > { > FILE *l_input_file, > *l_output_file; > > char l_sys_cmd [MAXNAMLEN]; > > int l_c; > > if ((l_input_file = fopen (p_source_file, "r")) == NULL) > { > return -1; > } > > if ((l_output_file = fopen (p_dest_file, "w")) == NULL) > { > return -2; > } > > while ((l_c = getc (l_input_file)) != EOF) > { > putc (l_c, l_output_file); > } > > if (fclose (l_input_file) == EOF) > { > return -3; > } > > if (fclose (l_output_file) == EOF) > { > return -4; > } > > if (strcmp (p_permissions, "XXX") != 0) > { > strcpy (l_sys_cmd, "chmod "); > strcat (l_sys_cmd, p_permissions); > strcat (l_sys_cmd, " "); > strcat (l_sys_cmd, p_dest_file); > system (l_sys_cmd); > } > > return 0; > > } /* End of copy_file */ > > /*************************************************************** > ***************************************************************/ > > /* > * This routine moves the file specified from one directory to > * another. > * > * Parameters: > * 1. Base name of file to be moved. > * 2. Source directory name. > * 3. Destination directory name. > * > * Return values: > * 0 : No errors > * -1 : Error in rename function. > * > */ > > int move_file (char p_base_file_name[], > char p_source_dir_name[], > char p_dest_dir_name[]) > { > char l_source_name [MAXNAMLEN], > l_dest_name [MAXNAMLEN], > l_sys_cmd [MAXNAMLEN]; > > DIR *l_directory_pointer; > > /* Check to see that the destination directory exists. */ > if ((l_directory_pointer = opendir (p_dest_dir_name)) == NULL) > { > /* Create the destination directory. */ > strcpy (l_sys_cmd, "mkdir "); > strcat (l_sys_cmd, p_dest_dir_name); > system (l_sys_cmd); > strcpy (l_sys_cmd, "chmod 777 "); > strcat (l_sys_cmd, p_dest_dir_name); > system (l_sys_cmd); > } > > strcpy (l_source_name, p_source_dir_name); > strcat (l_source_name, "/"); > strcat (l_source_name, p_base_file_name); > > strcpy (l_dest_name, p_dest_dir_name); > strcat (l_dest_name, "/"); > strcat (l_dest_name, p_base_file_name); > > if (rename (l_source_name, l_dest_name) != 0) > { > return -1; > } > > closedir (l_directory_pointer); > return 0; > } /* End of move_file */ > > /*************************************************************** > ***************************************************************/ > > /* > * This routine logs the message passed to it to the file > * script_launcher.log located in the directory specified > * by the LOG environment variable. * > * Parameters: > * 1. Base name of file to log to. > * 2. Message to be logged. > * > * Return values: > * 0 : No errors > * -1 : LOG environment variable not set. > * > */ > > int log_message (char p_file[], char p_message[]) > { > FILE *l_output_file; > > char l_log_file_name [MAXNAMLEN], > l_str_date_now [9], > l_str_time_now [14], > l_msg [400]; > > int l_time_len; > > struct tm *local; > > time_t l_time_now; > > if ((getenv("LOG")) == NULL) > { > return -1; > } > > l_time_now=time(NULL); > local=localtime(&l_time_now); > strftime(l_str_date_now,100,"%04Y/%02m/%02d",local); > strftime(l_str_time_now,100,"%02H:%02M:%02S:00",local); > > strcpy (l_log_file_name, getenv ("LOG")); > strcat (l_log_file_name, "/"); > strcat (l_log_file_name, p_file); > strcat (l_log_file_name, ".log"); > > sprintf (l_msg,"%s %s %s", l_str_date_now, l_str_time_now, > p_message); > > if (strlen (l_msg) > 395) > { > l_msg [399] = '\0'; > } > > umask(0); > l_output_file = fopen (l_log_file_name, "a"); > fprintf (l_output_file, "%s\n", l_msg); > fclose (l_output_file); > > return 0; > > } /* End of log_message */ > > /*************************************************************** > ***************************************************************/ > > > In article <KDJ%5.109856$yO2.3247911_at_telenews.teleline.es>, > "Ant" <anorfri_at_teleline.es> wrote: > > Hello !!! > > > > Now I have a new (and big for me) problem. It's because I must run an exe > > file (a Pro C program) from a stored procedure. I run Oracle (8.0.4.0.0) on > > Compaq Unix (OSF1) V4.0. I've tried to do this whit the "host" built in, > > but it's not supported on stored program units. So, How could I run an exe > > file from Oracle? > > > > Thanks > > > > Ant > > > > > > > Sent via Deja.com > http://www.deja.com/Received on Tue Dec 19 2000 - 09:15:47 CST