socket++-1.12.13/0000755000175000017500000000000011676325373011454 5ustar stbstbsocket++-1.12.13/acconfig.h0000644000175000017500000000134111676325304013367 0ustar stbstb/* Define if extern "C" is needed arround include files */ #undef EXTERN_C_BEGIN #undef EXTERN_C_END /* Define either as _sys_siglist or sys_siglist */ #undef SYS_SIGLIST /* Define the argument type for signal handler function */ #undef SIGHND_ARGTYPE /* Define either as _sys_errlist or sys_errlist */ #undef SYS_ERRLIST /* Define SYS_ERRLIST_DECLARED if extern char* SYS_ERRLIST []; is found */ #undef SYS_ERRLIST_DECLARED /* Define SA_RESTART if it is not defined in sys/signal.h */ #undef SA_RESTART /* Define if you have libg++ */ #undef _S_LIBGXX /* Version */ #undef SOCKET_MAJOR_VERSION #undef SOCKET_MINOR_VERSION #undef SOCKET_MICRO_VERSION /* Configuration Options */ #undef ENABLE_DEBUG @BOTTOM@ #include socket++-1.12.13/Makefile.am0000644000175000017500000000003011676325304013473 0ustar stbstbSUBDIRS = socket++ doc socket++-1.12.13/AUTHORS0000644000175000017500000000022511676325304012515 0ustar stbstbMain Author: ============ 1992-1996 Gnanasekaran Swaminathan Other Authors: 2002-2004 Herbert Straub socket++-1.12.13/NEWS0000644000175000017500000000424211676325373012155 0ustar stbstbVersion: 1.12.13: * Removing all forgotten GNU/GPL license informations from the source code. Version: 1.12.11: * Major Bugfix: Dan Muller reporting this problem: "It's all in the sockbuf::write function. there is a while loop, and it throws on send error, but, if connection is non-blocking, and "slow", but no error occurs, only wval < len bytes are sent... in every step of the loop, BUT have a look at which bytes are sent, allways from the beginning of the buf, buf is not incremented, that's what I think is a bug." --> This should be now corrected (see Changelog for details). All other versions of Socket++ containing this error! * GNU/GPL License: I removed this terms in all files for my changes, because Matthew Faupel reported the incompatibility of the original license and the GNU/GPL. The further development are under the same condition as the original license. * Socket++ License disallow source code changes? Sekar Swaminathan sends the message: "It is a free code. You can modify, copy, and distribute and use it in anyway as you see fit. Other people are maintaining it and ported it to different OSes. Other than that, not much has changed as far as I know. I haven't looked at it recently." Version: 1.12.10: * The uninitializied err sockerr variable can lead in a segmentation fault, if the exception handler of the calling program call sockerr errstr() method. This situation can test with the testprogram tsinwrite. * New configuration option --enable-debug for test/development code or bugfixing sessions. Version: 1.12.9: * "Named Sockets" with sockbuf::setname(). This helps in situation (ex. communication error), when a sockerr exception is thrown. The text in the sockerr exception containing the name of the socket. Version 1.12: * Removing all global variables * Shared Library * Improved sockerr class with a Operation String Specification. All sockbuf methods using the new Operation String Specification in the throw statement. * Header file in ${prefix}/include/socket++/ New Version of socket++: http://members.aon.at/hstraub/linux/socket++/index.html Freshmeat: http://freshmeat.net/projects/socketxx/ socket++-1.12.13/socket++/0000755000175000017500000000000011676325557013076 5ustar stbstbsocket++-1.12.13/socket++/ftp.h0000644000175000017500000000776111676325304014041 0ustar stbstb// ftp.h // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #ifndef FTP_H #define FTP_H #include #ifndef WIN32 # include #else #define MAXPATHLEN MAX_PATH #endif // !WIN32 class ftp: public protocol { public: enum reptype { rt_ascii_nonprint, rt_ascii_telnet, rt_ascii_asa, rt_ebcdic_nonprint, rt_ebcdic_telnet, rt_ebcdic_asa, rt_image, rt_local }; enum filestru { fs_file, fs_record, fs_page }; enum transmode { tm_stream, tm_block, tm_comp }; enum replycodea { rca_posprelim = '1', rca_poscomp = '2', rca_posinter = '3', rca_error = '4', rca_negtranscomp = '4', rca_negpermcomp = '5' }; enum replycodeb { rcb_syntax = '0', rcb_info = '1', rcb_conn = '2', rcb_auth = '3', rcb_unspec = '4', rcb_filesys = '5' }; class ftpbuf: public protocol::protocolbuf { // the following are used when this is used as a server char* usr; char* password; char* account; char cwd [MAXPATHLEN]; char parentdir [MAXPATHLEN]; filestru fs; transmode tm; sockinetaddr udata; // user will listen at this addr for data conn. int serverportno; char replycode [5]; std::ostream* o; replycodea send_cmd (const char* cmd, const char* arg=0); replycodea ftpdata (int portno, std::istream* i, std::ostream* out, const char* cmd, const char* arg=0); ftpbuf (ftpbuf&); ftpbuf& operator = (ftpbuf&); public: ftpbuf (std::ostream* out = 0); replycodea get_response (); const char* reply_code () const { return replycode; } replycodea help () { return send_cmd ("HELP"); } replycodea noop () { return send_cmd ("NOOP"); } replycodea quit () { return send_cmd ("QUIT"); } replycodea abort () { return send_cmd ("ABOR"); } replycodea user (const char* name) {return send_cmd ("USER", name);} replycodea passwd (const char* pw) {return send_cmd ("PASS", pw); } replycodea acct (const char* ac) {return send_cmd ("ACCT", ac);} replycodea cd (const char* dir); replycodea useraddr (sockinetaddr sa); replycodea useraddr (const char* host, int portno); replycodea server_port (int portno); replycodea rep_type (reptype rt); replycodea file_stru (filestru fs); replycodea trans_mode (transmode tm); // service commands replycodea getfile (const char* rpath, const char* lpath); replycodea list (const char* lpath=0, int justnames = 0); replycodea putfile (const char* lpath, const char* rpath); replycodea putfile (const char* lpath); replycodea append (const char* lpath, const char* rpath); replycodea allocate (int numbytes); replycodea restart (int marker); replycodea rename (const char* rpath, const char* newrpath); replycodea rmfile (const char* rpath); replycodea rmdir (const char* rpath); replycodea mkdir (const char* rpath); replycodea pwd () { return send_cmd ("PWD"); } replycodea system () { return send_cmd ("SYST"); } replycodea status () { return send_cmd ("STAT"); } virtual void serve_clients (int portno = -1); virtual const char* rfc_name () const { return "ftp"; } virtual const char* rfc_doc () const { return "rfc959"; } }; protected: ftp (): std::ios (0) {} public: ftp (std::ostream* out); ~ftp () { delete std::ios::rdbuf (); std::ios::init (0); } ftpbuf* rdbuf () { return (ftpbuf*) protocol::rdbuf (); } ftpbuf* operator -> () { return rdbuf (); } }; #endif // !FTP_H socket++-1.12.13/socket++/Makefile.am0000644000175000017500000000114511676325304015121 0ustar stbstbINCLUDES = -I$(top_srcdir) -I$(top_builddir) lib_LTLIBRARIES = libsocket++.la libsocket___la_SOURCES = sockstream.cpp sockstream.h \ sockinet.cpp sockinet.h \ sockunix.cpp sockunix.h\ pipestream.cpp pipestream.h \ fork.cpp fork.h \ protocol.cpp protocol.h \ echo.cpp echo.h \ smtp.cpp smtp.h \ ftp.cpp ftp.h \ sig.cpp sig.h libsocketincludedir=$(includedir)/socket++ libsocketinclude_HEADERS = \ sockstream.h \ sockinet.h \ sockunix.h\ pipestream.h \ fork.h \ protocol.h \ echo.h \ smtp.h \ ftp.h \ sig.h libsocket___la_LDFLAGS = -version-info @LIBSOCKET_SO_VERSION@ libsocket___la_LIBADD = socket++-1.12.13/socket++/protocol.cpp0000644000175000017500000000266711676325304015444 0ustar stbstb// protocol.h -*- C++ -*- socket library // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #include #include #ifdef WIN32 # define EPROTONOSUPPORT WSAEPROTONOSUPPORT #endif const char* protocol::protocolbuf::protocol_name () const { char* ret = ""; if (pn == protocol::tcp) ret = "tcp"; if (pn == protocol::udp) ret = "udp"; return ret; } void protocol::protocolbuf::connect () { if (pn == protocol::nil) throw sockerr (EPROTONOSUPPORT); sockinetbuf::connect (localhost (), rfc_name (), protocol_name ()); } void protocol::protocolbuf::connect (unsigned long addr) // addr is in host byte order { if (pn == protocol::nil) throw sockerr (EPROTONOSUPPORT); sockinetbuf::connect (addr, rfc_name (), protocol_name ()); } void protocol::protocolbuf::connect (const char* host) { if (pn == protocol::nil) throw sockerr (EPROTONOSUPPORT); sockinetbuf::connect (host, rfc_name (), protocol_name ()); } void protocol::protocolbuf::connect (const char* host, int portno) { if (pn == protocol::nil) throw sockerr (EPROTONOSUPPORT); sockinetbuf::connect (host, portno); } socket++-1.12.13/socket++/echo.cpp0000644000175000017500000000270511676325304014512 0ustar stbstb// echo.C -*- C++ -*- socket library // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 using namespace std; #include #include #include #include void echo::echobuf::serve_clients (int portno) { if (protocol_name ()) { if (portno < 0) sockinetbuf::bind ((unsigned long) INADDR_ANY, "echo", protocol_name ()); else if (portno <= 1024) { sockinetbuf::bind (); cout << "Host: " << localhost () << endl << "Port: " << localport () << endl; } else sockinetbuf::bind ((unsigned long) INADDR_ANY, portno); // act as a server now listen (sockbuf::somaxconn); // commit suicide when we receive SIGTERM Fork::suicide_signal (SIGTERM); for (;;) { sockbuf s = accept (); Fork f (1, 1); // kill my children when I get terminated. if (f.is_child ()) { char buf [1024]; int rcnt; while ((rcnt = s.read (buf, 1024)) > 0) while (rcnt != 0) { int wcnt = s.write (buf, rcnt); if (wcnt == -1) throw sockerr (errno); rcnt -= wcnt; } sleep (300); exit (0); } } } } socket++-1.12.13/socket++/local.h0000644000175000017500000000575211676325304014340 0ustar stbstb#ifdef _WIN32 # include # include #else #ifdef _S_LIBGXX # include # include # include #else # include # include # include #endif EXTERN_C_BEGIN #ifdef HAVE_STRING_H # include #else # ifdef HAVE_MEMORY_H # include # endif #endif #ifdef _ALL_SOURCE # define _BSD 44 // AIX # include # ifndef _POSIX_SOURCE # define _POSIX_SOURCE # endif # undef _ALL_SOURCE #endif #include #ifdef HAVE_SYS_WAIT # include #endif #include #include #ifndef SA_RESTART # define SA_RESTART 0 #endif EXTERN_C_END #if defined (__sun__) && !defined (__svr4__) && defined (_S_LIBGXX) // libg++-2.6.x has stopped providing prototypes for the following // for sunos 4.1.x extern "C" { int socketpair (int domain, int typ, int protocol, int* sockpair); int socket (int domain, int typ, int protocol); int bind (int sock, void* addr, int addrlen); int connect (int sock, void* addr, int addrlen); int listen (int sock, int num); int accept (int sock, void* addr, int* addrlen); int recv (int sock, void* buf, int buflen, int msgflag); int recvfrom (int sock, void* buf, int buflen, int msgflag, void* addr, int* addrlen); int send (int sock, void* buf, int buflen, int msgflag); int sendto (int sock, void* buf, int buflen, int msgflag, void* addr, int addrlen); int recvmsg (int sock, struct msghdr* msg, int msgflag); int sendmsg (int sock, struct msghdr* msg, int msgflag); int select (int sock, void* rd, void* wr, void* ex, struct timeval* tv); int getsockopt (int sock, int level, int option, void* val, int* vallen); int setsockopt (int sock, int level, int option, void* val, int vallen); int getsockname (int sock, void* addr, int* addrlen); int getpeername (int sock, void* addr, int* addrlen); int ioctl (int sock, int flag, void* arg); pid_t vfork (); } #endif #if !defined (__linux__) // LN extern "C" int shutdown (int, int); // they have forgotten this #endif // does not have a prototype for inet_addr () and gethostname() extern "C" unsigned long inet_addr (const char*); // arpa/in.h does not provide a protype for the following extern "C" char* inet_ntoa (in_addr ina); #if !(defined (__linux__) || defined(__FreeBSD__)) extern "C" int gethostname (char* hostname, int len); #if !(defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__APPLE__)) extern char* SYS_SIGLIST []; #endif #endif #ifdef __osf__ extern "C" { int select (int, fd_set*, fd_set*, fd_set*, timeval*); unsigned short ntohs (unsigned short); unsigned short htons (unsigned short); unsigned long ntohl (unsigned long); unsigned long htonl (unsigned long); } #endif #ifndef SYS_ERRLIST_DECLARED extern char* SYS_ERRLIST []; #endif #undef SYS_ERRLIST_DECLARED typedef RETSIGTYPE (*sighnd) (SIGHND_ARGTYPE); #endif // WIN32 socket++-1.12.13/socket++/sockunix.h0000644000175000017500000000505511676325304015105 0ustar stbstb// sockunix.h -*- C++ -*- socket library // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #ifndef _SOCKUNIX_H #define _SOCKUNIX_H #include #include class sockunixaddr: public sockAddr, public sockaddr_un { public: ~sockunixaddr () {} sockunixaddr (const char* path); sockunixaddr (const sockunixaddr& suna); operator void* () const { return addr_un (); } sockaddr_un* addr_un () const { return (sockaddr_un*)this; } int size () const { return sizeof (sockaddr_un); } int family () const { return sun_family; } sockaddr* addr() const {return (sockaddr*) addr_un (); } }; class sockunixbuf: public sockbuf { public: enum domain { af_unix = AF_UNIX }; sockunixbuf (const sockbuf::sockdesc& sd); sockunixbuf (const sockunixbuf& su); sockunixbuf (sockbuf::type ty, int proto=0); // sockunixbuf& operator = (const sockunixbuf& su); ~sockunixbuf () {} virtual void bind (sockAddr& sa); void bind (const char* path); virtual void connect (sockAddr& sa); void connect (const char* path); }; class isockunix: public isockstream { public: isockunix (const sockbuf::sockdesc& sd); isockunix (const sockunixbuf& sb); isockunix (sockbuf::type ty=sockbuf::sock_stream, int proto=0); ~isockunix(); sockunixbuf* operator -> () { return (sockunixbuf*)rdbuf (); } }; class osockunix: public osockstream { public: osockunix (const sockbuf::sockdesc& sd); osockunix (const sockunixbuf& sb); osockunix (sockbuf::type ty=sockbuf::sock_stream, int proto=0); ~osockunix (); sockunixbuf* operator -> () { return (sockunixbuf*)rdbuf (); } }; class iosockunix: public iosockstream { public: iosockunix (const sockbuf::sockdesc& sd); iosockunix (const sockunixbuf& sb); iosockunix (sockbuf::type ty=sockbuf::sock_stream, int proto=0); ~iosockunix (); sockunixbuf* operator -> () { return (sockunixbuf*)rdbuf (); } }; #endif // _SOCKUNIX_H socket++-1.12.13/socket++/echo.h0000644000175000017500000000233711676325304014160 0ustar stbstb// echo.h -*- C++ -*- socket library // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #ifndef ECHO_H #define ECHO_H #include class echo: public protocol { public: class echobuf: public protocol::protocolbuf { public: echobuf (sockinetbuf& si): protocol::protocolbuf (si) {} echobuf (protocol::p_name pname) : protocol::protocolbuf (pname) {} virtual void serve_clients (int portno = -1); virtual const char* rfc_name () const { return "echo"; } virtual const char* rfc_doc () const { return "rfc862"; } }; protected: echo (): std::ios(0) {} public: echo (protocol::p_name pname) : std::ios (0) { std::ios::init (new echobuf (pname)); } ~echo () { delete std::ios::rdbuf (); std::ios::init (0); } echobuf* rdbuf () { return (echobuf*) protocol::rdbuf (); } echobuf* operator -> () { return rdbuf (); } }; #endif // !ECHO_H socket++-1.12.13/socket++/protocol.h0000644000175000017500000000305611676325304015102 0ustar stbstb// protocol.h -*- C++ -*- socket library // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #ifndef PROTOCOL_H #define PROTOCOL_H #include class protocol: public iosockstream { public: enum p_name { nil = 0, tcp = sockbuf::sock_stream, udp = sockbuf::sock_dgram }; class protocolbuf: public sockinetbuf { private: p_name pn; void bind (sockAddr& sa) { sockbuf::bind (sa); } void connect (sockAddr& sa) { sockbuf::connect (sa); } public: protocolbuf (sockinetbuf& si): sockinetbuf (si), pn (protocol::nil) {} protocolbuf (p_name pname) : sockinetbuf ((sockbuf::type) pname, 0), pn (pname) {} void bind () { serve_clients (); } void connect (); void connect (unsigned long addr); void connect (const char* host); void connect (const char* host, int portno); const char* protocol_name () const; virtual void serve_clients (int portno = -1) = 0; virtual const char* rfc_name () const = 0; virtual const char* rfc_doc () const = 0; }; protocol (): std::ios (0), iosockstream(NULL) {} // NULL seems like a very bad idea }; #endif // PROTOCOL_H socket++-1.12.13/socket++/sig.h0000644000175000017500000000626711676325304014032 0ustar stbstb// socket++ library. sig.h // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. #ifndef SIG_H #define SIG_H #include #include #include #include // all signal handlers must be derived from // class sig::hnd. class signal will // maintain a list of pointers to sig::hnd // objects for a signal. If a signal occurs, // all sig::hnds associated with the // signal are invoked. // sig::hnd object will insert itself into // the signal handler list for a signo. Its // dtor will delete the signal handler object // from the signal handler list for a signo. // Thus if a user wants to add a signal handler, // all that needs to be done is to simply // instantiate the signal handler object, // and if the user wants to remove the signal // handler, all that needs to done is to // delete the object and its dtor will remove // itself from the signal handler list. // Note: you cannot mix sig with other means // of setting signal handlers. class sig; class siginit; class sigerr {}; class sig { public: friend class siginit; class hnd { int signo; public: hnd (int signo); virtual ~hnd (); virtual void operator () (int s) = 0; }; typedef hnd* phnd; typedef std::list phndlist; typedef std::map > sigmap; private: sigmap smap; sig () {} ~sig () {} public: // add signal handler h for signal signo // return true on success. false otherwise. bool set (int signo, hnd* h); // remove signal handler h for signal signo // return true on success. false otherwise. // Note: the user needs to delete h. bool unset (int signo, hnd* h); // remove all signal handers for signal signo void unset (int signo); // mask signal signo. Prevent signo from being seen // by our process. Note: not all signals can be // blocked. void mask (int signo) const; // block signal signo_b when inside a signo_a handler // Note: the process will see signo_b once signo_a handler // is finished void mask (int signo_a, int signo_b) const; // unmask signal signo. Enable signo to be seen by // our process. void unmask (int signo) const; // unblock signal signo_b when inside a signo_a handler void unmask (int signo_a, int signo_b) const; // is signal signo pending? bool ispending (int signo) const; // set of signals pending sigset_t pending () const; // make some system calls to terminate after they are // interrupted (set == false). Otherwise resume system // call (set == true). Not available on all systems. void sysresume (int signo, bool set) const; // process a software signal signo void kill (int signo); static sig& nal; // sig::nal is the only object of class sig }; class siginit { friend class sig; static siginit init; sig* s; public: siginit (): s (0) { if (this == &init) s = new sig; } ~siginit () { if (this == &init) delete s; } }; #endif // SIG_H socket++-1.12.13/socket++/smtp.h0000644000175000017500000000453511676325304014227 0ustar stbstb// smtp.h -*- C++ -*- socket library // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #ifndef SMTP_H #define SMTP_H #include class smtp: public protocol { public: class smtpbuf : public protocol::protocolbuf { std::ostream* o; // send all the responses to o void send_cmd (const char* cmd, const char* s = 0, const char* p = 0); void get_response (); smtpbuf (smtpbuf&); smtpbuf& operator = (smtpbuf&); public: smtpbuf (std::ostream* out = 0) : protocol::protocolbuf (protocol::tcp), o (out) {} void send_buf (const char* buf, int buflen); void helo (); void quit () { send_cmd ("QUIT"); } void turn () { send_cmd ("TURN"); } void rset () { send_cmd ("RSET"); } void noop () { send_cmd ("NOOP"); } void vrfy (const char* s) { send_cmd ("VRFY ", s); } void expn (const char* s) { send_cmd ("EXPN ", s); } void data () { send_cmd ("DATA"); } void data (const char* buf, int buflen); void data (const char* filename); // filename = 0 => stdin void mail (const char* reverse_path); void rcpt (const char* forward_path); void help (const char* s = 0); virtual void serve_clients (int portno = -1); virtual const char* rfc_name () const { return "smtp"; } virtual const char* rfc_doc () const { return "rfc821"; } }; protected: smtp(): std::ios (0) {} public: smtp (std::ostream* out): std::ios (0) { std::ios::init (new smtpbuf (out)); } ~smtp () { delete std::ios::rdbuf (); std::ios::init (0); } int get_response (char* buf, int len); smtpbuf* rdbuf () { return (smtpbuf*) protocol::rdbuf (); } smtpbuf* operator -> () { return rdbuf (); } }; extern std::ostream& operator << (std::ostream& o, smtp& s); #endif // SMTP_H socket++-1.12.13/socket++/fork.cpp0000644000175000017500000001031411676325304014530 0ustar stbstb// Fork.C -*- C++ -*- socket library // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #include #include #include // perror in solaris2.3 is declared here #include #include #include #include #include #include using std::cerr; using std::endl; Fork::ForkProcess* Fork::ForkProcess::list = 0; Fork::KillForks Fork::killall; Fork::~Fork () { if (process->pid <= 0) delete process; } Fork::KillForks::~KillForks () // First, kill all children whose kill_child flag is set. // Second, wait for other children to die. { for (ForkProcess* cur = Fork::ForkProcess::list; cur; cur = cur->next) if (cur->kill_child) delete cur; while (Fork::ForkProcess::list && wait (0) > 0); } Fork::ForkProcess::ForkProcess (bool kill, bool give_reason) : kill_child (kill), reason (give_reason), next (0) { if (list == 0) { struct sigaction sa; sa.sa_handler = (void(*)(int)) sighnd (&Fork::ForkProcess::reaper_nohang); sigemptyset (&sa.sa_mask); sa.sa_flags = SA_RESTART; sigaction (SIGCHLD, &sa, 0); } pid = fork (); if (pid > 0) { next = list; list = this; } else if (pid == 0) { // child process. clear list ForkProcess* p = list; while (p) { ForkProcess* nxt = p->next; p->pid = 0; delete p; p = nxt; } list = 0; if (kill_child) { struct sigaction sa; sa.sa_handler = (void(*)(int)) sighnd (&Fork::ForkProcess::commit_suicide); sigemptyset (&sa.sa_mask); sa.sa_flags = SA_RESTART; sigaction (SIGTERM, &sa, 0); } } } Fork::ForkProcess::~ForkProcess () { if (pid > 0) { if (kill_child) kill (pid, SIGTERM); reap_child (); // I remove myself from list if (list == this) list = list->next; else { for (ForkProcess* p = list; p; p = p->next) if (p->next == this) { p->next = next; break; } } } } void Fork::ForkProcess::kill_process () const { if (pid > 0) { kill (pid, SIGKILL); reap_child (); } } void Fork::ForkProcess::reap_child () const { int status; if (pid > 0 && waitpid (pid, &status, 0) == pid && reason) infanticide_reason (pid, status); } void Fork::ForkProcess::infanticide_reason (pid_t pid, int status) { if (pid <= 0) return; if (WIFSTOPPED (status)) cerr << "process " << pid << " gets " << SYS_SIGLIST [WSTOPSIG (status)] << endl; else if (WIFEXITED (status)) cerr << "process " << pid << " exited with status " << WEXITSTATUS (status) << endl; else if (WIFSIGNALED (status)) cerr << "process " << pid << " got " << SYS_SIGLIST [WTERMSIG (status)] << endl; } void Fork::ForkProcess::reaper_nohang (int signo) { if (signo != SIGCHLD) return; int status; pid_t wpid; if ((wpid = waitpid (-1, &status, WNOHANG)) > 0) { ForkProcess* prev = 0; ForkProcess* cur = list; while (cur) { if (cur->pid == wpid) { cur->pid = -1; if (prev) prev->next = cur->next; else list = list->next; if (cur->reason) infanticide_reason (wpid, status); delete cur; break; } prev = cur; cur = cur->next; } } } void Fork::ForkProcess::commit_suicide (int) { // if this process has any children we kill them. ForkProcess* p = list; while (p) { ForkProcess* next = p->next; if (!p->kill_child) // otherwise ForkProcess::~ForkProcess will take care kill (p->pid, SIGKILL); delete p; // ForkProcess::~ForkProcess will call reap_child (). p = next; } exit (0x0f); } void Fork::suicide_signal (int signo) // commit suicide at the signal signo { struct sigaction sa; sa.sa_handler = (void(*)(int)) sighnd (&Fork::ForkProcess::commit_suicide); sigemptyset (&sa.sa_mask); sa.sa_flags = 0; if (sigaction (signo, &sa, 0) == -1) perror ("Fork: Cannot commit suicide with the specified signal"); } socket++-1.12.13/socket++/sockstream.cpp0000644000175000017500000005650311676325455015763 0ustar stbstb// sockstream.C -*- C++ -*- socket library // Copyright (C) 2002 Herbert Straub for my changes, see ChangeLog. // // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 // // You can simultaneously read and write into // a sockbuf just like you can listen and talk // through a telephone. Hence, the read and the // write buffers are different. That is, they do not // share the same memory. // // Read: // gptr() points to the start of the get area. // The unread chars are gptr() - egptr(). // base() points to the read buffer // // eback() is set to base() so that pbackfail() // is called only when there is no place to // putback a char. And pbackfail() always returns EOF. // // Write: // pptr() points to the start of the put area // The unflushed chars are pbase() - pptr() // pbase() points to the write buffer. // epptr() points to the end of the write buffer. // // Output is flushed whenever one of the following conditions // holds: // (1) pptr() == epptr() // (2) EOF is written // (3) linebuffered and '\n' is written // // Unbuffered: // Input buffer size is assumed to be of size 1 and output // buffer is of size 0. That is, egptr() <= base()+1 and // epptr() == pbase(). // // Version: 1.2 2002-07-25 Herbert Straub // Improved Error Handling - extending the sockerr class by cOperation using namespace std; #include #include #ifdef HAVE_SSTREAM #include #else #include #endif #include #if defined(__APPLE__) #typedef int socklen_t; #endif #ifndef WIN32 EXTERN_C_BEGIN # include # include # include # include # include EXTERN_C_END #else # define socklen_t int # define EWOULDBLOCK WSAEWOULDBLOCK # define EINPROGRESS WSAEINPROGRESS # define EALREADY WSAEALREADY # define ENOTSOCK WSAENOTSOCK # define EDESTADDRREQ WSAEDESTADDRREQ # define EMSGSIZE WSAEMSGSIZE # define EPROTOTYPE WSAEPROTOTYPE # define ENOPROTOOPT WSAENOPROTOOPT # define EPROTONOSUPPORT WSAEPROTONOSUPPORT # define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT # define EOPNOTSUPP WSAEOPNOTSUPP # define EPFNOSUPPORT WSAEPFNOSUPPORT # define EAFNOSUPPORT WSAEAFNOSUPPORT # define EADDRINUSE WSAEADDRINUSE # define EADDRNOTAVAIL WSAEADDRNOTAVAIL # define ENETDOWN WSAENETDOWN # define ENETUNREACH WSAENETUNREACH # define ENETRESET WSAENETRESET # define ECONNABORTED WSAECONNABORTED # define ECONNRESET WSAECONNRESET # define ENOBUFS WSAENOBUFS # define EISCONN WSAEISCONN # define ENOTCONN WSAENOTCONN # define ESHUTDOWN WSAESHUTDOWN # define ETOOMANYREFS WSAETOOMANYREFS # define ETIMEDOUT WSAETIMEDOUT # define ECONNREFUSED WSAECONNREFUSED # define ELOOP WSAELOOP # define EHOSTDOWN WSAEHOSTDOWN # define EHOSTUNREACH WSAEHOSTUNREACH # define EPROCLIM WSAEPROCLIM # define EUSERS WSAEUSERS # define EDQUOT WSAEDQUOT # define EISCONN WSAEISCONN # define ENOTCONN WSAENOTCONN # define ECONNRESET WSAECONNRESET # define ECONNREFUSED WSAECONNREFUSED # define ETIMEDOUT WSAETIMEDOUT # define EADDRINUSE WSAEADDRINUSE # define EADDRNOTAVAIL WSAEADDRNOTAVAIL # define EWOULDBLOCK WSAEWOULDBLOCK #endif // !WIN32 #ifndef BUFSIZ # define BUFSIZ 1024 #endif #ifdef FD_ZERO # undef FD_ZERO // bzero causes so much trouble to us #endif #define FD_ZERO(p) (memset ((p), 0, sizeof *(p))) const char* sockerr::errstr () const { #ifndef WIN32 return SYS_ERRLIST [err]; #else return 0; // TODO #endif } bool sockerr::io () const // recoverable io error. { switch (err) { case EWOULDBLOCK: case EINPROGRESS: case EALREADY: return true; } return false; } bool sockerr::arg () const // recoverable argument error. { switch (err) { case ENOTSOCK: case EDESTADDRREQ: case EMSGSIZE: case EPROTOTYPE: case ENOPROTOOPT: case EPROTONOSUPPORT: case ESOCKTNOSUPPORT: case EOPNOTSUPP: case EPFNOSUPPORT: case EAFNOSUPPORT: case EADDRINUSE: case EADDRNOTAVAIL: return true; } return false; } bool sockerr::op () const // operational error encountered { switch (err) { case ENETDOWN: case ENETUNREACH: case ENETRESET: case ECONNABORTED: case ECONNRESET: case ENOBUFS: case EISCONN: case ENOTCONN: case ESHUTDOWN: case ETOOMANYREFS: case ETIMEDOUT: case ECONNREFUSED: case ELOOP: case ENAMETOOLONG: case EHOSTDOWN: case EHOSTUNREACH: case ENOTEMPTY: # if !defined(__linux__) // LN case EPROCLIM: # endif case EUSERS: case EDQUOT: return true; } return false; } bool sockerr::conn () const // return true if err is EISCONN, ENOTCONN, ECONNRESET, ECONNREFUSED, // ETIMEDOUT, or EPIPE { switch (err) { case EISCONN: case ENOTCONN: case ECONNRESET: case ECONNREFUSED: case ETIMEDOUT: case EPIPE: return true; } return false; } bool sockerr::addr () const // return true if err is EADDRINUSE or EADDRNOTAVAIL { switch (err) { case EADDRINUSE: case EADDRNOTAVAIL: return true; } return false; } bool sockerr::benign () const // return true if err is EINTR, EWOULDBLOCK, or EAGAIN { switch (err) { case EINTR: case EWOULDBLOCK: // On FreeBSD (and probably on Linux too) // EAGAIN has the same value as EWOULDBLOCK #if !defined(__linux__) && !(defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__APPLE__)) // LN case EAGAIN: #endif return true; } return false; } sockbuf::sockbuf (const sockbuf::sockdesc& sd) // : rep (new sockbuf::sockcnt (sd.sock)) { rep = new sockbuf::sockcnt (sd.sock); char_type* gbuf = new char_type [BUFSIZ]; char_type* pbuf = new char_type [BUFSIZ]; setg (gbuf, gbuf + BUFSIZ, gbuf + BUFSIZ); setp (pbuf, pbuf + BUFSIZ); rep->gend = gbuf + BUFSIZ; rep->pend = pbuf + BUFSIZ; } sockbuf::sockbuf (int domain, sockbuf::type st, int proto) : rep (0) { SOCKET soc = ::socket (domain, st, proto); if (soc == SOCKET_ERROR) #ifndef WIN32 throw sockerr (errno, "sockbuf::sockbuf"); #else throw sockerr(WSAGetLastError(), "sockbuf::sockbuf"); #endif rep = new sockbuf::sockcnt (soc); char_type* gbuf = new char_type [BUFSIZ]; char_type* pbuf = new char_type [BUFSIZ]; setg (gbuf, gbuf + BUFSIZ, gbuf + BUFSIZ); setp (pbuf, pbuf + BUFSIZ); rep->gend = gbuf + BUFSIZ; rep->pend = pbuf + BUFSIZ; } sockbuf::sockbuf (const sockbuf& sb) : //streambuf (sb), rep (sb.rep) { // the streambuf::streambuf (const streambuf&) is assumed // to haved handled pbase () and gbase () correctly. rep->cnt++; } /*sockbuf& sockbuf::operator = (const sockbuf& sb) { if (this != &sb && rep != sb.rep && rep->sock != sb.rep->sock) { streambuf::operator = (sb); this->sockbuf::~sockbuf(); // the streambuf::operator = (const streambuf&) is assumed // to have handled pbase () and gbase () correctly. rep = sb.rep; rep->cnt++; } return *this; }*/ sockbuf::~sockbuf () { overflow (eof); // flush write buffer if (--rep->cnt == 0) { delete [] pbase (); delete [] eback (); #ifndef WIN32 int c = close (rep->sock); #else int c = closesocket(rep->sock); #endif delete rep; if (c == SOCKET_ERROR) #ifndef WIN32 throw sockerr (errno, "sockbuf::~sockbuf", sockname.c_str()); #else throw sockerr(WSAGetLastError(), "sockbuf::~sockbuf", sockname.c_str()); #endif } } bool sockbuf::is_open () const // if socket is still connected to the peer, return true // else return false { return false; } int sockbuf::sync () // we never return -1 because we throw sockerr // exception in the event of an error. { if (pptr () && pbase () < pptr () && pptr () <= epptr ()) { // we have some data to flush try { write (pbase (), pptr () - pbase ()); } catch (int wlen) { // write was not completely successful #ifdef HAVE_SSTREAM stringstream sb; #else strstream sb; #endif string err ("sockbuf::sync"); err += "(" + sockname + ")"; if (wlen) { // reposition unwritten chars char* pto = pbase (); char* pfrom = pbase () + wlen; int len = pptr () - pbase () - wlen; while (pfrom < pptr ()) *pto++ = *pfrom++; setp (pbase (), (char_type*) rep->pend); pbump (len); sb << " wlen=(" << wlen << ")"; err += sb.rdbuf()->str(); } throw sockerr (errno, err.c_str ()); } setp (pbase (), (char_type*) rep->pend); } // we cannot restore input data back to the socket stream // thus we do not do anything on the input stream return 0; } int sockbuf::showmanyc () const // return the number of chars in the input sequence { if (gptr () && gptr () < egptr ()) return egptr () - gptr (); return 0; } sockbuf::int_type sockbuf::underflow () { if (gptr () == 0) return eof; // input stream has been disabled if (gptr () < egptr ()) return (unsigned char) *gptr (); // eof is a -ve number; make it // unsigned to be diff from eof int rlen = read (eback (), (char*) rep->gend - (char*) eback ()); if (rlen == 0) return eof; setg (eback (), eback (), eback () + rlen); return (unsigned char) *gptr (); } sockbuf::int_type sockbuf::uflow () { int_type ret = underflow (); if (ret == eof) return eof; gbump (1); return ret; } streamsize sockbuf::xsgetn (char_type* s, streamsize n) { int rval = showmanyc (); if (rval >= n) { memcpy (s, gptr (), n * sizeof (char_type)); gbump (n); return n; } memcpy (s, gptr (), rval * sizeof (char_type)); gbump (rval); if (underflow () != eof) return rval + xsgetn (s + rval, n - rval); return rval; } sockbuf::int_type sockbuf::pbackfail (int c) { return eof; } sockbuf::int_type sockbuf::overflow (sockbuf::int_type c) // if pbase () == 0, no write is allowed and thus return eof. // if c == eof, we sync the output and return 0. // if pptr () == epptr (), buffer is full and thus sync the output, // insert c into buffer, and return c. // In all cases, if error happens, throw exception. { if (pbase () == 0) return eof; if (c == eof) return sync (); if (pptr () == epptr ()) sync (); *pptr () = (char_type)c; pbump (1); return c; } streamsize sockbuf::xsputn (const char_type* s, streamsize n) { int wval = epptr () - pptr (); if (n <= wval) { memcpy (pptr (), s, n * sizeof (char_type)); pbump (n); return n; } memcpy (pptr (), s, wval * sizeof (char_type)); pbump (wval); if (overflow () != eof) return wval + xsputn (s + wval, n - wval); return wval; } void sockbuf::bind (sockAddr& sa) { if (::bind (rep->sock, sa.addr (), sa.size ()) == -1) throw sockerr (errno, "sockbuf::bind", sockname.c_str()); } void sockbuf::connect (sockAddr& sa) { if (::connect(rep->sock, sa.addr (), sa.size()) == -1) throw sockerr (errno, "sockbuf::connect", sockname.c_str()); } void sockbuf::listen (int num) { if (::listen (rep->sock, num) == -1) throw sockerr (errno, "sockbuf::listen", sockname.c_str()); } sockbuf::sockdesc sockbuf::accept (sockAddr& sa) { int len = sa.size (); int soc = -1; if ((soc = ::accept (rep->sock, sa.addr (), (socklen_t*) // LN &len)) == -1) throw sockerr (errno, "sockbuf::sockdesc", sockname.c_str()); return sockdesc (soc); } sockbuf::sockdesc sockbuf::accept () { int soc = -1; if ((soc = ::accept (rep->sock, 0, 0)) == -1) throw sockerr (errno, "sockbuf::sockdesc", sockname.c_str()); return sockdesc (soc); } int sockbuf::read (void* buf, int len) { if (rep->rtmo != -1 && is_readready (rep->rtmo)==0) { throw sockerr (ETIMEDOUT, "sockbuf::read", sockname.c_str()); } if (rep->oob && atmark ()) throw sockoob (); int rval = 0; if ((rval = ::read (rep->sock, (char*) buf, len)) == -1) throw sockerr (errno, "sockbuf::read", sockname.c_str()); return rval; } int sockbuf::recv (void* buf, int len, int msgf) { if (rep->rtmo != -1 && is_readready (rep->rtmo)==0) throw sockerr (ETIMEDOUT, "sockbuf::recv", sockname.c_str()); if (rep->oob && atmark ()) throw sockoob (); int rval = 0; if ((rval = ::recv (rep->sock, (char*) buf, len, msgf)) == -1) throw sockerr (errno, "sockbuf::recv", sockname.c_str()); return rval; } int sockbuf::recvfrom (sockAddr& sa, void* buf, int len, int msgf) { if (rep->rtmo != -1 && is_readready (rep->rtmo)==0) throw sockerr (ETIMEDOUT, "sockbuf::recvfrom", sockname.c_str()); if (rep->oob && atmark ()) throw sockoob (); int rval = 0; int sa_len = sa.size (); if ((rval = ::recvfrom (rep->sock, (char*) buf, len, msgf, sa.addr (), (socklen_t*) // LN &sa_len)) == -1) throw sockerr (errno, "sockbuf::recvfrom", sockname.c_str()); return rval; } int sockbuf::write(const void* buf, int len) // upon error, write throws the number of bytes writen so far instead // of sockerr. { char *pbuf = (char*) buf; if (rep->stmo != -1 && is_writeready (rep->stmo)==0) throw sockerr (ETIMEDOUT, "sockbuf::write", sockname.c_str()); int wlen=0; while(len>0) { int wval = ::write (rep->sock, pbuf+wlen, len); if (wval == -1) throw wlen; len -= wval; wlen += wval; } return wlen; // == len if every thing is all right } int sockbuf::send (const void* buf, int len, int msgf) // upon error, write throws the number of bytes writen so far instead // of sockerr. { char *pbuf = (char *) buf; if (rep->stmo != -1 && is_writeready (rep->stmo)==0) throw sockerr (ETIMEDOUT, "sockbuf::send", sockname.c_str()); int wlen=0; while(len>0) { int wval = ::send (rep->sock, pbuf+wlen, len, msgf); if (wval == -1) throw wlen; len -= wval; wlen += wval; } return wlen; } int sockbuf::sendto (sockAddr& sa, const void* buf, int len, int msgf) // upon error, write throws the number of bytes writen so far instead // of sockerr. { char *pbuf = (char *) buf; if (rep->stmo != -1 && is_writeready (rep->stmo)==0) throw sockerr (ETIMEDOUT, "sockbuf::sendto", sockname.c_str()); int wlen=0; while(len>0) { int wval = ::sendto (rep->sock, pbuf+wlen, len, msgf, sa.addr (), sa.size()); if (wval == -1) throw wlen; len -= wval; wlen += wval; } return wlen; } #if !defined(__linux__) && !defined(WIN32) // does not have sendmsg or recvmsg int sockbuf::recvmsg (msghdr* msg, int msgf) { if (rep->rtmo != -1 && is_readready (rep->rtmo)==0) throw sockerr (ETIMEDOUT, "sockbuf::recvmsg", sockname.c_str()); if (rep->oob && atmark ()) throw sockoob (); int rval = ::recvmsg(rep->sock, msg, msgf); if (rval == -1) throw sockerr (errno, "sockbuf::recvmsg", sockname.c_str()); return rval; } int sockbuf::sendmsg (msghdr* msg, int msgf) // upon error, write throws the number of bytes writen so far instead // of sockerr. { if (rep->stmo != -1 && is_writeready (rep->stmo)==0) throw sockerr (ETIMEDOUT, "sockbuf::sendmsg", sockname.c_str()); int wlen = ::sendmsg (rep->sock, msg, msgf); if (wlen == -1) throw 0; return wlen; } #endif // !__linux__ && !WIN32 int sockbuf::sendtimeout (int wp) { int oldstmo = rep->stmo; rep->stmo = (wp < 0) ? -1: wp; return oldstmo; } int sockbuf::recvtimeout (int wp) { int oldrtmo = rep->rtmo; rep->rtmo = (wp < 0) ? -1: wp; return oldrtmo; } int sockbuf::is_readready (int wp_sec, int wp_usec) const { fd_set fds; FD_ZERO (&fds); FD_SET (rep->sock, &fds); timeval tv; tv.tv_sec = wp_sec; tv.tv_usec = wp_usec; int ret = select (rep->sock+1, &fds, 0, 0, (wp_sec == -1) ? 0: &tv); if (ret == -1) throw sockerr (errno, "sockbuf::is_readready", sockname.c_str()); return ret; } int sockbuf::is_writeready (int wp_sec, int wp_usec) const { fd_set fds; FD_ZERO (&fds); FD_SET (rep->sock, &fds); timeval tv; tv.tv_sec = wp_sec; tv.tv_usec = wp_usec; int ret = select (rep->sock+1, 0, &fds, 0, (wp_sec == -1) ? 0: &tv); if (ret == -1) throw sockerr (errno, "sockbuf::is_writeready", sockname.c_str()); return ret; } int sockbuf::is_exceptionpending (int wp_sec, int wp_usec) const { fd_set fds; FD_ZERO (&fds); FD_SET (rep->sock, &fds); timeval tv; tv.tv_sec = wp_sec; tv.tv_usec = wp_usec; int ret = select (rep->sock+1, 0, 0, &fds, (wp_sec == -1) ? 0: &tv); if (ret == -1) throw sockerr (errno, "sockbuf::is_exceptionpending", sockname.c_str()); return ret; } void sockbuf::shutdown (shuthow sh) { switch (sh) { case shut_read: delete [] eback (); setg (0, 0, 0); break; case shut_write: delete [] pbase (); setp (0, 0); break; case shut_readwrite: shutdown (shut_read); shutdown (shut_write); break; } if (::shutdown(rep->sock, sh) == -1) throw sockerr (errno, "sockbuf::shutdown", sockname.c_str()); } int sockbuf::getopt (int op, void* buf, int len, int level) const { if (::getsockopt (rep->sock, level, op, (char*) buf, (socklen_t*) // LN &len) == -1) throw sockerr (errno, "sockbuf::getopt", sockname.c_str()); return len; } void sockbuf::setopt (int op, void* buf, int len, int level) const { if (::setsockopt (rep->sock, level, op, (char*) buf, len) == -1) throw sockerr (errno, "sockbuf::setopt", sockname.c_str()); } sockbuf::type sockbuf::gettype () const { int ty=0; getopt (so_type, &ty, sizeof (ty)); return sockbuf::type(ty); } int sockbuf::clearerror () const { int err=0; getopt (so_error, &err, sizeof (err)); return err; } bool sockbuf::debug () const { int old = 0; getopt (so_debug, &old, sizeof (old)); return old!=0; } bool sockbuf::debug (bool set) const { int old=0; int opt = set; getopt (so_debug, &old, sizeof (old)); setopt (so_debug, &opt, sizeof (opt)); return old!=0; } bool sockbuf::reuseaddr () const { int old = 0; getopt (so_reuseaddr, &old, sizeof (old)); return old!=0; } bool sockbuf::reuseaddr (bool set) const { int old=0; int opt = set; getopt (so_reuseaddr, &old, sizeof (old)); setopt (so_reuseaddr, &opt, sizeof (opt)); return old!=0; } bool sockbuf::keepalive () const { int old = 0; getopt (so_keepalive, &old, sizeof (old)); return old!=0; } bool sockbuf::keepalive (bool set) const { int old=0; int opt = set; getopt (so_keepalive, &old, sizeof (old)); setopt (so_keepalive, &opt, sizeof (opt)); return old!=0; } bool sockbuf::dontroute () const { int old = 0; getopt (so_dontroute, &old, sizeof (old)); return old!=0; } bool sockbuf::dontroute (bool set) const { int old = 0; int opt = set; getopt (so_dontroute, &old, sizeof (old)); setopt (so_dontroute, &opt, sizeof (opt)); return old!=0; } bool sockbuf::broadcast () const { int old=0; getopt (so_broadcast, &old, sizeof (old)); return old!=0; } bool sockbuf::broadcast (bool set) const { int old = 0; int opt = set; getopt (so_broadcast, &old, sizeof (old)); setopt (so_broadcast, &opt, sizeof (opt)); return old!=0; } bool sockbuf::oobinline () const { int old=0; getopt (so_oobinline, &old, sizeof (old)); return old!=0; } bool sockbuf::oobinline (bool set) const { int old = 0; int opt = set; getopt (so_oobinline, &old, sizeof (old)); setopt (so_oobinline, &opt, sizeof (opt)); return old!=0; } bool sockbuf::oob (bool b) { bool old = rep->oob; rep->oob = b; return old; } sockbuf::socklinger sockbuf::linger () const { socklinger old (0, 0); getopt (so_linger, &old, sizeof (old)); return old; } sockbuf::socklinger sockbuf::linger (sockbuf::socklinger opt) const { socklinger old (0, 0); getopt (so_linger, &old, sizeof (old)); setopt (so_linger, &opt, sizeof (opt)); return old; } int sockbuf::sendbufsz () const { int old=0; getopt (so_sndbuf, &old, sizeof (old)); return old; } int sockbuf::sendbufsz (int sz) const { int old=0; getopt (so_sndbuf, &old, sizeof (old)); setopt (so_sndbuf, &sz, sizeof (sz)); return old; } int sockbuf::recvbufsz () const { int old=0; getopt (so_rcvbuf, &old, sizeof (old)); return old; } int sockbuf::recvbufsz (int sz) const { int old=0; getopt (so_rcvbuf, &old, sizeof (old)); setopt (so_rcvbuf, &sz, sizeof (sz)); return old; } bool sockbuf::atmark () const // return true, if the read pointer for socket points to an // out of band data { #ifndef WIN32 int arg; if (::ioctl (rep->sock, SIOCATMARK, &arg) == -1) throw sockerr (errno, "sockbuf::atmark", sockname.c_str()); #else unsigned long arg = 0; if (::ioctlsocket(rep->sock, SIOCATMARK, &arg) == SOCKET_ERROR) throw sockerr (WSAGetLastError(), "sockbuf::atmark", sockname.c_str()); #endif // !WIN32 return arg!=0; } #ifndef WIN32 int sockbuf::pgrp () const // return the process group id that would receive SIGIO and SIGURG // signals { int arg; if (::ioctl (rep->sock, SIOCGPGRP, &arg) == -1) throw sockerr (errno, "sockbuf::pgrp", sockname.c_str()); return arg; } int sockbuf::pgrp (int new_pgrp) const // set the process group id that would receive SIGIO and SIGURG signals. // return the old pgrp { int old = pgrp (); if (::ioctl (rep->sock, SIOCSPGRP, &new_pgrp) == -1) throw sockerr (errno, "sockbuf::pgrp", sockname.c_str()); return old; } void sockbuf::closeonexec (bool set) const // if set is true, set close on exec flag // else clear close on exec flag { if (set) { if (::ioctl (rep->sock, FIOCLEX, 0) == -1) throw sockerr (errno, "sockbuf::closeonexec", sockname.c_str()); } else { if (::ioctl (rep->sock, FIONCLEX, 0) == -1) throw sockerr (errno, "sockbuf::closeonexec", sockname.c_str()); } } #endif // !WIN32 long sockbuf::nread () const // return how many chars are available for reading in the recvbuf of // the socket. { long arg; #ifndef WIN32 if (::ioctl (rep->sock, FIONREAD, &arg) == -1) throw sockerr (errno, "sockbuf::nread", sockname.c_str()); #else if (::ioctlsocket (rep->sock, FIONREAD, (unsigned long *) &arg) == SOCKET_ERROR) throw sockerr (WSAGetLastError(), "sockbuf::nread", sockname.c_str()); #endif // !WIN32 return arg; } long sockbuf::howmanyc () const // return how many chars are available for reading in the input buffer // and the recvbuf of the socket. { return showmanyc () + nread (); } void sockbuf::nbio (bool set) const // if set is true, set socket to non-blocking io. Henceforth, any // write or read operation will not wait if write or read would block. // The read or write operation will result throwing a sockerr // exception with errno set to EWOULDBLOCK. { #ifndef WIN32 int arg = set; if (::ioctl (rep->sock, FIONBIO, &arg) == -1) throw sockerr (errno, "sockbuf::nbio", sockname.c_str()); #else unsigned long arg = (set)?1:0; if (::ioctlsocket (rep->sock, FIONBIO, &arg) == -1) throw sockerr (WSAGetLastError(), "sockbuf::nbio", sockname.c_str()); #endif // !WIN32 } #ifndef WIN32 void sockbuf::async (bool set) const // if set is true, set socket for asynchronous io. If any io is // possible on the socket, the process will get SIGIO { int arg = set; if (::ioctl (rep->sock, FIOASYNC, &arg) == -1) throw sockerr (errno, "sockbuf::async", sockname.c_str()); } #endif // !WIN32 osockstream& crlf (osockstream& o) { o << "\r\n"; o.rdbuf ()->pubsync (); return o; } osockstream& lfcr (osockstream& o) { o << "\n\r"; o.rdbuf ()->pubsync (); return o; } socket++-1.12.13/socket++/fork.h0000644000175000017500000000322011676325304014173 0ustar stbstb// Fork.h -*- C++ -*- socket library // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #ifndef FORK_H #define FORK_H #include #include #include class Fork { public: class KillForks { public: KillForks () {} ~KillForks (); }; class ForkProcess { friend Fork::KillForks::~KillForks (); static void infanticide_reason (pid_t pid, int status); static void reaper_nohang (int); static ForkProcess* list; public: pid_t pid; const bool kill_child; const bool reason; ForkProcess* next; ForkProcess (bool kill, bool give_reason); ~ForkProcess (); void kill_process () const; void reap_child () const; static void commit_suicide (int); }; private: static KillForks killall; ForkProcess* process; Fork (Fork&); // no copy constructor definition provided Fork& operator = (Fork&); // no assignment operator definition provided public: Fork (bool kill = 0, bool reason = 0) : process (new ForkProcess (kill, reason)) {} ~Fork (); int is_child () const { return process->pid == 0; } int is_parent () const { return process->pid > 0; } int process_id () const { return process->pid; } static void suicide_signal (int signo = SIGTERM); }; #endif // FORK_H socket++-1.12.13/socket++/sockunix.cpp0000644000175000017500000000671611676325557015457 0ustar stbstb// sockunix.cpp -*- C++ -*- socket library // Copyright (C) 2002 Herbert Straub // // sockunix.C -*- C++ -*- socket library // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 // 2002-07-28 Version 1.2 (C) Herbert Straub // Eliminating sorry_about_global_temp inititialisation. This don't work // in combination with NewsCache. My idea is: initializing the classes with (0) // and in the second step call ios::init (sockinetbuf *) and iosockstream::init ... // The constructors of isockunix, osockunix and iosockunix are changed. using namespace std; #include #include #include sockunixaddr::sockunixaddr (const char* path) { sun_family = sockunixbuf::af_unix; ::strcpy (sun_path, path); } sockunixaddr::sockunixaddr (const sockunixaddr& suna) { sun_family = sockunixbuf::af_unix; ::strcpy (sun_path, suna.sun_path); } sockunixbuf::sockunixbuf (const sockbuf::sockdesc& sd) : sockbuf (sd.sock) {} sockunixbuf::sockunixbuf (const sockunixbuf& su) : sockbuf (su) {} sockunixbuf::sockunixbuf (sockbuf::type ty, int proto) : sockbuf (af_unix, ty, proto) {} /*sockunixbuf& sockunixbuf::operator = (const sockunixbuf& su) { sockbuf::operator = (su); return *this; }*/ void sockunixbuf::bind (sockAddr& sa) { sockbuf::bind (sa); } void sockunixbuf::bind (const char* path) { sockunixaddr sa (path); bind (sa); } void sockunixbuf::connect (sockAddr& sa) { sockbuf::connect (sa); } void sockunixbuf::connect (const char* path) { sockunixaddr sa (path); connect (sa); } isockunix::isockunix (const sockbuf::sockdesc& sd) : ios (0), isockstream(0) { sockunixbuf *t = new sockunixbuf (sd); ios::init (t); isockstream::init (t); } isockunix::isockunix (sockbuf::type ty, int proto) : ios (0), isockstream(0) { sockunixbuf *t = new sockunixbuf (ty, proto); ios::init (t); isockstream::init (t); } isockunix::isockunix (const sockunixbuf& sb) : ios (0), isockstream(0) { sockunixbuf *t = new sockunixbuf (sb); ios::init (t); isockstream::init (t); } isockunix::~isockunix () { delete ios::rdbuf (); } osockunix::osockunix (const sockbuf::sockdesc& sd) : ios (0), osockstream(0) { sockunixbuf *t = new sockunixbuf (sd); ios::init (t); osockstream::init (t); } osockunix::osockunix (sockbuf::type ty, int proto) : ios (0), osockstream(0) { sockunixbuf *t = new sockunixbuf (ty, proto); ios::init (t); osockstream::init (t); } osockunix::osockunix (const sockunixbuf& sb) : ios (0), osockstream(0) { sockunixbuf *t= new sockunixbuf (sb); ios::init (t); osockstream::init (t); } osockunix::~osockunix () { delete ios::rdbuf (); } iosockunix::iosockunix (const sockbuf::sockdesc& sd) : ios (0), iosockstream(0) { sockunixbuf *t = new sockunixbuf (sd); ios::init (t); iosockstream::init (t); } iosockunix::iosockunix (sockbuf::type ty, int proto) : ios (0), iosockstream(0) { sockunixbuf *t = new sockunixbuf (ty, proto); ios::init (t); iosockstream::init (t); } iosockunix::iosockunix (const sockunixbuf& sb) : ios (0), iosockstream(0) { sockunixbuf *t = new sockunixbuf (sb); ios::init (t); iosockstream::init (t); } iosockunix::~iosockunix () { delete ios::rdbuf (); } socket++-1.12.13/socket++/pipestream.cpp0000644000175000017500000000706111676325503015746 0ustar stbstb// pipestream.cpp -*- C++ -*- socket library // Copyright (C) 2002 Herbert Straub // // pipestream.C -*- C++ -*- socket library // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 // 2002-07-28 Version 1.2 (C) Herbert Straub // Eliminating sorry_about_global_temp inititialisation. This don't work // in combination with NewsCache. My idea is: initializing the classes with (0) // and in the second step call ios::init (sockbuf *) and iosockstream::init ... // The constructors of ipipestream, opipestream and iopipestream are changed. using namespace std; #include #include #include #include // environ is not given a declaration in sun's extern char** environ; // child closes s2 and uses s1 // parent closes s1 and uses s2 enum domain { af_unix = 1 }; iopipestream* iopipestream::head = 0; static sockbuf* createpipestream (const char* cmd, int mode) { int sockets[2]; if (::socketpair (af_unix, sockbuf::sock_stream, 0, sockets) == -1) throw sockerr (errno); pid_t pid = ::vfork (); if (pid == -1) throw sockerr (errno); if (pid == 0) { // child process if (::close (sockets[1]) == -1) throw sockerr (errno); if ((mode & ios::in) && ::dup2 (sockets[0], 1) == -1) throw sockerr (errno); if ((mode & ios::out) && ::dup2 (sockets[0], 0) == -1) throw sockerr (errno); if (::close (sockets[0]) == -1) throw sockerr (errno); const char* argv[4]; argv[0] = "/bin/sh"; argv[1] = "-c"; argv[2] = cmd; argv[3] = 0; execve ("/bin/sh", (char**) argv, environ); throw sockerr (errno); } // parent process if (::close (sockets[0]) == -1) throw sockerr (errno); sockbuf* s = new sockbuf (sockbuf::sockdesc(sockets[1])); if (!(mode & ios::out)) s->shutdown (sockbuf::shut_write); if (!(mode & ios::in)) s->shutdown (sockbuf::shut_read); return s; } ipipestream::ipipestream (const char* cmd) : ios (0), isockstream(0) { sockbuf *t = createpipestream (cmd, ios::in); ios::init (t); isockstream::init (t); } opipestream::opipestream (const char* cmd) : ios (0), osockstream(0) { sockbuf *t = createpipestream (cmd, ios::out); ios::init (t); osockstream::init (t); } iopipestream::iopipestream (const char* cmd) : ios (0), iosockstream(0), cpid (-1), next (0) { sockbuf *t = createpipestream (cmd, ios::in|ios::out); ios::init (t); iosockstream::init (t); } iopipestream::iopipestream(sockbuf::type ty, int proto) : ios (0), iosockstream(NULL), cpid (-1), next (head) // probably NULL is not a good idea //LN { if (::socketpair(af_unix, ty, proto, sp) == -1) throw sockerr (errno); head = this; } pid_t iopipestream::fork () { pid_t pid = ::fork (); // donot use vfork here if (pid == -1) throw sockerr (errno); if (pid > 0) { // parent process while (head) { if (::close (head->sp[1]) == -1) throw sockerr (errno); head->cpid = pid; head->init (new sockbuf (sockbuf::sockdesc(head->sp[0]))); head = head->next; } } else { // child process while (head) { if (::close (head->sp[0]) == -1) throw sockerr (errno); head->cpid = 0; head->init (new sockbuf (sockbuf::sockdesc(head->sp[1]))); head = head->next; } } return pid; } socket++-1.12.13/socket++/sockinet.cpp0000644000175000017500000002270511676325523015420 0ustar stbstb// sockinet.C -*- C++ -*- socket library // Copyright (C) 2002 Herbert Straub // // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 // 2002-07-25 Version 1.2 (C) Herbert Straub // Adding improved Error Handling in sockerr class // sockinetaddr::setport if the first character of the port parameter is a // digit, then the parameter is interpreted as a number // 2002-07-28 Version 1.2 (C) Herbert Straub // Eliminating sorry_about_global_temp inititialisation. This don't work // in combination with NewsCache. My idea is: initializing the classes with (0) // and in the second step call ios::init (sockinetbuf *) and iosockstream::init ... // The constructors of isockinet, osockinet and iosockinet are changed. using namespace std; #include #include #if defined(__APPLE) typedef int socklen_t; #endif #ifndef WIN32 EXTERN_C_BEGIN # include # include # include # include # include # include # include EXTERN_C_END #else # define socklen_t int # define EADDRNOTAVAIL WSAEADDRNOTAVAIL # define EADDRINUSE WSAEADDRINUSE # define ENOPROTOOPT WSAENOPROTOOPT #endif // !WIN32 void herror(const char*); sockinetaddr::sockinetaddr () { sin_family = sockinetbuf::af_inet; sin_addr.s_addr = htonl(INADDR_ANY); sin_port = 0; } sockinetaddr::sockinetaddr(unsigned long addr, int port_no) // addr and port_no are in host byte order { sin_family = sockinetbuf::af_inet; sin_addr.s_addr = htonl(addr); sin_port = htons(port_no); } sockinetaddr::sockinetaddr(unsigned long addr, const char* sn, const char* pn) // addr is in host byte order { sin_family = sockinetbuf::af_inet; sin_addr.s_addr = htonl (addr); // Added by cgay@cs.uoregon.edu May 29, 1993 setport(sn, pn); } sockinetaddr::sockinetaddr (const char* host_name, int port_no) // port_no is in host byte order { setaddr(host_name); sin_port = htons(port_no); } sockinetaddr::sockinetaddr(const char* hn, const char* sn, const char* pn) { setaddr(hn); setport(sn, pn); } sockinetaddr::sockinetaddr (const sockinetaddr& sina) { sin_family = sockinetbuf::af_inet; sin_addr.s_addr = sina.sin_addr.s_addr; sin_port = sina.sin_port; } void sockinetaddr::setport(const char* sn, const char* pn) { if (isdigit (*sn)) { sin_port = htons(atoi(sn)); } else { servent* sp = getservbyname(sn, pn); if (sp == 0) throw sockerr (EADDRNOTAVAIL, "sockinetaddr::setport"); sin_port = sp->s_port; } } int sockinetaddr::getport () const { return ntohs (sin_port); } void sockinetaddr::setaddr(const char* host_name) { if ( (sin_addr.s_addr = inet_addr(host_name)) == INADDR_NONE) { hostent* hp = gethostbyname(host_name); if (hp == 0) throw sockerr (EADDRNOTAVAIL, "sockinetaddr::setaddr"); memcpy(&sin_addr, hp->h_addr, hp->h_length); sin_family = hp->h_addrtype; } else sin_family = sockinetbuf::af_inet; } const char* sockinetaddr::gethostname () const { if (sin_addr.s_addr == htonl(INADDR_ANY)) { static char hostname[64]; if (::gethostname(hostname, 63) == -1) return ""; return hostname; } hostent* hp = gethostbyaddr((const char*) &sin_addr, sizeof(sin_addr), family()); if (hp == 0) return ""; if (hp->h_name) return hp->h_name; return ""; } sockinetbuf::sockinetbuf (const sockbuf::sockdesc& sd) : sockbuf (sd.sock) {} sockinetbuf::sockinetbuf(sockbuf::type ty, int proto) : sockbuf (af_inet, ty, proto) {} sockinetaddr sockinetbuf::localaddr() const { sockinetaddr sin; int len = sin.size(); if (::getsockname(rep->sock, sin.addr (), (socklen_t*) // LN &len) == -1) throw sockerr (errno, "sockinetbuf::localaddr"); return sin; } int sockinetbuf::localport() const { sockinetaddr sin = localaddr(); if (sin.family() != af_inet) return -1; return sin.getport(); } const char* sockinetbuf::localhost() const { sockinetaddr sin = localaddr(); if (sin.family() != af_inet) return ""; return sin.gethostname(); } sockinetaddr sockinetbuf::peeraddr() const { sockinetaddr sin; int len = sin.size(); if (::getpeername(rep->sock, sin.addr (), (socklen_t*) // LN &len) == -1) throw sockerr (errno, "sockinetbuf::peeraddr"); return sin; } int sockinetbuf::peerport() const { sockinetaddr sin = peeraddr(); if (sin.family() != af_inet) return -1; return sin.getport(); } const char* sockinetbuf::peerhost() const { sockinetaddr sin = peeraddr(); if (sin.family() != af_inet) return ""; return sin.gethostname(); } void sockinetbuf::bind_until_success (int portno) // a. bind to (INADDR_ANY, portno) // b. if success return // c. if failure and errno is EADDRINUSE, portno++ and go to step a. { for (;;) { try { bind (portno++); } catch (sockerr e) { // if (e.errno () != EADDRINUSE) throw; if (e.serrno () != EADDRINUSE) throw; // LN continue; } break; } } void sockinetbuf::bind (sockAddr& sa) { sockbuf::bind (sa); } void sockinetbuf::bind (int port_no) { sockinetaddr sa ((long unsigned int) // LN INADDR_ANY, port_no); bind (sa); } void sockinetbuf::bind (unsigned long addr, int port_no) // address and portno are in host byte order { sockinetaddr sa (addr, port_no); bind (sa); } void sockinetbuf::bind (const char* host_name, int port_no) { sockinetaddr sa (host_name, port_no); bind (sa); } void sockinetbuf::bind (unsigned long addr, const char* service_name, const char* protocol_name) { sockinetaddr sa (addr, service_name, protocol_name); bind (sa); } void sockinetbuf::bind (const char* host_name, const char* service_name, const char* protocol_name) { sockinetaddr sa (host_name, service_name, protocol_name); bind (sa); } void sockinetbuf::connect (sockAddr& sa) { sockbuf::connect (sa); } void sockinetbuf::connect (unsigned long addr, int port_no) // address and portno are in host byte order { sockinetaddr sa (addr, port_no); connect (sa); } void sockinetbuf::connect (const char* host_name, int port_no) { sockinetaddr sa (host_name, port_no); connect (sa); } void sockinetbuf::connect (unsigned long addr, const char* service_name, const char* protocol_name) { sockinetaddr sa (addr, service_name, protocol_name); connect (sa); } void sockinetbuf::connect (const char* host_name, const char* service_name, const char* protocol_name) { sockinetaddr sa (host_name, service_name, protocol_name); connect (sa); } sockbuf::sockdesc sockinetbuf::accept () { return sockbuf::accept (); } sockbuf::sockdesc sockinetbuf::accept (sockAddr& sa) { return sockbuf::accept (sa); } sockbuf::sockdesc sockinetbuf::accept (unsigned long addr, int port_no) { sockinetaddr sa (addr, port_no); return accept (sa); } sockbuf::sockdesc sockinetbuf::accept (const char* host_name, int port_no) { sockinetaddr sa (host_name, port_no); return accept (sa); } bool sockinetbuf::tcpnodelay () const { struct protoent* proto = getprotobyname ("tcp"); if (proto == 0) throw sockerr (ENOPROTOOPT, "sockinetbuf::tcpnodelay"); int old = 0; getopt (TCP_NODELAY, &old, sizeof (old), proto->p_proto); return old!=0; } bool sockinetbuf::tcpnodelay (bool set) const { struct protoent* proto = getprotobyname ("tcp"); if (proto == 0) throw sockerr (ENOPROTOOPT, "sockinetbuf::tcpnodelay"); int old = 0; int opt = set; getopt (TCP_NODELAY, &old, sizeof (old), proto->p_proto); setopt (TCP_NODELAY, &opt, sizeof (opt), proto->p_proto); return old!=0; } isockinet::isockinet (const sockbuf::sockdesc& sd) : ios(0), isockstream(0) { sockinetbuf *t = new sockinetbuf (sd); ios::init (t); isockstream::init (t); } isockinet::isockinet (sockbuf::type ty, int proto) : ios (0), isockstream(0) { sockinetbuf *t = new sockinetbuf (ty, proto); ios::init (t); isockstream::init (t); } isockinet::isockinet (const sockinetbuf& sb) : ios (0), isockstream(0) { sockinetbuf *t = new sockinetbuf (sb); ios::init (t); isockstream::init (t); } isockinet::~isockinet () { delete ios::rdbuf (); } osockinet::osockinet (const sockbuf::sockdesc& sd) : ios (0), osockstream(0) { sockinetbuf *t = new sockinetbuf (sd); ios::init (t); osockstream::init (t); } osockinet::osockinet (sockbuf::type ty, int proto) : ios (0), osockstream(0) { sockinetbuf *t = new sockinetbuf (ty, proto); ios::init (t); osockstream::init (t); } osockinet::osockinet (const sockinetbuf& sb) : ios (0), osockstream(0) { sockinetbuf *t = new sockinetbuf (sb); ios::init (t); osockstream::init (t); } osockinet::~osockinet () { delete ios::rdbuf (); } iosockinet::iosockinet (const sockbuf::sockdesc& sd) : ios (0), iosockstream(0) { sockinetbuf *t = new sockinetbuf(sd); ios::init (t); iosockstream::init (t); } iosockinet::iosockinet (sockbuf::type ty, int proto) : ios (0), iosockstream (0) { sockinetbuf *t = new sockinetbuf (ty, proto); ios::init (t); iosockstream::init (t); } iosockinet::iosockinet (const sockinetbuf& sb) : ios (0), iosockstream(0) { sockinetbuf *t = new sockinetbuf (sb); ios::init (t); iosockstream::init (t); } iosockinet::~iosockinet () { delete ios::rdbuf (); } socket++-1.12.13/socket++/pipestream.h0000644000175000017500000000360011676325304015405 0ustar stbstb// pipestream.h -*- C++ -*- socket library // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #ifndef _PIPESTREAM_H #define _PIPESTREAM_H #include class ipipestream: public isockstream { protected: // ipipestream (): std::ios (0) {} public: ipipestream (const char* cmd); ~ipipestream () { delete std::ios::rdbuf (); } }; class opipestream: public osockstream { protected: // opipestream (): std::ios(0) {} public: opipestream (const char* cmd); ~opipestream () { delete std::ios::rdbuf (); } }; class iopipestream: public iosockstream { private: iopipestream(const iopipestream& sp); // no defintion provided iopipestream& operator = (iopipestream&); // no definition provided protected: int sp[2]; // socket pair // if iopipstream (sockbuf::type, int) created this object, // then cpid is significant. Otherwise it is set to -1. // cpid is child pid if this is parent // cpid is 0 if this is child pid_t cpid; iopipestream* next; // next in the chain. Used only by // iopipstream (sockbuf::type, int) static iopipestream* head; // list to take care of by fork() public: iopipestream(sockbuf::type ty=sockbuf::sock_stream, int proto=0); iopipestream(const char* cmd); ~iopipestream () { delete std::ios::rdbuf (); } pid_t pid () const { return cpid; } // returns cpid static pid_t fork(); // sets cpid of all iopipestream* in the head }; #endif // _PIPESTREAM_H socket++-1.12.13/socket++/ftp.cpp0000644000175000017500000001536111676325304014367 0ustar stbstb// ftp.h // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #include #include #include #include #include #include #include #include #include // for sprintf #include using namespace std; #if defined (__osf__) && defined (__DECCXX) extern "C" { # include } #else # include #endif char reptype [][8] = { "A N", "A T", "A C", "E N", "E T", "E C", "I", "L " }; char filestru [][8] = { "F", "R", "P" }; char transmode [][8] = { "S", "B", "C" }; // ftpdata waits on a port at the local machine. // When a connection is made, it receives a file from remote // host if the ostream o is set, or it sends a file to the remote // host if the istream i is set. ftp::replycodea ftp::ftpbuf::ftpdata (int portno, istream* i, ostream* o, const char* cmd, const char* arg) { sockinetbuf sb (sockbuf::sock_stream, 0); sb.bind_until_success (portno); useraddr (sb.localaddr ()); sb.listen (1); if (send_cmd (cmd, arg) >= ftp::rca_error) return ftp::rca_error; if (o) { sockbuf c = sb.accept (); // read data from c and put it in o char buf [1024]; int rdsz; while ((rdsz = c.sgetn (buf, 1024)) != EOF) o->write (buf, rdsz); } else if (i) { sockbuf c = sb.accept (); // read data from i and send it to c char buf [1024]; int rdsz; streambuf* rb = i->rdbuf (); while ((rdsz = rb->sgetn (buf, 1024)) > 0) { int wrsz = c.sputn (buf, rdsz); if (rdsz != wrsz) cerr << "write error\n"; } } // Note: sockbuf object c must have been destructed by the time you reach // here. return get_response (); } ftp::replycodea ftp::ftpbuf::get_response () // get all the response that one can get and send all of them to o { // if o is 0, then we trash data. int firstline = 1; while (underflow () != EOF) { int n = in_avail (); if (n < 5) continue; // data is of this form: 221 repsonse or 221-response char* q = gptr (); char* p = q; // zap upto int i = 0; for (i = 2; i <= n; i++, p++) if (*p == '\r' && *(p+1) == '\n') { break; } if (o) o->write (q, i); gbump (i); if (firstline) { strncpy (replycode, q, 3); replycode [3] = ' '; if (q [3] == ' ') break; firstline = 0; } else if (strncmp (q, replycode, 4) == 0) break; } return (replycodea) replycode [0]; } ftp::replycodea ftp::ftpbuf::send_cmd (const char* cmd, const char* arg) { xsputn (cmd, ::strlen (cmd)); if (arg) { xsputn (" ", 1); xsputn (arg, ::strlen (arg)); } xsputn ("\r\n", 2); sync (); return get_response (); } ftp::ftp (ostream* out) : ios (0) { ios::init (new ftpbuf (out)); } ftp::ftpbuf::ftpbuf (ostream* out) : protocol::protocolbuf (protocol::tcp), o (out) { replycode [4] = 0; } void ftp::ftpbuf::serve_clients (int portno) // right now no server ftp class can be used as a server {} ftp::replycodea ftp::ftpbuf::cd (const char* dir) { return send_cmd ("CWD", dir); } ftp::replycodea ftp::ftpbuf::useraddr (sockinetaddr sa) { if (sa.sin_addr.s_addr == 0) { // local host char hostname [64]; if (::gethostname (hostname, 63) == -1) throw sockerr (EADDRNOTAVAIL); hostent* hp = gethostbyname (hostname); if (hp == 0) throw sockerr (EADDRNOTAVAIL); memcpy (&sa.sin_addr, hp->h_addr, hp->h_length); } struct in_addr ina = sa.sin_addr; int portno = ntohs(sa.sin_port); char* ina_p = inet_ntoa (ina); char addr [80]; char* p = 0; strcpy (addr, ina_p); while ((p = strchr (addr, '.'))) *p = ','; int hi_portno = portno >> 8; int lo_portno = portno & 0xff; sprintf (addr + strlen (addr), ",%d,%d", hi_portno, lo_portno); return send_cmd ("PORT", addr); } ftp::replycodea ftp::ftpbuf::useraddr (const char* hostname, int portno) { return useraddr (sockinetaddr (hostname, portno)); } ftp::replycodea ftp::ftpbuf::server_port (int portno) { int hi_portno = portno >> 8; int lo_portno = portno & 0xff; char port [80]; sprintf (port, "%d,%d", hi_portno, lo_portno); return send_cmd ("PASV", port); } ftp::replycodea ftp::ftpbuf::rep_type (ftp::reptype rt) { return send_cmd ("TYPE", ::reptype [int(rt)]); } ftp::replycodea ftp::ftpbuf::file_stru (ftp::filestru fs) { return send_cmd ("STRU", ::filestru [int(fs)]); } ftp::replycodea ftp::ftpbuf::trans_mode (ftp::transmode tm) { return send_cmd ("STRU", ::transmode [int(tm)]); } ftp::replycodea ftp::ftpbuf::getfile (const char* rpath, const char* lpath) { if (lpath == 0) lpath = rpath; if (rpath == 0) list (); ofstream f (lpath); return ftpdata (10000, 0, &f, "RETR", rpath); } ftp::replycodea ftp::ftpbuf::list (const char* rpath, int justnames) { if (justnames) return ftpdata (10000, 0, o, "NLST", rpath); else return ftpdata (10000, 0, o, "LIST", rpath); } ftp::replycodea ftp::ftpbuf::putfile (const char* lpath, const char* rpath) { if (rpath == 0) rpath = lpath; if (lpath == 0) return ftp::rca_error; ifstream f(lpath); return ftpdata (10000, &f, 0, "STOR", rpath); } ftp::replycodea ftp::ftpbuf::putfile (const char* lpath) { if (lpath == 0) return ftp::rca_error; ifstream f(lpath); return ftpdata (10000, &f, 0, "STOU", lpath); } ftp::replycodea ftp::ftpbuf::append (const char* lpath, const char* rpath) { if (lpath == 0) return ftp::rca_error; if (rpath == 0) rpath = lpath; ifstream f(lpath); return ftpdata (10000, &f, 0, "APPE", 0); } ftp::replycodea ftp::ftpbuf::allocate (int numbytes) { char b[32]; sprintf (b, "%d", numbytes); return send_cmd ("ALLO", b); } ftp::replycodea ftp::ftpbuf::restart (int marker) { char b[32]; sprintf (b, "%d", marker); return send_cmd ("REST", b); } ftp::replycodea ftp::ftpbuf::rename (const char* rpath, const char* newrpath) { if (rpath == 0 || newrpath == 0) return ftp::rca_error; if (send_cmd ("RNFR", rpath) >= ftp::rca_error) return rca_error; return send_cmd ("RNTO", newrpath); } ftp::replycodea ftp::ftpbuf::rmfile (const char* rpath) { return send_cmd ("DELE", rpath); } ftp::replycodea ftp::ftpbuf::rmdir (const char* rpath) { return send_cmd ("RMD", rpath); } ftp::replycodea ftp::ftpbuf::mkdir (const char* rpath) { return send_cmd ("MKD", rpath); } socket++-1.12.13/socket++/sockstream.h0000644000175000017500000002350511676325537015425 0ustar stbstb// sockstream.h -*- C++ -*- socket library // Copyright (C) 2002 Herbert Straub // // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 // // Version: 1.2 2002-07-25 Herbert Straub // Improved Error Handling - extending the sockerr class by cOperation // 2003-03-06 Herbert Straub // adding sockbuf::getname und setname (sockname) // sockbuf methods throw method name + sockname #ifndef _SOCKSTREAM_H #define _SOCKSTREAM_H #include // must be ANSI compatible #include #include #include #include #include #include #ifndef WIN32 # include # include # include # define SOCKET int # define SOCKET_ERROR -1 #else # include # pragma comment(lib, "Wininet") #endif #ifdef __linux__ # define MSG_MAXIOVLEN 16 #endif // __linux__ // socket exception classes class sockerr { int err; std::string text; public: sockerr (int e, const char *operation = NULL): err (e) { if (operation != NULL) { text = operation; } } sockerr (int e, const char *operation, const char *specification) : err (e) { if (operation != NULL) text = operation; if (specification != NULL) { text += "("; text += specification; text += ")"; } } sockerr (int e, const std::string &operation): err (e) { text = operation; } sockerr (const sockerr &O) { err = O.err; text = O.text; } const char* what () const { return "sockerr"; } const char* operation () const { return text.c_str(); } // int errno () const { return err; } int serrno () const { return err; } // LN const char* errstr () const; bool error (int eno) const { return eno == err; } bool io () const; // non-blocking and interrupt io recoverable error. bool arg () const; // incorrect argument supplied. recoverable error. bool op () const; // operational error. recovery difficult. bool conn () const; // connection error bool addr () const; // address error bool benign () const; // recoverable read/write error like EINTR etc. }; class sockoob { public: const char* what () const { return "sockoob"; } }; // socket address classes struct sockaddr; class sockAddr { public: virtual ~sockAddr() {} virtual operator void* () const =0; operator sockaddr* () const { return addr (); } virtual int size () const =0; virtual int family () const =0; virtual sockaddr* addr () const =0; }; struct msghdr; // socket buffer class class sockbuf: public std::streambuf { public: enum type { sock_stream = SOCK_STREAM, sock_dgram = SOCK_DGRAM, sock_raw = SOCK_RAW, sock_rdm = SOCK_RDM, sock_seqpacket = SOCK_SEQPACKET }; enum option { so_debug = SO_DEBUG, so_reuseaddr = SO_REUSEADDR, so_keepalive = SO_KEEPALIVE, so_dontroute = SO_DONTROUTE, so_broadcast = SO_BROADCAST, so_linger = SO_LINGER, so_oobinline = SO_OOBINLINE, so_sndbuf = SO_SNDBUF, so_rcvbuf = SO_RCVBUF, so_error = SO_ERROR, so_type = SO_TYPE }; enum level { sol_socket = SOL_SOCKET }; enum msgflag { msg_oob = MSG_OOB, msg_peek = MSG_PEEK, msg_dontroute = MSG_DONTROUTE, #if !(defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__APPLE__)) msg_maxiovlen = MSG_MAXIOVLEN #endif }; enum shuthow { shut_read, shut_write, shut_readwrite }; enum { somaxconn = SOMAXCONN }; struct socklinger { int l_onoff; // option on/off int l_linger; // linger time socklinger (int a, int b): l_onoff (a), l_linger (b) {} }; typedef char char_type; typedef std::streampos pos_type; typedef std::streamoff off_type; typedef int int_type; typedef int seekdir; // const int_type eof = EOF; enum { eof = EOF }; // LN struct sockdesc { int sock; sockdesc (int d): sock (d) {} }; protected: struct sockcnt { SOCKET sock; int cnt; int stmo; // -1==block, 0==poll, >0 == waiting time in secs int rtmo; // -1==block, 0==poll, >0 == waiting time in secs bool oob; // check for out-of-band byte while reading void* gend; // end of input buffer void* pend; // end of output buffer sockcnt(SOCKET s) : sock(s), cnt(1), stmo (-1), rtmo (-1), oob (false), gend (0), pend (0) {} }; sockcnt* rep; // counts the # refs to sock std::string sockname; // name of sockbuf - Herbert Straub #if 0 virtual sockbuf* setbuf (char_type* s, int_type* n); virtual pos_type seekoff (off_type off, seekdir way, std::ios::openmode which = ios::in|ios::out); virtual pos_type seekpos (pos_type sp, std::ios::openmode which = ios::in|ios::out); #endif virtual int sync (); virtual int showmanyc () const; virtual std::streamsize xsgetn (char_type* s, std::streamsize n); virtual int_type underflow (); virtual int_type uflow (); virtual int_type pbackfail (int_type c = eof); virtual std::streamsize xsputn (const char_type* s, std::streamsize n); virtual int_type overflow (int_type c = eof); public: sockbuf (const sockdesc& sd); sockbuf (int domain, type, int proto); sockbuf (const sockbuf&); // sockbuf& operator = (const sockbuf&); virtual ~sockbuf (); int sd () const { return rep->sock; } int pubsync () { return sync (); } virtual bool is_open () const; virtual void bind (sockAddr&); virtual void connect (sockAddr&); void listen (int num=somaxconn); virtual sockdesc accept (); virtual sockdesc accept (sockAddr& sa); int read (void* buf, int len); int recv (void* buf, int len, int msgf=0); int recvfrom(sockAddr& sa, void* buf, int len, int msgf=0); #if !defined(__linux__) && !defined(WIN32) int recvmsg (msghdr* msg, int msgf=0); int sendmsg (msghdr* msg, int msgf=0); #endif int write (const void* buf, int len); int send (const void* buf, int len, int msgf=0); int sendto (sockAddr& sa, const void* buf, int len, int msgf=0); int sendtimeout (int wp=-1); int recvtimeout (int wp=-1); int is_readready (int wp_sec, int wp_usec=0) const; int is_writeready (int wp_sec, int wp_usec=0) const; int is_exceptionpending (int wp_sec, int wp_usec=0) const; void shutdown (shuthow sh); int getopt(int op, void* buf, int len, int level=sol_socket) const; void setopt(int op, void* buf, int len, int level=sol_socket) const; type gettype () const; int clearerror () const; bool debug () const; bool debug (bool set) const; bool reuseaddr () const; bool reuseaddr (bool set) const; bool keepalive () const; bool keepalive (bool set) const; bool dontroute () const; bool dontroute (bool set) const; bool broadcast () const; bool broadcast (bool set) const; bool oobinline () const; bool oobinline (bool set) const; bool oob () const { return rep->oob; } bool oob (bool b); int sendbufsz () const; int sendbufsz (int sz) const; int recvbufsz () const; int recvbufsz (int sz) const; socklinger linger () const; socklinger linger (socklinger opt) const; socklinger linger (int onoff, int tm) const { return linger (socklinger (onoff, tm)); } bool atmark () const; long nread () const; long howmanyc () const; void nbio (bool set=true) const; inline void setname (const char *name); inline void setname (const std::string &name); inline const std::string& getname (); #ifndef WIN32 void async (bool set=true) const; int pgrp () const; int pgrp (int new_pgrp) const; void closeonexec (bool set=true) const; #endif }; class isockstream: public std::istream { protected: // isockstream (): std::istream(rdbuf()), ios (0) {} public: isockstream(sockbuf* sb): std::ios (sb), std::istream(sb) {} virtual ~isockstream () {} sockbuf* rdbuf () { return (sockbuf*)std::ios::rdbuf(); } sockbuf* operator -> () { return rdbuf(); } }; class osockstream: public std::ostream { protected: // osockstream (): ostream(static_cast<>rdbuf()), std::ios (0) {} public: osockstream(sockbuf* sb): std::ios (sb), std::ostream(sb) {} virtual ~osockstream () {} sockbuf* rdbuf () { return (sockbuf*)std::ios::rdbuf(); } sockbuf* operator -> () { return rdbuf(); } }; class iosockstream: public std::iostream { protected: iosockstream (); public: iosockstream(sockbuf* sb): std::ios (sb), std::iostream(sb) {} virtual ~iosockstream () {} sockbuf* rdbuf () { return (sockbuf*)std::ios::rdbuf(); } sockbuf* operator -> () { return rdbuf(); } }; // manipulators extern osockstream& crlf (osockstream&); extern osockstream& lfcr (osockstream&); // inline void sockbuf::setname (const char *name) { sockname = name; } void sockbuf::setname (const std::string &name) { sockname = name; } const std::string& sockbuf::getname () { return sockname; } #endif // _SOCKSTREAM_H socket++-1.12.13/socket++/sig.cpp0000644000175000017500000001154211676325304014355 0ustar stbstb// socket++ library. sig.C // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. #include #include //explicit template instantiation. typedef sig::phnd phnd; typedef sig::phndlist phndlist; //template class list; //template class map >; //static sigerr se; //commended out by Herbert Straub // Change all se to sigerr siginit siginit::init; sig& sig::nal = *siginit::init.s; typedef void (*sighnd_type) (int); extern "C" { static void sighandler (int signo) { sig::nal.kill (signo); } } sig::hnd::hnd (int s) : signo (s) { sig::nal.set (signo, this); } sig::hnd::~hnd () { sig::nal.unset (signo, this); } bool sig::set (int signo, sig::hnd* hnd) { if (hnd == 0) return false; phndlist& v = smap [signo]; if (v.empty ()) { struct sigaction sa; if (sigaction (signo, 0, &sa) == -1) throw sigerr(); if (sa.sa_handler != sighnd_type (&sighandler)) { // setting for the first time sa.sa_handler = (void(*)(int)) sighnd_type (&sighandler); if (sigemptyset (&sa.sa_mask) == -1) throw sigerr(); sa.sa_flags = 0; if (sigaction (signo, &sa, 0) == -1) throw sigerr(); } v.push_back (hnd); return true; } phndlist::iterator j = find (v.begin(), v.end (), hnd); if (j == v.end ()) { v.push_back (hnd); return true; } return false; } bool sig::unset (int signo, sig::hnd* hnd) { if (hnd == 0) return false; phndlist& v = smap [signo]; phndlist::iterator j = find (v.begin(), v.end (), hnd); if (j != v.end ()) { v.erase (j); return true; } return false; } void sig::unset (int signo) { phndlist& v = smap [signo]; v.erase (v.begin (), v.end ()); struct sigaction sa; if (sigaction (signo, 0, &sa) == -1) throw sigerr(); if (sa.sa_handler == sighnd_type (&sighandler)) { sa.sa_handler = (void(*)(int)) sighnd_type (SIG_DFL); if (sigemptyset (&sa.sa_mask) == -1) throw sigerr(); sa.sa_flags = 0; if (sigaction (signo, &sa, 0) == -1) throw sigerr(); } } void sig::mask (int signo) const { sigset_t s; if (sigemptyset (&s) == -1) throw sigerr(); if (sigaddset (&s, signo) == -1) throw sigerr(); if (sigprocmask (SIG_BLOCK, &s, 0) == -1) throw sigerr(); } void sig::unmask (int signo) const { sigset_t s; if (sigemptyset (&s) == -1) throw sigerr(); if (sigaddset (&s, signo) == -1) throw sigerr(); if (sigprocmask (SIG_UNBLOCK, &s, 0) == -1) throw sigerr(); } void sig::mask (int siga, int sigb) const { struct sigaction sa; if (sigaction (siga, 0, &sa) == -1) throw sigerr(); if (sa.sa_handler != sighnd_type (&sighandler)) { sa.sa_handler = (void(*)(int)) sighnd_type (&sighandler); if (sigemptyset (&sa.sa_mask) == -1) throw sigerr(); sa.sa_flags = 0; } if (sigaddset (&sa.sa_mask, sigb) == -1) throw sigerr(); if (sigaction (siga, &sa, 0) == -1) throw sigerr(); } void sig::unmask (int siga, int sigb) const { struct sigaction sa; if (sigaction (siga, 0, &sa) == -1) throw sigerr(); if (sa.sa_handler != sighnd_type (&sighandler)) { sa.sa_handler = (void(*)(int)) sighnd_type (&sighandler); if (sigemptyset (&sa.sa_mask) == -1) throw sigerr(); sa.sa_flags = 0; } else { if (sigdelset (&sa.sa_mask, sigb) == -1) throw sigerr(); } if (sigaction (siga, &sa, 0) == -1) throw sigerr(); } void sig::sysresume (int signo, bool set) const { struct sigaction sa; if (sigaction (signo, 0, &sa) == -1) throw sigerr(); if (sa.sa_handler != sighnd_type (&sighandler)) { sa.sa_handler = (void(*)(int)) sighnd_type (&sighandler); if (sigemptyset (&sa.sa_mask) == -1) throw sigerr(); sa.sa_flags = 0; } #if !(defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__) || defined(__sun__) || defined(__linux__) || defined(__APPLE)) // Early SunOS versions may have SA_INTERRUPT. I can't confirm. if (set == false) sa.sa_flags |= SA_INTERRUPT; else sa.sa_flags &= ~SA_INTERRUPT; if (sigaction (signo, &sa, 0) == -1) throw sigerr(); #endif } struct procsig { int signo; procsig (int s): signo (s) {} void operator () (phnd& ph) { (*ph) (signo); } }; void sig::kill (int signo) { phndlist& v = smap [signo]; // struct procsig used to be here // LN for_each (v.begin (), v.end (), procsig (signo)); } sigset_t sig::pending () const { sigset_t s; if (sigemptyset (&s) == -1) throw sigerr(); if (sigpending (&s) == -1) throw sigerr(); return s; } bool sig::ispending (int signo) const { sigset_t s = pending (); switch (sigismember (&s, signo)) { case 0: return false; case 1: return true; } throw sigerr(); } socket++-1.12.13/socket++/sockinet.h0000644000175000017500000001132611676325304015057 0ustar stbstb// sockinet.h -*- C++ -*- socket library // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #ifndef _SOCKINET_H #define _SOCKINET_H #include #ifndef WIN32 # include #endif // !WIN32 class sockinetaddr: public sockAddr, public sockaddr_in { protected: void setport (const char* sn, const char* pn="tcp"); void setaddr (const char* hn); public: ~sockinetaddr () {} sockinetaddr (); sockinetaddr (unsigned long addr, int port_no=0); sockinetaddr (const char* host_name, int port_no=0); sockinetaddr (unsigned long addr, const char* service_name, const char* protocol_name="tcp"); sockinetaddr (const char* host_name, const char* service_name, const char* protocol_name="tcp"); sockinetaddr (const sockinetaddr& sina); operator void* () const { return addr_in (); } sockaddr_in* addr_in () const { return (sockaddr_in*) this; } int size () const { return sizeof (sockaddr_in); } int family() const { return sin_family; } sockaddr* addr () const { return (sockaddr*) addr_in (); } int getport () const; const char* gethostname() const; }; class sockinetbuf: public sockbuf { public: enum domain { af_inet = AF_INET }; sockinetbuf (const sockbuf::sockdesc& sd); sockinetbuf (const sockinetbuf& si): sockbuf (si) {} sockinetbuf (sockbuf::type ty, int proto=0); sockinetbuf& operator=(const sockinetbuf& si); ~sockinetbuf () {} sockinetaddr localaddr() const; int localport() const; const char* localhost() const; sockinetaddr peeraddr() const; int peerport() const; const char* peerhost() const; void bind_until_success (int portno); virtual void bind (sockAddr& sa); void bind (int port_no=0); // addr is assumed to be INADDR_ANY // and thus defaults to local host void bind (unsigned long addr, int port_no); void bind (const char* host_name, int port_no=0); void bind (unsigned long addr, const char* service_name, const char* protocol_name="tcp"); void bind (const char* host_name, const char* service_name, const char* protocol_name="tcp"); virtual void connect (sockAddr& sa); void connect (unsigned long addr, int port_no); void connect (const char* host_name, int port_no); void connect (unsigned long addr, const char* service_name, const char* protocol_name="tcp"); void connect (const char* host_name, const char* service_name, const char* protocol_name="tcp"); virtual sockdesc accept (); virtual sockdesc accept (sockAddr& sa); sockdesc accept (unsigned long addr, int port_no); sockdesc accept (const char* host_name, int port_no); bool tcpnodelay () const; bool tcpnodelay (bool set) const; }; class isockinet: public isockstream { public: isockinet (const sockbuf::sockdesc& sd); isockinet (const sockinetbuf& sb); isockinet (sockbuf::type ty=sockbuf::sock_stream, int proto=0); ~isockinet (); sockinetbuf* rdbuf () { return (sockinetbuf*)std::ios::rdbuf (); } sockinetbuf* operator -> () { return rdbuf (); } }; class osockinet: public osockstream { public: osockinet (const sockbuf::sockdesc& sd); osockinet (const sockinetbuf& sb); osockinet (sockbuf::type ty=sockbuf::sock_stream, int proto=0); ~osockinet (); sockinetbuf* rdbuf () { return (sockinetbuf*)std::ios::rdbuf (); } sockinetbuf* operator -> () { return rdbuf (); } }; class iosockinet: public iosockstream { public: iosockinet (const sockbuf::sockdesc& sd); iosockinet (const sockinetbuf& sb); iosockinet (sockbuf::type ty=sockbuf::sock_stream, int proto=0); ~iosockinet (); sockinetbuf* rdbuf () { return (sockinetbuf*)std::ios::rdbuf (); } sockinetbuf* operator -> () { return rdbuf (); } }; #endif // _SOCKINET_H socket++-1.12.13/socket++/smtp.cpp0000644000175000017500000000642611676325304014563 0ustar stbstb// smtp.C -*- C++ -*- socket library // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #include #include #include #include #include #include #include using namespace std; void smtp::smtpbuf::get_response () // get all the response that one can get and send all of them to o { // if o is 0, then we trash data. while (underflow () != EOF) { int n = in_avail (); if (n < 5) continue; // data is of this form: 221 repsonse or 221-response char* q = gptr (); char* p = q; // zap upto for (int i = 2; i <= n; i++, p++) if (*p == '\r' && *(p+1) == '\n') { if (o) o->write (q, i); gbump (i); break; } if (q [3] != '-') break; } } void smtp::smtpbuf::send_cmd (const char* cmd, const char* s, const char* p) { xsputn (cmd, ::strlen (cmd)); if (s) xsputn (s, ::strlen (s)); if (p) xsputn (p, ::strlen (p)); xsputn ("\r\n", 2); sync (); if (o) get_response (); } void smtp::smtpbuf::helo () { if (o) get_response (); send_cmd ("HELO ", localhost ()); } void smtp::smtpbuf::mail (const char* reverse_path) { if (reverse_path) send_cmd ("MAIL FROM:<", reverse_path, ">"); else send_cmd ("MAIL FROM:<>"); } void smtp::smtpbuf::rcpt (const char* forward_path) { if (forward_path) send_cmd ("RCPT TO:<", forward_path, ">"); } void smtp::smtpbuf::help (const char* s) { send_cmd ("HELP ", s); } void smtp::smtpbuf::send_buf (const char* buf, int len) { if (buf == 0 || len <= 0) return; // send line by line const unsigned char* p = (const unsigned char*) buf; if (*p == '.') sputc ((unsigned int) '.'); for (int i = 0; i < len; i++, p++) { if (*p == '\n') { sputc ((unsigned int) '\r'); sputc (*p); if (*(p+1) == '.') sputc ((unsigned int) '.'); } else sputc (*p); } } void smtp::smtpbuf::data (const char* buf, int len) { data (); send_buf (buf, len); xsputn ("\r\n.\r\n", 5); sync (); if (o) get_response (); } void smtp::smtpbuf::data (const char* filename) { data (); int fd = 0; char buf [1024]; int rcnt; if (filename == 0 || (fd = ::open (filename, O_RDONLY )) == -1) fd = 0; while ((rcnt = ::read (fd, buf, 1024)) > 0) send_buf (buf, rcnt); xsputn ("\r\n.\r\n", 5); sync (); if (o) get_response (); } int smtp::get_response (char* buf, int len) // same as get line except what it returns // return 1 if output continues after this line // return 0 if output has terminated { if (len < 8) { this->getline (buf, len); return 0; } buf [3] = 0; this->getline (buf, len); return buf [3] == '-'; } ostream& operator << (ostream& o, smtp& s) { char buf [1024]; int cont = 1; while (cont) { cont = s.get_response (buf, 1024); o << buf << endl; } return o; } void smtp::smtpbuf::serve_clients (int portno) { } socket++-1.12.13/vc60.pdb0000644000175000017500000000000011676325304012701 0ustar stbstbsocket++-1.12.13/doc/0000755000175000017500000000000011676325304012213 5ustar stbstbsocket++-1.12.13/doc/Makefile.am0000644000175000017500000000003711676325304014247 0ustar stbstbinfo_TEXINFOS = socket++.texi socket++-1.12.13/doc/socket++.texi0000644000175000017500000023337611676325304014542 0ustar stbstb\input texinfo @c -*-texinfo-*- @c %**start of header @setfilename socket++.info @settitle C++ socket classes @c %**end of header @syncodeindex fn cp @iftex @finalout @end iftex @ifinfo @dircategory Programming & development tools @direntry * socket++: (socket++.info). C++ family of socket classes. @end direntry This info file describes the C++ family of socket classes. Copyright (C) 1992,1993,1994 Gnanasekaran Swaminathan Permission is granted to make and distribute verbatim copies of this document provided the copyright notice and this permission notice are preserved on all copies. @end ifinfo @titlepage @title C++ Socket Classes @subtitle Version: 12Jan97 1.11 @author Gnanasekaran Swaminathan @page @vskip 0pt plus 1filll Copyright @copyright{} 1992,1993,1994 Gnanasekaran Swaminathan @sp 2 This is Version: 12Jan97 1.11 of the C++ family of socket classes. @sp 2 Permission is granted to make and distribute verbatim copies of this document provided the copyright notice and this permission notice are preserved on all copies. @end titlepage @ifinfo @node Top, Copying, (dir), (dir) @top Socket++ Library Socket++ is a family of C++ classes that gives the same interface as the iostream classes for input and output for communication between processes.@refill This documentation describes Version: 12Jan97 1.11 of socket++ library.@refill @end ifinfo @menu * Copying:: Copyright information. * Acknowledgments:: Thanks! * Overview of Socket++:: Overview of socket++ library. * sockbuf Class:: Socket streambuf class. * sockAddr Class:: Base class for socket addresses. * sockinetbuf Class:: Socket class for INET address family. * sockinetaddr Class:: Address class for INET address family of sockets. * sockunixbuf Class:: Socket class for UNIX address family. * sockunixaddr Class:: Address class for UNIX address family of sockets. * sockstream Classes:: I/O socket stream classes and some examples. * pipestream Classes:: I/O stream classes that provides pipe, socketpair, and popen facilities. * Fork Class:: Use the Fork class to fork a child process. * protocol Class:: Protocol base class. * echo Class:: Class implementing the Echo protocol. * smtp Class:: Class implementing the SMTP protocol. * Error Handling:: Describes the default error handling in the socket++ library. * Pitfalls:: Common mistakes that socket++ library users make. * Index:: Index to concepts and program names @end menu @node Copying @unnumbered Socket++ Library Copyright Notice @cindex copyright notice @cindex Copyright Copyright (C) 1992,1993,1994 Gnanasekaran Swaminathan Permission is granted to use at your own risk and distribute this software in source and binary forms provided the above copyright notice and this paragraph are preserved on all copies. This software is provided "as is" with no express or implied warranty.@refill @node Acknowledgments @unnumbered Acknowledgments @cindex acknowledgments Gordon Joly for reporting bugs in pipestream class implementation and providing an ftp site for the socket++ library at cs.ucl.ac.uk:~ftp/coside/gnu/socket++-1.x.tar.gz He also knows how to make the socket++ library a shared library. Jim Anderson for reporting a bug in sockinet.C Carl Gay for reporting a bug and a fix in sockinet.C Oliver Imbusch for reporting a bug in Makefile.in and suggesting several enhancements for sockbuf class. Dierk Wendt for reporting errors in the socket++ documentation. Per Bothner for configure, config.sub, config.shared and move-if-change files that are used to generate Makefile. These files are taken from his libg++-2.4 and hence, these files are governed by the Copyright Notice found in the file LICENCE in libg++. @node Overview of Socket++ @chapter Overview of Socket++ Library @cindex overview of socket++ Socket++ library defines a family of C++ classes that can be used more effectively than directly calling the underlying low-level system functions. One distinct advantage of the socket++ is that it has the same interface as that of the iostream so that the users can perform type-safe input output. See your local IOStream library documentation for more information on iostreams.@refill @code{streambuf} counterpart of the socket++ is @code{sockbuf}. @code{sockbuf} is an endpoint for communication with yet another @code{sockbuf} or simply a @code{socket} descriptor. @code{sockbuf} has also methods that act as interfaces for most of the commonly used system calls that involve sockets. @xref{sockbuf Class}, for more information on the socket buffer class. For each communication domain, we derive a new class from @code{sockbuf} that has some additional methods that are specific to that domain. At present, only @var{unix} and @var{inet} domains are supported. @code{sockunixbuf} class and @code{sockinetbuf} class define the @var{unix} and @var{inet} domain of sockets respectively. @xref{sockunixbuf Class}, for @var{unix} sockets and @xref{sockinetbuf Class}, for @var{inet} sockets. We also have domain specific socket address classes that are derived from a common base class called @code{sockAddr}. @code{sockunixaddr} class is used for @var{unix} domain addresses and @code{sockinetaddr} class is used for @var{inet} domain addresses. For more information on address classes see @ref{sockAddr Class}, @ref{sockunixaddr Class}, and @ref{sockinetaddr Class}. @quotation @emph{Note}: @code{sockAddr} is not spelled @code{sockaddr} in order to prevent name clash with the @code{struct sockaddr} declared in @file{}. @end quotation We noted earlier that socket++ provides the same interface as the iostream library. For example, in the internet domain, we have @code{isockinet}, @code{osockinet}, and @code{iosockinet} classes that are counterparts to @code{istream}, @code{ostream}, and @code{iostream} classes of IOStream library. For more details on @code{iosockstream} classes see @xref{sockstream Classes}. The services of @code{pipe()}, @code{socketpair()}, and @code{popen()} system calls are provided by the @code{pipestream} class. @xref{pipestream Classes}. @node sockbuf Class @chapter @code{sockbuf} Class @cindex sockbuf class @cindex class sockbuf @code{sockbuf} class is derived from @code{streambuf} class of the iostream library. You can simultaneously read and write into a @code{sockbuf} just like you can listen and talk through a telephone. To accomplish the above goal, we maintain two independent buffers for reading and writing. @menu * Constructors:: How to construct a @code{sockbuf} object and how to open a socket? * Destructor:: How to destruct a @code{sockbuf} object and how to close a socket? * Reading and Writing:: How to use @code{sockbuf} as @code{streambuf}? * Connection Establishment:: How to bind an address and establish a connection? * Socket Options:: How to set and get socket options? * Timeouts:: How to gracefully handle connection inactivity? @end menu @node Constructors @section Constructors @cindex sockbuf constructors @findex sockbuf::type @code{sockbuf} constructors sets up an endpoint for communication. A @code{sockbuf} object so created can be read from and written to in linebuffered mode. To change mode, refer to @code{streambuf} class in your IOStream library. @quotation @cindex flushing buffers @emph{Note}: If you are using AT&T IOStream library, then the linebuffered mode is permanently turned off. Thus, you need to explicitly flush a socket stream. You can flush a socket stream buffer in one of the following four ways: @example // os is a socket ostream os << "this is a test" << endl; os << "this is a test\n" << flush; os << "this is a test\n"; os.flush (); os << "this is a test\n"; os->sync (); @end example @end quotation @code{sockbuf} objects are created as follows where @itemize @minus @item @code{s} and @code{so} are @code{sockbuf} objects @item @code{sd} is an integer which is a socket descriptor @item @code{af} and @code{proto} are integers which denote domain number and protocol number respectively @item @code{ty} is a @code{sockbuf::type} and must be one of @code{sockbuf::sock_stream}, @code{sockbuf::sock_dgram}, @code{sockbuf::sock_raw}, @code{sockbuf::sock_rdm}, and @code{sockbuf::sock_seqpacket} @end itemize @table @code @item sockbuf s(sd); @itemx sockbuf s; @findex sockbuf::sockbuf Set socket descriptor of @code{s} to @code{sd} (defaults to -1). @code{sockbuf} destructor will close @code{sd}. @item sockbuf s(af, ty, proto); Set socket descriptor of @code{s} to @code{::socket(af, int(ty), proto);} @item sockbuf so(s); Set socket descriptor of @code{so} to the socket descriptor of @code{s}. @item s.open(ty, proto) @findex sockbuf::open does nothing and returns simply @code{0}, the null pointer to @code{sockbuf}. @item s.is_open() @findex sockbuf::is_open returns a non-zero number if the socket descriptor is open else return 0. @item s = so; @findex sockbuf::operator= return a reference @code{s} after assigning @code{s} with @code{so}. @end table @node Destructor @section Destructor @cindex sockbuf destructor @findex sockbuf::shuthow @code{sockbuf::~sockbuf()} flushes output and closes its socket if no other sockbuf is referencing it and _S_DELETE_DONT_CLOSE flag is not set. It also deletes its read and write buffers. In what follows, @itemize @minus @item @code{s} is a @code{sockbuf} object @item @code{how} is of type @code{sockbuf::shuthow} and must be one of @code{sockbuf::shut_read}, @code{sockbuf::shut_write}, and @code{sockbuf::shut_readwrite} @end itemize @table @code @item sockbuf::~sockbuf() @findex sockbuf::~sockbuf flushes output and closes its socket if no other @code{sockbuf} object is referencing it before deleting its read and write buffers. If the _S_DELETE_DONT_CLOSE flag is set, then the socket is not closed. @item s.close() @findex sockbuf::close closes the socket even if it is referenced by other @code{sockbuf} objects and _S_DELETE_DONT_CLOSE flag is set. @item s.shutdown(how) @findex sockbuf::shutdown shuts down read if @code{how} is @code{sockbuf::shut_read}, shuts down write if @code{how} is @code{sockbuf::shut_write}, and shuts down both read and write if @code{how} is @code{sockbuf::shut_readwrite}. @end table @node Reading and Writing @section Reading and Writing @cindex sockbuf reading @cindex sockbuf writing @code{sockbuf} class offers several ways to read and write and tailors the behavior of several virtual functions of @code{streambuf} for socket communication. In case of error, @code{sockbuf::error(const char*)} is called. In what follows, @itemize @minus @item @code{s} is a @code{sockbuf} object @item @code{buf} is buffer of type @code{char*} @item @code{bufsz} is an integer and is less than @code{sizeof(buf)} @item @code{msgf} is an integer and denotes the message flag @item @code{sa} is of type @code{sockAddr} @item @code{msgh} is a pointer to @code{struct msghdr} @item @code{wp} is an integer and denotes time in seconds @item @code{c} is a char @end itemize @table @code @item s.is_open() @findex sockbuf::is_open returns a non-zero number if the socket descriptor is open else return 0. @item s.is_eof() @findex sockbuf::is_eof returns a non-zero number if the socket has seen EOF while reading else return 0. @item s.write(buf, bufsz) @findex sockbuf::write returns an int which must be equal to @code{bufsz} if @code{bufsz} chars in the @code{buf} are written successfully. It returns 0 if there is nothing to write or if, in case of timeouts, the socket is not ready for write @ref{Timeouts}. @item s.send(buf, bufsz, msgf) @findex sockbuf::send @findex sockbuf::msgflag same as @code{sockbuf::write} described above but allows the user to control the transmission of messages using the message flag @code{msgf}. If @code{msgf} is @code{sockbuf::msg_oob} and the socket type of @code{s} is @code{sockbuf::sock_stream}, @code{s} sends the message in @var{out-of-band} mode. If @code{msgf} is @code{sockbuf::msg_dontroute}, @code{s} sends the outgoing packets without routing. If @code{msgf} is 0, which is the default case, @code{sockbuf::send} behaves exactly like @code{sockbuf::write}. @item s.sendto(sa, buf, bufsz, msgf) @findex sockbuf::sendto same as @code{sockbuf::send} but works on unconnected sockets. @code{sa} specifies the @var{to} address for the message. @item s.sendmsg(msgh, msgf) @findex sockbuf::sendmsg same as @code{sockbuf::send} but sends a @code{struct msghdr} object instead. @item s.sys_write(buf, bufsz) @findex sockbuf::sys_write calls @code{sockbuf::write} and returns the result. Unlike @code{sockbuf::write} @code{sockbuf::sys_write} is declared as a virtual function. @item s.read(buf, bufsz) @findex sockbuf::read returns an int which is the number of chars read into the @code{buf}. In case of EOF, return EOF. Here, @code{bufsz} indicates the size of the @code{buf}. In case of timeouts, return 0 @ref{Timeouts}. @item s.recv(buf, bufsz, msgf) @findex sockbuf::recv @findex sockbuf::msgflag same as @code{sockbuf::read} described above but allows the user to receive @var{out-of-band} data if @code{msgf} is @code{sockbuf::msg_oob} or to preview the data waiting to be read if @code{msgf} is @code{sockbuf::msg_peek}. If @code{msgf} is 0, which is the default case, @code{sockbuf::recv} behaves exactly like @code{sockbuf::read}. @item s.recvfrom(sa, buf, bufsz, msgf) @findex sockbuf::recvfrom same as @code{sockbuf::recv} but works on unconnected sockets. @code{sa} specifies the @var{from} address for the message. @item s.recvmsg(msgh, msgf) @findex sockbuf::recvmsg same as @code{sockbuf::recv} but reads a @code{struct msghdr} object instead. @item s.sys_read(buf, bufsz) @findex sockbuf::sys_read calls @code{sockbuf::read} and returns the result. Unlike @code{sockbuf::read} @code{sockbuf::sys_read} is declared as a virtual function. @item s.is_readready(wp_sec, wp_usec) @findex sockbuf::is_readready returns a non-zero int if @code{s} has data waiting to be read from the communication channel. If @code{wp_sec >= 0}, it waits for @code{wp_sec 10^6 + wp_usec} microseconds before returning 0 in case there are no data waiting to be read. If @code{wp_sec < 0}, then it waits until a datum arrives at the communication channel. @code{wp_usec} defaults to 0. @quotation @emph{Please Note}: The data waiting in @code{sockbuf}'s own buffer is different from the data waiting in the communication channel. @end quotation @item s.is_writeready(wp_sec, wp_usec) @findex sockbuf::is_writeready returns a non-zero int if data can be written onto the communication channel of @code{s}. If @code{wp_sec >= 0}, it waits for @code{wp_sec 10^6 + wp_usec} microseconds before returning 0 in case no data can be written. If @code{wp_sec < 0}, then it waits until the communication channel is ready to accept data. @code{wp_usec} defaults to 0. @quotation @emph{Please Note}: The buffer of the @code{sockbuf} class is different from the buffer of the communication channel buffer. @end quotation @item s.is_exceptionpending(wp_sec, wp_usec) @findex sockbuf::is_exceptionpending returns non-zero int if @code{s} has any exception events pending. If @code{wp_sec >= 0}, it waits for @code{wp_sec 10^6 + wp_usec} microseconds before returning 0 in case @code{s} does not have any exception events pending. If @code{wp_sec < 0}, then it waits until an expception event occurs. @code{wp_usec} defaults to 0. @quotation @emph{Please Note}: The exceptions that @code{sockbuf::is_exceptionpending} is looking for are different from the C++ exceptions. @end quotation @item s.flush_output() @findex sockbuf::flush_output flushes the output buffer and returns the number of chars flushed. In case of error, return EOF. @code{sockbuf::flush_output} is a protected member function and it is not available for general public. @item s.doallocate() @findex sockbuf::doallocate allocates free store for read and write buffers of @code{s} and returns 1 if allocation is done and returns 0 if there is no need. @code{sockbuf::doallocate} is a protected virtual member function and it is not available for general public. @item s.underflow() @findex sockbuf::underflow returns the unread char in the buffer as an unsigned char if there is any. Else returns EOF if @code{s} cannot allocate space for the buffers, cannot read or peer is closed. @code{sockbuf::underflow} is a protected virtual member function and it is not available for general public. @item s.overflow(c) @findex sockbuf::overflow if @code{c==EOF}, call and return the result of @code{flush_output()}, else if @code{c=='\n'} and @code{s} is linebuffered, call @code{flush_output()} and return @code{c} unless @code{flush_output()} returns EOF, in which case return EOF. In any other case, insert char @code{c} into the buffer and return @code{c} as an unsigned char. @code{sockbuf::overflow} is a protected member virtual function and it is not available for general public. @quotation @emph{Node:} linebuffered mode does not work with AT&T IOStream library. Use explicit flushing to flush @code{sockbuf}. @end quotation @item s.sync() @findex sockbuf::sync @cindex flushing output calls @code{flush_output()} and returns the result. Useful if the user needs to flush the output without writing newline char into the write buffer. @item s.xsputn(buf, bufsz) @findex sockbuf::xsputn write @code{bufsz} chars into the buffer and returns the number of chars successfully written. Output is flushed if any char in @code{buf[0..bufsz-1]} is @code{'\n'}. @item s.recvtimeout(wp) @findex sockbuf::recvtimeout sets the recv timeout to @code{wp} seconds. If @code{wp} is -1, it is a block and if @code{wp} is 0, it is a poll. It affects all read functions. If the socket is not read ready within @code{wp} seconds, the read call will return 0. It also affects @code{sockbuf::underflow}. @code{sockbuf::underflow} will not set the @code{_S_EOF_SEEN} flag if it is returning EOF because of timeout. @code{sockbuf::recvtimeout} returns the old recv timeout value. @item s.sendtimeout(wp) @findex sockbuf::sendtimeout sets the send timeout to @code{wp} seconds. If @code{wp} is -1, it is a block and if @code{wp} is 0, it is a poll. It affects all write functions. If the socket is not write ready within @code{wp} seconds, the write call will return 0. @code{sockbuf::sendtimeout} returns the old send timeout value. @end table @node Connection Establishment @section Establishing connections @cindex connection establishment @cindex names A name must be bound to a @code{sockbuf} if processes want to refer to it and use it for communication. Names must be unique. A @var{unix} name is a 3-tuple, @var{}. An @var{inet} name is a 5-tuple, @var{}. @code{sockbuf::bind} is used to specify the local half of the name---@var{} for @var{unix} and @var{} for @var{inet}. @code{sockbuf::connect} and @code{sockbuf::accept} are used to specify the peer half of the name---@var{} for @var{unix} and @var{} for @var{inet}. In what follows, @itemize @minus @item @code{s} and @code{so} are @code{sockbuf} objects @item @code{sa} is a @code{sockAddr} object @item @code{nc} is an integer denoting the number of connections to allow @end itemize @table @code @item s.bind(sa) @findex sockbuf::bind @cindex binding addresses binds @code{sockAddr} @code{sa} as the local half of the name for @code{s}. It returns 0 on success and returns the errno on failure. @item s.connect(sa) @findex sockbuf::connect @cindex connect @code{sockbuf::connect} uses @code{sa} to provide the peer half of the name for @code{s} and to establish the connection itself. @code{sockbuf::connect} also provides the local half of the name automatically and hence, the user should not use @code{sockbuf::bind} to bind any local half of the name. It returns 0 on success and returns the errno on failure. @item s.listen(nc) @findex sockbuf::listen @cindex listening makes @code{s} ready to accept connections. @code{nc} specifies the maximum number of outstanding connections that may be queued and must be at least 1 and less than or equal to @code{sockbuf::somaxconn} which is usually 5 on most systems. @item sockbuf so = s.accept(sa) @itemx sockbuf so = s.accept() @findex sockbuf::accept @cindex accepting connections accepts connections and returns the peer address in @code{sa}. @code{s} must be a listening @code{sockbuf}. See @code{sockbuf::listen} above. @end table @node Socket Options @section Getting and Setting Socket Options @cindex socket options @cindex option setting @cindex option getting Socket options are used to control a socket communication. New options can be set and old value of the options can be retrived at the protocol level or at the socket level by using @code{setopt} and @code{getopt} member functions. In addition, you can also use special member functions to get and set specific options. In what follows, @itemize @minus @item @code{s} is a @code{sockbuf} object @item @code{opval} is an integer and denotes the option value @item @code{op} is of type @code{sockbuf::option} and must be one of @itemize @bullet @item @code{sockbuf::so_error} used to retrieve and clear error status @item @code{sockbuf::so_type} used to retrieve type of the socket @item @code{sockbuf::so_debug} is used to specify recording of debugging information @item @code{sockbuf::so_reuseaddr} is used to specify the reuse of local address @item @code{sockbuf::so_keepalive} is used to specify whether to keep connections alive or not @item @code{sockbuf::so_dontroute} is used to specify whether to route messages or not @item @code{sockbuf::so_broadcast} is used to specify whether to broadcast @code{sockbuf::sock_dgram} messages or not @item @code{sockbuf::so_oobinline} is used to specify whether to inline @var{out-of-band} data or not. @item @code{sockbuf::so_linger} is used to specify for how long to linger before shutting down @item @code{sockbuf::so_sndbuf} is used to retrieve and to set the size of the send buffer (communication channel buffer not @code{sockbuf}'s internal buffer) @item @code{sockbuf::so_rcvbuf} is used to retrieve and to set the size of the recv buffer (communication channel buffer not @code{sockbuf}'s internal buffer) @end itemize @end itemize @table @code @item s.getopt(op, &opval, sizeof(opval), oplevel) @findex sockbuf::getopt @cindex getsockopt gets the option value of the @code{sockbuf::option} @code{op} at the option level @code{oplevel} in @code{opval}. It returns the actual size of the buffer @code{opval} used. The default value of the @code{oplevel} is @code{sockbuf::sol_socket}. @item s.setopt(op, &opval, sizeof(opval), oplevel) @findex sockbuf::setopt @cindex setsockopt sets the option value of the @code{sockbuf::option} @code{op} at the option level @code{oplevel} to @code{opval}. The default value of the @code{oplevel} is @code{sockbuf::sol_socket}. @item s.gettype() @findex sockbuf::gettype gets the socket type of @code{s}. The return type is @code{sockbuf::type}. @item s.clearerror() @findex sockbuf::clearerror gets and clears the error status of the socket. @item s.debug(opval) @findex sockbuf::debug if @code{opval} is not -1, set the @code{sockbuf::so_debug} option value to @code{opval}. In any case, return the old option value of @code{sockbuf::so_debug} option. The default value of @code{opval} is -1. @item s.reuseaddr(opval) @findex sockbuf::reuseaddr if @code{opval} is not -1, set the @code{sockbuf::so_reuseaddr} option value to @code{opval}. In any case, return the old option value of @code{sockbuf::so_reuseaddr} option. The default value of @code{opval} is -1. @item s.dontroute(opval) @findex sockbuf::dontroute if @code{opval} is not -1, set the @code{sockbuf::so_dontroute} option value to @code{opval}. In any case, return the old option value of @code{sockbuf::so_dontroute} option. The default value of @code{opval} is -1. @item s.oobinline(opval) @findex sockbuf::oobinline if @code{opval} is not -1, set the @code{sockbuf::so_oobinline} option value to @code{opval}. In any case, return the old option value of @code{sockbuf::so_oobinline} option. The default value of @code{opval} is -1. @item s.broadcast(opval) @findex sockbuf::broadcast if @code{opval} is not -1, set the @code{sockbuf::so_broadcast} option value to @code{opval}. In any case, return the old option value of @code{sockbuf::so_broadcast} option. The default value of @code{opval} is -1. @item s.keepalive(opval) @findex sockbuf::keepalive if @code{opval} is not -1, set the @code{sockbuf::so_keepalive} option value to @code{opval}. In any case, return the old option value of @code{sockbuf::so_keepalive} option. The default value of @code{opval} is -1. @item s.sendbufsz(opval) @findex sockbuf::sndbuf if @code{opval} is not -1, set the new send buffer size to @code{opval}. In any case, return the old buffer size of the send buffer. The default value of @code{opval} is -1. @item s.recvbufsz(opval) @findex sockbuf::rcvbuf if @code{opval} is not -1, set the new recv buffer size to @code{opval}. In any case, return the old buffer size of the recv buffer. The default value of @code{opval} is -1. @item s.linger(tim) @findex sockbuf::linger if @code{tim} is positive, set the linger time to tim seconds. If @code{tim} is 0, set the linger off. In any case, return the old linger time if it was set earlier. Otherwise return -1. The default value of @code{tim} is -1. @end table @node Timeouts @section Time Outs While Reading and Writing @cindex timeouts @cindex read timeouts @cindex write timeouts Time outs are very useful in handling data of unknown sizes and formats while reading and writing. For example, how does one communicate with a socket that sends chunks of data of unknown size and format? If only @code{sockbuf::read} is used without time out, it will block indefinitely. In such cases, time out facility is the only answer. The following idiom is recommended. @xref{Pitfalls} for a complete example. @example int old_tmo = s.recvtimeout (2) // set time out (2 seconds here) for (;;) @{ // read or write char buf[256]; int rval = s.read (buf, 256); if (rval == 0 || rval == EOF) break; // process buf here @} s.recvtimeout (old_tmo); // reset time out @end example In what follows, @itemize @minus @item @code{s} is a @code{sockbuf} object @item @code{wp} is waiting period in seconds @end itemize @table @code @item s.recvtimeout(wp) @findex sockbuf::recvtimeout sets the recv timeout to @code{wp} seconds. If @code{wp} is -1, it is a block and if @code{wp} is 0, it is a poll. It affects all read functions. If the socket is not read ready within @code{wp} seconds, the read call will return 0. It also affects @code{sockbuf::underflow}. @code{sockbuf::underflow} will not set the @code{_S_EOF_SEEN} flag if it is returning EOF because of timeout. @code{sockbuf::recvtimeout} returns the old recv timeout value. @item s.sendtimeout(wp) @findex sockbuf::sendtimeout sets the send timeout to @code{wp} seconds. If @code{wp} is -1, it is a block and if @code{wp} is 0, it is a poll. It affects all write functions. If the socket is not write ready within @code{wp} seconds, the write call will return 0. @code{sockbuf::sendtimeout} returns the old send timeout value. @end table @node sockAddr Class @chapter sockAddr Class @cindex sockAddr class @cindex base address class Class @code{sockAddr} is an abstract base class for all socket address classes. That is, domain specific socket address classes are all derived from @code{sockAddr} class. @quotation @emph{Note}: @code{sockAddr} is not spelled @code{sockaddr} in order to prevent name clash with @code{struct sockaddr} declared in @file{}. @end quotation Non-abstract derived classes must have definitions for the following functions. @table @code @item sockAddr::operator void* () @findex sockAddr::operator void* should simply return @code{this}. @item sockAddr::size() @findex sockAddr::size should return @code{sizeof(*this)}. The return type is @code{int}. @item sockAddr::family() @findex sockAddr::family should return address family (domain name) of the socket address. The return type is @code{int} @end table @node sockinetbuf Class @chapter sockinetbuf Class @cindex sockinetbuf class @cindex inet domain @code{sockinetbuf} class is derived from @code{sockbuf} class and inherits most of the public functions of @code{sockbuf}. @xref{sockbuf Class}, for more information on @code{sockbuf}. In addition, it provides methods for getting @code{sockinetaddr} of local and peer connections. @xref{sockinetaddr Class}, for more information on @code{sockinetaddr}. @menu * Methods sockinetbuf:: Describes sockinetbuf member functions. * Datagram INET:: A pair of example programs demonstrating datagram connection in inet domain. * Stream INET:: A pair of example programs demonstrating stream connection in inet domain. @end menu @node Methods sockinetbuf @section Methods In what follows, @itemize @minus @item @code{ty} denotes the type of the socket connection and is of type @code{sockbuf::type} @item @code{proto} denotes the protocol and is of type int @item @code{si, ins} are @code{sockbuf} objects and are in @var{inet} domain @item @code{adr} denotes an @var{inet} address in host byte order and is of type unsigned long @item @code{serv} denotes a service like "nntp" and is of type char* @item @code{proto} denotes a protocol like "tcp" and is of type char* @item @code{thostname} is of type char* and denotes the name of a host like @code{"kelvin.acc.virginia.edu"} or @code{"128.143.24.31"}. @item @code{portno} denotes a port in host byte order and is of type int @end itemize @table @code @item sockinetbuf ins(ty, proto) @findex sockinetbuf::sockinetbuf Constructs a @code{sockinetbuf} object @code{ins} whose socket communication type is @code{ty} and protocol is @code{proto}. @code{proto} defaults to 0. @item sockinetbuf ins(si) Constructs a @code{sockinetbuf} object @code{ins} which uses the same socket as @code{si} uses. @item ins = si @findex sockinetbuf::operator = performs the same function as @code{sockbuf::operator=}. @xref{sockbuf Class}, for more details. @item ins.open(ty, proto) @findex sockinetbuf::open create a new @code{sockinetbuf} whose type and protocol are @code{ty} and @code{proto} respectively and assign it to @code{ins}. @item sockinetaddr sina = ins.localaddr() @findex sockinetbuf::localaddr @findex getsockname (see sockinetbuf::localaddr) returns the local @var{inet} address of the @code{sockinetbuf} object @code{ins}. The call will make sense only after a call to either @code{sockbuf::bind} or @code{sockbuf::connect}. @item sockinetaddr sina = ins.peeraddr() @findex sockinetbuf::peeraddr @findex getpeername (see sockinetbuf::peeraddr) returns the peer @var{inet} address of the @code{sockinetbuf} object @code{ins}. The call will make sense only after a call to @code{sockbuf::connect}. @item const char* hn = ins.localhost() @findex sockinetbuf::localhost returns the local @var{inet} thostname of the @code{sockinetbuf} object @code{ins}. The call will make sense only after a call to either @code{sockbuf::bind} or @code{sockbuf::connect}. @item const char* hn = ins.peerhost() @findex sockinetbuf::peerhost returns the peer @var{inet} thostname of the @code{sockinetbuf} object @code{ins}. The call will make sense only after a call to @code{sockbuf::connect}. @item int pn = ins.localport() @findex sockinetbuf::localport returns the local @var{inet} port number of the @code{sockinetbuf} object @code{ins} in host byte order. The call will make sense only after a call to either @code{sockbuf::bind} or @code{sockbuf::connect}. @item int pn = ins.peerport() @findex sockinetbuf::peerport returns the peer @var{inet} port number of the @code{sockinetbuf} object @code{ins} in local host byte order. The call will make sense only after a call to @code{sockbuf::connect}. @item ins.bind () @findex sockinetbuf::bind binds @code{ins} to the default address @var{INADDR_ANY} and the default port. It returns 0 on success and returns the errno on failure. @item ins.bind (adr, portno) binds @code{ins} to the address @code{adr} and the port @code{portno}. It returns 0 on success and returns the errno on failure. @item ins.bind (adr, serv, proto) binds @code{ins} to the address, @code{adr} and the port corresponding to the service @code{serv} and the protocol @code{proto}>. It returns 0 on success and returns the errno on failure. @item ins.bind (thostname, portno) binds @code{ins} to the address corresponding to the hostname @code{thostname} and the port @code{portno}. It returns 0 on success and returns the errno on failure. @item ins.bind (thostname, serv, proto) binds @code{ins} to the address corresponding to the hostname @code{thostname} and the port corresponding to the service @code{serv} and the protocol @code{proto}>. It returns 0 on success and returns the errno on failure. @item ins.connect (adr, portno) @findex sockinetbuf::connect connects @code{ins} to the address @code{adr} and the port @code{portno}. It returns 0 on success and returns the errno on failure. @item ins.connect (adr, serv, proto) connects @code{ins} to the address, @code{adr} and the port corresponding to the service @code{serv} and the protocol @code{proto}>. It returns 0 on success and returns the errno on failure. @item ins.connect (thostname, portno) connects @code{ins} to the address corresponding to the hostname @code{thostname} and the port @code{portno}. It returns 0 on success and returns the errno on failure. @item ins.connect (thostname, serv, proto) connects @code{ins} to the address corresponding to the hostname @code{thostname} and the port corresponding to the service @code{serv} and the protocol @code{proto}>. It returns 0 on success and returns the errno on failure. @end table @node Datagram INET @section @var{inet} Datagram Sockets @cindex sockinetbuf dgram example @cindex datagram inet @cindex isockinet example @cindex osockinet example The following two programs illustrates how to use @code{sockinetbuf} class for datagram connection in @var{inet} domain. @code{tdinread.cc} also shows how to use @code{isockinet} class and @code{tdinwrite.cc} shows how to use @code{osockinet} class. @subheading tdinread.cc @example // reads data sent by tdinwrite.cc #include int main(int ac, char** av) @{ isockinet is (sockbuf::sock_dgram); is->bind(); cout << "localhost = " << so.localhost() << endl << "localport = " << so.localport() << endl; char buf[256]; int n; is >> n; cout << av[0] << ": "; while(n--) @{ is >> buf; cout << buf << ' '; @} cout << endl; return 0; @} @end example @subheading tdinwrite.cc @example // sends data to tdinread.cc #include #include int main(int ac, char** av) @{ if (ac < 3) @{ cerr << "USAGE: " << av[0] << " thostname port-number " << "data ... " << endl; return 1; @} osockinet os (sockbuf::sock_dgram); os->connect (av[1], atoi(av[2])); cout << "local: " << so.localport() << ' ' << so.localhost() << endl << "peer: " << so.peerport() << ' ' << so.peerhost() << endl; os << ac-3; av += 3; while(*av) os << *av++ << ' '; os << endl; return 0; @} @end example @node Stream INET @section @var{inet} Stream Sockets @cindex stream inet @cindex sockinetbuf stream example @cindex iosockinet example The following two programs illustrates the use of @code{sockinetbuf} class for stream connection in @var{inet} domain. It also shows how to use @code{iosockinet} class. @subheading tsinread.cc @example // receives strings from tsinwrite.cc and sends the strlen // of each string back to tsinwrite.cc #include int main() @{ sockinetbuf si(sockbuf::sock_stream); si.bind(); cout << si.localhost() << ' ' << si.localport() << endl; si.listen(); iosockinet s = si.accept(); char buf[1024]; while (s >> buf) @{ cout << buf << ' '; s << ::strlen(buf) << endl; @} cout << endl; return 0; @} @end example @subheading tsinwrite.cc @example // sends strings to tsinread.cc and gets back their length // usage: tsinwrite hostname portno // see the output of tsinread for what hostname and portno to use #include #include int main(int ac, char** av) @{ iosockinet sio (sockbuf::sock_stream); sio->connect (av[1], atoi (av[2])); sio << "Hello! This is a test\n" << flush; // terminate the while loop in tsinread.cc si.shutdown(sockbuf::shut_write); int len; while (s >> len) cout << len << ' '; cout << endl; return 0; @} @end example @node sockinetaddr Class @chapter sockinetaddr Class @cindex sockinetaddr class @cindex inet address class Class @code{sockinetaddr} is derived from @code{sockAddr} declared in @code{} and from @code{sockaddr_in} declared in @code{}. Always use a @code{sockinetaddr} object for an address with @var{inet} domain of sockets. @xref{Connection Establishment}. In what follows, @itemize @minus @item @code{adr} denotes an @var{inet} address in host byte order and is of type unsigned long @item @code{serv} denotes a service like "nntp" and is of type char* @item @code{proto} denotes a protocol like "tcp" and is of type char* @item @code{thostname} is of type char* and denotes the name of a host like @code{"kelvin.acc.virginia.edu"} or @code{"128.143.24.31"}. @item @code{portno} denotes a port in host byte order and is of type int @end itemize @table @code @item sockinetaddr sina @findex sockinetaddr::sockinetaddr Constructs a @code{sockinetaddr} object @code{sina} with default address @var{INADDR_ANY} and default port number 0. @item sockinetaddr sina(adr, portno) Constructs a @code{sockinetaddr} object @code{sina} setting inet address to @code{adr} and the port number to @code{portno}. @code{portno} defaults to 0. @item sockinetaddr sina(adr, serv, proto) Constructs a @code{sockinetaddr} object @code{sina} setting inet address to @code{adr} and the port number corresponding to the service @code{serv} and the protocol @code{proto}. The protocol defaults to "tcp". @item sockinetaddr sina(thostname, portno) Constructs a @code{sockinetaddr} object @code{sina} setting inet address to the address of @code{thostname} and the port number to @code{portno}. @code{portno} defaults to 0. @item sockinetaddr sina(thostname, serv, proto) Constructs a @code{sockinetaddr} object @code{sina} setting inet address to the address of @code{thostname} and the port number corresponding to the service @code{serv} and the protocol @code{proto}. The protocol defaults to "tcp". @item void* a = sina @findex sockinetaddr::operator void* returns the address of the @code{sockaddr_in} part of @code{sockinetaddr} object @code{sina} as void*. @item int sz = sina.size() @findex sockinetaddr::size returns the sizeof @code{sockaddr_in} part of @code{sockinetaddr} object @code{sina}. @item int af = sina.family() @findex sockinetaddr::family returns @code{sockinetbuf::af_inet} if all is well. @item int pn = sina.getport() @findex sockinetaddr::getport returns the port number of the @code{sockinetaddr} object @code{sina} in host byte order. @item const char* hn = getthostname() @findex sockinetaddr::getthostname returns the host name of the @code{sockinetaddr} object @code{sina}. @end table @node sockunixbuf Class @chapter sockunixbuf Class @cindex sockunixbuf class @cindex unix domain @code{sockunixbuf} class is derived from @code{sockbuf} class declared in @code{} and hence, inherits most of the public member functions of @code{sockbuf}. @xref{sockbuf Class}, for more information on @code{sockbuf}. @menu * Methods sockunixbuf:: Describes sockunixbuf member functions * Datagram UNIX:: A pair of example programs demonstrating datagram connection in @var{unix} domain * Stream UNIX:: A pair of example programs demonstrating stream connection in @var{unix} domain @end menu @node Methods sockunixbuf @section Methods In what follows, @itemize @minus @item @code{ty} denotes the socket type and is of type @code{sockbuf::type} @item @code{proto} denotes the protocol number and is of type int @item @code{su} is a @code{sockbuf} and must be in @var{unix} domain @item @code{path} is the @var{unix} path name like "/tmp/unix_socket" @end itemize @table @code @item sockunixbuf uns(ty, proto) @findex sockunixbuf::sockunixbuf Constructs a @code{sockunixbuf} object @code{uns} with @code{ty} as its type and @code{proto} as its protocol number. @code{proto} defaults to 0. @item sockunixbuf uns = su Constructs a @code{sockunixbuf} object @code{uns} which uses the same socket as is used by @code{su}. @item uns = su @findex sockunixbuf::operator = @code{sockunixbuf} object @code{uns} closes its current socket if no other @code{sockbuf} is referring to it and uses the socket that @code{sockbuf} object @code{su} is using. @item uns.open(ty, proto) @findex sockunixbuf::open create a @code{sockunixbuf} object with @code{ty} as its type and @code{proto} as its protocol and assign the @code{sockunixbuf} object so created to @code{*this}. It returns @code{this}. @code{proto} defaults to 0. @item uns.bind(path) @findex sockunixbuf::bind binds @code{uns} to the @var{unix} pathname @code{path}. It returns 0 on success and returns the errno on failure. @item uns.connect(path) @findex sockunixbuf::connect connects @code{uns} to the @var{unix} pathname @code{path}. It returns 0 on success and returns the errno on failure. @end table @node Datagram UNIX @section @var{unix} Datagram Sockets @cindex datagram unix @cindex isockunix example @cindex osockunix example The following two programs illustrates how to use @code{sockunixbuf} class for datagram connection in @var{unix} domain. @code{tdunread.cc} also shows how to use @code{isockunix} class and @code{tdunwrite.cc} shows how to use @code{osockunix} class. @subheading tdunread.cc @example // reads data sent by tdunwrite.cc #include #include #include int main(int ac, char** av) @{ if (ac != 2) @{ cerr << "USAGE: " << av[0] << " socket_path_name\n"; return 1; @} // isockunix builds the sockunixbuf object isockunix su (sockbuf::sock_dgram); su->bind(av[1]); cout << "Socket name = " << av[1] << endl; if (chmod(av[1], 0777) == -1) @{ perror("chmod"); return 1; @} char buf[1024]; int i; su >> i; cout << av[0] << ": " << i << " strings: "; while (i--) @{ su >> buf; cout << buf << ' '; @} cout << endl; unlink(av[1]); return 0; @} @end example @subheading tdunwrite.cc @example // sends data to tdunread.cc #include int main(int ac, char** av) @{ if (ac < 2) @{ cerr << "USAGE: " << av[0] << " socket_path_name data...\n"; return 1; @} osockunix su (sockbuf::sock_dgram); su->connect (av[1]); su << ac << ' '; while (*av) @{ su << av[i] << ' '; av++; @} su << endl; return 0; @} @end example @node Stream UNIX @section @var{unix} Stream Sockets @cindex stream unix @cindex sockunixbuf example @cindex iosockunix example The following two programs illustrates how to use @code{sockunixbuf} class for stream connection in @var{unix} domain. It also shows how to use @code{iosockunix} class. @subheading tsunread.cc @example // exchanges char strings with tsunwrite.cc #include #include #include int main(int ac, char** av) @{ if (ac != 2) @{ cerr << "USAGE: " << av[0] << " socket_path_name\n"; return 1; @} sockunixbuf su(sockbuf::sock_stream); su.bind(av [1]); cout << "Socket name = " << av[1] << endl; if (chmod(av[1], 0777) == -1) @{ perror("chmod"); return 1; @} su.listen(3); iosockunix ioput = su.accept (); char buf[1024]; ioput << av[0] << ' ' << av[1] << endl; while ( ioput >> buf ) cout << av[0] << ": " << buf << endl; unlink(av[1]); return 0; @} @end example @subheading tsunwrite.cc @example // exchanges char strings with tsunread.cc #include int main(int ac, char** av) @{ if (ac < 2) @{ cerr << "USAGE: " << av[0] << " socket_path_name data...\n"; return 1; @} iosockunix oput (sockbuf::sock_stream); oput->connect (av [1]); char buf[128]; oput >> buf; cout << buf << ' '; oput >> buf; cout << buf << endl; while (*av) oput << *av++ << ' '; oput << endl; return 0; @} @end example @node sockunixaddr Class @chapter sockunixaddr Class @cindex sockunixaddr class @cindex unix address class Class @code{sockunixaddr} is derived from class @code{sockAddr} declared in @code{} and from struct @code{sockaddr_un} declared in @code{}. Always use @code{sockunixaddr} objects for addresses with @var{unix} domain of sockets. @xref{Connection Establishment}. In what follows, @itemize @minus @item @code{path} is the @var{unix} path name like "/tmp/unix_socket" @end itemize @table @code @item sockunixaddr suna(path) @findex sockunixaddr::sockunixaddr Constructs a @code{sockunixaddr} object @code{suna} with @code{path} as the @var{unix} path name. @item void* a = suna @findex sockunixaddr::operator void* returns the address of the @code{sockaddr_un} part of @code{sockunixaddr} object @code{suna} as void*. @item int sz = suna.size() @findex sockunixaddr::size returns the sizeof @code{sockaddr_un} part of @code{sockunixaddr} object @code{suna}. @item int af = suna.family() @findex sockunixaddr::family returns @code{sockunixbuf::af_unix} if all is well. @end table @node sockstream Classes @chapter sockstream Classes @cindex sockstream classes @cindex iosockstream classes sockstream classes are designed in such a way that they provide the same interface as their stream counterparts do. We have @code{isockstream} derived from @code{istream} and @code{osockstream} derived from @code{ostream}. We also have @code{iosockstream} which is derived from @code{iostream}. Each domain also has its own set of @code{stream} classes. For example, @code{unix} domain has @code{isockunix}, @code{osockunix}, and @code{iosockunix} derived from @code{isockstream}, @code{osockstream}, and @code{iosockstream} respectively. Similarly, @code{inet} domain has @code{isockinet}, @code{osockinet}, and @code{iosockinet}. @menu * iosockstream:: Generic IOStream classes for sockbuf buffers. * iosockinet:: IOStream classes for @var{inet} domain of sockets. * iosockunix:: IOStream classes for @var{unix} domain of sockets. @end menu @node iosockstream @section iosockstreams @subsection isockstream Class @cindex isockstream class Since @code{isockstream} is publicly derived from @code{istream}, most of the public functions of @code{istream} are also available in @code{isockstream}. @code{isockstream} redefines @code{rdbuf()} defined in its virtual base class @code{ios}. Since, @code{ios::rdbuf()} is not virtual, care must be taken to call the correct @code{rdbuf()} through a reference or a pointer to an object of class @code{isockstream}. In what follows, @itemize @minus @item @code{sb} is a @code{sockbuf} object @item @code{sbp} is a pointer to a @code{sockbuf} object @end itemize @table @code @item isockstream is(sb) @findex isockstream::isockstream Constructs an @code{isockstream} object @code{is} with @code{sb} as its @code{sockbuf}. @item isockstream is(sbp) Constructs an @code{isockstream} object @code{is} with @code{*sbp} as its @code{sockbuf}. @item sbp = is.rdbuf() @findex isockstream::rdbuf returns a pointer to the @code{sockbuf} of the @code{isockstream} object @code{is}. @item isockstream::operator -> () @findex isockstream::operator-> returns a pointer to the @code{isockstream}'s @code{sockbuf} so that the user can use @code{isockstream} object as a @code{sockbuf} object. @example is->connect (sa); // same as is.rdbuf()->connect (sa); @end example @end table @subsection osockstream Class @cindex osockstream class Since @code{osockstream} is publicly derived from @code{ostream}, most of the public functions of @code{ostream} are also available in @code{osockstream}. @code{osockstream} redefines @code{rdbuf()} defined in its virtual base class @code{ios}. Since, @code{ios::rdbuf()} is not virtual, care must be taken to call the correct @code{rdbuf()} through a reference or a pointer to an object of class @code{osockstream}. In what follows, @itemize @minus @item @code{sb} is a @code{sockbuf} object @item @code{sbp} is a pointer to a @code{sockbuf} object @end itemize @table @code @item osockstream os(sb) @findex osockstream::osockstream Constructs an @code{osockstream} object @code{os} with @code{sb} as its @code{sockbuf}. @item osockstream os(sbp) Constructs an @code{osockstream} object @code{os} with @code{*sbp} as its @code{sockbuf}. @item sbp = os.rdbuf() @findex osockstream::rdbuf returns a pointer to the @code{sockbuf} of the @code{osockstream} object @code{os}. @item osockstream::operator -> () @findex osockstream::operator-> returns a pointer to the @code{osockstream}'s @code{sockbuf} so that the user can use @code{osockstream} object as a @code{sockbuf} object. @example os->connect (sa); // same as os.rdbuf()->connect (sa); @end example @end table @subsection iosockstream Class @cindex iosockstream class Since @code{iosockstream} is publicly derived from @code{iostream}, most of the public functions of @code{iostream} are also available in @code{iosockstream}. @code{iosockstream} redefines @code{rdbuf()} defined in its virtual base class @code{ios}. Since, @code{ios::rdbuf()} is not virtual, care must be taken to call the correct @code{rdbuf()} through a reference or a pointer to an object of class @code{iosockstream}. In what follows, @itemize @minus @item @code{sb} is a @code{sockbuf} object @item @code{sbp} is a pointer to a @code{sockbuf} object @end itemize @table @code @item iosockstream io(sb) @findex iosockstream::iosockstream Constructs an @code{iosockstream} object @code{io} with @code{sb} as its @code{sockbuf}. @item iosockstream io(sbp) Constructs an @code{iosockstream} object @code{io} with @code{*sbp} as its @code{sockbuf}. @item sbp = io.rdbuf() @findex iosockstream::rdbuf returns a pointer to the @code{sockbuf} of the @code{iosockstream} object @code{io}. @item iosockstream::operator -> () @findex iosockstream::operator-> returns a pointer to the @code{iosockstream}'s @code{sockbuf} so that the user can use @code{iosockstream} object as a @code{sockbuf} object. @example io->connect (sa); // same as io.rdbuf()->connect (sa); @end example @end table @node iosockinet @section iosockinet Stream Classes We discus only @code{isockinet} class here. @code{osockinet} and @code{iosockinet} are similar and are left out. However, they are covered in the examples that follow. @subsection isockinet @cindex isockinet class @cindex class isockinet @code{isockinet} is used to handle interprocess communication in @var{inet} domain. It is derived from @code{isockstream} class and it uses a @code{sockinetbuf} as its stream buffer. @xref{iosockstream}, for more details on @code{isockstream}. @xref{sockinetbuf Class}, for information on @code{sockinetbuf}. In what follows, @itemize @minus @item @code{ty} is a @code{sockbuf::type} and must be one of @code{sockbuf::sock_stream}, @code{sockbuf::sock_dgram}, @code{sockbuf::sock_raw}, @code{sockbuf::sock_rdm}, and @code{sockbuf::sock_seqpacket} @item @code{proto} denotes the protocol number and is of type int @item @code{sb} is a @code{sockbuf} object and must be in @var{inet} domain @item @code{sinp} is a pointer to an object of @code{sockinetbuf} @end itemize @table @code @item isockinet is (ty, proto) @findex isockinet::isockinet constructs an @code{isockinet} object @code{is} whose @code{sockinetbuf} buffer is of the type @code{ty} and has the protocol number @code{proto}. The default protocol number is 0. @item isockinet is (sb) constructs a @code{isockinet} object @code{is} whose @code{sockinetbuf} is @code{sb}. @code{sb} must be in @var{inet} domain. @item isockinet is (sinp) constructs a @code{isockinet} object @code{is} whose @code{sockinetbuf} is @code{sinp}. @item sinp = is.rdbuf () @findex isockinet::rdbuf returns a pointer to the @code{sockinetbuf} of @code{isockinet} object @code{is}. @item isockinet::operator -> @findex isockinet::operator-> returns @code{sockinetbuf} of @code{sockinet} so that the @code{sockinet} object acts as a smart pointer to @code{sockinetbuf}. @example is->localhost (); // same as is.rdbuf ()->localhost (); @end example @end table @subsection iosockinet examples @cindex iosockinet examples The first pair of examples demonstrates datagram socket connections in the @var{inet} domain. First, @code{tdinread} prints its local host and local port on stdout and waits for input in the connection. @code{tdinwrite} is started with the local host and local port of @code{tdinread} as arguments. It sends the string "How do ye do!" to @code{tdinread} which in turn reads the string and prints on its stdout. @example // tdinread.cc #include int main () @{ char buf[256]; isockinet is (sockbuf::sock_dgram); is->bind (); cout << is->localhost() << ' ' << is->localport() << endl; is.getline (buf); cout << buf << endl; return 0; @} @end example @example // tdinwrite.cc--tdinwrite hostname portno #include #include int main (int ac, char** av) @{ osockinet os (sockbuf::sock_dgram); os->connect (av[1], atoi(av[2])); os << "How do ye do!" << endl; return 0; @} @end example The next example communicates with an nntp server through a @code{sockbuf::sock_stream} socket connection in @var{inet} domain. After establishing a connection to the nntp server, it sends a "HELP" command and gets back the HELP message before sending the "QUIT" command. @example // tnntp.cc #include int main () @{ char buf[1024]; iosockinet io (sockbuf::sock_stream); io->connect ("murdoch.acc.virginia.edu", "nntp", "tcp"); io.getline (buf, 1024); cout << buf << endl; io << "HELP\r\n" << flush; io.getline (buf, 1024); cout << buf << endl; while (io.getline (buf, 1024)) if (buf[0] == '.' && buf[1] == '\r') break; else if (buf[0] == '.' && buf[1] == '.') cout << buf+1 << endl; else cout << buf << endl; io << "QUIT\r\n" << flush; io.getline (buf, 1024); cout << buf << endl; return 0; @} @end example @node iosockunix @section iosockunix Classes @cindex iosockunix class We discuss only @code{isockunix} here. @code{osockunix} and @code{iosockunix} are similar. @subsection isockunix class @cindex isockunix class @cindex class isockunix @code{isockunix} is used to handle interprocess communication in @var{unix} domain. It is derived from @code{isockstream} class and it uses a @code{sockunixbuf} as its stream buffer. @xref{iosockstream}, for more details on @code{isockstream}. @xref{sockunixbuf Class}, for information on @code{sockunixbuf}. In what follows, @itemize @minus @item @code{ty} is a @code{sockbuf::type} and must be one of @code{sockbuf::sock_stream}, @code{sockbuf::sock_dgram}, @code{sockbuf::sock_raw}, @code{sockbuf::sock_rdm}, and @code{sockbuf::sock_seqpacket} @item @code{proto} denotes the protocol number and is of type int @item @code{sb} is a @code{sockbuf} object and must be in @var{unix} domain @item @code{sinp} is a pointer to an object of @code{sockunixbuf} @end itemize @table @code @item isockunix is (ty, proto) @findex isockunix::isockunix constructs an @code{isockunix} object @code{is} whose @code{sockunixbuf} buffer is of the type @code{ty} and has the protocol number @code{proto}. The default protocol number is 0. @item isockunix is (sb) constructs a @code{isockunix} object @code{is} whose @code{sockunixbuf} is @code{sb}. @code{sb} must be in @var{unix} domain. @item isockunix is (sinp) constructs a @code{isockunix} object @code{is} whose @code{sockunixbuf} is @code{sinp}. @item sinp = is.rdbuf () @findex isockunix::rdbuf returns a pointer to the @code{sockunixbuf} of @code{isockunix} object @code{is}. @item isockunix::operator -> @findex isockunix::operator-> returns @code{sockunixbuf} of @code{sockunix} so that the @code{sockunix} object acts as a smart pointer to @code{sockunixbuf}. @example is->localhost (); // same as is.rdbuf ()->localhost (); @end example @end table @subsection iosockunix examples @cindex iosockunix examples @code{tsunread} listens for connections. When @code{tsunwrite} requests connection, @code{tsunread} accepts it and waits for input. @code{tsunwrite} sends the string "Hello!!!" to @code{tsunread}. @code{tsunread} reads the string sent by @code{tsunwrite} and prints on its stdout. @example // tsunread.cc #include #include int main () @{ sockunixbuf sunb (sockbuf::sock_stream); sunb.bind ("/tmp/socket+-"); sunb.listen (2); isockunix is = sunb.accept (); char buf[32]; is >> buf; cout << buf << endl; unlink ("/tmp/socket+-"); return 0; @} @end example @example // tsunwrite.cc #include int main () @{ osockunix os (sockbuf::sock_stream); os->connect ("/tmp/socket++"); os << "Hello!!!\n" << flush; return 0; @} @end example @node pipestream Classes @chapter pipestream Classes @cindex pipestream classes @cindex pipestream examples @findex popen @findex pipe @findex socketpair @code{pipestream} stream classes provide the services of the @var{UNIX} system calls @code{pipe} and @code{socketpair} and the C library function @code{popen}. @code{ipipestream}, @code{opipestream}, and @code{iopipestream} are obtained by simply deriving from @code{isockstream}, @code{osockstream} and @code{iosockstream} respectively. @xref{sockstream Classes} for details. In what follows, @itemize @minus @item @code{ip} is an @code{ipipestream} object @item @code{op} is an @code{opipestream} object @item @code{iop} is an @code{iopipestream} object @item @code{cmd} is a char* denoting an executable like "wc" @item @code{ty} is of type @code{sockbuf::type} indicating the type of the connection @item @code{proto} is an @code{int} denoting a protocol number @end itemize @table @code @item ipipestream ip(cmd) @findex ipipestream::ipipestream construct an @code{ipipestream} object @code{ip} such that the output of the command @code{cmd} is available as input through @code{ip}. @item opipestream op(cmd) @findex opipestream::opipestream construct an @code{opipestream} object @code{op} such that the input for the command @code{cmd} can be send through @code{op}. @item iopipestream iop(cmd) @findex iopipestream::iopipestream construct an @code{iopipestream} object @code{iop} such that the input and the output to the command @code{cmd} can be sent and received through @code{iop}. @item iopipestream iop(ty, proto) construct a @code{iopipestream} object @code{iop} whose socket is a socketpair of type @code{ty} with protocol number @code{proto}. @code{ty} defaults to @code{sockbuf::sock_stream} and @code{proto} defaults to 0. Object @code{iop} can be used either as a @code{pipe} or as a @code{socketpair}. @item iop.pid () @findex iopipestream::pid return the process id of the child if the current process is the parent or return 0. If the process has not forked yet, return -1. @item iopipestream::fork () @findex iopipestream::fork @code{fork()} is a static function of class @code{iopipestream}. @code{fork()} forks the current process and appropriately sets the @code{cpid} field of the @code{iopipestream} objects that have not forked yet. @end table @menu * pipe Example:: How to use pipestream as pipe? * socketpair Example:: How to use pipestream as socketpair? * popen Example:: How to use pipestream as popen? @end menu @node pipe Example @section pipestream as pipe @cindex pipe example @code{pipe} is used to communicate between parent and child processes in the @var{unix} domain. The following example illustrates how to use @code{iopipestream} class as a @code{pipe}. The parent sends the string "I am the parent" to the child and receives the string "I am the child" from child. The child, in turn, receives the string "I am the parent" from parent and sends the string "I am the child" to the parent. Note the same @code{iopipestream} object is used for input and output in each process. @example #include int main() @{ iopipestream p; if ( p.fork() ) @{ char buf[128]; p << "I am the parent\n" << flush; cout << "parent: "; while(p >> buf) cout << buf << ' '; cout << endl; @}else @{ char buf[128]; p.getline(buf, 127); cout << "child: " << buf << endl; p << "I am the child\n" << flush; @} return 0; @} @end example @node socketpair Example @section pipestream as socketpair @cindex socketpair example Like pipes, socketpairs also allow communication between parent and child processes. But socketpairs are more flexible than pipes in the sense that they let the users choose the socket type and protocol. The following example illustrates the use of @code{iopipestream} class as a @code{socketpair} whose type is @code{sockbuf::sock_dgram}. The parent sends the string "I am the parent" to the child and receives the string "I am the child" from the child. The child, in turn, receives and sends the strings "I am the parent" and "I am the child" respectively from and to the parent. Note in the following example that the same @code{iopipestream} object is used for both the input and the output in each process. @example #include int main() @{ iopipestream p(sockbuf::sock_dgram); if ( iopipestream::fork() ) @{ char buf[128]; p << "I am the parent\n" << flush; p.getline(buf, 127); cout << "parent: " << buf << endl; @}else @{ char buf[128]; p.getline(buf, 127); cout << "child: " << buf << endl; p << "I am the child\n" << flush; @} return 0; @} @end example @node popen Example @section pipestream as popen @cindex popen example @code{popen} is used to call an executable and send inputs and outputs to that executable. For example, the following example executes "/bin/date", gets its output, and prints it to stdout. @example #include int main () @{ char buf[128]; ipipestream p("/bin/date"); p.getline (buf, 127); cout << buf << endl; return 0; @} @end example Here is an example that prints "Hello World!!" on stdout. It uses @code{opipestream} object. @example #include int main () @{ opipestream p("/bin/cat"); p << "Hello World!!\n" << endl; return 0; @} @end example The following example illustrates the use of @code{iopipestream} for both input and output. @example #include int main() @{ char buf[128]; iopipestream p("lpc"); p << "help\nquit\n" << flush; while ( p.getline(buf, 127) ) cout << buf << endl; return 0; @} @end example @node Fork Class @chapter Fork Class @cindex fork class You can effectively use the @code{Fork} wrapper class to create child processes. You can use the @code{Fork} class, instead of directly using the system call fork (), if you desire the following: @itemize @bullet @item Avoid zombie processes @item Optionally kill child processes when the parent process terminates. @item Want to know the reason for abnormal termination of child processes. @end itemize In what follows, @itemize @minus @item @code{killchild} is an integer. @item @code{reason} is an integer. @item @code{signo} is a valid signal. @item @code{f} is a @code{Fork} object. @end itemize @table @code @item Fork f(killchild, reason) @findex Fork::Fork constructs a @code{Fork} object @code{f}. The constructor creates a child process. When the parent process terminates, it will kill the child process if @code{killchild} is not 0. Otherwise, the parent process will wait until all its child processes die. If @code{reason} is not 0, then it gives the reason for a child process's death on the stderr. @item f.is_child () @findex Fork::is_child returns 1 if the current process is the child process following the fork in constructing the @code{Fork} object @code{f}. Otherwise, return 0. @item f.is_parent () @findex Fork::is_parent returns 1 if the current process is the parent process following the fork in constructing the @code{Fork} object @code{f}. Otherwise, return 0. @item f.process_id () @findex Fork::process_id returns the process id of the child process, if the current process is the parent process. Returns 0, if the current process is the child process. Returns -1, if fork failed. @item Fork::suicide_signal (signo) @findex Fork::suicide_signal is a static function. Upon the reciept of the signal @code{signo}, the current process will kill all its child processes created through @code{Fork::Fork(int, int)} irrespective of the value of the @code{killchild} flag used in the construction of the @code{Fork} objects. @code{signo} defaults to SIGTERM signal. @end table @section Fork Example @cindex fork example The following example illustrates the use of the @code{Fork} class to create child processes. First, we set up @var{SIGTERM} signal handler to kill all the child processes, by callling @code{Fork::suicide_signal ()}. Second, we create several child and grandchild processes. You can kill the top most parent process and all its children by sending a @var{SIGTERM} signal to the top most parent process. @example // tfork.C #include #include static void print (char* name, pid_t child) @{ if (child) cerr << "Parent " << getppid () << "; " << name << ' ' << getpid () << "; Child " << child << ";\n"; @} int main (int ac, char** av) @{ Fork::suicide_signal (SIGTERM); Fork a(0, 1); print ("a", a.process_id ()); if (a.is_child ()) @{ sleep (3000); @} else if (a.is_parent ()) @{ Fork b (1, 1); print ("b", b.process_id ()); @{ Fork c (b.is_parent (), 1); if (b.is_child ()) print ("cchild", c.process_id ()); else print ("cparent", c.process_id ()); if (c.is_child ()) @{ sleep (3000); return 0; @} @} if (b.is_child ()) @{ sleep (120); return 0x8; @} @} return 0; @} @end example @node protocol Class @chapter Class protocol @cindex protocol class @code{protocol} class is the base class for all the other application protocol classes like @code{echo}, @code{smtp}, etc. @code{protocol} is derived publicly from @code{iosockstream}. It uses @code{protocolbuf} class, a nested class of @code{protocol}, as its stream buffer. The @code{protocol} class is an abstract class and thus, you cannot instantiate an object of @code{protocol}. @section Class protocol::protocolbuf @cindex protocolbuf class @code{protocol::protocolbuf} class is publicly derived from @code{sockinetbuf} and thus, it inherits all the latter's public member functions. In addition, the @code{protocolbuf} defines the following member functions. In what follows, @itemize @minus @item @code{p} is an object of a non-abstract class derived from @code{protocolbuf}. @item @code{pname} is the transport protocol name which is either @code{protocol::tcp} or @code{protocol::udp}. @item @code{addr} is an unsigned long denoting the valid address of a machine in host byte order. @item @code{host} is a char string denoting the name of a machine like "kelvin.seas.virginia.edu". @item @code{portno} is an int and denotes the port number in host byte order. @end itemize @table @code @item protocol::protocolbuf::protocolbuf (pname) @findex protocolbuf::protocolbuf constructs @code{protocolbuf} object with the transport protocol set to @code{pname}. @item p.protocol_name () @findex protcolbuf::protocol_name returns the name of the transport protocol of @code{p} as a char string. @item p.rfc_name () @findex protocolbuf::rfc_name returns the name of the application protocol name of @code{p} as a char string. @code{protocolbuf::rfc_name ()} is a pure virtual function; thus, any class derived from @code{protocol::protocolbuf} should provide a definition for @code{protocolbuf::rfc_name ()}. @item p.rfc_doc () @findex protocolbuf::rfc_doc returns the RFC document name of the application protocol of @code{p} as a char string. @code{protocolbuf::rfc_doc ()} is a pure virtual function; thus, any class derived from @code{protocol::protocolbuf} should provide a definition for @code{protocolbuf::rfc_doc ()}. @item p.serve_clients (portno) @findex protocolbuf::serve_clients converts @code{p} into a server. Use the port specified in @code{/etc/services} for the application if @code{portno} < 0. Use a default port if @code{0 <= portno <= 1024}. Otherwise, use @code{portno} as the port to accept clients requesting service. @code{protocolbuf::serve_clients()} is pure virtual function; thus, any class derived from @code{protocol::protocolbuf} should provide a definition for @code{protocolbuf::serve_clients()}. Please do not change the meaning of @code{portno} when you derive your own class. @item p.bind () @findex protocolbuf::bind same as @code{p.serve_clients (-1)}. It returns 0 on success and returns the errno on failure. @item p.connect () @findex protocolbuf::connect connects to the local host's server for the application. @code{p} acts as the client. It returns 0 on success and returns the errno on failure. @item p.connect (addr) connects to the server running at the machine with address, @code{addr}. @code{p} acts as the client. It returns 0 on success and returns the errno on failure. @item p.connect (host) connects to the server running at the machine, @code{host}. @code{p} acts as the client. It returns 0 on success and returns the errno on failure. @item p.connect (host, portno) connects to the server servicing clients at @code{portno} at the machine, @code{host}. Unlike this connect call, the other variants of connect uses the port specified in the @code{/etc/services} file. It returns 0 on success and returns the errno on failure. @end table @node echo Class @chapter Echo Class @cindex echo class The @code{echo} class implements RFC 862. An @code{echo} object, as a client, will get back what ever data it sends to an @code{echo} server. Similarly, an @code{echo} object, as a server, will echo back the data it receives from its client. The @code{echo} class is derived from @code{protocol} class, and uses @code{echo::echobuf} as its stream buffer. @code{echo::echobuf} is in turn is derived from @code{protocol::protcolbuf}. In what follows, @itemize @minus @item @code{e} is a @code{echo} object. @item @code{pname} is a transport protocol name and must be either @code{protocol::tcp} or @code{protocol::udp}. @end itemize @table @code @item echo e (pname) @findex echo::echo constructs the @code{echo} object, @code{e} with @code{pname} as its transport protocol name. @item echo::operator -> () @findex echo::operator-> an @code{echo} object is a smart pointer for the underlying @code{echobuf}. @end table @subsection tsecho.C @example // echo server. Serves clients at port 4000. #include #include int main () @{ echo server (protocol::tcp); server->serve_clients (4000); return 1; @} @end example @subsection tcecho.C @example // echo client. Sends "mary had a litte lamb" to the server #include #include int main () @{ echo e(protocol::tcp); e->connect ("kelvin.seas.virginia.edu", 4000); cout << e->rfc_name () << ' ' << e->rfc_doc () << endl; e << "mary had a little lamb\r\n" << flush; char buf [256]; e.getline (buf, 255); cout << "got back: " << buf << endl; return 0; @} @end example @node smtp Class @chapter SMTP Class @cindex smtp class The @code{smtp} class, which is derived from @code{protocol} class, implements RFC 821. It can be used only as a client. Server function is not yet implemented. @code{smtp} uses @code{smtp::smtpbuf} as its underlying stream buffer. Also, like the @code{protocol} class, @code{smtp} is a smart pointer class for it is @code{smtp::smtpbuf}. In what follows, @itemize @minus @item @code{s} is an @code{smtp} object. @item @code{sb} is an @code{smtp::smtpbuf} object. @item @code{io} is a pointer to an @code{ostream}. @item @code{buf} is a char buffer of length @code{buflen}. @item @code{str, str0, str1, ...} are all char strings. @end itemize @table @code @item smtp s (io) @findex smtp::smtp constructs an @code{smtp} client, @code{s}. Any response the client gets from the server is sent to the ostream, @code{io}. @item sb.get_response () @findex smtpbuf::get_response gets the server response and sends it to @code{io} of the @code{smtpbuf}. @item sb.send_cmd (str0, str1, str2) @findex smtpbuf::send_cmd concatenates strings @code{str0}, @code{str1}, and @code{str2} and sends the concatenated string to the server before getting its response. @item sb.send_buf (buf, buflen) @findex smtpbuf::send_buf sends the contents of the @code{buf} to the server. @item sb.helo () @item sb.help (str) @item sb.quit () @item sb.turn () @item sb.rset () @item sb.noop () @item sb.data () @item sb.vrfy (str) @item sb.expn (str) implements the respective @var{smtp} commands. See RFC 821 for the meaning of each. @item sb.mail (str) sends the mail command to the server. @code{str} is the the reverse path or the @var{FROM} address. @item sb.rcpt (str) sends the recipient command to the server. @code{str} is the forward path or the @var{TO} address. @item sb.data (buf, buflen) sends the contents of the buffer, @code{buf} as the mail data to the recipient previously established through @code{smtpbuf::rcpt()} calls. @item sb.data (filename) sends the contents of the file, @code{filename} as the mail data to the recipient previously established through @code{smtpbuf::rcpt()} calls. @end table @subsection tcsmtp.C @example // smtp client. // The president sends a message to gs4t@@virginia.edu. #include #include #include #include int main () @{ smtp client (&cout); // establish connection client->connect ("fulton.seas.virginia.edu"); client->helo (); // get help client->help (); // setup the FROM address client->mail ("president@@whitehouse.gov"); // setup the TO address client->rcpt ("gs4t@@virginia.edu"); // send the message client->data (); client << "Hi Sekar, I appoint you as the director of NASA\r\n" << flush; client << " -Bill, Hill, and Chel\r\n" << flush; cout << client; // get the server response. // finally quit client->quit (); return 0; @} @end example @node Error Handling @chapter Error Handling @cindex error handling Each class in the Socket++ library uses @code{error(const char*)} member function to report any errors that may occur during a system call. It first calls @code{perror()} to report the error message for the @code{errno} set by the system call. It then calls @code{sock_error (const char* nm, const char* errmsg)} where @code{nm} is the name of the class. The @code{sock_error()} function simply prints the @code{nm} and the @code{errmsg} on the @var{stderr}. @node Pitfalls @chapter Pitfalls @cindex pitfalls @cindex common mistakes Deadlocks in datagram sockets are the most common mistakes that novices make. To alleviate the problem, @code{sockbuf} class provides timeout facilities that can be used effectively to avoid deadlocks. Consider the following simple tsmtp example which sends the HELP command to a smtp server and gets back the help message. Suppose it does not know the size of the help message nor the format of the message. In such cases, the timeout facilities of @code{sockbuf} class provides the required tools. The example terminates the help message reception if the there is no input activity from the smtp server for 10 seconds. @subheading tsmtp.cc @example @cindex timeout example #include int main() @{ iosockinet sio(sockbuf::sock_stream); sio->connect("kelvin.seas.virginia.edu", "smtp", "tcp"); char buf[512]; sio.getline(buf, 511); cout << buf << endl; sio << "HELO kelvin\n" << flush; sio.getline(buf, 511); cout << buf << endl; sio << "HELP\n" << flush; // set the receive timeout to 10 seconds int tmo = sio->recvtimeout(10); while ( sio.getline(buf, 511) ) cout << buf << endl; // if the above while loop terminated due to timeout // clear the state of sio. if ( !sio->is_eof() ) sio.clear(); sio->recvtimeout(tmo); // reset the receive timeout time sio << "QUIT\n" << flush; sio.getline(buf, 511); cout << buf << endl; return 0; @} @end example @node Index @unnumbered Index @printindex cp @contents @bye socket++-1.12.13/README30000644000175000017500000000101711676325304012410 0ustar stbstbSocket++-1.12 ------------ o) Improved ErrorHandling in sockerr and sockbuf Copyright Notice: ----------------- Portions Copyright (C) 2002 Herbert Straub for all my changes (see ChangeLog) Copyright (C) 1992-1996 Gnanasekaran Swaminathan Permission is granted to use at your own risk and distribute this software in source and binary forms provided the above copyright notice and this paragraph are preserved on all copies. This software is provided "as is" with no express or implied warranty. socket++-1.12.13/ChangeLog0000644000175000017500000001345411676325304013227 0ustar stbstb2004-09-30 Herbert Straub * New Version: 1.12.12 2004-08-12 Herbert Straub * Bugfix: sig.cpp changing sighnd_type typedef, compiling error with g++ V3.4; reported by Tilman Linneweh 2004-05-06 Herbert Straub * Bugfix: test/tcftp.C -> include getpass(...) 2004-07-05 Herbert Straub * Bugfix: removing "using namespace std" from sockstream.h and change all .cpp files. Reported by Georg Baum . Also all test/*.C 2003-11-29 Herbert Straub * Bugfix: ::write writing wrong buffer segements (if the write operation is splitted). reported by Dan Muller methods: sockbuf::write, sockbuf::send, sockbuf::sendto 2003-11-10 Herbert Straub * Feature: -Wall compiler options is default * Bugfix: change initialization order in constructor isockstream, osockstream, iosockstream * Bugfix: Tilman Linneweh Patch: local.h preprocessor condition for FreeBSD (gethostname) * Bugfix: change incompatible license from GNU/GPL to the original license terms for the following files: test/simple_http.C, test/test_sockerr.C, test/thostnames.C. Reported by Matthew Faupel 2003-04-26 Herbert Straub * Bugfix: sockerr contructor doesn't initialize the class variable err. This can lead in a segmentation fault, if errstr () will called. * Feature: new configuration option --enable-debug * New Version: 1.12.10 * New Library Version 1:1:0 2003-03-14 Herbert Straub * New Version: 1.12.9 * New Library Version: 1:0:0 2003-03-10 Herbert Straub * Mac OS X Porting Patch: from Jason Toffaletti 2003-03-06 Herbert Straub * Feature: class sockbuf new methods: setname(sockname), getname * Feature: all methods of class sockbuf throw error description: method name and sockname * Bugfix: fixing include errors (scket++/... wrong). 2003-04-05 Herbert Straub 2002-12-06 Herbert Straub * Bugfix: correcting the COPYING, NEWS and README3 file * New socket++.spec: from Carles Arjona * socket++.spec: correcting the Source URL to: * http://www.hstraub.at/linux/downloads/src/ * New Version: 1.12.8 2002-11-25 Herbert Straub * Bugfix: *.h files not installed (thanks to Tilman Linneweh ) changing Makefile.am * include files: now in ${prefix}/include/socket++ * Change: all #includes to #include * Bufgix: removing test/thostnames.STATIC testprogram, Makefile.in, config.cache, configure, config.h, config.log, config.h.in * Bugfix configure.in: -> AC_INIT(configure.in) * Bugfix: Fork.* to fork.* * Bugfix: installing socket++.info (thanks to Tilman Linneweh) * New Version: 1.12.7 2002-11-23 Herbert Straub * adding: absent Makefile.am, configure.in, autogen, AUTHORS, COPYING, NEWS, THANKS files * New Version: 1.12.6 2002-11-15 Herbert Straub * Now using libtool and libtool versioning modify configure.in, create Makefile.am http://sources.redhat.com/autobook/autobook/autobook_91.html http://www.gnu.org/software/libtool/manual.html#SEC34 * test/tsig-0.C: Changing struct hnd to class hnd and moving it from main. Link Error with gcc 2.95.4 * RPM: Thanks to Carles Arjona for a working RPM SpecFile for this version * New Version: 1.12.5 2002-10-13 Herbert Straub * New Version: 1.12.4 2002-10-08 Herbert Straub * FreeBSD Port Patch: from Tilman Linneweh for sig.cpp same for Linux (SA_INTERRUPT) * configure: Change Compilertest from c++ g++ gcc CC cxx cc++ cl to g++ c++ gcc CC cxx cc++ cl No Exception Handling on Linux, if compiled with c++ * configure: removed compiler flag: --no-rtti * test/tsig-0.C: some changes * sig.cpp: removing static sigerr se; 2002-10-08 Herbert Straub * FreeBSD Port Patch: from Tilman Linneweh for sockstream.cpp 2002-10-08 Herbert Straub * New Version: 1.12.3 2002-10-08 Herbert Straub * FreeBSD Port Patches: from Tilman Linneweh 1. local.h: SYS_SIGLIST 2. sockstream.h: msg_maxiovlen 3. Adding description text in socket++.texi 2002-09-28 Herbert Straub * Renaming Version to: 1.12.1 * Removing check compiler version code (Troubles with Debian g++ 3.2) * in configure.in * Removing -fno-rtti and -fexceptions in configure.in * Create the small testprogram test/test_sockerr.cxx 2002-09-27 Herbert Straub * Test compatibility with NewsCache * Adding INSTALL Instruction, TODO * Version: 1.2.3 2002-07-28 Herbert Straub * Improvement: Eliminating sorry_about_global_temp inititialisation. This don't work in combination with NewsCache. My idea is: initializing the classes with (0) and in the second step call ios::init (sockinetbuf *) and iosockstream::init ... The constructors of isockinet, osockinet and iosockinet are changed. * Improvement: same in sockunix.cpp * Improvement: same in pipestream.cpp * Bugfix: g++ 3.1 Compatibility in directory test for: tpopentest.C, tsendfile.C, tfork.C, tfork0.C, tsig-0.C 2002-07-25 Herbert Straub * Improvement: Adding improved error Handling in sockerr class * Improvement sockinetaddr::setport: If the first character of the port parameter is a digit, then the parameter is interpreted as a number. socket++-1.12.13/README20000644000175000017500000000110311676325304012403 0ustar stbstbSocket++-1.11ln --------------- This is a modified version 1.11 of the Socket++ library. I had to change the source code a bit to make it compile with egcs-2.91.66 and gcc-2.96 (Linux). This modified code will not necessarily compile under other platforms than Linux (i386). It has not been tested. If this code happens to compile with your compiler, that's good. But if it doesn't, I really can't help you. I actually even don't know very well how the code works, I just changed the lines that wouldn't compile. This source code was modified by: Lauri Nurmi socket++-1.12.13/Default.SUP0000644000175000017500000000007111676325304013421 0ustar stbstb//SUPPRESSIONPROJ:Default //VERSION:5.00 //ENABLE:Yes socket++-1.12.13/vc60.idb0000644000175000017500000000000011676325304012672 0ustar stbstbsocket++-1.12.13/THANKS0000644000175000017500000000065111676325304012363 0ustar stbstbThanks to: * Dan Muller writing wrong buffer segements error * Jason Toffaletti Mac OS X Porting Patch * Carles Arjona RPM Packager * Tilman Linneweh FreeBSD Port and many patches * Matthew Faupel report incomatible licencse terms If I forgot somebody, please send an email to me and accept my apologies. socket++-1.12.13/autogen0000755000175000017500000000065511676325304013044 0ustar stbstb#!/bin/sh # Copyright 2002, 2003 Herbert Straub if [ -f config.cache ]; then rm config.cache fi if [ -f Makefile ]; then make clean fi echo "libtoolize..." if test `uname -s` = Darwin; then glibtoolize --automake else libtoolize --automake fi echo "aclocal..." aclocal echo "autoheader..." autoheader echo "automake..." automake --add-missing echo "autoconf..." autoconf echo "Next run ./configure" echo "Next run make" socket++-1.12.13/configure.in0000644000175000017500000001152311676325304013761 0ustar stbstbdnl Use autoconf on this directory to produce configure script dnl Use autoheader on this file to produce config.h.in dnl Then use configure script to generate makefile from Makefile.in dnl a distinct socket++ file AC_INIT(configure.in) # Details: http://sources.redhat.com/autobook/autobook/autobook_91.html # +1 : ? : +1 == new interface that does not break old one # +1 : ? : 0 == new interface that breaks old one # ? : ? : 0 == no new interfaces, but breaks apps # ? :+1 : ? == just some internal changes, nothing breaks but might work # better # CURRENT : REVISION : AGE LIBSOCKET_SO_VERSION=1:2:0 SOCKET_VERSION=1.12.12 AC_SUBST(SOCKET_VERSION) AC_SUBST(LIBSOCKET_SO_VERSION) dnl For automake VERSION=$SOCKET_VERSION PACKAGE=socket dnl Inititalize automake stuff AM_INIT_AUTOMAKE(socket++,$SOCKET_VERSION) dnl Specify a configuration file AM_CONFIG_HEADER(socket++/config.h) dnl check for programs AC_PROG_MAKE_SET AC_LANG_CPLUSPLUS AC_PROG_CXX AM_PROG_LIBTOOL AC_PROG_INSTALL AC_CHECK_PROG(MAKEDEPEND, makedepend, makedepend, :) dnl not a smiley :( dnl AC_PROG_CPP dnl later macros will use it dnl AC_PROG_CXXCPP dnl later macros will use it CXXFLAGS="-Wall ${CXXFLAGS}" dnl Configuration Options AC_ARG_ENABLE(debug, [ --enable-debug turn on verbosity [default=no]], if eval "test x$enable_debug = xyes"; then AC_DEFINE(ENABLE_DEBUG) CXXFLAGS="${CXXFLAGS} -g -O0" fi, ) dnl check for libraries AC_CHECK_LIB(nsl, t_accept, NETWORK_LIBS="$NETWORK_LIBS -lnsl") AC_CHECK_LIB(socket, socket, NETWORK_LIBS="$NETWORK_LIBS -lsocket") AC_SUBST(NETWORK_LIBS) dnl check for header files AC_LANG_SAVE AC_LANG_CPLUSPLUS AC_CHECK_HEADERS(string.h memory.h sstream string) AC_CHECK_HEADER(_G_config.h, AC_DEFINE(_S_LIBGXX)) AC_LANG_RESTORE AC_HEADER_SYS_WAIT dnl check for typedefs AC_PID_T dnl check for structures dnl check for compiler characteristics AC_SUBST(CXX_INCLUDE_PATH) AC_SUBST(CFLAGS) AC_SUBST(CXXFLAGS) AC_SUBST(LDFLAGS) dnl check for library functions and global variables AC_RETSIGTYPE AC_FUNC_VFORK AC_HAVE_FUNCS(select) AC_MSG_CHECKING(for sys_siglist) AC_CACHE_VAL(socketxx_cv_siglist, [ AC_TRY_LINK([ # include # include ], [ #ifndef _sys_siglist extern char* _sys_siglist[]; #endif puts(*_sys_siglist); ], socketxx_cv_siglist=_sys_siglist, socketxx_cv_siglist=sys_siglist) ]) AC_DEFINE_UNQUOTED(SYS_SIGLIST, $socketxx_cv_siglist) AC_MSG_RESULT($socketxx_cv_siglist) AC_MSG_CHECKING(for sys_errlist) AC_CACHE_VAL(socketxx_cv_errlist, [ AC_TRY_LINK([ # include # include ], [ #ifndef _sys_errlist extern char* _sys_errlist[]; #endif puts(*_sys_errlist); ], socketxx_cv_errlist=_sys_errlist, socketxx_cv_errlist=sys_errlist) ]) AC_DEFINE_UNQUOTED(SYS_ERRLIST, $socketxx_cv_errlist) AC_MSG_RESULT($socketxx_cv_errlist) AC_MSG_CHECKING(for sys_errlist prototype) AC_CACHE_VAL(socketxx_cv_errlist_proto, [ AC_LANG_SAVE AC_LANG_CPLUSPLUS AC_TRY_COMPILE( [ #include #include #include #include ], [ puts (*$socketxx_cv_errlist); ], socketxx_cv_errlist_proto=yes, socketxx_cv_errlist_proto=no) ]) AC_LANG_RESTORE if test $socketxx_cv_errlist_proto = yes; then AC_DEFINE(SYS_ERRLIST_DECLARED) fi AC_MSG_RESULT($socketxx_cv_errlist_proto) AC_MSG_CHECKING(for signal handler arg type) AC_CACHE_VAL(socketxx_cv_sighnd_argtype, [ AC_LANG_SAVE AC_LANG_CPLUSPLUS AC_TRY_COMPILE([ # include # include void sigh (int s, int c, void* p, void* a) {} ], [ typedef RETSIGTYPE (*funcptr) (...); struct sigaction sa; sa.sa_handler = funcptr (&sigh); ], socketxx_cv_sighnd_argtype=..., AC_TRY_COMPILE([ # include # include void sigh (int s, int c, void* p, void* a); ], [ typedef RETSIGTYPE (*funcptr) (int); struct sigaction sa; sa.sa_handler = funcptr (&sigh); ], socketxx_cv_sighnd_argtype=int, socketxx_cv_sighnd_argtype=void)) ]) AC_LANG_RESTORE AC_DEFINE_UNQUOTED(SIGHND_ARGTYPE, $socketxx_cv_sighnd_argtype) AC_MSG_RESULT($socketxx_cv_sighnd_argtype) dnl the following check was provided by dnl Blair Zajac AC_MSG_CHECKING(if extern \"C\" wrappers are needed) AC_CACHE_VAL(bz_cv_cplusplus_needexternCwrapper, [ AC_LANG_SAVE AC_LANG_CPLUSPLUS AC_TRY_LINK([ # include # include ], [ char buf[100]; strcpy(buf, "Hello world\n"); ], bz_cv_cplusplus_needexternCwrapper=no, bz_cv_cplusplus_needexternCwrapper=yes) ]) AC_LANG_RESTORE if test $bz_cv_cplusplus_needexternCwrapper = no; then AC_DEFINE(EXTERN_C_BEGIN,) AC_DEFINE(EXTERN_C_END,) else AC_DEFINE(EXTERN_C_BEGIN, extern "C" {) AC_DEFINE(EXTERN_C_END, }) fi AC_MSG_RESULT($bz_cv_cplusplus_needexternCwrapper) dnl check for system dnl generate output files AC_OUTPUT(Makefile socket++/Makefile doc/Makefile test/Makefile) socket++-1.12.13/README0000644000175000017500000001436611676325304012340 0ustar stbstbThis directory contains the source for the C++ socket library Version: 12Jan1997 1.11 Manifest: -------- README.....................this file configure config.h.in, Makefile.in, acconfig.h configure.in...............configuring files sockstream.h...............contains sockbuf, sockAddr, isockstream, osockstream, iosockstream class declarations sockstream.C...............related to sockstream.h pipestream.h...............contains ipipestream, opipestream, and iopipestream class definitions. They are used instead of pipe and socketpair system calls and popen C library function call. pipestream.C...............related to pipestream.h sockinet.h.................contains sockinetbuf, sockinetaddr classes. It also contains the definitions of isockinet, osockinet, and iosockinet stream classes. sockinet.C.................related to sockinet.h sockunix.h.................contains sockunix, sockunixaddr classes. It also contains the definitions of isockunix, osockunix, and iosockunix stream classes. sockunix.C.................related to sockunix.h Fork.h.....................wrapper class for fork () system call. sig.h......................wrapper class Unix signals. protocol.h, protocol.C.....base class for application protocols. echo.h, echo.C.............Echo application protocol class. smtp.h, smtp.C.............SMTP application protocol class. ftp.h, ftp.C...............FTP application protocol class. socket++.texi..............texinfo file for libsocket++.a ./test ------ tdunread.cc, tdunwrite.cc..test files for datagram unix sockets tdinread.cc, tdinwrite.cc..test files for datagram inet sockets tsunread.cc, tsunwrite.cc..test files for stream unix sockets tsinread.cc, tsinwrite.cc..test files for stream inet sockets tpipe.cc...................test file for pipe system call tsockpair.cc...............test file for sockpair system call tpopen.cc, tpopentest.cc...test files for popen function testall.cc.................runs all the above tests testall.exp................correct output of testall tnntp.cc, tsmtp.cc, twhois.cc tsendfiles.cc, thostnames.cc...........Some more examples Copyright Notice: ---------------- Copyright (C) 1992-1996 Gnanasekaran Swaminathan Permission is granted to use at your own risk and distribute this software in source and binary forms provided the above copyright notice and this paragraph are preserved on all copies. This software is provided "as is" with no express or implied warranty. Installation Note: ----------------- This software has been tested in sun4 running SunOs4.1.3 machine only. If you are having problems with any aspect of socket++, please email me at gs4t@virginia.edu. We can fix it together. This software works with proposed C++ standard iostream library. Thus if you are using libg++, you need at least libg++-2.7.2. Your C++ compiler should be able to handle C++ exceptions and templates. Thus if you are using G++, you need at least gcc-2.7.2. socket++.texi needs at least texinfo-2.16. Gcc, libg++, and texinfo are all available for anonymous ftp from prep.ai.mit.edu:/pub/gnu cd socket++-1.11 env CCC=c++ ./configure --prefix="your favorite location" make cd test make check If you are using a compiler that is invoked by a command other than c++, use that command instead on CCC=c++ in the above. Testing: ------- make check will automatically run testall. You can also manually test as follows: ./testall > testall.out diff -c testall.out testall.exp If there are any differences, manually check whether testall.out and testall.exp have the same lines but only their order is different. If they have the same lines but for the order, you have installed properly. Otherwise, try to findout what might be the reason and if you couldn't please email me with your problem at gs4t@virginia.edu. Bug reports: ----------- Send them to me at gs4t@virginia.edu News: ---- 12Jan97 1.11 . This release brings back error handling through the use of exceptions. I have not included any other enhancements in this release. . Document is out-of-date. I will work on it in the next release. . class sig is added. It is useful for handling signals. 17Oct95 1.10 . Made to work cleanly in RS6000 machines . Bug fixes sent in by Blair incorporated. 07Aug95 1.9 . Exceptions dropped as many compilers do not support it yet. A number of small bug fixes. . Made to work with libg++-2.7.0 and gcc-2.7.0 . Configuration simplified greatly by Blair. 15Jan95 1.8 . Error handling greatly enhanced through the use of exceptions. . FTP class added. 08Nov94 1.7 . First stable version. Known to work in sunos4, aix3.2, hpux, ultrix, linux, and osf2. Acknowledgements: ---------------- Gordon Joly for reporting bugs in pipestream class implementation. He also knows how to make the socket++ library a shared library. Jim Anderson for reporting a bug in sockinet.C Carl Gay for reporting a bug and a fix in sockinet.C Oliver Imbusch for reporting a bug in Makefile.in and suggesting several enhancements for sockbuf class. Dierk Wendt for reporting errors in the socket++ documentation. Christian Schlichtherle for sending patches for linux support. Ed Martini and taylor d fraley sent in some more linux fixes. Dan R. Greening for a fix in sockstream.h Mike Christiansen for sending patches for hpux support and memory leaks. He used purify to check for memory leaks. Nanlin Xiao for sending fixes to compile under Objectcenter C++ compiler. Solaris support is still weak, and thus the names of people who helped to port to solaris is not listed here yet. V. Olshevsky for catching sequence point bugs in tdinwrite.C. Blair Zajac provided the autoconfig files and Makefile.ins needed to generate the configure and Makefiles and a number of bug fixes. Enjoy! -Sekar Gnanasekaran Swaminathan (gs4t@virginia.edu) CSIS Lab. Dept. of Elec. Eng. University of Virginia Charlottesville VA 22903 socket++-1.12.13/test/0000755000175000017500000000000011676325304012425 5ustar stbstbsocket++-1.12.13/test/test_sockerr.C0000644000175000017500000000164711676325304015250 0ustar stbstb/* test_sockerr.cxx * -- Copyright (C) 2002 by Herbert Straub * * Permission is granted to use at your own risk and distribute this software * in source and binary forms provided the above copyright notice and this * paragraph are preserved on all copies. This software is provided "as is" * with no express or implied warranty. */ #include using namespace std; void f1 (); int main (int argc, char *argv[]) { sockerr err (4711, "Test Error"); try { throw (err); } catch (sockerr e) { cout << "Catching sockeer with " << e.serrno () << " and " << e.operation () << endl; } catch (...) { cout << "Catching void" << endl; } try { f1(); } catch (sockerr e) { cout << "Catching sockeer with " << e.serrno () << " and " << e.operation () << endl; } catch (...) { cout << "Catching void" << endl; } } void f1 () { throw (sockerr (311, "Test Error", "f1")); } socket++-1.12.13/test/tsig-0.C0000644000175000017500000000421111676325304013632 0ustar stbstb// socket++ library. tsig-0.C // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. #include #include #include using namespace std; class hnd: public sig::hnd { public: int id; hnd (int signo): sig::hnd (signo), id (signo) {} hnd (int signo, int i): sig::hnd (signo), id (i) {} void operator () (int s) { cout << "handler for " << id << endl; cout << "Sleeping .." << endl; sleep (5); cout << "..finished" << endl; if (sig::nal.ispending (s)) { cout << "Signal pendig" << endl; } // cout << "Pending signals = " << hex << sig::nal.pending () << dec << endl; // commented out by LN sigset_t set; for (unsigned int i=0; i<_SIGSET_NWORDS; i++) { cout << "sigset[" << i << "]: " << set.__val[i] << endl; } for (unsigned int i=1; i<15; i++) { cout << "ispending(" << i << "): " << sig::nal.ispending (i) << endl; } cout << "called by " << s << endl; } }; int main (int ac, char** av) { hnd sterm0 (SIGTERM); hnd sterm1 (SIGTERM, SIGTERM * 100); hnd sint (SIGINT); hnd susr1 (SIGUSR1); hnd susr2 (SIGUSR2); hnd squit (SIGQUIT); /* sig::nal.set (SIGTERM, &sterm0); sig::nal.set (SIGTERM, &sterm1); sig::nal.set (SIGINT, &sint); sig::nal.set (SIGUSR1, &susr1); sig::nal.set (SIGUSR2, &susr2); sig::nal.set (SIGQUIT, &squit); */ cout << "SIGSET_NWORDS: " << _SIGSET_NWORDS << endl; try { hnd illegal (300); } catch (sigerr e) { //cout << "sigerr exception thrown by illegal(300)\n"; cout << "catched..." << endl; } sig::nal.mask (SIGTERM, SIGUSR1); sig::nal.mask (SIGTERM, SIGUSR2); pid_t pid = getpid (); cout << "send SIGUSR2\n"; kill (pid, SIGTERM); sleep (20); sig::nal.unmask (SIGTERM, SIGUSR2); cout << "send SIGUSR2 again\n"; kill (pid, SIGTERM); sleep (300); return 0; } socket++-1.12.13/test/tsockpair.C0000644000175000017500000000205511676325304014532 0ustar stbstb// tsockpair.cc. Test for -*- C++ -*- socket library // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #include using namespace std; int main(int ac, char** av) { iopipestream p(sockbuf::sock_dgram); if (p.fork()) { // I am the Parent p << ac << endl; while (*av) { p << *av++ << ' '; } p << endl; char buf[128]; p.getline(buf,127); cout << "Parent: " << buf << endl; } else { // I am the Child int cnt=0; int i; char buf[32]; p >> i; cout << "Child: " << i << ": "; while (i--){ p >> buf; cout << buf << ' '; cnt++; } cout << endl; p << "Child received " << cnt << " strings\n" << flush; } return 0; } socket++-1.12.13/test/tpopentest.C0000644000175000017500000000170011676325304014734 0ustar stbstb// socket++ library. tpopentest.cc // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #include #include #include using namespace std; int main(int ac, char** av) { if (ac != 2) { cerr << "USAGE: " << av[0] << " -iob\n"; return 1; } char buf[256]; switch (av[1][1]) { case 'i': cin.getline (buf, 255); cout << av[0] << ' ' << av[1] << ": " << buf << endl; break; case 'o': cout << av[0] << ' ' << av[1] << ": Hello O world!!!" << endl; break; case 'b': cin.getline(buf, 255); cout << buf << endl; system (buf); break; } return 0; } socket++-1.12.13/test/testall.exp0000644000175000017500000000265011676325304014616 0ustar stbstbSocket name = /tmp/soc ./tdunread: 7 strings: ./tdunwrite /tmp/soc mary had a little lamb ./tdinread: mary had a little lamb socket type = 2 socket linger time = 0 socket linger time = 10 socket linger time = 0 socket keepalive = 0 socket keepalive = 1 socket clearerror = 0 socket debug = 0 socket debug = 1 socket reuse = 0 socket reuse = 1 Socket name = /tmp/soc ./tsunread: ./tsunwrite ./tsunread: /tmp/soc ./tsunread: mary ./tsunread: had ./tsunread: a ./tsunread: little ./tsunread: lamb sleeping for 3 sec tsinread: 356 haha 23.5 tsinread: oooiiii ! tsinwrite1: INT STRING DOUBLE received tsinwrite2: STRING CHAR received tpipe parent got: lamb little a had mary ./tpipe tpipe child got: 5 4 3 2 1 0 tsockpair Child: 6: ./tsockpair mary had a little lamb tsockpair Parent: Child received 6 strings tpopen Got from ipopen: ./tpopentest -o: Hello O world!!! tpopen ./tpopentest -i: this is sent to tpopentest tpopen Result from iopopen: echo test one two three test one two three twhois: Knuth, Donald E. (DEK) Stanford University Computer Science Department Stanford, CA 94305-2140 (415) 723-4367 DEK@SAIL.STANFORD.EDU Record last updated on 02-Apr-96. Please be advised that this whois server only contains DOD Information. All INTERNET Domain, IP Network Number, and ASN records are kept in the Internet Registry, RS.INTERNIC.NET. thostnames: h : 128.143.2.7 : UVAARPA.VIRGINIA.EDU : : : : socket++-1.12.13/test/thostnames.C0000644000175000017500000000503411676325304014720 0ustar stbstb// socket++ library. thostnames.C // Copyright (C) 2002 Herbert Straub // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 1.2 2002-07-25 Herbert Straub // Test bind and improved Error Handling #include #include #include using namespace std; static void get_text (iosockstream& s); class test : public iosockinet { public: test () : iosockinet (sockbuf::sock_stream) { cout << "Constructor rdbuf: " << (unsigned int) rdbuf() << endl; } }; int main(int ac, char** av) { iosockinet sio(sockbuf::sock_stream); test t; if (ac != 4) { cerr << "USAGE: " << av[0] << " toServer service bindAddr\n"; return 1; } sio.rdbuf()->setname ("Testsocket"); cout << "rdbuf: " << (unsigned int) sio.rdbuf() << "\n"; cout << "socketname: " << sio.rdbuf()->getname() << endl; try { sockinetaddr addrInterface (av[3]); sockinetaddr addrServer (av[1], av[2]); sio->bind (addrInterface); sio->connect (addrServer); } catch (sockerr e) { cout << "Catched sockerr while in connect" << endl; cout << "errno: " << e.serrno() << endl; cout << "errtext: " << e.errstr () << endl; cout << "Operation: " << e.operation () << endl; sio.setstate(ios::badbit); } catch (...) { cout << "Catchall Zweig" << endl; return 1; } cout << "good: " << sio.good() << endl; try { sio->keepalive (55); cout << "Keepalive: " << sio->keepalive() << endl; } catch (sockerr e) { cout << "Catched sockerr in keepalive" << endl; cout << "errno: " << e.serrno() << endl; cout << "errtext: " << e.errstr () << endl; cout << "Operation: " << e.operation () << endl; sio.setstate(ios::badbit); } sio << "help" << "\r\n" << flush; get_text (sio); return 0; } void get_text(iosockstream& s) { char buf[1024]; int tmo = s->recvtimeout(30); // wait for 30 sec before timing out if (s.getline (buf, 1023)) cout << buf << endl; if (strncmp (buf, "BEGIN", 5) == 0) while (s.getline (buf, 1023)) { cout << buf << endl; if (strncmp (buf, "END", 3) == 0) break; } else while (s.getline (buf, 1023)) { cout << buf << endl; if (!isspace (buf [0])) break; } if ( !s.eof() ) s.clear(); s->recvtimeout(tmo); //reset timeout to the previous value } socket++-1.12.13/test/tcftp.C0000644000175000017500000000176711676325304013664 0ustar stbstb// Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #include #include using namespace std; int main (int ac, char** av) { // this is an ftp client // It retrieves the file from the host if (ac != 4) { cerr << "USAGE: " << av [0] << " hostname user filename\n"; return 1; } ftp f (&cout); // establish connection f->connect (av [1]); f->get_response (); // get the connection response // set access f->user (av [2]); f->passwd (getpass ("passwd: ")); // get help f->help (); // set representation type to image f->rep_type (ftp::rt_image); // list the home directory f->list (); // quit f->quit (); } socket++-1.12.13/test/tsendfiles.C0000644000175000017500000000336011676325304014673 0ustar stbstb// Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #include #include #include #include #include using namespace std; static int send_cmd(iosockstream&, const char* cmd=0); int main(int ac, char** av) { if (ac < 3) { cerr << "USAGE: " << av[0] << " recipient-email-addr files...\n"; return 1; } char rcpt[512]; char sender[512]; iosockinet sio(sockbuf::sock_stream); sio->connect(sio->localhost(), "smtp", "tcp"); send_cmd(sio, 0); send_cmd(sio, "HELO"); sprintf(rcpt, "RCPT TO:%s", av[1]); passwd* pw = getpwuid( getuid() ); sprintf(sender, "MAIL FROM:<%s@%s>", pw->pw_name, sio->localhost()); for (int i=2; i < ac; i++) { send_cmd(sio, sender); send_cmd(sio, rcpt); send_cmd(sio, "DATA"); sio << "\r\n------------------------" << av[i] << "------------------------\r\n" << flush; ifstream cin(av[i]); char buf[512]; while(cin.getline(buf, 511)) { if (buf[0] == '.' && buf[1] == 0) { cerr << av[0] << ": char '.' on a line of its own\n"; return 1; } sio << buf << "\r\n" << flush; } sio << "\r\n.\r\n" << flush; send_cmd(sio, 0); } send_cmd(sio, "QUIT"); } int send_cmd(iosockstream& s, const char* cmd) { char buf[256]; if (cmd) s << cmd << "\r\n" << flush; s.getline(buf, 255); cout << buf << endl; return 0; } socket++-1.12.13/test/tcsmtp.C0000644000175000017500000000212511676325304014043 0ustar stbstb// Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #include #include #include #include using namespace std; int main (int ac, char** av) { if (ac < 4) { cerr << "USAGE: " << av [0] << " host recipient files...\n"; return 1; } smtp client (&cout); // establish connection client->connect (av [1]); client->helo (); // get help client->help (); // get the FROM address char sender [256]; passwd* pw = getpwuid( getuid() ); sprintf(sender, "%s@%s", pw->pw_name, client->localhost()); // send the files for (int i = 3; i < ac; i++) { client->mail (sender); client->rcpt (av [2]); client->data (av [i]); client->rset (); } // finally quit client->quit (); return 0; } socket++-1.12.13/test/simple_httpd.C0000644000175000017500000000675411676325304015241 0ustar stbstb/* simple_httpd.C * -- Copyright (C) 2003 by Herbert Straub * * Permission is granted to use at your own risk and distribute this software * in source and binary forms provided the above copyright notice and this * paragraph are preserved on all copies. This software is provided "as is" * with no express or implied warranty. */ /* * This little program implements a very simple http server (only for * testing purposes). It usess: iosockinet, sockbuf, Fork. */ #include #include #include #include #include #include #include #ifdef HAVE_SSTREAM #include #else #include #endif using namespace std; int process_request (iosockinet *sock); void get_filesize (const char *name, string &buffer); int main (int argc, char **argv) { sockinetbuf sin (sockbuf::sock_stream); Fork *pF; sin.bind (); cout << "localhost = " << sin.localhost() << endl; cout << "localport = " << sin.localport() << endl; sin.listen (); for (;;) { iosockinet *sock; sock = new iosockinet (sin.accept ()); sockaddr_in *remote_sock = sock->rdbuf()->peeraddr().addr_in(); cout << "socksockaddr_in.addr() = " << remote_sock << endl; cout << "port: " << ntohs(remote_sock->sin_port) << endl; cout << "addr: " << hex << inet_ntoa(remote_sock->sin_addr) << endl; cout << "peerhost: " << sock->rdbuf()->peerhost() << endl; pF = new Fork (0, 1); if (pF->is_child ()) { sock->rdbuf()->keepalive (1); process_request (sock); return (0); } } } int process_request (iosockinet *sock) { string buffer; string filename; ifstream file; try { while (1) { getline (*sock, buffer); buffer[buffer.length()-1] = '\n'; cout << "buffer: " << buffer << endl; if (sock->eof()) break; // g++ < 3.0 : strncmp !! if (strncmp (buffer.c_str(), "quit", 4) == 0) //if (buffer.compare (0, 4, "quit") == 0) break; if (buffer.length() == 0) break; if (buffer[0] == '\n') break; // g++ < 3.0 : strncmp !! if (strncmp (buffer.c_str(), "GET", 4) == 0) //if (buffer.compare (0, 4, "GET") == 0) filename.assign (buffer, 4, buffer.rfind (" HTTP")-3); } } catch (sockerr s) { cout << "catched " << endl; goto END; } //filename.insert (0, "."); filename.replace (filename.length()-1, 1, ""); cout << "Filename: " << filename << endl; file.open (filename.c_str()); if (file.bad() || !file.is_open() || !file.good()) { cout << "Error opening file: " << filename << endl; goto END; } *sock << "HTTP/1.1 200 OK\r\n"; *sock << "Server: socket++ Testserver\r\n"; get_filesize (filename.c_str(), buffer); *sock << "Content-Length: " << buffer << "\r\n"; *sock << "Connection: close\r\n"; *sock << "Content-Type: plain/text; charset=iso-8859-1\r\n"; *sock << "\r\n"; sock->flush(); try { for (getline(file, buffer); !file.eof(); getline(file,buffer)) { cout << "Sending Buffer: " << buffer << endl; *sock << buffer << "\r\n"; } sock->flush(); } catch (sockerr e) { cout << "Catched sockerr" << endl; } file.close (); END: try { sock->rdbuf()->shutdown(sockbuf::shut_readwrite); } catch (...) { // if the client break the connection, then // the shutdown method throws sockerr } delete sock; return 0; } void get_filesize (const char *name, string &buffer) { struct stat buf; #ifdef HAVE_SSTREAM stringstream sb; #else strstream sb; #endif if (stat (name, &buf) == -1) buf.st_size = 0; sb << buf.st_size; buffer = sb.rdbuf()->str(); } socket++-1.12.13/test/tdinwrite.C0000644000175000017500000000414711676325304014550 0ustar stbstb// tdinwrite.cc. Test for -*- C++ -*- socket library // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #include #include #include using namespace std; int main(int ac, char** av) { if (ac < 3) { cerr << "USAGE: " << av[0] << " thostname port-number " << "data ... " << endl; return 1; } osockinet osin (sockbuf::sock_dgram); osin->connect (av[1], atoi (av[2])); cout << "local: " << osin->localport() << ' ' << osin->localhost() << endl << "peer: " << osin->peerport() << ' ' << osin->peerhost() << endl; // test socket options cout << "socket type = " << osin->gettype() << endl; cout << "socket linger time = " << osin->linger(1, 10).l_linger << endl; cout << "socket linger time = " << osin->linger(1, 0).l_linger << endl; cout << "socket linger time = " << osin->linger().l_linger << endl; // cout << "socket send bufsz = " << osin->sendbufsz() << endl; // cout << "socket recv bufsz = " << osin->recvbufsz() << endl; cout << "socket keepalive = " << osin->keepalive(true) << endl; cout << "socket keepalive = " << osin->keepalive(false) << endl; cout << "socket clearerror = " << osin->clearerror() << endl; cout << "socket debug = " << osin->debug(true) << endl; cout << "socket debug = " << osin->debug(false) << endl; cout << "socket reuse = " << osin->reuseaddr(true) << endl; cout << "socket reuse = " << osin->reuseaddr(false) << endl; #if 0 // def __linux__ int timeo = 0; osin->getopt(sockbuf::so_sndtimeo, &timeo, sizeof(timeo)); cout << "socket sendtimeo = " << timeo << endl; osin->getopt(sockbuf::so_rcvtimeo, &timeo, sizeof(timeo)); cout << "socket recvtimeo = " << timeo << endl; #endif osin << ac-3; av += 3; while(*av) osin << *av++ << ' '; osin << endl; return 0; } socket++-1.12.13/test/tsunread.C0000644000175000017500000000217011676325304014356 0ustar stbstb// tsunread.cc. Test for -*- C++ -*- socket library // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #include #include #include #include using namespace std; #if defined (__alpha) && defined (__DECCXX) extern "C" int chmod (const char*, int); #endif int main(int ac, char** av) { if (ac != 2) { cerr << "USAGE: " << av[0] << " socket_path_name\n"; return 1; } sockunixbuf su (sockbuf::sock_stream); su.bind (av[1]); cout << "Socket name = " << av[1] << endl; if (chmod(av[1], 0777) == -1) { perror("chmod"); return 1; } su.listen (3); iosockunix iosun (su.accept()); char buf[1024]; iosun << av[0] << ' ' << av[1] << endl; while ( iosun >> buf ) cout << av[0] << ": " << buf << endl; unlink (av[1]); return 0; } socket++-1.12.13/test/tsinwrite.C0000644000175000017500000000336411676325304014567 0ustar stbstb// tsinwrite.cc. Test for -*- C++ -*- socket library // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 // // 2003-04-26 Herbert Straub: try-catch block on connect (test sockerr) #include #include #include #include using namespace std; int main(int ac, char** av) { if (ac < 3) { cerr << "USAGE: " << av[0] << " machinename port " << "format-string data...\n"; return 1; } iosockinet sio (sockbuf::sock_stream); try { sio->connect(av [1], atoi (av [2])); } catch (sockerr e) { cout << "sockerr!!" << endl; cout << "errno: " << e.serrno () << endl; cout << "operation: " << e.operation () << endl; cout << "errstr: " << e.errstr () << endl; return 1; } // sio->shutdown(sockbuf::shut_read); // cout << "local port = " << sio->localport() << endl // << " peer port = " << sio->peerport() << endl // << "local host = " << sio->localhost() << endl // << " peer host = " << sio->peerhost() << endl; av += 3; while (*av) sio << *av++ << ' '; // space is neccessary sio << endl; // endl to flush output char buf[256]; while (sio >> buf) cout << buf << ' '; cout << endl; // sio << "%f%d%c " // space is necessary // << 236.9 << ' ' // << 56 << ' ' // << 'c' << endl; // endl to flush output return 0; } socket++-1.12.13/test/tdunread.C0000644000175000017500000000233211676325304014337 0ustar stbstb// tdunread.cc. Test for -*- C++ -*- socket library // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #include #include #include #include // solaris2.3 perror is here #include // solaris 2.3 chmod is here #include #include using namespace std; void terminate (void) { exit (1); } void unexpected (void) { abort (); } int main(int ac, char** av) { if (ac != 2) { cerr << "USAGE: " << av[0] << " socket_path_name\n"; return 1; } isockunix su (sockbuf::sock_dgram); su->bind(av[1]); cout << "Socket name = " << av[1] << endl; if (chmod (av[1], 0777) == -1) { perror("chmod"); return 1; } char buf[1024]; int i; su >> i; cout << av[0] << ": " << i << " strings: "; while (i--) { su >> buf; cout << buf << ' '; } cout << endl; unlink(av[1]); return 0; } socket++-1.12.13/test/tfork0.C0000644000175000017500000000162511676325304013742 0ustar stbstb// Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #include #include using namespace std; static void print (char* name, pid_t child) { if (child) { cerr << "Parent " << getppid () << "; " << name << ' ' << getpid () << "; Child " << child << ";\n"; } else if (0) { cerr << "Parent " << getppid () << "; " << name << "'s child " << getpid () << ";\n"; } } int main (int ac, char** av) { Fork A (1, 1); print ("A", A.process_id ()); if (A.is_child ()) { sleep (120); return 0x8; } sleep (30); return 0; } socket++-1.12.13/test/tsinread.C0000644000175000017500000000347111676325304014347 0ustar stbstb// tsinread.cc. Test for -*- C++ -*- socket library // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #include #include using namespace std; static void process_input (iosockinet& s); int main() { sockinetbuf sin (sockbuf::sock_stream); sin.bind(); cout << "localhost = " << sin.localhost() << endl << "localport = " << sin.localport() << endl; sin.listen(); for(;;) { { iosockinet s (sin.accept()); process_input(s); } // lets use select to find out whether a socket is ready if (!sin.is_readready(2)) { // the socket is not ready. Let us sleep for 1 sec. sleep(1); } iosockinet s2 (sin.accept()); process_input(s2); break; // let us get out of here forever } return 0; } static void process_input(iosockinet& sio) { char buf[256]; char* p = buf; sio >> p; while (*p) { if (*p != '%') cout << *p; else switch (*++p) { case 'd': { int i; sio >> i; cout << i << ' '; sio << "INT "; break; } case 'f': { double d; sio >> d; cout << d << ' '; sio << "DOUBLE "; break; } case 's': { char str[256]; sio >> str; cout << str << ' '; sio << "STRING "; break; } case 'c': { char c; sio >> c; cout << c << ' '; sio << "CHAR "; break; } case '%': cout << '%' << ' '; break; default: cout << '%' << *p; } p++; } sio << "received" << endl; cout << endl; } socket++-1.12.13/test/tnntp.C0000644000175000017500000000217611676325304013702 0ustar stbstb// Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #include #include using namespace std; static int send_cmd(const char*, iosockstream&); static int get_text(istream&); int main() { iosockinet sio(sockbuf::sock_stream); sio->connect("localhost", "nntp", "tcp"); send_cmd(0, sio); send_cmd("HELP", sio); get_text(sio); send_cmd("QUIT", sio); return 0; } int send_cmd(const char* cmd, iosockstream& s) { if (cmd) s << cmd << "\r\n" << flush; char buf[256]; s.getline(buf, 255); cout << buf << endl; if (buf[0] == '4' || buf[1] == '5') return 1; return 0; } int get_text(istream& s) { char buf[256]; while (s.getline(buf, 255)) if (buf[0] == '.') { if (buf[1] == '.') cout << buf+1 << endl; else return 0; }else cout << buf << endl; return 1; } socket++-1.12.13/test/tsecho.C0000644000175000017500000000137411676325304014023 0ustar stbstb// This may look like C code, but it is really -*- C++ -*- // tpopentest.cc. Test for -*- C++ -*- socket library // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #include #include using namespace std; int main (int ac, char** av) { if (ac != 2) { cerr << "USAGE: " << av [0] << " portno\n"; return 1; } echo server (protocol::tcp); server->serve_clients (atoi (av [1])); return 2; } socket++-1.12.13/test/tpopen.C0000644000175000017500000000170711676325304014043 0ustar stbstb// tpopen.cc. Test for -*- C++ -*- socket library // Copyright (C) 1992,1993,1994 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright // notice and this paragraph are preserved on all copies. // This software is provided "as is" with no express or implied warranty. // // Version: 12Jan97 1.11 #include #include using namespace std; int main() { char buf[128]; ipipestream ipopen("./tpopentest -o"); cout << "Got from ipopen: "; while(ipopen >> buf) cout << buf << ' '; cout << endl; opipestream opopen("./tpopentest -i"); opopen << "this is sent to tpopentest" << endl; iopipestream iopopen("./tpopentest -b"); iopopen << "echo test one two three" << endl; cout << "Result from iopopen: "; while (iopopen >> buf) cout << buf << ' '; cout << endl; return 0; } socket++-1.12.13/test/tbind-1.C0000644000175000017500000000122311676325304013765 0ustar stbstb// Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #include using namespace std; int main () { isockinet is; try { is->bind (40); } catch (sockerr e) { cerr << e.errstr () << endl; return 1; } catch (...) { cerr << "unknown exception occured\n"; return 1; } return 0; } socket++-1.12.13/test/twhois.C0000644000175000017500000000205211676325304014045 0ustar stbstb// Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #include using namespace std; int main(int ac, char** av) { if (ac != 2 && ac != 3) { cerr << "USAGE: " << av[0] << " [ -l ] user_name\n"; return 1; } iosockinet sio (sockbuf::sock_stream); if (ac == 3) { if (av[1][0] != '-' || av[1][1] != 'l') { cerr << "USAGE: " << av[0] << " [ -l ] user_name\n"; return 1; } // use local whois server sio->connect ("128.143.2.20", "whois", "tcp"); sio << av[2] << "\r\n" << flush; } else { sio->connect ("nic.ddn.mil", "whois", "tcp"); sio << av[1] << "\r\n" << flush; } char buf[1024]; while ( sio.getline(buf, 1023) ) cout << buf << endl; cout << endl; return 0; } socket++-1.12.13/test/tbind-0.C0000644000175000017500000000111011676325304013757 0ustar stbstb// Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #include using namespace std; int main () { isockinet is; try { is->bind (4020); } catch (sockerr e) { cerr << e.errstr () << endl; return 1; } return 0; } socket++-1.12.13/test/tsmtp.C0000644000175000017500000000436711676325304013712 0ustar stbstb// socket++ library. tsmtp.C // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 // 2003-03-06 Herbert Straub: variable from and to #include #include #include using namespace std; static void send_cmd(iosockstream&, const char* cmd=0); static void get_text(iosockstream&); int main(int ac, char** av) { if (ac != 4) { cerr << "USAGE: " << av[0] << " hostname from to\n"; return 1; } try { iosockinet sio (sockbuf::sock_stream); sio.rdbuf()->setname ("smtp socket"); string buffer; sio->connect(av[1], "smtp", "tcp"); //send_cmd(sio, 0); send_cmd(sio, "HELO kelvin.seas.virginia.edu"); send_cmd(sio, "HELP"); buffer = "MAIL FROM: "; buffer += av[2]; send_cmd(sio, buffer.c_str()); buffer = "RCPT TO: "; buffer += av[3]; send_cmd(sio, buffer.c_str()); send_cmd(sio, "DATA"); cout << "terminate your input with cntrl-D\n\n"; while(getline(cin, buffer)) { if (buffer[0] == '.') sio << '.'; sio << buffer << "\r\n"; } sio << "\r\n.\r\n" << flush; send_cmd(sio, 0); send_cmd(sio, "HELP"); send_cmd(sio, "QUIT"); } catch (sockerr err) { cout << "catched"<< endl; cout << "catched sockerr: " << err.serrno() << " : " << err.operation () << endl; } catch (...) { cout << "unknown exception" << endl; } return 0; } void send_cmd(iosockstream& s, const char* cmd) { if (cmd) { s << cmd << "\r\n" << flush; } get_text (s); } void get_text(iosockstream& s) { string buffer; int tmo = s->recvtimeout(2); // wait for 1 sec before timing out try { // FIXME: Straub debug while ( getline(s, buffer) ) { if (buffer[0] == '.' && buffer[1] == '\r' && buffer[2] == '\n') break; cout << buffer << endl; } } catch (sockerr e) { cout << "catched sockerr" << endl; } if ( !s.eof() ) s.clear(); s->recvtimeout(tmo); //reset timeout to the previous value } socket++-1.12.13/test/testall.C0000644000175000017500000000564011676325304014206 0ustar stbstb// testall.cc. Test for -*- C++ -*- socket library // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #include #include #include using namespace std; int main(int ac, char** av) { char buf[256]; int portno; char thostname[64]; ipipestream tdunread("./tdunread /tmp/soc"); tdunread.getline(buf, 255); cout << buf << endl; ipipestream tdunwrite("./tdunwrite /tmp/soc mary had a little lamb"); while ( tdunread.getline(buf, 255) ) cout << buf << endl; cout << endl; ipipestream tdinread("./tdinread"); tdinread >> buf >> buf >> thostname >> buf >> buf >> portno; tdinread.getline(buf, 255); sprintf(buf, "./tdinwrite %s %d mary had a little lamb", thostname, portno); ipipestream tdinwrite(buf); while ( tdinread.getline(buf, 255) ) cout << buf << endl; tdinwrite.getline(buf, 255); tdinwrite.getline(buf, 255); while ( tdinwrite.getline(buf, 255) ) cout << buf << endl; cout << endl; ipipestream tsunread("./tsunread /tmp/soc"); tsunread.getline(buf, 255); cout << buf << endl; ipipestream tsunwrite("./tsunwrite /tmp/soc mary had a little lamb"); while ( tsunread.getline(buf, 255) ) cout << buf << endl; cout << endl; ipipestream tsinread("./tsinread"); tsinread >> buf >> buf >> thostname >> buf >> buf >> portno; tsinread.getline(buf, 255); sprintf(buf, "./tsinwrite %s %d %%d%%s%%f 356 haha 23.5", thostname, portno); ipipestream tsinwrite1(buf); sprintf(buf, "./tsinwrite %s %d %%s%%c oooiiii !", thostname, portno); cout << "sleeping for 3 sec\n"; sleep(3); ipipestream tsinwrite2(buf); while ( tsinread.getline(buf, 255) ) cout << "tsinread: " << buf << endl; while ( tsinwrite1.getline(buf, 255) ) cout << "tsinwrite1: " << buf << endl; while ( tsinwrite2.getline(buf, 255) ) cout << "tsinwrite2: " << buf << endl; cout << endl; ipipestream tpipe("./tpipe mary had a little lamb"); while ( tpipe.getline(buf, 255) ) cout << "tpipe " << buf << endl; cout << endl; ipipestream tsockpair("./tsockpair mary had a little lamb"); while ( tsockpair.getline(buf, 255) ) cout << "tsockpair " << buf << endl; cout << endl; ipipestream tpopen ("./tpopen"); while ( tpopen.getline(buf, 255) ) cout << "tpopen " << buf << endl; cout << endl; ipipestream twhois("./twhois .knuth,donald"); cout <<"twhois:\n"; while ( twhois.getline(buf, 255) ) cout << buf << endl; cout << endl; ipipestream thost("./thostnames uvaarpa.virginia.edu"); cout << "thostnames:\n"; while ( thost.getline(buf, 255) ) cout << buf << endl; cout << endl; return 0; } socket++-1.12.13/test/tfork.C0000644000175000017500000000241611676325304013661 0ustar stbstb// Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #include #include using namespace std; static void print (char* name, pid_t child) { if (child) { cerr << "Parent " << getppid () << "; " << name << ' ' << getpid () << "; Child " << child << ";\n"; } else if (0) { cerr << "Parent " << getppid () << "; " << name << "'s child " << getpid () << ";\n"; } } int main (int ac, char** av) { Fork::suicide_signal (SIGTERM); Fork a(0, 1); print ("a", a.process_id ()); if (a.is_child ()) { sleep (3000); } else if (a.is_parent ()) { Fork b (1, 1); print ("b", b.process_id ()); { Fork c (b.is_parent (), 1); if (b.is_child ()) print ("cchild", c.process_id ()); else print ("cparent", c.process_id ()); if (c.is_child ()) { sleep (3000); return 0; } } if (b.is_child ()) { sleep (120); return 0x8; } } return 0; } socket++-1.12.13/test/tpopen-ftp.C0000644000175000017500000000123111676325304014622 0ustar stbstb// Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #include using namespace std; int main() { char buf[128]; iopipestream p("ftp"); // p->unbuffered(); // commented out by LN p << "help\r\n" << flush; while ( p.getline(buf, 127) ) cout << buf << endl; return 0; } socket++-1.12.13/test/tpopen-lpc.C0000644000175000017500000000115211676325304014611 0ustar stbstb// Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #include using namespace std; int main() { char buf[128]; iopipestream p("lpc"); p << "help\nquit\n" << flush; while ( p.getline(buf, 127) ) cout << buf << endl; return 0; } socket++-1.12.13/test/tdinread.C0000644000175000017500000000153111676325304014323 0ustar stbstb// tdinread.cc. Test for -*- C++ -*- socket library // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #include using namespace std; int main(int ac, char** av) { isockinet isin (sockbuf::sock_dgram); isin->bind (2000); cout << "localhost = " << isin->localhost() << endl << "localport = " << isin->localport() << endl; char buf[256]; int n; isin >> n; cout << av[0] << ": "; while(n--) { isin >> buf; cout << buf << ' '; } cout << endl; return 0; } socket++-1.12.13/test/tpipe.C0000644000175000017500000000170511676325304013655 0ustar stbstb// tpipe.cc. Test for -*- C++ -*- socket library // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #include #include using namespace std; int main(int ac, char** av) { iopipestream p; if ( p.fork() ) { // I am the parent cout << "parent got: "; while (ac--) { char buf[32]; buf [0] = 0; p << ac << endl; p >> buf; cout << buf << ' '; } cout << endl; } else { // I am the child int i; cout << "child got: "; while (p >> i) { p << av[i] << endl; cout << i << ' '; } cout << endl; } return 0; } socket++-1.12.13/test/Makefile.in0000644000175000017500000000353211676325304014475 0ustar stbstbsrcdir = . CC = @CC@ CXX = @CXX@ CFLAGS = @CFLAGS@ CXXFLAGS = @CXXFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = -L$(srcdir)/.. -L$(srcdir)/../socket++/.libs -lsocket++ @NETWORK_LIBS@ TESTSRCS = tdunread.C tdunwrite.C \ tdinread.C tdinwrite.C \ tsunread.C tsunwrite.C \ tsinread.C tsinwrite.C \ tpipe.C \ tsockpair.C \ tpopen.C tpopen-lpc.C tpopen-ftp.C \ tpopentest.C \ testall.C \ tnntp.C \ tsmtp.C \ tsendfiles.C \ thostnames.C \ twhois.C \ tfork.C tfork0.C \ tsecho.C tcecho.C \ tcsmtp.C \ tcftp.C \ tbind-0.C tbind-1.C \ tsig-0.C \ test_sockerr.C \ simple_httpd.C TESTOBJS = $(TESTSRCS:.C=.o) TESTS = $(TESTSRCS:.C=) DEPEND_SOURCES = $(srcdir)/*.C .SUFFIXES: .o .C .cc .cc.o .C.o: $(CXX) -c $(CXXFLAGS) -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../socket++ $< .PHONY: check check: testall.out diff -c testall.exp testall.out || make -f Makefile.in message message: @echo @echo If there are any differences, manually check whether @echo testall.out and testall.exp have the same lines but @echo only their order is different. If they have the same @echo lines but for the order, you have installed properly. @echo Otherwise, try to findout what might be the reason and @echo if you could not please email me with your problem at @echo gs4t@virginia.edu @echo testall.out: $(TESTS) ./testall > testall.out $(TESTS): $(TESTOBJS) $(CXX) $(CXXFLAGS) -o $@ $@.o $(LIBS) update-version: for i in $(TESTSRCS); \ do \ sed -e "s/Version: [0-9a-zA-Z]* [0-9.]*/Version: `date +%d%h%y` $(VERSION)/g" $$i > TMP$$i; \ mv TMP$$i $$i; \ done clean: -rm -f *~ *.o core $(TESTS) distclean: clean -rm -f Makefile distcopy: mkdir -p ../socket++-$(VERSION)/test for f in $(TESTSRCS) Makefile.in testall.exp; \ do \ (cd ../socket++-$(VERSION)/test; ln -s ../../test/$$f $$f) \ done depend: makedepend $(CXXINCLUDES) $(TESTSRCS) socket++-1.12.13/test/tsunwrite.C0000644000175000017500000000150311676325304014574 0ustar stbstb// tsunwrite.cc. Test for -*- C++ -*- socket library // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #include using namespace std; int main(int ac, char** av) { if (ac < 2) { cerr << "USAGE: " << av[0] << " socket_path_name data...\n"; return 1; } iosockunix iosun (sockbuf::sock_stream); iosun->connect(av[1]); char buf[128]; iosun >> buf; cout << buf << ' '; iosun >> buf; cout << buf << endl; while (*av) iosun << *av++ << ' '; iosun << endl; return 0; } socket++-1.12.13/test/tdunwrite.C0000644000175000017500000000152311676325304014557 0ustar stbstb// tdunwrite.cc. Test for -*- C++ -*- socket library // Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #include #include using namespace std; void terminate (void) { exit (1); } void unexpected (void) { abort (); } int main(int ac, char** av) { if (ac < 2) { cerr << "USAGE: " << av[0] << " socket_path_name data...\n"; return 1; } osockunix su (sockbuf::sock_dgram); su->connect (av[1]); su << ac << ' '; while (*av) { su << *av << ' '; av++; } su << endl; return 0; } socket++-1.12.13/test/tcecho.C0000644000175000017500000000174411676325304014004 0ustar stbstb// Copyright (C) 1992-1996 Gnanasekaran Swaminathan // // Permission is granted to use at your own risk and distribute this software // in source and binary forms provided the above copyright notice and this // paragraph are preserved on all copies. This software is provided "as is" // with no express or implied warranty. // // Version: 12Jan97 1.11 #include #include using namespace std; int main (int ac, char** av) { if (ac < 3) { cerr << "USAGE: " << av [0] << " remote-host portno string...\n"; return 1; } int portno = atoi (av [2]); echo e(protocol::tcp); if (portno == 0) e->connect (av [1]); else e->connect (av [1], portno); cout << e->rfc_name () << ' ' << e->rfc_doc () << endl; for (int i = 0; i < ac; i++) { char buf [256]; cout << "sending: " << av [i] << endl; e << av [i] << endl; e.getline (buf, 255); cout << "got back: " << buf << endl; } return 0; } socket++-1.12.13/socket++.spec0000644000175000017500000000443011676325304013741 0ustar stbstbName: socket++ Summary: A C++ interface for sockets. Version: 1.12.10 Release: 1 Copyright: Freely Distributable Group: Development/Libraries Source: http://www.hstraub.at/linux/downloads/src/%{name}-%{version}.tar.gz Vendor: Gnanasekaran Swaminathan URL: http://members.aon.at/hstraub/linux/socket++/ Packager: Herbert Straub BuildRequires: autoconf automake texinfo libtool info BuildRoot: %{_tmppath}/%{name}-root %description Socket++ library defines a family of C++ classes that can be used more effectively than directly calling the underlying low-level system functions. One distinct advantage of the socket++ is that it has the same interface as that of the iostream so that the users can perform type-safe input output. This is a modified version of the original socket++ 1.11 Library %prep %setup %build ./autogen %configure make %install [ "$RPM_BUILD_ROOT" != "" ] && rm -rf $RPM_BUILD_ROOT mkdir -p $RPM_BUILD_ROOT make DESTDIR=$RPM_BUILD_ROOT install rm -f $RPM_BUILD_ROOT%{_infodir}/dir %clean [ "$RPM_BUILD_ROOT" != "" ] && rm -rf $RPM_BUILD_ROOT %post /sbin/ldconfig /sbin/install-info %{_infodir}/socket++.info.gz %{_infodir}/dir %preun if [ "$1" = 0 ]; then /sbin/install-info --delete %{_infodir}/socket++.info.gz %{_infodir}/dir fi %postun /sbin/ldconfig %files %{_includedir}/socket++/* %{_libdir}/* %{_infodir}/* %doc COPYING README* ChangeLog AUTHORS THANKS NEWS %changelog * Sat Apr 26 2003 Herbert Straub - new upstream version - version 1.12.10-1 RPM * Fri Mar 13 2003 Herbert Straub - new upstream version - version 1.12.9-1 RPM * Fri Dec 06 2002 Herbert Straub - new upstream version, new fixed up spec file from Carles Arjona - version 1.12.8-1 RPM * Wed Nov 27 2002 Carles Arjona - fixed up spec file - version 1.12.7-1 RPM * Sat Nov 23 2002 Herbert Straub - new upstream version - version 1.12.6-1 RPM * Sun Nov 15 2002 Herbert Straub - new upstream version - version 1.12.5-1 RPM * Sun Nov 10 2002 Carles Arjona - added BuildRoot support - version 1.12.4-1 RPM * Thu Oct 08 2002 Herbert Straub - version 1.12.3 RPM * Fri Jul 06 2001 Lauri Nurmi - version 1.11ln3 RPM socket++-1.12.13/COPYING0000755000175000017500000000075311676325304012511 0ustar stbstbCopyright Notice: ----------------- Copyright (C) 1992-1996 Gnanasekaran Swaminathan Permission is granted to use at your own risk and distribute this software in source and binary forms provided the above copyright notice and this paragraph are preserved on all copies. This software is provided "as is" with no express or implied warranty. Copyright Notice: ----------------- Portions Copyright (C) 2002-2003 Herbert Straub for all my changes (see ChangeLog) socket++-1.12.13/INSTALL0000644000175000017500000002250511676325304012503 0ustar stbstbQuick Installation Instructions =============================== $> ./autogen $> ./configure --prefix=/usr $> make $> su $> make install Quick Installation Instructsions Debug Version ============================================== $> ./autogen $> ./configure --prefix=/usr --enable-debug $> make S> su $> make install Basic Installation ================== These are generic installation instructions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. (Caching is disabled by default to prevent problems with accidental use of stale cache files.) If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You only need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. If you're using `csh' on an old version of System V, you might need to type `sh ./configure' instead to prevent `csh' from trying to execute `configure' itself. Running `configure' takes awhile. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package. 4. Type `make install' to install the programs and any data files and documentation. 5. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for variables by setting them in the environment. You can do that on the command line like this: ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix *Note Environment Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you must use a version of `make' that supports the `VPATH' variable, such as GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. If you have to use a `make' that does not support the `VPATH' variable, you have to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. Installation Names ================== By default, `make install' will install the package's files in `/usr/local/bin', `/usr/local/man', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PATH'. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you give `configure' the option `--exec-prefix=PATH', the package will use PATH as the prefix for installing programs and libraries. Documentation and other data files will still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=PATH' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Optional Features ================= Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of host the package will run on. Usually `configure' can figure that out, but if it prints a message saying it cannot guess the host type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the host type. If you are _building_ compiler tools for cross-compiling, you should use the `--target=TYPE' option to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the host platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. In this case, you should also specify the build platform with `--build=TYPE', because, in this case, it may not be possible to guess the build platform (it sometimes involves compiling and running simple test programs, and this can't be done if the compiler is a cross compiler). Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Environment Variables ===================== Variables not defined in a site shell script can be set in the environment passed to configure. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc will cause the specified gcc to be used as the C compiler (unless it is overridden in the site shell script). `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of the options to `configure', and exit. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details.