/* * send_files.c - Part of AFD, an automatic file distribution program. * Copyright (c) 2005 - 2022 Holger Kiehl * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "afddefs.h" DESCR__S_M3 /* ** NAME ** send_files - sends files from the AFD queue to some host ** ** SYNOPSIS ** void send_files(int no_selected, int *select_list) ** ** DESCRIPTION ** send_files() will send all files selected in the show_queue ** dialog to some destination, with the help of the xsend_file ** dialog. Only files that are in the queue will be send. ** ** RETURN VALUES ** None. ** ** AUTHOR ** H.Kiehl ** ** HISTORY ** 07.02.2005 H.Kiehl Created ** */ DESCR__E_M3 #include #include #include #include #include #include #include #include #include #include #include #include "mafd_ctrl.h" #include "show_queue.h" /* External global variables. */ extern Display *display; extern Widget listbox_w, statusbox_w; extern XT_PTR_TYPE toggles_set; extern char font_name[], *p_work_dir; extern struct queued_file_list *qfl; extern struct queue_tmp_buf *qtb; extern struct sol_perm perm; /*############################## send_files() ###########################*/ void send_files(int no_selected, int *select_list) { int fd, i, length = 0, limit_reached = 0, not_found = 0, to_do = 0; /* Number still to be done. */ off_t dnb_size; uid_t euid, /* Effective user ID. */ ruid; /* Real user ID. */ char *args[7], file_name_file[MAX_PATH_LENGTH], fullname[MAX_PATH_LENGTH + 1 + MAX_HOSTNAME_LENGTH + 1 + MAX_FILENAME_LENGTH + 1], user_message[256]; FILE *fp; #ifdef HAVE_STATX struct statx stat_buf; #else struct stat stat_buf; #endif struct dir_name_buf *dnb; static int user_limit = 0; static unsigned int counter = 0; if ((perm.send_limit > 0) && (user_limit >= perm.send_limit)) { (void)sprintf(user_message, "User limit (%d) for sending reached!", perm.send_limit); show_message(statusbox_w, user_message); return; } /* Map to directory name buffer. */ (void)sprintf(fullname, "%s%s%s", p_work_dir, FIFO_DIR, DIR_NAME_FILE); if ((fd = open(fullname, O_RDONLY)) == -1) { (void)xrec(ERROR_DIALOG, "Failed to open() <%s> : %s (%s %d)", fullname, strerror(errno), __FILE__, __LINE__); return; } #ifdef HAVE_STATX if (statx(fd, "", AT_STATX_SYNC_AS_STAT | AT_EMPTY_PATH, STATX_SIZE, &stat_buf) == -1) #else if (fstat(fd, &stat_buf) == -1) #endif { (void)xrec(ERROR_DIALOG, "Failed to access <%s> : %s (%s %d)", fullname, strerror(errno), __FILE__, __LINE__); (void)close(fd); return; } #ifdef HAVE_STATX if (stat_buf.stx_size > 0) #else if (stat_buf.st_size > 0) #endif { char *ptr; if ((ptr = mmap(NULL, #ifdef HAVE_STATX stat_buf.stx_size, PROT_READ, #else stat_buf.st_size, PROT_READ, #endif MAP_SHARED, fd, 0)) == (caddr_t) -1) { (void)xrec(ERROR_DIALOG, "Failed to mmap() to <%s> : %s (%s %d)", fullname, strerror(errno), __FILE__, __LINE__); (void)close(fd); return; } #ifdef HAVE_STATX dnb_size = stat_buf.stx_size; #else dnb_size = stat_buf.st_size; #endif ptr += AFD_WORD_OFFSET; dnb = (struct dir_name_buf *)ptr; (void)close(fd); } else { (void)xrec(ERROR_DIALOG, "Dirname database file is empty. (%s %d)", __FILE__, __LINE__); (void)close(fd); return; } #if SIZEOF_PID_T == 4 (void)sprintf(file_name_file, ".file_name_file.%d.%d", #else (void)sprintf(file_name_file, ".file_name_file.%lld.%d", #endif (pri_pid_t)getpid(), counter); counter++; euid = geteuid(); ruid = getuid(); if (euid != ruid) { if (seteuid(ruid) == -1) { (void)fprintf(stderr, "Failed to seteuid() to %d : %s (%s %d)\n", ruid, strerror(errno), __FILE__, __LINE__); } } if ((fp = fopen(file_name_file, "w")) == NULL) { (void)fprintf(stderr, "Failed to fopen() %s : %s (%s %d)\n", file_name_file, strerror(errno), __FILE__, __LINE__); exit(INCORRECT); } if (euid != ruid) { if (seteuid(euid) == -1) { (void)fprintf(stderr, "Failed to seteuid() to %d : %s (%s %d)\n", euid, strerror(errno), __FILE__, __LINE__); } } for (i = 0; i < no_selected; i++) { if (((qfl[select_list[i] - 1].queue_type == SHOW_OUTPUT) && (toggles_set & SHOW_OUTPUT)) || (qfl[select_list[i] - 1].queue_type == SHOW_UNSENT_OUTPUT)) { if (qfl[select_list[i] - 1].queue_tmp_buf_pos != -1) { if ((perm.send_limit > 0) && ((user_limit + to_do) >= perm.send_limit)) { limit_reached++; } else { (void)sprintf(fullname, "%s%s%s/%s/%s", p_work_dir, AFD_FILE_DIR, OUTGOING_DIR, qtb[qfl[select_list[i] - 1].queue_tmp_buf_pos].msg_name, qfl[select_list[i] - 1].file_name); #ifdef HAVE_STATX if (statx(0, fullname, AT_STATX_SYNC_AS_STAT, 0, &stat_buf) == -1) #else if (stat(fullname, &stat_buf) == -1) #endif { not_found++; } else { (void)fprintf(fp, "%s|%s\n", fullname, qfl[select_list[i] - 1].file_name); to_do++; } } } } else if (qfl[select_list[i] - 1].queue_type == SHOW_TIME_JOBS) { if ((perm.send_limit > 0) && ((user_limit + to_do) >= perm.send_limit)) { limit_reached++; } else { (void)sprintf(fullname, "%s%s%s/%x/%s", p_work_dir, AFD_FILE_DIR, AFD_TIME_DIR, qfl[select_list[i] - 1].job_id, qfl[select_list[i] - 1].file_name); #ifdef HAVE_STATX if (statx(0, fullname, AT_STATX_SYNC_AS_STAT, 0, &stat_buf) == -1) #else if (stat(fullname, &stat_buf) == -1) #endif { not_found++; } else { (void)fprintf(fp, "%s\n", fullname); to_do++; } } } else if ((qfl[select_list[i] - 1].queue_type != SHOW_RETRIEVES) && (qfl[select_list[i] - 1].queue_type != SHOW_PENDING_RETRIEVES)) { if ((perm.send_limit > 0) && ((user_limit + to_do) >= perm.send_limit)) { limit_reached++; } else { if (qfl[select_list[i] - 1].hostname[0] == '\0') { (void)sprintf(fullname, "%s/%s", dnb[qfl[select_list[i] - 1].dir_id_pos].dir_name, qfl[select_list[i] - 1].file_name); } else { (void)sprintf(fullname, "%s/.%s/%s", dnb[qfl[select_list[i] - 1].dir_id_pos].dir_name, qfl[select_list[i] - 1].hostname, qfl[select_list[i] - 1].file_name); } #ifdef HAVE_STATX if (statx(0, fullname, AT_STATX_SYNC_AS_STAT, 0, &stat_buf) == -1) #else if (stat(fullname, &stat_buf) == -1) #endif { not_found++; } else { (void)fprintf(fp, "%s\n", fullname); to_do++; } } } } if (fclose(fp) == EOF) { (void)fprintf(stderr, "Failed to fclose() %s : %s (%s %d)\n", file_name_file, strerror(errno), __FILE__, __LINE__); } if (munmap(((char *)dnb - AFD_WORD_OFFSET), dnb_size) == -1) { (void)xrec(INFO_DIALOG, "munmap() error : %s (%s %d)", strerror(errno), __FILE__, __LINE__); } if (euid != ruid) { if (seteuid(ruid) == -1) { (void)fprintf(stderr, "Failed to seteuid() to %d : %s (%s %d)\n", ruid, strerror(errno), __FILE__, __LINE__); } } if (to_do > 0) { char progname[XSEND_FILE_LENGTH + 1]; (void)strcpy(progname, XSEND_FILE); args[0] = progname; args[1] = WORK_DIR_ID; args[2] = p_work_dir; args[3] = "-f"; args[4] = font_name; args[5] = file_name_file; args[6] = NULL; make_xprocess(progname, progname, args, -1); } else { (void)unlink(file_name_file); } if (euid != ruid) { if (seteuid(euid) == -1) { (void)fprintf(stderr, "Failed to seteuid() to %d : %s (%s %d)\n", euid, strerror(errno), __FILE__, __LINE__); } } /* Show user a summary of what was done. */ user_message[0] = ' '; user_message[1] = '\0'; if (to_do > 0) { if (to_do == 1) { length = sprintf(user_message, "1 file to be send"); } else { length = sprintf(user_message, "%d files to be send", to_do); } } if (not_found > 0) { if (length > 0) { length += sprintf(&user_message[length], ", %d not found", not_found); } else { length = sprintf(user_message, "%d not found", not_found); } } if (limit_reached > 0) { if (length > 0) { length += sprintf(&user_message[length], ", %d not send due to limit", limit_reached); } else { length = sprintf(user_message, "%d not send due to limit", limit_reached); } } show_message(statusbox_w, user_message); return; }