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

📄 efax_controller.cpp

📁 用于使用moden进行传真的源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    // being tested can be changed by efax_controller_childexit_handler()    if (state == close_child_connections || state == restart_standby) {          if (*prog_config.receive_dirname) {	// now delete 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;	int result = rmdir(full_dirname.c_str()); // only deletes the directory if it is empty	if (result == -1 && errno == ENOTEMPTY) {	  // before assuming a fax has been successfully received, check to see	  // if [fax_name].001 is of 0 size (if it is delete it)	  struct stat statinfo;	  std::string file_name(full_dirname);	  file_name += '/';	  file_name += prog_config.receive_dirname;	  file_name += ".001";	  if (!stat(file_name.c_str(), &statinfo)	      && !statinfo.st_size) {	    unlink(file_name.c_str());	    rmdir(full_dirname.c_str());	  }	  else fax_received_notify();	}	// 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 state_val = state;      state = inactive; // this is needed even if we are going to call receive()      // now restart if in standby mode      if (state_val == restart_standby) receive(receive_standby);    }    else if (state == send_success || state == send_fail) {      if (state == send_success) {	save_sent_fax();	if (last_fax_item_sent.is_socket_file) {	  // if we are sending a print job via the socket server, notify the	  // Socket_server object which created the temporary file (the server	  // object will clean up by deleting it and also cause the socket	  // file list to be updated - we do not need to do that here)	  remove_from_socket_server_filelist(last_fax_item_sent.file_list[0]);	}      }      else cleanup_fax_send_fail();      unjoin_child();      state = inactive;    }    // Note: there is a possible race condition at this point immediately before    // we operate on change_state_count.  It is theoretically possible (though    // very unlikely) that efax_controller_childexit_handler() could fire between us    // testing state above and us operating on change_state_count below, because    // of, say, an exec() failure in executing efax to send or receive a    // fax.  To avoid this we increment change_state_count (including in    // efax_controller_childexit_handler()) instead of just setting it to true    // and decrement it (as below) instead of setting it to false.  This means that    // even if efax_controller_childexit_handler() fires at this precise point in    // the code, when it has finished change_state_count will hold the value 2 and    // not 1, so after being decremented below it will still hold the value 1, so    // causing this function to be called again recursively at the end of this     // function, so operating correctly on the values of state set up in    // efax_controller_childexit_handler()    change_state_count--;    display_state();    if (change_state_count > 0) timer_event();  }}void EfaxController::display_state(void) {  write_state(state_messages[state].c_str());}void EfaxController::join_child(void) {  // we do not need a mutex for this - join_child() and unjoin_child() are  // only called in the initial (GUI) thread  stdout_connection = Glib::signal_io().connect(sigc::mem_fun(*this, &EfaxController::read_pipe_slot),						stdout_pipe.get_read_fd(), Glib::IO_IN);}void EfaxController::unjoin_child(void) {  // we do not need a mutex for this - join_child() and unjoin_child() are  // only called in the initial (GUI) thread, and stdout_pipe is only manipulated  // in that thread or after a new single-threaded process has been launched with fork()  stdout_pipe.close();  stdout_connection.disconnect();}void EfaxController::kill_child(void) {  if (child_pid) kill(child_pid, SIGTERM);  Glib::usleep(500000);               // now really make sure  if (child_pid) kill(child_pid, SIGKILL);}void EfaxController::save_sent_fax(void) {    // get a time value to create the directory name into which the fax is to be saved  struct std::tm* time_p;  std::time_t time_count;      std::time(&time_count);  time_p = std::localtime(&time_count);  // now create the directory into which the fax files to be saved  std::string fileout_name;  if (!prog_config.homedir.empty()) {    fileout_name = prog_config.homedir;    fileout_name += "/faxsent/";  }  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 fax is saved, and it probably won't appear in\n"		"the fax list!\n");  }  const char dirname_format[] = "%y%m%d%H%M%S";  char top_dirname[MAX_TEMP_NAME + 1];  std::strftime(top_dirname, MAX_TEMP_NAME + 1, dirname_format, time_p);  std::string temp(fileout_name);  temp += top_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);    std::strftime(top_dirname, MAX_TEMP_NAME + 1, dirname_format, time_p);    temp = fileout_name + top_dirname;  }  if (count == 4) {    write_error("Can't create directory to save fax\n");    return;  }  // now make fileout_name the same as the directory name for the saved faxes  // that we have just created  fileout_name += top_dirname;  const std::string fileout_dirname(fileout_name); // keep for later to enter a description  // and now complete the unsuffixed file name of the destination files  fileout_name += '/';  fileout_name += top_dirname;  // now create a string containing the date for the fax description  // glibc has const struct tm* as last param of strftime()  // but the const does not appear to be guaranteed by POSIX  // so do localtime() again just in case  time_p = std::localtime(&time_count);  const char date_description_format[] = "(%H%M %Z %d %b %Y)";  const int max_description_datesize = 126;  char date_description[max_description_datesize];  std::strftime(date_description, max_description_datesize, date_description_format, time_p);  // now copy files into the relevant directory for the fax pages to be saved  std::vector<std::string> file_basename_vec; // this is used in making the fax description  int out_partnumber = 1; // in order to generate the suffix for each fax page as saved  std::vector<std::string>::const_iterator sentname_iter;  for (sentname_iter = last_fax_item_sent.file_list.begin();       sentname_iter != last_fax_item_sent.file_list.end(); ++sentname_iter) {    std::string::size_type pos = sentname_iter->find_last_of('/');    if (pos == std::string::npos || pos + 2 > sentname_iter->size()) {      write_error("Not valid file name to save -- can't save sent fax\n");    }    else {      // save the file base name for later use in making the fax description      pos++;      file_basename_vec.push_back(sentname_iter->substr(pos));      // make the suffixes      int in_partnumber = 1;#ifdef HAVE_STRINGSTREAM      std::ostringstream in_suffix_strm;      in_suffix_strm << '.' << std::setfill('0')		     << std::setw(3) << in_partnumber;      std::ostringstream out_suffix_strm;      out_suffix_strm << '.' << std::setfill('0')		      << std::setw(3) << out_partnumber;      // make the suffixed source and destination files      std::string suffixed_inname = *sentname_iter + in_suffix_strm.str();      std::string suffixed_outname = fileout_name + out_suffix_strm.str();#else      std::ostrstream in_suffix_strm;      in_suffix_strm << '.' << std::setfill('0')		     << std::setw(3) << in_partnumber << std::ends;      const char* in_suffix = in_suffix_strm.str();      std::ostrstream out_suffix_strm;      out_suffix_strm << '.' << std::setfill('0')		      << std::setw(3) << out_partnumber << std::ends;      const char* out_suffix = out_suffix_strm.str();      // make the suffixed source and destination files      std::string suffixed_inname = *sentname_iter + in_suffix;      std::string suffixed_outname = fileout_name + out_suffix;      delete[] in_suffix;      delete[] out_suffix;#endif      std::ifstream filein;      std::ofstream fileout;      const int BLOCKSIZE = 1024;      char block[BLOCKSIZE];      while (!access(suffixed_inname.c_str(), R_OK)	     && (filein.open(suffixed_inname.c_str(), std::ios::in), filein) // use comma operator to check filein	     && (fileout.open(suffixed_outname.c_str(), std::ios::out), fileout)) { // ditto for fileout	while (filein) {	  filein.read(block, BLOCKSIZE);	  fileout.write(block, filein.gcount());	}	filein.clear();	filein.close();	fileout.clear();	fileout.close();	unlink(suffixed_inname.c_str());     	in_partnumber++;	out_partnumber++;#ifdef HAVE_STRINGSTREAM	in_suffix_strm.str("");	in_suffix_strm << '.' << std::setfill('0')		       << std::setw(3) << in_partnumber;	out_suffix_strm.str("");	out_suffix_strm << '.' << std::setfill('0')			<< std::setw(3) << out_partnumber;	// make the suffixed source and destination files	suffixed_inname = *sentname_iter + in_suffix_strm.str();	suffixed_outname = fileout_name + out_suffix_strm.str();#else	std::ostrstream in_suffix_strm;	in_suffix_strm << '.' << std::setfill('0')		       << std::setw(3) << in_partnumber << std::ends;	in_suffix = in_suffix_strm.str();	std::ostrstream out_suffix_strm;	out_suffix_strm << '.' << std::setfill('0')			<< std::setw(3) << out_partnumber << std::ends;	out_suffix = out_suffix_strm.str();	// make the suffixed source and destination files	suffixed_inname = *sentname_iter + in_suffix;	suffixed_outname = fileout_name + out_suffix;	delete[] in_suffix;	delete[] out_suffix;#endif      }      fileout.clear();      if (in_partnumber < 2) write_error("There was a problem saving all or part of the sent fax\n");    }  }  // now save the sent fax description  if (out_partnumber > 1) {    const std::string description_filename(fileout_dirname + "/Description");    std::ofstream fileout(description_filename.c_str(), std::ios::out);    if (fileout) {      if (last_fax_item_sent.is_socket_file) fileout << gettext("PRINT JOB");      else {	std::vector<std::string>::const_iterator filename_iter;	for (filename_iter = file_basename_vec.begin();	     filename_iter != file_basename_vec.end(); ++filename_iter) {      	  if (filename_iter != file_basename_vec.begin()) fileout << '+';	  fileout << *filename_iter;	}      }      if (!last_fax_item_sent.number.empty()) {	fileout << " --> " << last_fax_item_sent.number;      }      fileout << ' ' << date_description;    }    else write_error("Cannot save sent fax description\n");  }}void EfaxController::cleanup_fax_send_fail(void) {  std::vector<std::string>::const_iterator filename_iter;  for (filename_iter = last_fax_item_sent.file_list.begin();       filename_iter != last_fax_item_sent.file_list.end(); ++filename_iter) {    // make the suffix    int partnumber = 1;#ifdef HAVE_STRINGSTREAM    std::ostringstream strm;    strm << '.' << std::setfill('0') << std::setw(3) << partnumber;    // make the suffixed file name    std::string filename = *filename_iter + strm.str();    while (!access(filename.c_str(), R_OK)) {      unlink(filename.c_str());      partnumber++;      strm.str("");      strm << '.' << std::setfill('0') << std::setw(3) << partnumber;      filename = *filename_iter + strm.str();    }#else    std::ostrstream strm;    strm << '.' << std::setfill('0') << std::setw(3) << partnumber << std::ends;    const char* suffix = strm.str();    // make the suffixed file name    std::string filename = *filename_iter + suffix;    delete[] suffix;    while (!access(filename.c_str(), R_OK)) {      unlink(filename.c_str());      partnumber++;      std::ostrstream strm;      strm << '.' << std::setfill('0') << std::setw(3) << partnumber << std::ends;      suffix = strm.str();      filename = *filename_iter + suffix;      delete[] suffix;    }#endif  }}bool efax_controller_childexit_handler(pid_t pid, int exit_code) {  /*    *  in order to avoid race conditions or unexpected results, it is enough    * (i)   to end this function by incrementing change_state_count   * (ii)  to test for change_state_count at the beginning of EfaxController::timer_event()   * (iii) to set state to inactive in EfaxController::timer_event() after that function   *       has finished acting on the value of state set in this handler   * (iv)  to decrement change_state_count at the end of EfaxController::timer_event()   *   * this is because only this signal handler sets state to restart_standby,   * send_success, send_fail and close_child_connections, and until   * EfaxController::timer_event() has changed the value of state from   * these values to inactive, then the program cannot launch another   * child process to exec() efax which would (when terminating) cause   * this handler to be invoked   */  if (pid == child_pid) {    child_pid = 0;    // this won't work if efax is suid root and we are not root    if (prog_config.lock_file) unlink(prog_config.lock_file);        if (state == EfaxController::closedown) // tell EfaxController::efax_closedown() the child is now dead      state = EfaxController::inactive;    else if (state == EfaxController::receive_standby	     && (!exit_code || exit_code == 3)) // get EfaxController::timer_event() to restart efax()      state = EfaxController::restart_standby;    else if (state == EfaxController::sending) {      if(!exit_code)            // get EfaxController::timer_event() to save the file in sent fax list	state = EfaxController::send_success;      else state = EfaxController::send_fail;    }    else if (state != EfaxController::inactive) // get EfaxController::timer_event() to close dead file descriptors and dead SigC connections      state = EfaxController::close_child_connections;    change_state_count++;    return true;  }  return false;}

⌨️ 快捷键说明

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