Logo Search packages:      
Sourcecode: efax-gtk version File versions


/* Copyright (C) 2001 to 2004 Chris Vine

This program is distributed under the General Public Licence, version 2.
For particulars of this and relevant disclaimers see the file
COPYING distributed with the source files.


#ifndef PROG_DEFS_H
#define PROG_DEFS_H

#include <unistd.h>
#include "config.h"

// deal with any configuration issues arising from config.h

#ifndef HAVE_BOOL
typedef int bool;
const bool false = 0;
const bool true = 1;

#ifndef ENABLE_NLS
inline const char* gettext(const char* text) {
  return text;

#ifndef HAVE_SSIZE_T
typedef signed int ssize_t;

typedef unsigned int socklen_t;

// deal with libsigc++
#include "sigc_compatibility.h"

// define some common exit codes

#define MEM_ERROR 10
#define CONFIG_ERROR 11
#define COM_ERROR 12
#define PIPE_ERROR 14
#define TERM_ERROR 15
#define ARG_ERROR 16
#define EXEC_ERROR 17
#define FORK_ERROR 18

#define RC_FILE "efax-gtkrc"

#include <vector>
#include <string>
#include <glibmm/ustring.h>
#include <glibmm/refptr.h>
#include <gdkmm/pixbuf.h>

// forward declaration for pointer to Glib::Mutex in struct Prog_config
namespace Glib {
  class Mutex;

using namespace std;    // until I get a Std C++ compliant compiler to test with

#define MAX_TEMP_NAME 12

/************************* threading issues *************************

1. This program uses certain functions which are not guaranteed by
   IEEE Std 1003.1 to be thread safe, and which are not protected by
   mutexes because this program only uses them in one thread.  These
   functions are:

     localtime() - used in the main (GUI) thread (efax_controller.cpp)
     readdir()   - used in the main (GUI) thread (fax_list.cpp)

     gethostbyaddr() ) used in the socket server thread (socket_server.cpp)
     gethostbyname() )

   If the program is modified to use any of these in a different thread,
   mutexes will need to be applied.

2. The program operates the following threads:

   - the initial GUI thread (the main program thread) (runs throughout
     program execution).

   - if the socket server is running, a socket server thread (runs
     whenever the socket server has been selected to run).  This
     involves the following methods of the Socket_server class:
       socket_thread(), accept_on_client(), is_valid_peer(),
       read_socket(), add_file(), write_stdout_from_thread() and
       save_queued_faxes().  (save_queued_faxes is called by both the
       main GUI thread and by the socket_server_thread - see the
       comments in that method about mutexes)

   - a temporary thread created to convert a postscript file to tiffg3
     files for faxing, involving the following methods of the
     EfaxController class:

       make_fax_thread() and get_gs_parms()

   - a temporary thread to prepare a fax for printing, involving the
     following methods of the FaxListDialog class:

       print_fax_thread(), get_print_from_stdin_parms(),
       get_fax_to_ps_parms() and delete_parms() (get_fax_to_ps_parms()
       is also called by the temporary thread invoked with
       view_fax_thread() and delete_parms() is also called by that
       thread and by the main (GUI) thread)

   - a temporary thread to view a fax, involving the following methods
     of the FaxListDialog class:

       view_fax_thread(), write_from_stdin(), get_ps_viewer_parms(),
       get_fax_to_ps_parms() and delete_parms() (get_fax_to_ps_parms()
       is also called by the temporary thread invoked with
       print_fax_thread() and delete_parms() is also called by that
       thread and by the main (GUI) thread)

3. The last member of the Prog_config class below is a pointer to a mutex object
   allocated in int main() in main.cpp.  The mutex should be locked whenever:

   (a) the main (GUI) thread is modifying a member of the Prog_config class, or
   (b) any worker thread is reading the Prog_config object.

   No worker thread should modify a Prog_config class member, to save excessive
   locking in this program

4. In addition, members of the Prog_config class which are not built-in types,
   and for which concurrent reads in different threads are not guaranteed, are
   read outside the main (GUI) thread as follows -

     - Prog_config::resolution is read by EfaxController::get_gs_parms()
       (in efax_controller.cpp)

     - Prog_config::page_size is read by EfaxController::get_gs_parms()
       (in efax_controller.cpp) and by FaxListDialog::get_fax_to_ps_parms() (in

     - Prog_config::page_dim is read by FaxListDialog::get_fax_to_ps_parms() (in

     - Prog_config::print_shrink is read by FaxListDialog::get_fax_to_ps_parms()
       (in fax_list.cpp)

     - Prog_config::print_cmd is read by FaxListDialog::get_print_from_stdin_parms()
       (in fax_list.cpp)

     - Prog_config::ps_view_cmd is read by FaxListDialog::get_ps_viewer_parms()
       (in fax_list.cpp)

     - Prog_config::permitted_clients_list is read by Socket_server::is_valid_peer()
       (in socket_server.cpp)

   These are protected by the mutex where read by these non-GUI
   threads and written to by the main (GUI) thread, but they should
   also be protected by the mutex wherever read by the main (GUI)
   thread unless it is known that there can be no concurrency with the
   execution of these other threads so far as concerns the reading of
   these members.  (In fact, as this program is written concurrent
   reads are only an issue with Prog_config::ps_view_cmd, and locking
   of it takes place in FileReadSelectDialog::get_view_file_parms()
   (in dialogs.cpp), FileListDialog::view_file() and
   FileListDialog::get_view_file_parms() (in filelist.cpp) and
   SocketListDialog::view_file() and
   SocketListDialog::get_view_file_parms() (in socket_list.cpp).)

5. See also the comments about thread sefety in the function
   write_error() in mainwindow.cpp.

6. It would have been convenient to have signal handling in a separate
   thread and then to sigwait() on the signals used by this program.
   However the main signal of interest is SIGCHLD, from which the
   termination of a send or receive session from efax can be detected,
   and information about the success or failure of the sending or
   receipt of the fax can be obtained and acted on.  Unfortunately,
   linuxthreads does not properly implement POSIX threads as regards
   signal handling, and with linuxthreads only the thread which
   fork()s will receive SIGCHLD.  Thus SIGCHLD cannot be received in a
   special signal handling thread.  Instead, a timer event handler is
   provided in MainWindow::timer_event() (which also calls
   EfaxController::timer_event()) which deals with interrupts and
   child exit handling.


struct Prog_config {
  std::string lock_file;
  std::string fixed_font;
  std::string homedir;
  std::string working_dir;
  char rings;
  char receive_dirname[MAX_TEMP_NAME + 1];
  bool tone_dial;
  bool found_rcfile;
  bool GPL_flag;
  bool print_popup;
  bool sock_server;
  bool sock_popup;
  bool other_sock_client_address;
  bool fax_received_popup;
  bool fax_received_exec;
  Glib::ustring my_name;
  Glib::ustring my_number;
  Glib::ustring page_size;  // either 'a4' 'letter' or 'legal'
  Glib::ustring page_dim;
  Glib::ustring resolution;
  Glib::ustring print_cmd;
  Glib::ustring print_shrink;
  Glib::ustring ps_view_cmd;
  Glib::ustring logfile_name;
  Glib::ustring sock_server_port;
  Glib::ustring fax_received_prog;
  std::vector<std::string> parms;
  std::vector<std::string> permitted_clients_list;
  Glib::RefPtr<Gdk::Pixbuf> window_icon_r;
  Glib::Mutex* mutex_p;

extern Prog_config prog_config;           // defined in main.cpp
Glib::ustring configure_prog(bool reread);// also defined in main.cpp (pass reread as true if
                                          // the program parameters are being reread)

// generic beep() function defined in main.cpp
void beep(void);

// general function for writing an error defined in mainwindow.cpp
// the message must not be larger than PIPE_BUF in size.  The function
// handles EINTR - you do not need to check this yourself.  The error
// messages are put in a pipe which is non-blocking - it will be
// emptied fairly promptly but messages should be less than PIPE_BUF
// in length or any excess may be lost (it returns the number of
// bytes written, so the return value can be used to achieve long
// writes, if really wanted).
ssize_t write_error(const char*);

// this function is defined in mainwindow.cpp, and will cause any
// message written to stderr to be taken by the in built error pipe
// in MainWindow.  Only call this in a child process after fork()ing.
int connect_to_stderr(void);


Generated by  Doxygen 1.6.0   Back to index