void __cdecl output_and_cleanup(int code) { FILE *f; string line; if (code == 0) { /* output result if any */ if ((f = fopen(getval("STDOUT"), "r")) != NULL) { if (redirect_stdout >= 0) { int fds[3]; fds[0] = 0; fds[1] = redirect_stdout; fds[2] = 2; push_fd(fds); } while((line = read_line(f)) != NULL) { fputs(line, stdout); free (line); } fclose(f); if (redirect_stdout >= 0) { pop_fd(); redirect_stdout = -1; } } } if (test_file('d', tmpdir)) rec_rmdir(tmpdir); { int count = 0; /* Give more than one chance to remove the files */ while ((count++ < 20) && test_file('d', tmpdir)) { Sleep(250); rec_rmdir(tmpdir); } } }
/*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ main() $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$*/ int main(int argc, char *argv[]) { #ifdef _WITH_BURST_2 int cb2_ret; #endif int exec_done, exit_status = TRANSFER_SUCCESS, ii, k, last_k, length, length_start, mask_file_name, #ifdef HAVE_SETPRIORITY sched_priority, #endif ret; time_t last_update_time, now, *p_file_mtime_buffer; char command_str[MAX_PATH_LENGTH + MAX_RECIPIENT_LENGTH], file_name[MAX_FILENAME_LENGTH], file_path[MAX_PATH_LENGTH], *fnp, *insert_list[MAX_EXEC_FILE_SUBSTITUTION], job_str[4], *p_command, *p_source_file, *p_file_name_buffer, *return_str = NULL, source_file[MAX_PATH_LENGTH], tmp_char, tmp_option[MAX_PATH_LENGTH + MAX_RECIPIENT_LENGTH]; struct job *p_db; #ifdef SA_FULLDUMP struct sigaction sact; #endif #ifdef WITH_FAST_MOVE nlink_t nlink; #endif #ifdef _OUTPUT_LOG clock_t end_time = 0, start_time = 0; struct tms tmsdummy; #endif CHECK_FOR_VERSION(argc, argv); #ifdef SA_FULLDUMP /* * When dumping core sure we do a FULL core dump! */ sact.sa_handler = SIG_DFL; sact.sa_flags = SA_FULLDUMP; sigemptyset(&sact.sa_mask); if (sigaction(SIGSEGV, &sact, NULL) == -1) { system_log(ERROR_SIGN, __FILE__, __LINE__, "sigaction() error : %s", strerror(errno)); exit(INCORRECT); } #endif /* Do some cleanups when we exit. */ if (atexit(sf_exec_exit) != 0) { system_log(ERROR_SIGN, __FILE__, __LINE__, "Could not register exit function : %s", strerror(errno)); exit(INCORRECT); } /* Initialise variables. */ local_file_counter = 0; files_to_send = init_sf(argc, argv, file_path, EXEC_FLAG); p_db = &db; if ((signal(SIGINT, sig_kill) == SIG_ERR) || (signal(SIGQUIT, sig_exit) == SIG_ERR) || (signal(SIGTERM, sig_exit) == SIG_ERR) || (signal(SIGSEGV, sig_segv) == SIG_ERR) || (signal(SIGBUS, sig_bus) == SIG_ERR) || (signal(SIGHUP, SIG_IGN) == SIG_ERR)) { system_log(ERROR_SIGN, __FILE__, __LINE__, "Failed to set signal handlers : %s", strerror(errno)); exit(INCORRECT); } /* Inform FSA that we have are ready to copy the files. */ if (gsf_check_fsa(p_db) != NEITHER) { fsa->job_status[(int)db.job_no].connect_status = EXEC_ACTIVE; fsa->job_status[(int)db.job_no].no_of_files = files_to_send; } /* Init job_str for exec_cmd(). */ job_str[0] = '['; job_str[1] = db.job_no + '0'; job_str[2] = ']'; job_str[3] = '\0'; #ifdef _WITH_BURST_2 do { if (burst_2_counter > 0) { if (fsa->debug > NORMAL_MODE) { trans_db_log(INFO_SIGN, __FILE__, __LINE__, NULL, "Bursting."); } } #endif /* _WITH_BURST_2 */ /* Prepare pointers and directory name. */ (void)strcpy(source_file, file_path); p_source_file = source_file + strlen(source_file); *p_source_file++ = '/'; #ifdef HAVE_SETPRIORITY if (db.exec_base_priority != NO_PRIORITY) { sched_priority = db.exec_base_priority; if (db.add_afd_priority == YES) { sched_priority += (int)(fsa->job_status[(int)db.job_no].unique_name[MAX_MSG_NAME_LENGTH - 1]); if (sched_priority > db.min_sched_priority) { sched_priority = db.min_sched_priority; } else if (sched_priority < db.max_sched_priority) { sched_priority = db.max_sched_priority; } } if ((sched_priority == db.current_priority) || ((db.current_priority > sched_priority) && (geteuid() != 0))) { sched_priority = NO_PRIORITY; } } else { sched_priority = NO_PRIORITY; } #endif p_command = db.exec_cmd; while ((*p_command == ' ') || (*p_command == '\t')) { p_command++; } if ((db.special_flag & EXEC_ONCE_ONLY) == 0) { char *p_end; /* Prepare insert list. */ p_end = p_command; k = 0; ii = 0; while ((*p_end != '\0') && (ii < MAX_EXEC_FILE_SUBSTITUTION)) { if ((*p_end == '%') && (*(p_end + 1) == 's')) { tmp_option[k] = *p_end; tmp_option[k + 1] = *(p_end + 1); insert_list[ii] = &tmp_option[k]; ii++; p_end += 2; k += 2; } else { tmp_option[k] = *p_end; p_end++; k++; } } if (ii >= MAX_EXEC_FILE_SUBSTITUTION) { trans_log(WARN_SIGN, __FILE__, __LINE__, NULL, NULL, "To many %%s in pexec option. Can oly handle %d.", MAX_EXEC_FILE_SUBSTITUTION); } tmp_option[k] = '\0'; p_command = tmp_option; last_k = k; } p_file_name_buffer = file_name_buffer; p_file_size_buffer = file_size_buffer; p_file_mtime_buffer = file_mtime_buffer; last_update_time = time(NULL); local_file_size = 0; exec_done = NO; for (files_send = 0; files_send < files_to_send; files_send++) { (void)strcpy(p_source_file, p_file_name_buffer); if (db.special_flag & EXEC_ONCE_ONLY) { if (exec_done == NO) { #ifdef _OUTPUT_LOG if (db.output_log == YES) { start_time = times(&tmsdummy); } #endif (void)sprintf(command_str, "cd %s && %s", file_path, p_command); if (fsa->debug > NORMAL_MODE) { trans_db_log(INFO_SIGN, __FILE__, __LINE__, NULL, "Executing command `%s' to send file `%s'", command_str, p_file_name_buffer); } if ((ret = exec_cmd(command_str, &return_str, transfer_log_fd, fsa->host_dsp_name, MAX_HOSTNAME_LENGTH, #ifdef HAVE_SETPRIORITY sched_priority, #endif job_str, (fsa->protocol_options & TIMEOUT_TRANSFER) ? (time_t)transfer_timeout : 0L, YES, YES)) != 0) { trans_log(ERROR_SIGN, __FILE__, __LINE__, NULL, NULL, "Failed to execute command %s [Return code = %d]", command_str, ret); if ((return_str != NULL) && (return_str[0] != '\0')) { char *end_ptr = return_str, *start_ptr; do { start_ptr = end_ptr; while ((*end_ptr != '\n') && (*end_ptr != '\0')) { end_ptr++; } if (*end_ptr == '\n') { *end_ptr = '\0'; end_ptr++; } trans_log(ERROR_SIGN, __FILE__, __LINE__, NULL, NULL, "%s", start_ptr); } while (*end_ptr != '\0'); } exit(EXEC_ERROR); } #ifdef _OUTPUT_LOG if (db.output_log == YES) { end_time = times(&tmsdummy); } #endif free(return_str); return_str = NULL; exec_done = YES; } } else { /* Write status to FSA? */ if (gsf_check_fsa(p_db) != NEITHER) { fsa->job_status[(int)db.job_no].file_size_in_use = *p_file_size_buffer; (void)strcpy(fsa->job_status[(int)db.job_no].file_name_in_use, p_file_name_buffer); } #ifdef _OUTPUT_LOG if (db.output_log == YES) { start_time = times(&tmsdummy); } #endif insert_list[ii] = &tmp_option[last_k]; tmp_char = *insert_list[0]; *insert_list[0] = '\0'; length_start = sprintf(command_str, "cd %s && %s", file_path, p_command); *insert_list[0] = tmp_char; fnp = p_file_name_buffer; mask_file_name = NO; do { if ((*fnp == ';') || (*fnp == ' ')) { mask_file_name = YES; break; } fnp++; } while (*fnp != '\0'); /* Generate command string with file name(s). */ length = 0; for (k = 1; k < (ii + 1); k++) { tmp_char = *insert_list[k]; *insert_list[k] = '\0'; if (mask_file_name == YES) { length += sprintf(command_str + length_start + length, "\"%s\"%s", p_file_name_buffer, insert_list[k - 1] + 2); } else { length += sprintf(command_str + length_start + length, "%s%s", p_file_name_buffer, insert_list[k - 1] + 2); } *insert_list[k] = tmp_char; } if ((ret = exec_cmd(command_str, &return_str, transfer_log_fd, fsa->host_dsp_name, MAX_HOSTNAME_LENGTH, #ifdef HAVE_SETPRIORITY sched_priority, #endif job_str, (fsa->protocol_options & TIMEOUT_TRANSFER) ? (time_t)transfer_timeout : 0L, YES, YES)) != 0) /* ie != SUCCESS */ { trans_log(ERROR_SIGN, __FILE__, __LINE__, NULL, NULL, "Failed to execute command %s [Return code = %d]", command_str, ret); if ((return_str != NULL) && (return_str[0] != '\0')) { char *end_ptr = return_str, *start_ptr; do { start_ptr = end_ptr; while ((*end_ptr != '\n') && (*end_ptr != '\0')) { end_ptr++; } if (*end_ptr == '\n') { *end_ptr = '\0'; end_ptr++; } trans_log(ERROR_SIGN, __FILE__, __LINE__, NULL, NULL, "%s", start_ptr); } while (*end_ptr != '\0'); } exit(EXEC_ERROR); } free(return_str); return_str = NULL; #ifdef _OUTPUT_LOG if (db.output_log == YES) { end_time = times(&tmsdummy); } #endif } /* Tell FSA we have done a file. */ if (gsf_check_fsa(p_db) != NEITHER) { fsa->job_status[(int)db.job_no].file_name_in_use[0] = '\0'; fsa->job_status[(int)db.job_no].no_of_files_done++; fsa->job_status[(int)db.job_no].file_size_in_use = 0; fsa->job_status[(int)db.job_no].file_size_in_use_done = 0; fsa->job_status[(int)db.job_no].file_size_done += *p_file_size_buffer; fsa->job_status[(int)db.job_no].bytes_send += *p_file_size_buffer; local_file_size += *p_file_size_buffer; local_file_counter += 1; now = time(NULL); if (now >= (last_update_time + LOCK_INTERVAL_TIME)) { last_update_time = now; update_tfc(local_file_counter, local_file_size, p_file_size_buffer, files_to_send, files_send); local_file_size = 0; local_file_counter = 0; } } #ifdef _WITH_TRANS_EXEC if (db.special_flag & TRANS_EXEC) { trans_exec(file_path, source_file, p_file_name_buffer); } #endif #ifdef _OUTPUT_LOG if (db.output_log == YES) { if (ol_fd == -2) { # ifdef WITHOUT_FIFO_RW_SUPPORT output_log_fd(&ol_fd, &ol_readfd); # else output_log_fd(&ol_fd); # endif } if ((ol_fd > -1) && (ol_data == NULL)) { output_log_ptrs(&ol_retries, &ol_job_number, &ol_data, &ol_file_name, &ol_file_name_length, &ol_archive_name_length, &ol_file_size, &ol_unl, &ol_size, &ol_transfer_time, &ol_output_type, db.host_alias, 0, EXEC); } } #endif /* Now archive file if necessary. */ if ((db.archive_time > 0) && (p_db->archive_dir[0] != FAILED_TO_CREATE_ARCHIVE_DIR)) { /* * By telling the function archive_file() that this * is the first time to archive a file for this job * (in struct p_db) it does not always have to check * whether the directory has been created or not. And * we ensure that we do not create duplicate names * when adding db.archive_time to msg_name. */ if (archive_file(file_path, p_file_name_buffer, p_db) < 0) { trans_log(ERROR_SIGN, __FILE__, __LINE__, NULL, NULL, "Failed to archive file `%s'", file_name); /* * NOTE: We _MUST_ delete the file we just send, * else the file directory will run full! */ if (unlink(source_file) == -1) { system_log(ERROR_SIGN, __FILE__, __LINE__, "Could not unlink() local file `%s' after copying it successfully : %s", source_file, strerror(errno)); } #ifdef _OUTPUT_LOG if (db.output_log == YES) { (void)memcpy(ol_file_name, db.p_unique_name, db.unl); if (db.trans_rename_rule[0] != '\0') { *ol_file_name_length = (unsigned short)sprintf(ol_file_name + db.unl, "%s%c/%s", p_file_name_buffer, SEPARATOR_CHAR, p_file_name_buffer) + db.unl; } else { (void)strcpy(ol_file_name + db.unl, p_file_name_buffer); *ol_file_name_length = (unsigned short)strlen(ol_file_name); ol_file_name[*ol_file_name_length] = SEPARATOR_CHAR; ol_file_name[*ol_file_name_length + 1] = '\0'; (*ol_file_name_length)++; } *ol_file_size = *p_file_size_buffer; *ol_job_number = fsa->job_status[(int)db.job_no].job_id; *ol_retries = db.retries; *ol_unl = db.unl; *ol_transfer_time = end_time - start_time; *ol_archive_name_length = 0; *ol_output_type = OT_NORMAL_DELIVERED + '0'; ol_real_size = *ol_file_name_length + ol_size; if (write(ol_fd, ol_data, ol_real_size) != ol_real_size) { system_log(ERROR_SIGN, __FILE__, __LINE__, "write() error : %s", strerror(errno)); } } #endif } else { if (fsa->debug > NORMAL_MODE) { trans_db_log(INFO_SIGN, __FILE__, __LINE__, NULL, "Archived file `%s'.", file_name); } #ifdef _OUTPUT_LOG if (db.output_log == YES) { (void)memcpy(ol_file_name, db.p_unique_name, db.unl); if (db.trans_rename_rule[0] != '\0') { *ol_file_name_length = (unsigned short)sprintf(ol_file_name + db.unl, "%s%c/%s", p_file_name_buffer, SEPARATOR_CHAR, p_file_name_buffer) + db.unl; } else { (void)strcpy(ol_file_name + db.unl, p_file_name_buffer); *ol_file_name_length = (unsigned short)strlen(ol_file_name); ol_file_name[*ol_file_name_length] = SEPARATOR_CHAR; ol_file_name[*ol_file_name_length + 1] = '\0'; (*ol_file_name_length)++; } (void)strcpy(&ol_file_name[*ol_file_name_length + 1], &db.archive_dir[db.archive_offset]); *ol_file_size = *p_file_size_buffer; *ol_job_number = fsa->job_status[(int)db.job_no].job_id; *ol_retries = db.retries; *ol_unl = db.unl; *ol_transfer_time = end_time - start_time; *ol_archive_name_length = (unsigned short)strlen(&ol_file_name[*ol_file_name_length + 1]); *ol_output_type = OT_NORMAL_DELIVERED + '0'; ol_real_size = *ol_file_name_length + *ol_archive_name_length + 1 + ol_size; if (write(ol_fd, ol_data, ol_real_size) != ol_real_size) { system_log(ERROR_SIGN, __FILE__, __LINE__, "write() error : %s", strerror(errno)); } } #endif } } else { #ifdef WITH_UNLINK_DELAY int unlink_loops = 0; try_again_unlink: #endif /* Delete the file we just have executed. */ if (unlink(source_file) == -1) { #ifdef WITH_UNLINK_DELAY if ((errno == EBUSY) && (unlink_loops < 20)) { (void)my_usleep(100000L); unlink_loops++; goto try_again_unlink; } #endif system_log(ERROR_SIGN, __FILE__, __LINE__, "Could not unlink() local file %s after copying it successfully : %s", source_file, strerror(errno)); } #ifdef _OUTPUT_LOG if (db.output_log == YES) { (void)memcpy(ol_file_name, db.p_unique_name, db.unl); if (db.trans_rename_rule[0] != '\0') { *ol_file_name_length = (unsigned short)sprintf(ol_file_name + db.unl, "%s%c/%s", p_file_name_buffer, SEPARATOR_CHAR, p_file_name_buffer) + db.unl; } else { (void)strcpy(ol_file_name + db.unl, p_file_name_buffer); *ol_file_name_length = (unsigned short)strlen(ol_file_name); ol_file_name[*ol_file_name_length] = SEPARATOR_CHAR; ol_file_name[*ol_file_name_length + 1] = '\0'; (*ol_file_name_length)++; } *ol_file_size = *p_file_size_buffer; *ol_job_number = fsa->job_status[(int)db.job_no].job_id; *ol_retries = db.retries; *ol_unl = db.unl; *ol_transfer_time = end_time - start_time; *ol_archive_name_length = 0; *ol_output_type = OT_NORMAL_DELIVERED + '0'; ol_real_size = *ol_file_name_length + ol_size; if (write(ol_fd, ol_data, ol_real_size) != ol_real_size) { system_log(ERROR_SIGN, __FILE__, __LINE__, "write() error : %s", strerror(errno)); } } #endif } /* * After each successful transfer set error counter to zero, * so that other jobs can be started. */ if (fsa->error_counter > 0) { int fd, #ifdef WITHOUT_FIFO_RW_SUPPORT readfd, #endif j; char fd_wake_up_fifo[MAX_PATH_LENGTH]; #ifdef LOCK_DEBUG lock_region_w(fsa_fd, db.lock_offset + LOCK_EC, __FILE__, __LINE__); #else lock_region_w(fsa_fd, db.lock_offset + LOCK_EC); #endif fsa->error_counter = 0; /* * Wake up FD! */ (void)sprintf(fd_wake_up_fifo, "%s%s%s", p_work_dir, FIFO_DIR, FD_WAKE_UP_FIFO); #ifdef WITHOUT_FIFO_RW_SUPPORT if (open_fifo_rw(fd_wake_up_fifo, &readfd, &fd) == -1) #else if ((fd = open(fd_wake_up_fifo, O_RDWR)) == -1) #endif { system_log(WARN_SIGN, __FILE__, __LINE__, "Failed to open() FIFO %s : %s", fd_wake_up_fifo, strerror(errno)); } else { if (write(fd, "", 1) != 1) { system_log(WARN_SIGN, __FILE__, __LINE__, "Failed to write() to FIFO %s : %s", fd_wake_up_fifo, strerror(errno)); } #ifdef WITHOUT_FIFO_RW_SUPPORT if (close(readfd) == -1) { system_log(DEBUG_SIGN, __FILE__, __LINE__, "Failed to close() FIFO %s : %s", fd_wake_up_fifo, strerror(errno)); } #endif if (close(fd) == -1) { system_log(DEBUG_SIGN, __FILE__, __LINE__, "Failed to close() FIFO %s : %s", fd_wake_up_fifo, strerror(errno)); } } /* * Remove the error condition (NOT_WORKING) from all jobs * of this host. */ for (j = 0; j < fsa->allowed_transfers; j++) { if ((j != db.job_no) && (fsa->job_status[j].connect_status == NOT_WORKING)) { fsa->job_status[j].connect_status = DISCONNECT; } } fsa->error_history[0] = 0; fsa->error_history[1] = 0; #ifdef LOCK_DEBUG unlock_region(fsa_fd, db.lock_offset + LOCK_EC, __FILE__, __LINE__); #else unlock_region(fsa_fd, db.lock_offset + LOCK_EC); #endif /* * Since we have successfully transmitted a file, no need to * have the queue stopped anymore. */ if (fsa->host_status & AUTO_PAUSE_QUEUE_STAT) { char *sign; #ifdef LOCK_DEBUG lock_region_w(fsa_fd, db.lock_offset + LOCK_HS, __FILE__, __LINE__); #else lock_region_w(fsa_fd, db.lock_offset + LOCK_HS); #endif fsa->host_status &= ~AUTO_PAUSE_QUEUE_STAT; if (fsa->host_status & HOST_ERROR_EA_STATIC) { fsa->host_status &= ~EVENT_STATUS_STATIC_FLAGS; } else { fsa->host_status &= ~EVENT_STATUS_FLAGS; } fsa->host_status &= ~PENDING_ERRORS; #ifdef LOCK_DEBUG unlock_region(fsa_fd, db.lock_offset + LOCK_HS, __FILE__, __LINE__); #else unlock_region(fsa_fd, db.lock_offset + LOCK_HS); #endif error_action(fsa->host_alias, "stop", HOST_ERROR_ACTION); event_log(0L, EC_HOST, ET_EXT, EA_ERROR_END, "%s", fsa->host_alias); if ((fsa->host_status & HOST_ERROR_OFFLINE_STATIC) || (fsa->host_status & HOST_ERROR_OFFLINE) || (fsa->host_status & HOST_ERROR_OFFLINE_T)) { sign = OFFLINE_SIGN; } else { sign = INFO_SIGN; } trans_log(sign, __FILE__, __LINE__, NULL, NULL, "Starting input queue that was stopped by init_afd."); event_log(0L, EC_HOST, ET_AUTO, EA_START_QUEUE, "%s", fsa->host_alias); } } /* if (fsa->error_counter > 0) */ #ifdef WITH_ERROR_QUEUE if (fsa->host_status & ERROR_QUEUE_SET) { remove_from_error_queue(db.job_id, fsa, db.fsa_pos, fsa_fd); } #endif if (fsa->host_status & HOST_ACTION_SUCCESS) { error_action(fsa->host_alias, "start", HOST_SUCCESS_ACTION); } p_file_name_buffer += MAX_FILENAME_LENGTH; p_file_size_buffer++; if (file_mtime_buffer != NULL) { p_file_mtime_buffer++; } } /* for (files_send = 0; files_send < files_to_send; files_send++) */ if (local_file_counter) { if (gsf_check_fsa(p_db) != NEITHER) { update_tfc(local_file_counter, local_file_size, p_file_size_buffer, files_to_send, files_send); local_file_size = 0; local_file_counter = 0; } } /* Do not forget to remove lock file if we have created one. */ if ((db.lock == LOCKFILE) && (fsa->active_transfers == 1)) { if (unlink(db.lock_file_name) == -1) { trans_log(ERROR_SIGN, __FILE__, __LINE__, NULL, NULL, "Failed to unlink() lock file `%s' : %s", db.lock_file_name, strerror(errno)); exit(REMOVE_LOCKFILE_ERROR); } else { if (fsa->debug > NORMAL_MODE) { trans_db_log(INFO_SIGN, __FILE__, __LINE__, NULL, "Removed lock file `%s'.", db.lock_file_name); } } } /* * Remove file directory with everything in it. */ if (rec_rmdir(file_path) == INCORRECT) { system_log(ERROR_SIGN, __FILE__, __LINE__, "Failed to rec_rmdir() `%s' : %s", file_path, strerror(errno)); exit_status = STILL_FILES_TO_SEND; } #ifdef _WITH_BURST_2 burst_2_counter++; } while ((cb2_ret = check_burst_2(file_path, &files_to_send, 0, # ifdef _WITH_INTERRUPT_JOB 0, # endif # ifdef _OUTPUT_LOG &ol_fd, # endif # ifndef AFDBENCH_CONFIG NULL, # endif NULL)) == YES); burst_2_counter--; if (cb2_ret == NEITHER) { exit_status = STILL_FILES_TO_SEND; } #endif /* _WITH_BURST_2 */ exitflag = 0; exit(exit_status); }