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

📄 efax_controller.cpp

📁 用于使用moden进行传真的源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    }    else if (access(filename_iter->c_str(), R_OK)) {      try {	write_error(Glib::locale_from_utf8(gettext("User does not have read permission on the file\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;    }    // unfortunately ghostscript does not handle long file names    // so we need to separate the file name from the full path (we will chdir() to the directory later)    // pos is already set to the position of the last '/' character    std::string dirname(filename_iter->substr(0, pos));    pos++;    std::string basename(filename_iter->substr(pos));    // 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*> gs_parms(get_gs_parms(basename));    // create a synchronising pipe - we need to wait() on gs having completed executing    // and then notify the parent process.  To wait() successfully we need to fork() once,    // reset the child signal handler, and then fork() again    Sync_pipe sync_pipe;    pid_t pid = fork();        if (pid == -1) {      write_error("Fork error\n");      std::exit(FORK_ERROR);    }    if (!pid) { // child process      // restore the default SIGCHLD signal handler with SA_RESTART      // for systems (such as Linux) which require it.  Also unblock      // signals in case we are blocking them on launching a thread      // elsewhere in this program (I cannot work out from IEEE 1003.1      // whether all masks are emptied on a fork() in any event)      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);      // this child process is single threaded, so we can use sigprocmask()      // rather than pthread_sigmask() (and should do so as sigprocmask()      // is guaranteed to be async-signal-safe)      sigprocmask(SIG_UNBLOCK, &sig_mask, 0);      struct sigaction sig_act;      sig_act.sa_handler = SIG_DFL;      sigemptyset(&sig_act.sa_mask);#ifdef SA_RESTART      sig_act.sa_flags = SA_RESTART;#else      sig_act.sa_flags = 0;#endif      sigaction(SIGCHLD, &sig_act, 0);	      connect_to_stderr();      // now fork() again      pid_t pid = fork();      if (pid == -1) {	write_error("Fork error\n");	_exit(FORK_ERROR); // we have already forked, so use _exit() not exit()      }      if (!pid) {  // child process - when everything is set up, we are going to do an exec()	// we don't need sync_pipe in this process - ignore it by calling release()	sync_pipe.release();	// now start up ghostscript	// first we need to connect stdin to /dev/null to make ghostscript terminate	int fd = open("/dev/null", O_RDWR);	dup2(fd, 0);	// now close stdout	dup2(fd, 1);	close(fd); // now stdin and stdout read/write to /dev/null, we can close the /dev/null file descriptor	// unfortunately ghostscript does not handle long file names	// so we need to chdir()	chdir(dirname.c_str());	execvp(gs_parms.first, gs_parms.second);	// if we reached this point, then the execvp() call must have failed	write_error("Can't find the ghostscript program - please check your installation\n"		    "and the PATH environmental variable\n");	// this child process must end here - use _exit() not exit()	_exit(EXEC_ERROR);       } // end of child process      // this is the parent process      // wait until ghostscript has produced the fax tiffg3 fax file.      // Note that we have already fork()ed before the fork() by this process      // so childexit_signalhandler in mainwindow.cpp will not pick up      // the end of the child process, so this wait() will work OK      wait(0);      // release the waiting parent process      sync_pipe.release();      // now end the process - use _exit() not exit()      _exit(0);    }    // wait on sync_pipe until we know gs has made all the files in tiffg3 format    sync_pipe.wait();    // release the memory allocated on the heap for    // the redundant gs_parms    // we are in the main parent process here - no worries about    // only being able to use async-signal-safe functions    delete_parms(gs_parms);    // now enter the names of the created files in sendfax_parms_vec    bool valid_file = false;    int partnumber = 1;#ifdef HAVE_STRINGSTREAM    std::ostringstream strm;    strm << *filename_iter << '.' << std::setfill('0')	 << std::setw(3) << partnumber;    int result = access(strm.str().c_str(), R_OK);        while (!result) {  // file OK      // valid_file only needs to be set true once, but it is more      // convenient to do it in this loop      valid_file = true;      // we do not need a mutex to protect sendfax_parms_vec - until      // EfaxController::timer_event() resets state to inactive, we cannot invoke      // sendfax() again      sendfax_parms_vec.push_back(strm.str());      partnumber++;      strm.str("");      strm << *filename_iter << '.' << std::setfill('0')	   << std::setw(3) << partnumber;      result = access(strm.str().c_str(), R_OK);    }#else    std::ostrstream strm;    strm << filename_iter->c_str() << '.' << std::setfill('0')	 << std::setw(3) << partnumber << std::ends;    const char* test_name = strm.str();    int result = access(test_name, R_OK);      while (!result) {  // file OK      // valid_file only needs to be set true once, but it is more      // convenient to do it in this loop      valid_file = true;      sendfax_parms_vec.push_back(test_name);      delete[] test_name;      partnumber++;      std::ostrstream strm;      strm << filename_iter->c_str() << '.' << std::setfill('0')	   << std::setw(3) << partnumber << std::ends;      test_name = strm.str();      result = access(test_name, R_OK);    }    delete[] test_name;#endif          if (!valid_file) {      try {	write_error(Glib::locale_from_utf8(gettext("Not valid postscript file\n")).c_str());      }      catch (Glib::ConvertError&) {	write_error("UTF-8 conversion error in EfaxController::make_fax_thread()\n");      }      // clean up and then end this worker thread      no_fax_made_notify();      return;    }  }  // we have now made the fax pages in tiffg3 format and entered them into sendfax_parms_vec.  // At the end of this method this worker thread will end, and emitting fax_made_notify  // will cause sendfax_slot() to be executed in the initial (GUI) thread  fax_made_notify();}std::pair<const char*, char* const*> EfaxController::get_receive_parms(int mode) {  std::vector<std::string> efax_parms(prog_config.parms);  std::string temp("-r");  temp += prog_config.receive_dirname;  efax_parms.push_back(temp);  if (mode == receive_takeover) efax_parms.push_back("-w");        else if (mode == receive_standby) {    temp = "-jS0=";    temp += prog_config.rings;    efax_parms.push_back(temp);    efax_parms.push_back("-s");    efax_parms.push_back("-w");  }        char** exec_parms = new char*[efax_parms.size() + 1];  std::vector<std::string>::const_iterator iter;  char**  temp_pp = exec_parms;  for (iter = efax_parms.begin(); iter != efax_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("efax-0.9a") + 1];  std::strcpy(prog_name, "efax-0.9a");    return std::pair<const char*, char* const*>(prog_name, exec_parms);}void EfaxController::receive(int mode) {  if (state != inactive) beep();  else {    // get a time value to create the directory name into which the fax is to be saved    // and to insert in prog_config.receive_dirname for parent and child    struct std::tm* time_p;    std::time_t time_count;        std::time(&time_count);    time_p = std::localtime(&time_count);    std::string fax_pathname;    if (!prog_config.homedir.empty()) {      fax_pathname = prog_config.homedir;      fax_pathname += "/faxin/";    }    else {      write_error("You don't have the $HOME environmental variable set.\n"		  "You may need to search for the directory in which\n"		  "the received fax is saved, and it probably won't\n"		  "appear in the fax list!\n");    }    const char format[] = "%y%m%d%H%M%S";    {      // lock the Prog_config object while we modify it      Glib::Mutex::Lock lock(*prog_config.mutex_p);      std::strftime(prog_config.receive_dirname, MAX_TEMP_NAME + 1, format, time_p);    }    std::string temp(fax_pathname);    temp += prog_config.receive_dirname;    // check whether directory already exists or can't be created    int count;    for (count = 0; count < 4 && mkdir(temp.c_str(), S_IRUSR | S_IWUSR | S_IXUSR); count++) {      sleep(1); // wait a second to get a different time      std::time(&time_count);      time_p = std::localtime(&time_count);      {	// lock the Prog_config object while we modify it	Glib::Mutex::Lock lock(*prog_config.mutex_p);	std::strftime(prog_config.receive_dirname, MAX_TEMP_NAME + 1, format, time_p);      }      temp = fax_pathname + prog_config.receive_dirname;    }    if (count == 4) {      write_error("Can't create directory to save fax\n");      {	// lock the Prog_config object while we modify it	Glib::Mutex::Lock lock(*prog_config.mutex_p);	*prog_config.receive_dirname = 0;      }      return;    }    fax_pathname += prog_config.receive_dirname;    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 = mode;    change_state_count++;    // 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*> receive_parms(get_receive_parms(mode));    // 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();      chdir(fax_pathname.c_str());      // wait before we call execvp() until the parent process has set itself up      // and releases this process      sync_pipe.wait();      // now start up efax in receive mode      execvp(receive_parms.first, receive_parms.second);      // if we reached this point, then the execvp() call must have failed      // report the error and end this process - use _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 receive_parms    // we are in the main parent process here - no worries about    // only being able to use async-signal-safe functions    delete_parms(receive_parms);  }}void EfaxController::delete_parms(std::pair<const char*, char* const*> parms_pair) {  delete[] parms_pair.first;  char* const* temp_pp = parms_pair.second;  for(; *temp_pp != 0; ++temp_pp) {    delete[] *temp_pp;  }  delete[] parms_pair.second;}bool EfaxController::read_pipe_slot(Glib::IOCondition) {  char pipe_buffer[PIPE_BUF + 1];  ssize_t result;  while ((result = stdout_pipe.read(pipe_buffer, PIPE_BUF)) > 0) {    pipe_buffer[result] = 0;    stdout_message(pipe_buffer);  }  if (result == -1                             // as this is a non-blocking pipe, result should      && (errno == EAGAIN || errno == EINTR)) {// end up being -1 with errno == EAGAIN    return true;                               // retain SigC connection  }  return false; // something has gone wrong (probably the pipe has been destroyed), so disconnect}void EfaxController::stop_slot(void) { if (state != inactive && state != close_child_connections) {      // else we need to deal with it here   stdout_message(gettext("\n*** Stopping send/receive session ***\n\n"));   kill_child(); }  else beep();}void EfaxController::timer_event(void) {  if (change_state_count) { // we only really need to test change_state_count to trigger    // a call to display_state(), but we need to test here at the outset to make sure    // that timer_event() is atomic for all further tests below, as all the variables

⌨️ 快捷键说明

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