/* * send_file.c - Part of AFD, an automatic file distribution program. * Copyright (c) 2005 - 2015 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_file - sends files by executing one of the aXXX programs ** ** SYNOPSIS ** void send_file(void) ** ** DESCRIPTION ** send_file() executes a command specified in 'cmd' by calling ** /bin/sh -c 'cmd', and returns after the command has been ** completed. All output is written to the text widget cmd_output. ** ** RETURN VALUES ** Returns INCORRECT when it fails to execute the command 'cmd'. ** In buffer will be the results of STDOUT and STDERR. ** ** AUTHOR ** H.Kiehl ** ** HISTORY ** 05.12.1999 H.Kiehl Created ** 31.01.2005 H.Kiehl Adapted from xexec_cmd(). ** */ DESCR__E_M3 #include #include /* strlen() */ #include /* exit() */ #include /* read(), close(), STDOUT_FILENO, */ /* STDERR_FILENO */ #include /* O_NONBLOCK */ #include #include /* wait() */ #include #include #include #include #include "xsend_file.h" #include "ftpdefs.h" #define READ 0 #define WRITE 1 /* External global variables. */ extern int button_flag, cmd_fd; extern char file_name_file[], url_file_name[]; extern pid_t cmd_pid; extern struct send_data *db; extern Display *display; extern Widget appshell, cmd_output, special_button_w; extern XmTextPosition wpr_position; extern XtInputId cmd_input_id; /* Local function prototypes. */ static void read_data(XtPointer, int *, XtInputId *); /*############################# send_file() #############################*/ void send_file(void) { int channels[2]; size_t length = 0; char cmd[2048]; /* * First put together the command from the input gathered. */ if (db->protocol == FTP) { length = sprintf(&cmd[length], "%s -c %s -p %d -m %c", AFTP, url_file_name, db->port, (char)db->transfer_mode); if (db->mode_flag & PASSIVE_MODE) { length += sprintf(&cmd[length], " -x"); } if (db->mode_flag & EXTENDED_MODE) { length += sprintf(&cmd[length], " -X"); } if (db->proxy_name[0] != '\0') { length += sprintf(&cmd[length], " -P %s", db->proxy_name); } } else if (db->protocol == SFTP) { length = sprintf(&cmd[length], "%s -c %s -p %d", ASFTP, url_file_name, db->port); } else if (db->protocol == SMTP) { length = sprintf(&cmd[length], "%s -c %s -p %d", ASMTP, url_file_name, db->port); if (db->attach_file_flag == YES) { length += sprintf(&cmd[length], " -e"); } } #ifdef _WITH_WMO_SUPPORT else if (db->protocol == WMO) { length = sprintf(&cmd[length], "%s -c %s -p %d", AWMO, url_file_name, db->port); } #endif else { #if SIZEOF_LONG == 4 (void)fprintf(stderr, "Unknown or not implemented protocol (%d)\n", #else (void)fprintf(stderr, "Unknown or not implemented protocol (%ld)\n", #endif db->protocol); exit(INCORRECT); } if ((db->protocol != SMTP) && (db->protocol != WMO)) { if (db->lock == SET_LOCK_DOT) { length += sprintf(&cmd[length], " -l DOT"); } else if (db->lock == SET_LOCK_DOT_VMS) { length += sprintf(&cmd[length], " -l DOT_VMS"); } else if (db->lock == SET_LOCK_PREFIX) { length += sprintf(&cmd[length], " -l %s", db->prefix); } if (db->create_target_dir == YES) { length += sprintf(&cmd[length], " -C"); } } if (db->subject[0] != '\0') { length += sprintf(&cmd[length], " -s \"%s\"", db->subject); } if (db->debug == YES) { length += sprintf(&cmd[length], " -v"); } #if SIZEOF_TIME_T == 4 (void)sprintf(&cmd[length], " -t %ld -f %s", #else (void)sprintf(&cmd[length], " -t %lld -f %s", #endif (pri_time_t)db->timeout, file_name_file); #ifdef DEBUG_SHOW_CMD printf("cmd=%s\n", cmd); #endif if (pipe(channels) == -1) { (void)fprintf(stderr, "pipe() error : %s (%s %d)\n", strerror(errno), __FILE__, __LINE__); exit(INCORRECT); } switch (cmd_pid = fork()) { case -1: /* Failed to fork. */ (void)fprintf(stderr, "fork() error : %s (%s %d)\n", strerror(errno), __FILE__, __LINE__); exit(INCORRECT); case 0 : /* Child process. */ (void)close(channels[READ]); dup2(channels[WRITE], STDOUT_FILENO); dup2(channels[WRITE], STDERR_FILENO); (void)execl("/bin/sh", "sh", "-c", cmd, (char *)0); _exit(INCORRECT); default: /* Parent process. */ (void)close(channels[WRITE]); cmd_fd = channels[READ]; cmd_input_id = XtAppAddInput(XtWidgetToApplicationContext(appshell), channels[READ], (XtPointer)XtInputReadMask, (XtInputCallbackProc)read_data, (XtPointer)NULL); } return; } /*++++++++++++++++++++++++++++ read_data() ++++++++++++++++++++++++++++++*/ static void read_data(XtPointer client_data, int *fd, XtInputId *id) { int n; char buffer[MAX_PATH_LENGTH + 1]; if ((n = read(*fd, buffer, MAX_PATH_LENGTH)) > 0) { buffer[n] = '\0'; XmTextInsert(cmd_output, wpr_position, buffer); wpr_position += n; XmTextShowPosition(cmd_output, wpr_position); XFlush(display); } else if (n == 0) { buffer[0] = '>'; buffer[1] = '\0'; XmTextInsert(cmd_output, wpr_position, buffer); XmTextShowPosition(cmd_output, wpr_position); XFlush(display); if (cmd_pid > 0) { if (wait(NULL) == -1) { (void)fprintf(stderr, "wait() error : %s (%s %d)\n", strerror(errno), __FILE__, __LINE__); exit(INCORRECT); } cmd_pid = 0; } if (cmd_input_id != 0L) { XtRemoveInput(cmd_input_id); cmd_input_id = 0L; if (close(cmd_fd) == -1) { (void)fprintf(stderr, "close() error : %s (%s %d)\n", strerror(errno), __FILE__, __LINE__); } } if (button_flag == STOP_BUTTON) { XmString xstr; /* Set button back to Send. */ xstr = XmStringCreateLtoR("Send", XmFONTLIST_DEFAULT_TAG); XtVaSetValues(special_button_w, XmNlabelString, xstr, NULL); XmStringFree(xstr); button_flag = SEND_BUTTON; } } return; }