⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 efax_controller.cpp

📁 用于使用moden进行传真的源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* Copyright (C) 2001 to 2004 Chris VineThis program is distributed under the General Public Licence, version 2.For particulars of this and relevant disclaimers see the fileCOPYING distributed with the source files.*/#include <unistd.h>#include <limits.h>#include <signal.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/wait.h>#include <fcntl.h>#include <errno.h>#ifdef HAVE_PTHREAD_SIGMASK #include <pthread.h>#endif#include <fstream>#include <iomanip>#include <ctime>#include <cstring>#include <cstdlib>#include <glibmm/main.h>#include <glibmm/convert.h>#include <glibmm/timer.h>#include <glibmm/thread.h>#include "efax_controller.h"#ifdef HAVE_STRINGSTREAM#include <sstream>#else#include <strstream>#endif#ifdef ENABLE_NLS#include <libintl.h>#endifstatic volatile pid_t child_pid = 0;static volatile sig_atomic_t state = EfaxController::inactive;static volatile sig_atomic_t change_state_count = 0;EfaxController::EfaxController(void) {  // set up state_messages  // it's OK to use std::string rather than Glib::ustring here, because  // the contents are passed to StatusLine::write_status(const char*) and  // std::string is just a transparent holder of the UTF-8 string  // until it reaches that method  state_messages.push_back(gettext("Inactive"));  state_messages.push_back(gettext("Sending fax"));  state_messages.push_back(gettext("Answering call"));  state_messages.push_back(gettext("Answering call"));  state_messages.push_back(gettext("Standing by to receive calls"));  state_messages.push_back("");  state_messages.push_back("");  state_messages.push_back("");  state_messages.push_back("");  state_messages.push_back("");  fax_made_notify.connect(sigc::mem_fun(*this, &EfaxController::sendfax_slot));  no_fax_made_notify.connect(sigc::mem_fun(*this, &EfaxController::no_fax_made_slot));}void EfaxController::efax_closedown(void) {  if (state != inactive) {    state = closedown;    kill_child();    while (state != inactive) Glib::usleep(500000);    if (*prog_config.receive_dirname) {      // now delete prog_config.receive_dirname if it is empty      std::string full_dirname;      if (!prog_config.homedir.empty()) {	full_dirname = prog_config.homedir;	full_dirname += "/faxin/";      }      full_dirname += prog_config.receive_dirname;      rmdir(full_dirname.c_str()); // only deletes the directory if it is empty      // lock the Prog_config object while we modify it      Glib::Mutex::Lock lock(*prog_config.mutex_p);      *prog_config.receive_dirname = 0;    }  }  unjoin_child();}int EfaxController::get_state(void) {  return state;}void EfaxController::init_sendfax_parms(void) {  sendfax_parms_vec = prog_config.parms;  // now add the first set of arguments to the copy of prog_config.parms  // in sendfax_parms_vec       struct std::tm* time_p;  std::time_t time_count;  std::time(&time_count);  time_p = std::localtime(&time_count);  char date_string[23];  const char format[] = "%a %d-%b-%Y %H:%M";  std::strftime(date_string, 23, format, time_p);  std::string temp("-h");  temp += date_string;  temp += "    ";  try {    temp += Glib::locale_from_utf8(gettext("From"));    temp += " ";    temp += Glib::locale_from_utf8(prog_config.my_name);  }  catch (Glib::ConvertError&) {    write_error("UTF-8 conversion error in EfaxController::init_sendfax_parms()\n");  }  temp += " (";  temp += prog_config.my_number + ") --> ";  temp += last_fax_item_sent.number + "    p.%d/%d";  sendfax_parms_vec.push_back(temp);  if (last_fax_item_sent.number.empty()) {    sendfax_parms_vec.push_back("-jX3");    sendfax_parms_vec.push_back("-t");    sendfax_parms_vec.push_back("");  }  else {    temp = "-t";    if (prog_config.tone_dial) temp += 'T';    else temp += 'P';    temp += last_fax_item_sent.number;    sendfax_parms_vec.push_back(temp);  }}void EfaxController::sendfax(const Fax_item& fax_item) {  if (state != inactive) beep();  else {    stdout_pipe.open(Pipe_fifo::non_block);    // efax is sensitive to timing, so set pipe write to non-block also    stdout_pipe.make_write_non_block();        state = sending;    change_state_count++;    last_fax_item_sent = fax_item;    // get the first set of arguments for the exec() call in sendfax_slot (because    // this is a multi-threaded program, we must do this before fork()ing because    // we use functions to get the arguments which are not async-signal-safe)    // the arguments are loaded into the EfaxController object member sendfax_parms_vec    init_sendfax_parms();    // now launch a worker thread to make up the fax pages in tiffg3 format    // for sending by efax - the thread will emit dispatcher fax_made_notify    // if the fax is correctly made up, which will call sendfax_slot() in this    // initial (GUI) thread, which in turn invokes efax and sends the fax.  If    // the fax is not correctly made up, the worker thread will emit dispatcher    // no_fax_made_notify, which will call no_fax_made_slot() in this initial    // (GUI) thread so as to clean up correctly    // first block off the signals for which we have set handlers so that the worker    // thread does not receive the signals, otherwise we will have memory synchronisation    // issues in multi-processor systems - we will unblock in the initial (GUI) thread    // as soon as the worker thread has been launched    sigset_t sig_mask;    sigemptyset(&sig_mask);    sigaddset(&sig_mask, SIGCHLD);    sigaddset(&sig_mask, SIGQUIT);    sigaddset(&sig_mask, SIGTERM);    sigaddset(&sig_mask, SIGINT);    sigaddset(&sig_mask, SIGHUP);#ifdef HAVE_PTHREAD_SIGMASK     pthread_sigmask(SIG_BLOCK, &sig_mask, 0);#else    sigprocmask(SIG_BLOCK, &sig_mask, 0);#endif    try {      Glib::Thread::create(sigc::mem_fun(*this, &EfaxController::make_fax_thread), false);    }    catch (Glib::ThreadError&) {      write_error("Cannot start thread to make fax for sending\n");      stdout_pipe.close();      change_state_count--;      state = inactive;    }    // now unblock signals so that the initial (GUI) thread can receive them#ifdef HAVE_PTHREAD_SIGMASK     pthread_sigmask(SIG_UNBLOCK, &sig_mask, 0);#else    sigprocmask(SIG_UNBLOCK, &sig_mask, 0);#endif  }}void EfaxController::no_fax_made_slot(void) {  cleanup_fax_send_fail();  stdout_pipe.close();  change_state_count--;  state = inactive;}std::pair<const char*, char* const*> EfaxController::get_sendfax_parms(void) {  // sendfax_parms_vec has already been filled by init_sendfax_parms() and by  // make_fax_thread() - so make up the C style arrays for the execvp() call  // in sendfax_slot()  char** exec_parms = new char*[sendfax_parms_vec.size() + 1];  std::vector<std::string>::const_iterator iter;  char**  temp_pp = exec_parms;  for (iter = sendfax_parms_vec.begin(); iter != sendfax_parms_vec.end(); ++iter, ++temp_pp) {    *temp_pp = new char[iter->size() + 1];    std::strcpy(*temp_pp, iter->c_str());  }  *temp_pp = 0;  char* prog_name = new char[std::strlen("efax-0.9a") + 1];  std::strcpy(prog_name, "efax-0.9a");  return std::pair<const char*, char* const*>(prog_name, exec_parms);}void EfaxController::sendfax_slot(void) {  // this method runs in the initial (GUI) thread - we do this because  // it exec()s a child process and we need to catch the SIGCHLD  // signal when it finishes in the initial thread so that  // efax_controller_childexit_handler() also only runs in the initial  // (GUI) thread.  That way, no memory synchronisation issues arise  // on multi-processor systems with respect to the variables accessed  // by EfaxController::timer_event(), which also runs in the initial  // (GUI) thread.  Linuxthreads will only allow the thread which fork()ed  // to pick up SIGCHLD (its signal handling is deficient with respect to  // the POSIX pthreads standard) thus requiring the use of Glib::Dispatcher  // to "swap" execution threads at this point to complete sending of the  // fax  // we get this process to run in the initial (GUI) thread by invoking  // it from a Glib::Dispatcher object in EfaxController::make_fax_thread(),  // which will execute the slot attached to that object (this method) in  // the thread in which the Glib::Dispatcher object was created.  The  // Glib::Dispatcher object was created as a member of the EfaxController  // object, and thus was created in the initial (GUI) thread  // get the arguments for the exec() call below (because this is a  // multi-threaded program, we must do this before fork()ing because  // we use functions to get the arguments which are not async-signal-safe)  std::pair<const char*, char* const*> sendfax_parms(get_sendfax_parms());  // set up a synchronising pipe  in case the child process finishes before  // fork() in parent space has returned (yes, with an exec() error that can  // happen with Linux kernel 2.6) - this is important because we test child_pid  // in efax_controller_childexit_handler()  Sync_pipe sync_pipe;  child_pid = fork();  if (child_pid == -1) {    write_error("Fork error - exiting\n");    std::exit(FORK_ERROR);  }  if (!child_pid) {  // child process - as soon as everything is set up we are going to do an exec()    // now we have forked, we can connect stdout_pipe to stdout    // and connect MainWindow::error_pipe to stderr    stdout_pipe.connect_to_stdout();    connect_to_stderr();    // wait before we call execvp() until the parent process has set itself up    // and releases this process    sync_pipe.wait();    execvp(sendfax_parms.first, sendfax_parms.second);    // if we reached this point, then the execvp() call must have failed    // report error and exit - uses _exit() and not exit()    write_error("Can't find the efax-0.9a program - please check your installation\n"		"and the PATH environmental variable\n");    _exit(EXEC_ERROR);   } // end of child process      // this is the parent process  stdout_pipe.make_readonly();   // since the pipe is unidirectional, we can close the write fd  join_child();  // now we have set up, release the child process  sync_pipe.release();      // release the memory allocated on the heap for  // the redundant sendfax_parms_pair  // we are in the main parent process here - no worries about  // only being able to use async-signal-safe functions  delete_parms(sendfax_parms);}std::pair<const char*, char* const*> EfaxController::get_gs_parms(const std::string& basename) {  // lock the Prog_config object to stop it being modified in the intial (GUI) thread  // while we are accessing it here  Glib::Mutex::Lock lock(*prog_config.mutex_p);  std::vector<std::string> parms;  std::string temp;  parms.push_back("gs");  parms.push_back("-q");  parms.push_back("-sDEVICE=tiffg3");  temp = "-r";  temp += prog_config.resolution;  parms.push_back(temp);  parms.push_back("-dNOPAUSE");  parms.push_back("-dSAFER");  temp = "-sOutputFile=";  temp += basename + ".%03d";  parms.push_back(temp);  temp = "-sPAPERSIZE=";  temp += prog_config.page_size;  parms.push_back(temp);  parms.push_back(basename);	  char** exec_parms = new char*[parms.size() + 1];  std::vector<std::string>::const_iterator iter;  char**  temp_pp = exec_parms;  for (iter = parms.begin(); iter != parms.end(); ++iter, ++temp_pp) {    *temp_pp = new char[iter->size() + 1];    std::strcpy(*temp_pp, iter->c_str());  }  *temp_pp = 0;    char* prog_name = new char[std::strlen("gs") + 1];  std::strcpy(prog_name, "gs");  return std::pair<const char*, char* const*>(prog_name, exec_parms);}void EfaxController::make_fax_thread(void) {  // convert the postscript file(s) into tiffg3 fax files, beginning at [filename].001  // we will use ghostscript.  we will also load the results into sendfax_parms_vec  std::vector<std::string>::const_iterator filename_iter;  // we do not need a mutex to protect last_fax_item - until EfaxController::timer_event()  // resets state to inactive, we cannot invoke sendfax() again  for (filename_iter = last_fax_item_sent.file_list.begin();       filename_iter != last_fax_item_sent.file_list.end(); ++filename_iter) {    std::string::size_type pos = filename_iter->find_last_of('/');    if (pos == std::string::npos || pos + 2 > filename_iter->size()) {      try {	write_error(Glib::locale_from_utf8(gettext("Not valid file name\n")).c_str());      }      catch (Glib::ConvertError&) {	write_error("UTF-8 conversion error in EfaxController::make_fax_thread()\n");      }      no_fax_made_notify();      // clean up and then end this worker thread      return;    }        else if (access(filename_iter->c_str(), F_OK)) {      try {	write_error(Glib::locale_from_utf8(gettext("File does not exist\n")).c_str());      }      catch (Glib::ConvertError&) {	write_error("UTF-8 conversion error in EfaxController::make_fax_thread()\n");      }      no_fax_made_notify();      // clean up and then end this worker thread      return;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -