diff options
author | schmidt <douglascraigschmidt@users.noreply.github.com> | 1998-09-07 04:49:01 +0000 |
---|---|---|
committer | schmidt <douglascraigschmidt@users.noreply.github.com> | 1998-09-07 04:49:01 +0000 |
commit | dceee5506c4b747d6c3801d3f1649f9305dff2d5 (patch) | |
tree | c487fc2eb5a13824b27c6983a5620f90c4442fe8 /apps/drwho | |
parent | 027290ebc37d5dd85440815f3d5840cd83b51b7a (diff) | |
download | ATCD-dceee5506c4b747d6c3801d3f1649f9305dff2d5.tar.gz |
*** empty log message ***
Diffstat (limited to 'apps/drwho')
81 files changed, 5576 insertions, 0 deletions
diff --git a/apps/drwho/BS_Client.cpp b/apps/drwho/BS_Client.cpp new file mode 100644 index 00000000000..9630f8713df --- /dev/null +++ b/apps/drwho/BS_Client.cpp @@ -0,0 +1,75 @@ +// $Id$ +#include "Options.h" +#include "new.h" +#include "File_Manager.h" +#include "BS_Client.h" + +BS_Client::BS_Client (void) +{ + this->count_ = File_Manager::open_file (Options::friend_file); + + if (this->count_ < 0) + ACE_ERROR ((LM_ERROR, "%p\n"n, Options::program_name)); + else + { + this->protocol_record_ = + new (PRIVATE_POOL) Protocol_Record[this->count_]; + this->sorted_record_ = + new (PRIVATE_POOL) Protocol_Record *[this->count_]; + + for (int i = 0; i < this->count_; i++) + { + Protocol_Record *rec_ptr = &this->protocol_record_[i]; + this->sorted_record_[i] = rec_ptr; + File_Manager::get_login_and_real_name (rec_ptr->key_name1_, + rec_ptr->key_name2_); + } + + ACE_OS::qsort (this->sorted_record_, + this->count_, + sizeof *this->sorted_record_, + (int (*)(const void *, const void *)) Binary_Search::name_compare); + } +} + +// This function is used to merge the KEY_NAME from server HOST_NAME +// into the sorted list of userids kept on the client's side. Since +// we *know* we are going to find the name we use the traditional +// binary search. + +Protocol_Record * +BS_Client::insert (char *key_name, int) +{ + int lo = 0; + int hi = this->count_ - 1; + Protocol_Record **sorted_buffer = this->sorted_record_; + + while (lo <= hi) + { + int mid = (lo + hi) / 2; + Protocol_Record *frp = sorted_buffer[mid]; + int cmp = ACE_OS::strcmp (key_name, + frp->get_login ()); + + if (cmp == 0) + return frp; + else if (cmp < 0) + hi = mid - 1; + else + lo = mid + 1; + } + + return 0; +} + +Protocol_Record * +BS_Client::get_each_entry (void) +{ + Protocol_Record *frp; + + while ((frp = Binary_Search::get_each_entry ()) != 0) + if (frp->get_drwho_list () != 0) + return frp; + + return 0; +} diff --git a/apps/drwho/BS_Client.h b/apps/drwho/BS_Client.h new file mode 100644 index 00000000000..bab7cd2f76f --- /dev/null +++ b/apps/drwho/BS_Client.h @@ -0,0 +1,49 @@ +/* -*- C++ -*- */ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// drwho +// +// = FILENAME +// BS_Client.h +// +// = DESCRIPTION +// Provides the client's binary search lookup table abstraction. +// +// = AUTHOR +// Douglas C. Schmidt +// +// ============================================================================ + +#if !defined (_BS_CLIENT_H) +#define _BS_CLIENT_H + +#include "Binary_Search.h" + +class BS_Client : public Binary_Search +{ + // = TITLE + // Provides the client's binary search lookup table abstraction. +public: + // = Initialization. + BS_Client (void); + // Constructor. + + virtual Protocol_Record *insert (char *key_name, + int max_len = MAXUSERIDNAMELEN); + // This function is used to merge the <key_name> from server + // <host_name> into the sorted list of userids kept on the client's + // side. Since we *know* we are going to find the name we use the + // traditional binary search. + + virtual Protocol_Record *get_each_entry (void); + // An iterator, similar to Binary_Search::get_next_friend, though in + // this case the friend records are returned in the order they + // appeared in the friend file, rather than in sorted order. Also, + // we skip over entries that don't have any hosts associated with + // them. +}; + +#endif /* _BS_CLIENT_H */ diff --git a/apps/drwho/BS_Server.cpp b/apps/drwho/BS_Server.cpp new file mode 100644 index 00000000000..16e344b7cb2 --- /dev/null +++ b/apps/drwho/BS_Server.cpp @@ -0,0 +1,113 @@ +// $Id$ +#include "BS_Server.h" +#include "new.h" + +// This constructor takes a message of sorted login names and loads up +// the symbol table on the server's side. It assumes that the number +// of friends is stored in the first MAXUSERIDNAMELEN bytes of the +// packet. Note that we assume that the client sends the login names +// in sorted order, so we don't bother sorting them! + +BS_Server::BS_Server (char *packet) +{ + char *buf_ptr = packet + MAXUSERIDNAMELEN; + + this->count_ = atoi (packet); + this->buffer_ = buf_ptr; + this->protocol_record_ = + new (PRIVATE_POOL) Protocol_Record[this->count_]; + this->sorted_record_ = + new (PRIVATE_POOL) Protocol_Record *[this->count_]; + + for (int i = 0; i < this->count_; i++) + { + Protocol_Record *rec_ptr = &this->protocol_record_[i]; + + this->sorted_record_[i] = rec_ptr; + rec_ptr->key_name1_ = buf_ptr; + + // Skip forward to the start of the next login name. + + while (*buf_ptr++ != '\0') + continue; + } + +} + +// Insert the HOST_NAME into the appropriate DRWHO_LIST slot if the +// KEY_NAME happens to be one of our friends. Binary search is used +// because the Protocol_Manager keeps a sorted representation of the +// friend names. +// +// Note that this binary search is tuned for unsuccessful searches, +// since most of the time we the KEY_NAME is *not* a friend (unless +// you've got *lots* of friends)! +// +// Note finally that we keep a cache of the last KEY_NAME that is +// looked up, as well as the result of the lookup. This speeds things +// up because the whod files tend to cluster userids together. */ + +Protocol_Record * +BS_Server::insert (char *key_name, int max_len) +{ + static char last_lookup[MAXHOSTNAMELEN]; + static int mid = 0; + static int result = 0; + Protocol_Record **buffer = this->sorted_record; + + // First check the cache... + if (ACE_OS::strncmp (last_lookup, key_name, max_len) == 0) + { + if (result == 0) + return 0; + } + else + { + // Store this away in the cache for the next iteration. + ACE_OS::strncpy (last_lookup, key_name, max_len); + + int hi = this->count - 1; + int lo = 0; + int cmp; + + while (lo < hi) + { + mid = (hi + lo + 1) / 2; + + cmp = ACE_OS::strncmp (key_name, buffer[mid]->get_login (), max_len); + + if (cmp < 0) + hi = mid - 1; + else + lo = mid; + } + + // This line is very subtle... ;-) + if (!(cmp == 0 || ACE_OS::strncmp (key_name, buffer[--mid]->get_login (), max_len) == 0)) + { + result = 0; + return 0; + } + } + + // If we get here we've located a friend. + + result = 1; + return buffer[mid]; +} + +// Returns the next friend in the sequence of sorted friends. Skips +// over the entries that don't have any hosts associated with them +// (because these entries weren't on the server machine. */ + +Protocol_Record * +BS_Server::get_next_entry (void) +{ + Protocol_Record *frp; + + while ((frp = Binary_Search::get_next_entry ()) != 0) + if (frp->get_drwho_list () != 0) + return frp; + + return 0; +} diff --git a/apps/drwho/BS_Server.h b/apps/drwho/BS_Server.h new file mode 100644 index 00000000000..d821acc7cf5 --- /dev/null +++ b/apps/drwho/BS_Server.h @@ -0,0 +1,47 @@ +/* -*- C++ -*- */ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// drwho +// +// = FILENAME +// BS_Server.h +// +// = DESCRIPTION +// Provides the server's binary search lookup table abstraction. +// +// = AUTHOR +// Douglas C. Schmidt +// +// ============================================================================ + +#if !defined (_BS_SERVER_H) +#define _BS_SERVER_H + +#include "Binary_Search.h" + +class BS_Server : public Binary_Search + // = TITLE + // Provides the server's binary search lookup table abstraction. +{ +public: + // = Initialization. + BS_Server (char *packet); + + virtual Protocol_Record *insert (char *key_name, + int max_len = MAXUSERIDNAMELEN); + // This function is used to merge the <key_name> from server + // <host_name> into the sorted list of userids kept on the client's + // side. + + virtual Protocol_Record *get_next_entry (void); + // An iterator, similar to Binary_Search::get_next_friend, though in + // this case the friend records are returned in the order they + // appeared in the friend file, rather than in sorted order. Also, + // we skip over entries that don't have any hosts associated with + // them. +}; + +#endif /* _BS_SERVER_H */ diff --git a/apps/drwho/Binary_Search.cpp b/apps/drwho/Binary_Search.cpp new file mode 100644 index 00000000000..237ea882875 --- /dev/null +++ b/apps/drwho/Binary_Search.cpp @@ -0,0 +1,77 @@ +// $Id$ +#include "Options.h" +#include "Binary_Search.h" + +// This function is passed to qsort to perform the comparison between +// login names for two friends. + +int +Binary_Search::name_compare (void *s1, void *s2) +{ + return ACE_OS::strcmp ((*(Protocol_Record **) s1)->key_name1_, + (*(Protocol_Record **) s2)->key_name1_); +} + +// Returns the next friend in the sequence of sorted friends. Note +// that this function would be simplified if we expanded the iterator +// interface to include an "initialize" and "next" function! + +Protocol_Record * +Binary_Search::get_next_entry (void) +{ + // Reset the iterator if we are starting from the beginning. + + if (this->current_ptr_ == 0) + this->current_ptr_ = this->sorted_record_; + + // Now check to see if we've hit the end, in which case we set + // things up for the next round! + + if (this->current_ptr_ < this->sorted_record_ + this->count_) + return *this->current_ptr_++; + else + { + this->current_ptr_ = 0; + return 0; + } +} + +// An iterator, similar to Binary_Search::get_next_friend, though in +// this case the friend records are returned in the order they +// appeared in the friend file, rather than in sorted order. Also, we +// skip over entries that don't have any hosts associated with them. + +Protocol_Record * +Binary_Search::get_each_entry (void) +{ + // Reset the iterator if we are starting from the beginning. + + if (this->current_index_ == -1) + this->current_index_ = 0; + + // Now check to see if we've hit the end, in which case we set + // things up for the next round! + + for (; + this->current_index_ < this->count_; + this->current_index_++) + if (this->protocol_record_[this->current_index_].drwho_list != 0) + return &this->protocol_record_[this->current_index_++]; + + this->current_index_ = -1; + return 0; +} + +Binary_Search::~Binary_Search (void) +{ + if (Options::get_opt (Options::DEBUG)) + ACE_DEBUG ((LM_DEBUG, "disposing Binary_Search\n")); +} + +// Used to initialize the values for the iterators... + +Binary_Search::Binary_Search (void) + : current_ptr_ (0), + current_index_ (0) +{ +} diff --git a/apps/drwho/Binary_Search.h b/apps/drwho/Binary_Search.h new file mode 100644 index 00000000000..3312fd5c778 --- /dev/null +++ b/apps/drwho/Binary_Search.h @@ -0,0 +1,71 @@ +/* -*- C++ -*- */ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// drwho +// +// = FILENAME +// Binary_Search.h +// +// = DESCRIPTION +// Defines a binary search abstraction for friend records. +// +// = AUTHOR +// Douglas C. Schmidt +// +// ============================================================================ + +#if defined (_BINARY_SEARCH_H) +#define _BINARY_SEARCH_H + +#include "Search_Struct.h" + +class Binary_Search : public Search_Struct +{ + // = TITLE + // Defines a binary search abstraction for friend records. +public: + // = Initialization and termination method. + Binary_Search (void); + // Initialize the values for the iterators... + + virtual ~Binary_Search (void); + // Destructor. + + virtual Protocol_Record *get_next_entry (void); + // Returns the next friend in the sequence of sorted friends. Note + // that this function would be simplified if we expanded the + // iterator interface to include an "initialize" and "next" + // function! + + virtual Protocol_Record *get_each_entry (void); + // An iterator, similar to Binary_Search::get_next_friend, though in + // this case the friend records are returned in the order they + // appeared in the friend file, rather than in sorted order. Also, + // we skip over entries that don't have any hosts associated with + // them. + + virtual Protocol_Record *insert (char *key_name, + int max_len = MAXUSERIDNAMELEN) = 0; + // This function is used to merge the <key_name> from server + // <host_name> into the sorted list of userids kept on the client's + // side. + + static int name_compare (void *, void *); + // This function is passed to qsort to perform the comparison + // between login names for two friends. + +protected: + Protocol_Record **current_ptr_; + int current_index_; + + Protocol_Record *protocol_record_; + Protocol_Record **sorted_record_; + + char *buffer_; + int buffer_size_; +}; + +#endif /* _BINARY_SEARCH_H */ diff --git a/apps/drwho/CM_Client.cpp b/apps/drwho/CM_Client.cpp new file mode 100644 index 00000000000..88783288ec1 --- /dev/null +++ b/apps/drwho/CM_Client.cpp @@ -0,0 +1,129 @@ +// $Id$ +#include "global.h" +#include "Options.h" +#include "Multicast_Manager.h" +#include "CM_Client.h" + +// Creates and binds a UDP socket... + +int +CM_Client::open (short port_number) +{ + int max_packet_size = UDP_PACKET_SIZE; + + Comm_Manager::sokfd = ACE_OS::socket (PF_INET, SOCK_DGRAM, 0); + + if (Comm_Manager::sokfd == ACE_INVALID_HANDLE) + return -1; + + ACE_OS::memset ((char *) &this->sin, 0, sizeof this->sin); + this->sin.sin_family = AF_INET; + this->sin.sin_port = htons (port_number); + + return 1; +} + +int +CM_Client::receive (int timeout) +{ + FD_ZERO (&this->read_fd_); + FD_SET (Comm_Manager::sokfd, &this->read_fd_); + + if (timeout > 0) + { + this->time_out_.tv_sec = timeout; + this->time_out_.tv_usec = 0; + this->top_ = &time_out; + } + + while (Multicast_Manager::outstanding_hosts_remain ()) + { + if (ACE_OS:;select (Comm_Manager::sokfd + 1, + &this->read_fd_, 0, 0, + this->top_) <= 0) + break; + else + { + int sin_len = sizeof this->sin; + ssize_t n = ACE_OS::recvfrom (Comm_Manager::sokfd, + this->recv_packet_, UDP_PACKET_SIZE, + 0, + (sockaddr *) &this->sin, + &sin_len); + + if (n < 0) + return -1; + else + { + if (Options::get_opt (Options::DEBUG) != 0) + { + hostent *np = ACE_OS::gethostbyaddr ((char *) &this->sin_.sin_addr, + sizeof this->sin_.sin_addr, + AF_INET); + + ACE_DEBUG ((LM_DEBUG, + "receiving from server host %s (%s)\n", + np->h_name, + inet_ntoa (this->sin.sin_addr))); + } + + if (this->demux (this->recv_packet, n) < 0) + return -1; + + Multicast_Manager::checkoff_host (this->sin.sin_addr); + } + } + } + + for (char *host_name; + Multicast_Manager::get_next_non_responding_host (host_name); + ) + ACE_DEBUG ((LM_DEBUG, + "%s did not respond\n", + host_name)); + return 1; +} + +int +CM_Client::send (void) +{ + int packet_length = 0; + + if (this->mux (this->send_packet, packet_length) < 0) + return -1; + + // Ship off the info to all the hosts. + + while (Multicast_Manager::get_next_host_addr (this->sin.sin_addr) != 0) + { + if (Options::get_opt (Options::DEBUG) != 0) + { + hostent *np = ACE_OS::gethostbyaddr ((char *) &this->sin.sin_addr, + sizeof this->sin.sin_addr, + AF_INET); + + ACE_DEBUG ((LM_DEBUG, + "sending to server host %s (%s)\n", + np->h_name, + inet_ntoa (this->sin.sin_addr))); + } + + if (sendto (Comm_Manager::sokfd, this->send_packet, packet_length, 0, (sockaddr *) &this->sin, sizeof this->sin) < 0) + return -1; + } + return 1; +} + +CM_Client::CM_Client (void) + : top (0) +{ +} + +CM_Client::~CM_Client (void) +{ + if (Options::get_opt (Options::DEBUG)) + ACE_DEBUG ((LM_DEBUG, "disposing CM_Client\n")); + + ACE_OS::closesocket (Comm_Manager::sokfd); +} + diff --git a/apps/drwho/CM_Client.h b/apps/drwho/CM_Client.h new file mode 100644 index 00000000000..02c386d6e8d --- /dev/null +++ b/apps/drwho/CM_Client.h @@ -0,0 +1,53 @@ +/* -*- C++ -*- */ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// drwho +// +// = FILENAME +// BS_Server.h +// +// = DESCRIPTION +// Provides a virtual communcations layer for the client in the +// drwho program. +// +// = AUTHOR +// Douglas C. Schmidt +// +// ============================================================================ + +#if defined (_CM_CLIENT_H) +#define _CM_CLIENT_H + +#include "ace/OS.h" +#include "global.h" +#include "Comm_Manager.h" + +class CM_Client : public Comm_Manager +{ + // = TITLE + // Provides a virtual communcations layer for the client in the + // drwho program. +public: + // = Initialization and termination. + CM_Client (void); + // Constructor. + + virtual ~CM_Client (void); + // Destructor. + + virtual int mux (char *packet, int &packet_length) = 0; + virtual int demux (char *packet, int &packet_length) = 0; + virtual int open (short port_number); + virtual int receive (int timeout = 0); + virtual int send (void); + +private: + fd_set read_fd_; + timeval time_out_; + timeval *top_; +}; + +#endif /* _CM_CLIENT_H */ diff --git a/apps/drwho/CM_Server.cpp b/apps/drwho/CM_Server.cpp new file mode 100644 index 00000000000..f9306553269 --- /dev/null +++ b/apps/drwho/CM_Server.cpp @@ -0,0 +1,85 @@ +// $Id$ +#include "global.h" +#include "Options.h" +#include "CM_Server.h" + +/* Creates and binds a UDP socket... */ + +int +CM_Server::open (short port_number) +{ + int max_packet_size = UDP_PACKET_SIZE; + + if ((this->sokfd = socket (PF_INET, SOCK_DGRAM, 0)) < 0) + return -1; + + bzero (&this->sin, sizeof this->sin); + this->sin.sin_family = AF_INET; + this->sin.sin_port = htons (port_number); + this->sin.sin_addr.s_addr = INADDR_ANY; + + /* This call fails if an rflo daemon is already running. */ + if (bind (this->sokfd, (sockaddr *) &this->sin, sizeof this->sin) < 0) + return -1; + +#ifndef i386 + /* Allow for very large datagrams. */ + + if (setsockopt (this->sokfd, SOL_SOCKET, SO_SNDBUF, (char *) &max_packet_size, sizeof max_packet_size) < 0) + return -1; +#endif + + return 1; +} + +int +CM_Server::receive (int) +{ + /* SUPPRESS 175 */ + int sin_len = sizeof this->sin; + int n; + + if (Options::get_opt (Options::DEBUG) != 0) + fprintf (stderr, "waiting for client to send...\n"); + + if ((n = recvfrom (this->sokfd, this->recv_packet, UDP_PACKET_SIZE, 0, (sockaddr *) &this->sin, &sin_len)) < 0) + return -1; + + if (Options::get_opt (Options::DEBUG) != 0) + fprintf (stderr, "receiving from client host %s\n", inet_ntoa (this->sin.sin_addr)); + + if (this->demux (this->recv_packet, n) < 0) + return -1; + + return 1; +} + +int +CM_Server::send (void) +{ + /* SUPPRESS 175 */ + int packet_length = 0; + + if (this->mux (this->send_packet, packet_length) < 0) + return -1; + + if (Options::get_opt (Options::DEBUG) != 0) + fprintf (stderr, "sending to client host %s\n", inet_ntoa (this->sin.sin_addr)); + + if (sendto (this->sokfd, this->send_packet, packet_length, 0, (sockaddr *) &this->sin, sizeof this->sin) < 0) + return -1; + + return 1; +} + +#ifndef __OPTIMIZE__ +CM_Server::CM_Server (void) +{} + +CM_Server::~CM_Server (void) +{ + if (Options::get_opt (Options::DEBUG)) + fprintf (stderr, "CM_Server\n"); + close (this->sokfd); +} +#endif /* __OPTIMIZE__ */ diff --git a/apps/drwho/CM_Server.h b/apps/drwho/CM_Server.h new file mode 100644 index 00000000000..db0cea2a33f --- /dev/null +++ b/apps/drwho/CM_Server.h @@ -0,0 +1,41 @@ +/* -*- C++ -*- */ +// $Id$ + +/* Provides a virtual communcations layer for the server in the drwho + program. */ + +#ifndef _CM_SERVER_H +#define _CM_SERVER_H + +#include "Options.h" +#include "ace/OS.h" +#include "global.h" +#include "Comm_Manager.h" + +class CM_Server : public Comm_Manager +{ +public: + CM_Server (void); + virtual ~CM_Server (void); + + virtual int open (short port_number); + virtual int receive (int timeout = 0); + virtual int send (void); + virtual int mux (char *packet, int &packet_length) = 0; + virtual int demux (char *packet, int &packet_length) = 0; +}; + +#ifdef __OPTIMIZE__ +inline +CM_Server::CM_Server (void) +{} + +inline +CM_Server::~CM_Server (void) +{ + if (Options::get_opt (Options::DEBUG)) + fprintf (stderr, "CM_Server\n"); + close (this->sokfd); +} +#endif /* __OPTIMIZE__ */ +#endif _CM_SERVER_H diff --git a/apps/drwho/ChangeLog b/apps/drwho/ChangeLog new file mode 100644 index 00000000000..f3f89ee2764 --- /dev/null +++ b/apps/drwho/ChangeLog @@ -0,0 +1,239 @@ +Sun Sep 6 22:48:52 1998 Douglas C. Schmidt <schmidt@tango.cs.wustl.edu> + + * Replaced all Str::*() methods with the new ACE::*() methods, + which are more "standard". + + * Began to work on drwho after a 5 year absence... + +Sun Feb 14 16:13:10 1993 Douglas C. Schmidt (schmidt at net1.ics.uci.edu) + + * Yow. Once again back at work... This time I fixed things up so + that the release compiles properly with Solaris 2.1 C++, g++ + 2.3.3, and the Sun C++ compiler on Sun OS 4.1.x. To do this I + had to change the user-defined memory allocator somewhat, since + the Sun C++ compiler was using the global NEW operator to + allocate pools of memory behind my back... Naturally, this + reaked havoc with the existing version in the server, which + returns all the allocated memory to the free list once a request + is satisfied. In addition, g++ had a weird multiple + inheritance/pure virtual function bug that I fixed by reordering + certain pure virtual functions. Oh what fun... ;-) Anyhow, + everything is now back in running order! + +Sun Dec 6 16:13:21 1992 Douglas C. Schmidt (schmidt at net1.ics.uci.edu) + + * Yow, well, after about 8 months of total neglect I'm finally + back at work on this program! The current changes I did today + involved getting drwho to compile with g++ 2.3.2. This required + a couple of small work arounds in the source code due to bugs, + but hey, I guess it is better than nothing right?! + + Also, I had to fix a couple of places where I didn't correctly + initialize static variables (the compiler implementations have + changed since last year obviously). Also, I've changed a couple + of the default server hosts to reflect the fascist policies of + our support group ;-) (I've no longer got access to certain + servers...) + + Anyhow, I think drwho is once again running with g++, so now I + can hand the release over to Ericka... ;-) + +Wed May 6 23:12:02 1992 Douglas C. Schmidt (schmidt at net4.ics.uci.edu) + + * There is something horribly wrong with g++ 2.1. Therefore, I + had to make a couple of changes in the pmc-rusers.C and + pm-client.C files in order to make the blasted thing compile + when I had pointers to member functions... Make sure to change + this back when g++ is fixed... + +Tue Feb 4 11:23:12 1992 Douglas C. Schmidt (schmidt at net6.ics.uci.edu) + + * The blasted program was crashing when there were consecutive + newlines in the input file. I fixed + File_Manager::get_login_and_real_name and + File_Manager::open_friends_file so that they detect and skip + over these consecutive newlines. + +Thu Nov 21 21:55:00 1991 Douglas C. Schmidt (schmidt at net6.ics.uci.edu) + + * Make the time that drwho uses to consider a host idle be a + command-line parameter. + +Wed Nov 13 14:24:40 1991 Douglas C. Schmidt (schmidt at bastille.ics.uci.edu) + + * Something else that ought to be done: + + Add a flag to the -R option that allows the hostname to be + printed using the internet address and/or the hostname... + +Sat Nov 9 13:45:30 1991 Douglas C. Schmidt (schmidt at bastille.ics.uci.edu) + + * Added zillions more changes yet again. We now have an rusers + compatibility mode (-R), to go along with the -a, -w, and + default (flo) options. + + * Changed the -w option so that it only returns the name of the + host machine where the user is logged in. This way, I can say: + + % talk schmidt@`drwho -w schmidt` + % rsh `drwho -w schmidt` w + + etc... ;-) + + * Added support for the -L option (print using login name rather + than real name). Also added support for the -l option (print + out verbosely, a la ls -l!). + +Sun Oct 27 21:32:15 1991 Douglas C. Schmidt (schmidt at bastille.ics.uci.edu) + + * Need to complete the -s and -S options to support sorting the + output by login name and real name, respectively... In order to + support the '*' indication with this scheme we probably need to + lists, one for active and one for inactive users! + +Tue Oct 22 00:13:21 1991 Douglas C. Schmidt (schmidt at net6.ics.uci.edu) + + * Make another zillion changes... + +Sun Oct 20 21:35:24 1991 Douglas C. Schmidt (schmidt at net6.ics.uci.edu) + + * Added support for the -p option to allow setting the client and + server port number from the command-line. + + * Things done so far: + + * Owen also wants an new rflo feature (done) + + I also want a version that given a command like: + + whereis omalley + + would return the login where that login is active if there is + one (ie. omalley@zola). Then you could have commands like: + + talk `whereis omalley` + + that would find where I am and try to talk to me there. + + * Another neat addition would be: have an option (e.g., `-a') so + that rflo would return *all* the users logged in and then look + up their names using the yp passwd stuff! (partially done, but + not very elegantly yet...). (done) + + * Make the port number a command-line option... (done) + + * we also need think about how to incorporate inheritance and + dynamic binding into this thang (probably it can be used for + the local/remote split, and also perhaps for the + friends/everyone split (see below)). (done) + + * Fix up the options stuff wrt the -F option etc... (done) + + * Have I fixed the is_active shit? (done) + + * we need a "message abstraction" that abstracts away from the + details of packets protocols and remote operations protocols. + (done). + + * Note, should make an option so we could read the names of the + hosts to query from a file... (done) + +Fri Oct 18 16:17:39 1991 Douglas C. Schmidt (schmidt at net6.ics.uci.edu) + + * I've made countless changes... + +Wed Oct 16 17:42:40 1991 Douglas C. Schmidt (schmidt at net6.ics.uci.edu) + + * Undid the message manager abstraction and merged it in with the + Friend_Manager client and server. This really cleans up the + interface! + + * Yow, make zillions of important changes to make the + client/server split more explicit... Now the Friend_Manager is + split into client and server, the message manager is split, and + the communications manager is also split. Each file is much + smaller and easier to understand! + +Mon Oct 14 18:36:55 1991 Douglas C. Schmidt (schmidt at net1.ics.uci.edu) + + * Added support for the -h and -? options, that print out a long + and short usage message, respectively. + +Tue Oct 1 09:28:29 1991 Douglas C. Schmidt (schmidt at net4.ics.uci.edu) + + * The -a option works a great deal better too... I added a check + in the File_Manager::open_passwd_file routine to strip off the + extra subfields in the pw_gecos field, since this info isn't + really very useful and makes the "real name" field too long! + + * Added some extra stuff to the Comm_Manager so that I could + change the max size of the UDP datagrams that are passed around. + As it turns out, I don't really need to do this, but it is more + robust this way... + +Thu Sep 26 14:00:45 1991 Douglas C. Schmidt (schmidt at net4.ics.uci.edu) + + * Make sun3 and sun4 subdirectories to help the build process! + + * Changed the UDP port number from 12346 to 12344 so I wouldn't + collide with Owen! + + * There is a weird bus error problem on the sun 4s... Hum... + + * Yow, got everything working again... + + * Still to do: + + * Think about fixing the -f option to work correctly for + *relative* filenames... + + * Make UDP_BUFFER_SIZE a command-line option... + + * Modify server.C to be started by inetd. + + * For -a option... if they are a friend, use the name from + .friend.dta otherwise use the name from the passwd file. + + * Don't forget about: + + delete Friend_Manager::friend_record; + delete Friend_Manager::sorted_record; + + Need to figure out a good way to deal with this! + +Mon Sep 23 16:09:46 1991 Douglas C. Schmidt (schmidt at net4.ics.uci.edu) + + * Added a neat feature that now allows the user to specify which + hosts to examine by specifying an option ('-F') on the + command-line that reads the contents of that file and inserts it + into the list of files. + +Wed Sep 18 10:46:41 1991 Douglas C. Schmidt (schmidt at bastille.ics.uci.edu) + + * We need to make all the interfaces throughout rflo much more + object-oriented, e.g.: + + * Made a host-manager abstraction to handle all the host + machine related operations. This makes the options stuff + *much* cleaner! + + * Make rflo compile with g++ 1.37.2! Now it compiles with cfront + 2.0, Saber C++ 1.0.1 and g++-1.39.0 and g++-1.37.2. + +Tue Sep 17 19:02:47 1991 Douglas C. Schmidt (schmidt at net4.ics.uci.edu) + + * Started merging in the stuff Owen did. I'm trying to maintain a + consistent programming style... The Owen stuff adds support for + timeouts and fixes problems with returning a count of the number + of friends! + +Wed Sep 4 10:14:51 1991 Douglas C. Schmidt (schmidt at net4.ics.uci.edu) + + * Things to do: + + * Add comprehensive daemon support for server.C. + * Add timeout stuff in case hosts are down! + * Talk to support about making a standard daemon. + * Fix the problem with returning the number of friends. + + diff --git a/apps/drwho/Comm_Manager.h b/apps/drwho/Comm_Manager.h new file mode 100644 index 00000000000..98f33a28d39 --- /dev/null +++ b/apps/drwho/Comm_Manager.h @@ -0,0 +1,26 @@ +/* -*- C++ -*- */ +// $Id$ + +/* Provides a virtual communcations layer for the drwho program. */ + +#ifndef _COMM_MANAGER_H +#define _COMM_MANAGER_H + +#include "ace/OS.h" +#include "global.h" + +class Comm_Manager +{ +protected: + char recv_packet[UDP_PACKET_SIZE]; + char send_packet[UDP_PACKET_SIZE]; + sockaddr_in sin; + int sokfd; + + virtual int mux (char *packet, int &packet_length) = 0; + virtual int demux (char *packet, int &packet_length) = 0; + virtual int open (short port_number) = 0; + virtual int receive (int timeout = 0) = 0; + virtual int send (void) = 0; +}; +#endif _COMM_MANAGER_H diff --git a/apps/drwho/Drwho_Node.cpp b/apps/drwho/Drwho_Node.cpp new file mode 100644 index 00000000000..7b3cb3867a5 --- /dev/null +++ b/apps/drwho/Drwho_Node.cpp @@ -0,0 +1,87 @@ +// $Id$ +#include "Drwho_Node.h" + +#ifndef __OPTIMIZE__ +/* Create a Drwho_Node object */ + +Drwho_Node::Drwho_Node (char *h_name, Drwho_Node *n) + : next (n), inactive_count (0), active_count (0), key_name1 (h_name), key_name2 (0) +{} + +Drwho_Node::Drwho_Node (void) + : next (0), inactive_count (0), active_count (0), key_name1 (0), tty_name (0), idle_time (0), key_name2 (0) +{} + +char * +Drwho_Node::get_login_name (void) +{ + return this->key_name1; +} + +char * +Drwho_Node::set_login_name (char *str) +{ + return this->key_name1 = str; +} + +char * +Drwho_Node::get_real_name (void) +{ + return this->key_name2; +} + +char * +Drwho_Node::set_real_name (char *str) +{ + return this->key_name2 = str; +} + +char * +Drwho_Node::get_host_name (void) +{ + return this->key_name1; +} + +char * +Drwho_Node::set_host_name (char *str) +{ + return this->key_name1 = str; +} + +int +Drwho_Node::get_active_count (void) +{ + return this->active_count; +} + +int +Drwho_Node::get_inactive_count (void) +{ + return this->active_count; +} + +int +Drwho_Node::set_active_count (int count) +{ + return this->active_count = count; +} + +int +Drwho_Node::set_inactive_count (int count) +{ + return this->inactive_count = count; +} + +int +Drwho_Node::set_idle_time (int it) +{ + return this->idle_time = it; +} + +int +Drwho_Node::get_idle_time (void) +{ + return this->idle_time; +} +#endif /* __OPTIMIZE__ */ + diff --git a/apps/drwho/Drwho_Node.h b/apps/drwho/Drwho_Node.h new file mode 100644 index 00000000000..e067525500d --- /dev/null +++ b/apps/drwho/Drwho_Node.h @@ -0,0 +1,121 @@ +/* -*- C++ -*- */ +// $Id$ + +/* Stores information about a host for a specific friend. */ + +#ifndef _DRWHO_NODE_H +#define _DRWHO_NODE_H + +#include "ace/OS.h" +#include "global.h" + +struct Drwho_Node +{ + char *key_name1; + char *key_name2; + char *tty_name; + int idle_time; + int active_count; + int inactive_count; + Drwho_Node *next; + + Drwho_Node (char *host, Drwho_Node *next); + Drwho_Node (void); + int get_active_count (void); + int get_inactive_count (void); + int set_active_count (int count); + int set_inactive_count (int count); + int set_idle_time (int idle_time); + int get_idle_time (void); + char *get_host_name (void); + char *set_host_name (char *str); + char *get_login_name (void); + char *set_login_name (char *); + char *get_real_name (void); + char *set_real_name (char *); +}; + +#ifdef __OPTIMIZE__ +inline +Drwho_Node::Drwho_Node (char *h_name, Drwho_Node *n) + : next (n), inactive_count (0), active_count (0), key_name1 (h_name), key_name2 (0) +{} + +inline +Drwho_Node::Drwho_Node (void) + : next (0), inactive_count (0), active_count (0), key_name1 (0), tty_name (0), idle_time (0), key_name2 (0) +{} + +inline char * +Drwho_Node::get_login_name (void) +{ + return this->key_name1; +} + +inline char * +Drwho_Node::set_login_name (char *str) +{ + return this->key_name1 = str; +} + +inline char * +Drwho_Node::get_real_name (void) +{ + return this->key_name2; +} + +inline char * +Drwho_Node::set_real_name (char *str) +{ + return this->key_name2 = str; +} + +inline char * +Drwho_Node::get_host_name (void) +{ + return this->key_name1; +} + +inline char * +Drwho_Node::set_host_name (char *str) +{ + return this->key_name1 = str; +} + +inline int +Drwho_Node::get_active_count (void) +{ + return this->active_count; +} + +inline int +Drwho_Node::get_inactive_count (void) +{ + return this->inactive_count; +} + +inline int +Drwho_Node::set_active_count (int count) +{ + return this->active_count = count; +} + +inline int +Drwho_Node::set_inactive_count (int count) +{ + return this->inactive_count = count; +} + +inline int +Drwho_Node::set_idle_time (int idle_time) +{ + return this->idle_time = idle_time; +} + +inline int +Drwho_Node::get_idle_time (void) +{ + return this->idle_time; +} +#endif /* __OPTIMIZE__ */ +#endif /* _DRWHO_NODE_H */ diff --git a/apps/drwho/EXAMPLE b/apps/drwho/EXAMPLE new file mode 100644 index 00000000000..a8ef4b12fe7 --- /dev/null +++ b/apps/drwho/EXAMPLE @@ -0,0 +1,311 @@ +Hi, + + I'm in the finishing stages of writing a program called +'drwho' (short for "Distributed RWHO"), that gets around certain rwho +limitations, adds functionality, and also prints a much prettier +listing of who's logged in around a network. Here's a short blurb +describing the program if you'd like to try it out (don't worry, no +Trojan horses... ;-)). + + The C++ source is in ~schmidt/languages/C++/drwho. It is a +tour de force of Object-Oriented Design and Programming!!! + + Hope you like it! + + Doug + +---------------------------------------- +p.s. Here are some samples. If you'd like to find out who's logged +in around here, try the following commands: + +# Prints out the help file + +% ~schmidt/bin/sun4/drwho -r -h +usage: drwho +-? prints a short usage message +-A append the following hostname to the list of predefined hostnames. +-a return information on *all* users remotely logged in (uses yp passwd). +-b run the server in the background (i.e., as a daemon). +-d turn on debugging. +-F use the following file contents to initialize the host list. +-f use the following file contents to initialize the friends database. +-H use the following hostname as part of the new list of hostnames. + this option overwrites the existing default names). +-h print a long usage message. +-L print the login name rather than the real name (which is the default). +-l print information in long format (works for all protocols). +-p set the port number (server must correspond). +-R print info using the rusers format. +-r do the remote lookups (i.e., local operations are the default). +-t set the amount of time we wait for servers to timeout. +-w return information on just one user. +---------------------------------------- + +# Find out where a particular person is logged in: + +% ~schmidt/bin/sun4/drwho -r -w brodbeck +chateau + +This is useful for remote commands that require a hostname, e.g.: + +% talk brodbeck@`drwho -r -w brodbeck` + +or + +% rsh `drwho-client -w brodbeck` "ps -aux | egrep -v 'root|schmidt'" +USER PID %CPU %MEM SZ RSS TT STAT START TIME COMMAND +brodbeck 21991 0.0 0.0 108 0 co IW Nov 8 0:10 /usr/bin/X11R4/xclock -r +bin 46 0.0 0.0 36 0 ? IW Oct 15 0:01 ypbind +brodbeck 21907 0.0 0.0 216 0 co IW Nov 8 0:00 -tcsh (tcsh) +brodbeck 22000 0.0 0.0 224 0 p1 IW Nov 8 0:01 -csh (tcsh) +brodbeck 21973 0.0 1.9 864 360 co S Nov 8 2:42 /usr/bin/X11R4/Xsun :0 - +brodbeck 21998 0.0 0.0 212 0 p0 IW Nov 8 0:00 -csh (tcsh) +brodbeck 22001 0.0 0.0 224 0 p3 IW Nov 8 0:02 -csh (tcsh) +brodbeck 22783 0.0 1.4 200 264 p3 S 14:07 0:00 vi one_page_summary +brodbeck 21972 0.0 0.0 40 0 co IW Nov 8 0:00 /usr/bin/X11/xinit -- -l +brodbeck 22803 0.0 0.0 40 0 p1 IW 14:12 0:00 more inbox/37 +brodbeck 21979 0.0 0.0 112 0 co IW Nov 8 0:00 olwm -3 -f +brodbeck 21992 0.0 0.5 108 96 co S Nov 8 0:23 /usr/bin/X11R4/xbiff -bg +brodbeck 21999 0.0 0.0 212 0 p2 IW Nov 8 0:00 -csh (tcsh) + +or + +% foreach host (`drwho -r -l -w brodbeck`) +? echo $host +? rsh $host w | egrep brodbeck +? end +---------------------------------------- + +# Find out which friends are logged in (* means currently active) + +% drwho -r -f ~schmidt/.friends.dta +remote friends logged on +------------------------ + Delectable Debi [chateau] + Chang-Kai Chek [hera] + Gary Gershwin [wagram paris buckaroo ics sherlock] + Andrew Harrison [buckaroo laguna ics cthulu] + Holly Hocs [jourdain] + Dr. Dave [laguna broadway] + Sam Horrocks [brochant paris buckaroo liege laguna ics bonnie john-bigboote] + Well Hung [net5] + Kari Knees [st-michel] + Ionas Rex [ics] + Dr. Ray [bonnie pan clipperton] + Frank Marino [bonnie] + David "fine" Levine [trinite dinsdale segur] + Clark Kent Madsen [pasteur] + Jo Jo Starbuck [segur] + Owen O'Palley [dinsdale porte-de-st-ouen] + Tim Morgan [glacier buckaroo ics john-parker] + Too Thieu [valentine] + Alex Nicolau [ics ck7] + Golden Bear [zola bear] + David Ruby [ics ocean steppingstone] + Elke Summers [aardvark] +*Doug O'las [pasteur beaver* net6*(2) net4] + Karl Marx Schwamb [abp] + Rick Selby [louvre] + this->self [pasteur bugfix] + Sheba [cardinal] + Tatsuda [valentine] + Cindy Twiddle [alexandre-dumas] +*Vanessa Redgrave [bonnie*(2)] + Zippy Ziv [pigalle trinite] +------------------------ +friends: 5 users: 168 + +---------------------------------------- + +# Find out everyone who is logged in everywhere! + +% drwho -r -a +remote users logged on +------------------------ + Barbara Weisenfluh [sunshine] + Jon Krause [laguna] + David Kramer [olympus] + Cindy Tittle Moore [alexandre-dumas] + Karl Schwamb [abp] +*Anh Hoang Tran [bonnie*] + Adam Uthcritam [buckaroo] + Harry Yessayan [chapelle] + Girish Kotmire [legion] +*Udhw68k [ics*] + Ruben Ernesto Ortega [simplon] + Jeanne Pickering [poisson] + Hai-Geng Wang [ics buckaroo esp cy4] + Keith A. Marino [bonnie] + cinouye [bonnie] + Mark Rentmeesters [laguna siam] + Heping He [crimee monceau] +*David Kakichi Kauahao Nitta [bonnie*] + Umesh Krishnaswamy [calliope] + David Kolson [purple] + Eddie Schwalb [cliff ocean broadway] + Phillip Raymond Colline [bonnie] + Scott Erickson [ics paris wagram buckaroo sherlock] + Doris Tonne [bonnie] + Alan Keren [brooks] + Debra Brodbeck [chateau] +*Uocsqnt [ics*] + Chung Ng [liege trocadero] +*John Romine [bonnie ics london woolamaloo paris buckaroo*(1) philosophy yoyodyne beaver] + Lisa Tellier [coyote] + Merri Naka [perfect-tommy] + David Eppstein [wormwood] + Heather Ross [bonnie ics paris john-yaya] +*Gary Hiromi Nakamura [bonnie*] + James Kipps [ocean] + Kamal Ali [pan ci4 focl] + Xiping Song [berault] +*Up4tusti [ics*] + Robert Allen Monroe [bonnie] + Craig Snider [gobelins] + Jose C. Barrios [chatelet] + Lynn Stauffer [cg3] +*Alastair Milne [ics*] + David Levine [trinite dinsdale segur] + Operator [laguna bonnie ics woolamaloo paris rome cecil buckaroo beanie philosophy] + Mary Franks [john-starbird] + Roni Potasman [esp enterprise] +*jli1 [bonnie*] + Wendy Lasher [voltaire] + John King [ics] +*skeung [bonnie*] + David Harnick-Shapiro [laguna bonnie ics woolamaloo glacier paris buckaroo beanie john-littlejohn john-yaya esp valentine] + Dennis Kibler [turing] +*Vanessa Yun-Yin Yuan [bonnie*(2)] + Tedd Hadley [etoile] + Hung Huang [net5] + George S. Lueker [john-wood] + Rina Dechter [john-grim] + Elke A. Rundensteiner [aardvark] + Richard Selby [louvre] + Thanh Lan Vu [bonnie] +*Steven Lafayette Smith [bonnie*] + Owen O'Malley [dinsdale porte-de-st-ouen] +*Dennis Troup [sainte-denis*(1)] + Alex Odyniec [ics] + Patrick Young [elysees] + Lubomir Bic [cj2] +*ryoshii [ics*] + Carmen Mendoza [anniebell] + Gregory Alan Bolcer [liege javel crimee] +*El Fattah [trix*(1)] +*Mei-Fan Chou [bonnie*] + X-MAN [net1] + Fei York Yee [bonnie] + Nikil Dutt [ics synthesis] + Sam Horrocks [laguna liege bonnie ics paris buckaroo brochant john-bigboote] + Alfred Bork [idyllwild] +*M i n h [bonnie*] + Ray Klefstad [bonnie pan clipperton] + Thieu Q. Nguyen [valentine] + Debra Richardson [zola bear] +*sjalali [bonnie*] + R. Kent Madsen [pasteur] +*Donna Rae Love [bonnie*] + Brian Christopher Pitterle [fdr] +*Shilpa V. Shukla [bonnie*] + Earl Wayne Jr. Hood [bonnie] + Young Kim [myrtle] + Stephanie Leif Aha [cardinal] +*Steven Daniel Wallace [bonnie*] + Szu-Ching Wang [bonnie] + Patrick Murphy [focl] + Paul O'Rorke [ci2] + Craig Alan Macfarlane [liege chateau-rouge] + Mats Heimdahl [duroc] + CF Engineer [ics] +*dialup [ics*] + Ki C. Kim [cy2] + Hadar Ziv [pigalle trinite] + Software Testing group [liege siam] + David Ruby [ics ocean steppingstone] +*Stephen Te-Lung Chen [bonnie*] + Michael Dillencourt [cubes] +*hlin1 [bonnie*] + Andrew Harrison [laguna ics buckaroo cthulu] + Ken Anderson [mabillon] + Alex Nicolau [ics ck7] +*John Richard Place [bonnie*(2)] +*Douglas C. Schmidt [pasteur beaver* net6*(2) net4] + Holly Hildreth [jourdain] + Kari Forester [st-michel] + Joy Schuler [scooter] + Michael Pazzani [pan] + Kazushige Shimono [valentine] + Joan Mahoney [segur] + John Self [pasteur bugfix] + Steve Morris [tweezer] + Isaac D Scherson [zeus] +*Dongpei Zhuo [bonnie*(2)] + Pat Harris [surrey] +*Robert Steven Zucker [siam*] + Tatsuya Suda [valentine] + Jeff Erickson [madeleine] + David A. Honig [laguna broadway] + Chi-Kai Chien [hera] + Dan Gajski [ics] +*Steven Novack [snowball*(1)] +*Chung Tak Wong [bonnie*(1)] + Tim Morgan [ics glacier buckaroo john-parker] +*Stephen James Martin [bonnie*] + Billie Bozarth [etoile jasmin] + You have new mail. [liege dinsdale ternes] +*Chiharu Sano [bonnie*] + Fran Paz [willis] +------------------------ +friends: 37 users: 163 +---------------------------------------- + +# Print out all machines and who is logged into each one + +% drwho -R -l +drwho-client -R -L +beanie operator +crimee harrison hhe +siam mrentme +alexandre-dumas tittle +avron heimdahl +cecil operator +elysees pyoung +pasteur madsen*(1) +sainte-denis troup +gobelins snider +bugfix self +mabillon kanderso*(3) +buckaroo operator david sam authcrit wang harrison jromine morgan yin +rome operator sam +paris operator jromine sam david heather +chateau brodbeck*(1) +wagram sam +simplon rortega +jourdain hildreth +javel gbolcer +bastille self schmidt*(1) +monceau hhe +glacier hhe david morgan +porte-de-st-ouen omalley +berault song +laguna operator harrison sam david jromine jkrause mrentme kanderso*(1) +jasmin bozarth +chateau-rouge cmacfarl +zola sam omalley +invalides mrentme +london operator jromine +brochant gbolcer +rennes steph +pigalle ziv +aardvark rundenst +chapelle yessayan +cad jianl*(1) +liege cmacfarl kari aporter yessayan rzucker sam +woolamaloo operator +st-michel kari +segur jmahoney +philosophy operator +sablon rundenst +dinsdale cmacfarl yessayan sam +---------------------------------------- diff --git a/apps/drwho/File_Manager.cpp b/apps/drwho/File_Manager.cpp new file mode 100644 index 00000000000..c93b6398a50 --- /dev/null +++ b/apps/drwho/File_Manager.cpp @@ -0,0 +1,162 @@ +// $Id$ +#include "global.h" +#include "ace/Mem_Map.h" +#include "File_Manager.h" + +/* Initialize statics... */ + +char *File_Manager::current_ptr = 0; +int File_Manager::number_of_friends = 0; +int File_Manager::max_key_length = 0; +char *File_Manager::buffer_ptr = 0; +int File_Manager::buffer_size = 0; + +/* Either opens the friends file (if FILE_NAME is not a NULL pointer) + or opens up the password file. In either case, the number of + entries in the file are returned, i.e., number of friends... */ + +int +File_Manager::open_file (char *file_name) +{ + return file_name == '\0' + ? File_Manager::open_passwd_file () + : File_Manager::open_friends_file (file_name); +} + +/* Returns the next LOGIN_NAME and REAL_NAME from the file. */ + +int +File_Manager::get_login_and_real_name (char *&login_name, char *&real_name) +{ + char *buf_ptr = File_Manager::current_ptr; + + login_name = buf_ptr; + + /* Skip to the end of the login name. */ + + while (isalnum (*buf_ptr)) + buf_ptr++; + + *buf_ptr++ = '\0'; + + /* Now skip over white space to *start* of real name! */ + + while (isspace (*buf_ptr) || *buf_ptr == '\0') + buf_ptr++; + + real_name = buf_ptr; + + while (*buf_ptr++ != '\n') + ; + + /* Clear the trailing blanks and junk. */ + + for (char *tmp_ptr = buf_ptr - 1; isspace (*tmp_ptr); tmp_ptr--) + *tmp_ptr = '\0'; + + /* Skip over consecutive blank lines. */ + + while (*buf_ptr == '\n') + buf_ptr++; + + File_Manager::current_ptr = buf_ptr; + return 1; +} + +/* Open up the yp passwd file and slurp all the users in! */ + +int +File_Manager::open_passwd_file (void) +{ + FILE *fp; + char *file_name; + struct passwd *pwent; + + file_name = tmpnam ((char *) 0); + + if ((fp = fopen (file_name, "w")) == 0) + return -1; + + for (setpwent (); (pwent = getpwent ()) != 0; ) + if (*pwent->pw_gecos != '\0') + { + char *cp = strchr (pwent->pw_gecos, ','); + + if (cp != 0) + *cp = '\0'; + + fprintf (fp, "%-8.8s %s\n", pwent->pw_name, pwent->pw_gecos); + File_Manager::number_of_friends++; + } + + endpwent (); + + fclose (fp); + + ACE_Mem_Map mmap (file_name); + + File_Manager::buffer_ptr = mmap.addr (); + + if (File_Manager::buffer_ptr >= 0) + { + File_Manager::buffer_size = mmap.size (); + File_Manager::current_ptr = File_Manager::buffer_ptr; + return File_Manager::number_of_friends; + } + return -1; +} + +/* This function opens up FILE_NAME and memory maps it in our address space. */ + +int +File_Manager::open_friends_file (char *file_name) +{ + char *fnp = file_name; + int fd; + + /* Split file_name into directory/file_name. */ + + if ((fnp = strrchr (file_name, '/')) != 0) + fd = open (file_name, O_RDONLY); + else + { + char directory[MAXPATHLEN]; + + strcpy (directory, getenv ("HOME")); + strcat (directory, "/"); + strcat (directory, file_name); + fd = open (directory, O_RDONLY); + } + + /* Do the mmaping if we got the file opened correctly... */ + + if (fd < 0) + return -1; + + ACE_Mem_Map mmap (fd); + + File_Manager::buffer_ptr = mmap.addr (); + + if (File_Manager::buffer_ptr >= 0) + { + File_Manager::buffer_size = mmap.size (); + File_Manager::current_ptr = File_Manager::buffer_ptr; + + /* Determine how many friends there are by counting the newlines. */ + + for (char *cp = File_Manager::buffer_ptr + File_Manager::buffer_size; + cp > File_Manager::buffer_ptr + ; ) + if (*--cp == '\n') + { + File_Manager::number_of_friends++; + + /* Skip consecutive newlines. */ + while (cp[-1] == '\n') + --cp; + } + return File_Manager::number_of_friends; + } + return -1; +} + diff --git a/apps/drwho/File_Manager.h b/apps/drwho/File_Manager.h new file mode 100644 index 00000000000..04dd2e2a099 --- /dev/null +++ b/apps/drwho/File_Manager.h @@ -0,0 +1,31 @@ +/* -*- C++ -*- */ +// $Id$ + +/* This module presents a file ADT for our friends info. */ + +#ifndef _FILE_MANAGER_H +#define _FILE_MANAGER_H + +#include "ace/OS.h" + +class File_Manager +{ +private: + static int number_of_friends; + static int max_key_length; + + static char *buffer_ptr; + static char *current_ptr; + static int buffer_size; + + static int open_friends_file (char *filename); + static int open_passwd_file (void); + +public: + static int open_file (char *filename); + static int get_login_and_real_name (char *&login_name, char *&real_name); +}; + +#ifdef __OPTIMIZE__ +#endif /* __OPTIMIZE__ */ +#endif /* _FILE_MANAGER_H */ diff --git a/apps/drwho/HT_Client.cpp b/apps/drwho/HT_Client.cpp new file mode 100644 index 00000000000..b829f1e2a96 --- /dev/null +++ b/apps/drwho/HT_Client.cpp @@ -0,0 +1,27 @@ +// $Id$ +#include "new.h" +#include "HT_Client.h" + +/* Insert a KEY_NAME into the hash table, if it doesn't already exist there. + What gets returned is a pointer to the node inserted. Note that we do our + own memory allocation here... */ + +Protocol_Record * +HT_Client::insert (char *key_name, int max_len) +{ + /* This is tricky... */ + + for (Protocol_Record **frpp = &this->hash_table[this->hash (key_name)]; + *frpp != 0 && strncmp ((*frpp)->get_login (), key_name, max_len) != 0; + frpp = &(*frpp)->next) + ; + + if (*frpp == 0) + { + *frpp = new (PRIVATE_POOL) Protocol_Record (ACE::strnew (key_name), *frpp); + this->count++; + } + return *frpp; +} + + diff --git a/apps/drwho/HT_Client.h b/apps/drwho/HT_Client.h new file mode 100644 index 00000000000..0831eb461bb --- /dev/null +++ b/apps/drwho/HT_Client.h @@ -0,0 +1,16 @@ +/* -*- C++ -*- */ +// $Id$ + +/* Provides the client's hash table abstraction. */ + +#ifndef _HT_CLIENT_H +#define _HT_CLIENT_H + +#include "Hash_Table.h" + +class HT_Client : public Hash_Table +{ +public: + virtual Protocol_Record *insert (char *key_name, int max_len = MAXUSERIDNAMELEN); +}; +#endif /* _HT_CLIENT_H */ diff --git a/apps/drwho/HT_Server.cpp b/apps/drwho/HT_Server.cpp new file mode 100644 index 00000000000..6b8f0b9d6fe --- /dev/null +++ b/apps/drwho/HT_Server.cpp @@ -0,0 +1,29 @@ +// $Id$ +#include "new.h" +#include "HT_Server.h" + +/* Insert a KEY_NAME into the hash table, if it doesn't already exist there. + What gets returned is a pointer to the node inserted. Note that we do our + own memory allocation here... */ + +Protocol_Record * +HT_Server::insert (char *key_name, int max_len) +{ + /* This is tricky... */ + + for (Protocol_Record **frpp = &this->hash_table[this->hash (key_name)]; + *frpp != 0 && strncmp ((*frpp)->get_login (), key_name, max_len) != 0; + frpp = &(*frpp)->next) + ; + + if (*frpp == 0) + { + /* Remember, the server must be very careful about stuff it + receives from the rwho manager, since it may not be NUL-terminated. + That's why we use ACE::strnnew ()... */ + + *frpp = new (PRIVATE_POOL) Protocol_Record (ACE::strnnew (key_name, max_len), *frpp); + this->count++; + } + return *frpp; +} diff --git a/apps/drwho/HT_Server.h b/apps/drwho/HT_Server.h new file mode 100644 index 00000000000..a5dc1987a78 --- /dev/null +++ b/apps/drwho/HT_Server.h @@ -0,0 +1,16 @@ +/* -*- C++ -*- */ +// $Id$ + +/* Provides the server's hash table abstraction. */ + +#ifndef _HT_SERVER_H +#define _HT_SERVER_H + +#include "Hash_Table.h" + +class HT_Server : public Hash_Table +{ +public: + virtual Protocol_Record *insert (char *key_name, int max_len = MAXUSERIDNAMELEN); +}; +#endif /* _HT_SERVER_H */ diff --git a/apps/drwho/Hash_Table.cpp b/apps/drwho/Hash_Table.cpp new file mode 100644 index 00000000000..15fb314370c --- /dev/null +++ b/apps/drwho/Hash_Table.cpp @@ -0,0 +1,90 @@ +// $Id$ +#include "Options.h" +#include "new.h" +#include "Hash_Table.h" + +Hash_Table::Hash_Table (void): current_ptr (0), current_index (0), hash_table_size (HASH_TABLE_SIZE) +{ + this->hash_table = new (PRIVATE_POOL) Protocol_Record *[this->hash_table_size]; + + ACE_OS::memset (this->hash_table, + 0, + this->hash_table_size * sizeof *this->hash_table); +} + +/* Hash using the "Hash PJW" algorithm. */ + +unsigned int +Hash_Table::hash (char *s) +{ + char *temp = s; + unsigned g; + unsigned hash = 0; + + for (int i = 0; i < MAXUSERIDNAMELEN && *temp != 0; i++) + { + hash = (hash << 4) + (*temp++ * 13); + if (g = hash & 0xf0000000) + { + hash ^= (g >> 24); + hash ^= g; + } + } + + return hash % this->hash_table_size; +} + +/* Iterate through the hash table returning one node at a time... */ + +Protocol_Record * +Hash_Table::get_next_entry (void) +{ + /* Reset the iterator if we are starting from the beginning. */ + + if (this->current_index == -1) + this->current_index = 0; + + if (this->current_ptr == 0) + { + + for (; + this->current_index < this->hash_table_size; + this->current_index++) + if (this->hash_table[this->current_index] != 0) + { + Protocol_Record *frp = this->hash_table[this->current_index++]; + this->current_ptr = frp->next; + return frp; + } + this->current_index = -1; + return 0; + } + else + { + Protocol_Record *frp = this->current_ptr; + this->current_ptr = this->current_ptr->next; + return frp; + } +} + +Protocol_Record * +Hash_Table::get_each_entry (void) +{ + return this->get_next_entry (); +} + +/* Frees up all the dynamic memory in the hash table. */ + +Hash_Table::~Hash_Table (void) +{ + if (Options::get_opt (Options::DEBUG)) + fprintf (stderr, "disposing Hash_Table\n"); + + for (int i = 0; i < this->hash_table_size; i++) + for (Protocol_Record *frp = this->hash_table[i]; frp != 0; ) + { + Protocol_Record *tmp = frp; + frp = frp->next; + } + +} diff --git a/apps/drwho/Hash_Table.h b/apps/drwho/Hash_Table.h new file mode 100644 index 00000000000..2df70290d31 --- /dev/null +++ b/apps/drwho/Hash_Table.h @@ -0,0 +1,30 @@ +/* -*- C++ -*- */ +// $Id$ + +/* Provides a hash function lookup abstraction for friend records. */ + +#ifndef _HASH_TABLE_H +#define _HASH_TABLE_H + +#include "Search_Struct.h" + +class Hash_Table : public Search_Struct +{ +protected: + enum {HASH_TABLE_SIZE = 500}; + + Protocol_Record **hash_table; + Protocol_Record *current_ptr; + int current_index; + int hash_table_size; + + unsigned int hash (char *s); + +public: + Hash_Table (void); + virtual ~Hash_Table (void); + virtual Protocol_Record *insert (char *key_name, int max_len = MAXUSERIDNAMELEN) = 0; + virtual Protocol_Record *get_next_entry (void); + virtual Protocol_Record *get_each_entry (void); +}; +#endif /* _HASH_TABLE_H */ diff --git a/apps/drwho/Makefile b/apps/drwho/Makefile new file mode 100644 index 00000000000..ed75fe64512 --- /dev/null +++ b/apps/drwho/Makefile @@ -0,0 +1,427 @@ +#---------------------------------------------------------------------------- +# $Id$ +# +# Makefile for drwho +#---------------------------------------------------------------------------- + +#---------------------------------------------------------------------------- +# Local macros +#---------------------------------------------------------------------------- + +SHARED-SRC = Protocol_Manager \ + Drwho_Node \ + Rwho_DB_Manager \ + Multicast_Manager \ + Protocol_Record \ + Options \ + File_Manager \ + Hash_Table \ + Binary_Search \ + Search_Struct \ + Single_Lookup \ + new +SHARED-OBJ = $(addsuffix .o,$(SHARED-SRC)) + +CLIENT-SRC = PM_Client \ + CM_Client \ + HT_Client \ + BS_Client \ + PMC_All \ + PMC_Flo \ + PMC_Usr \ + SL_Client \ + PMC_Ruser \ + SM_Client \ + SMR_Client \ + SML_Client +CLIENT-OBJ = $(addsuffix .o,$(CLIENT-SRC)) + +SERVER-SRC = PM_Server \ + CM_Server \ + HT_Server \ + BS_Server \ + PMS_All \ + PMS_Flo \ + PMS_Usr \ + SL_Server \ + PMS_Ruser \ + SM_Server \ + SMR_Server \ + SMR_Client +SERVER-OBJ = $(addsuffix .o,$(SERVER-SRC)) + +LSRC = client.cpp server.cpp \ + $(addsuffix .cpp,$(SHARED-SRC)) \ + $(addsuffix .cpp,$(CLIENT-SRC)) \ + $(addsuffix .cpp,$(SERVER-SRC)) + +BIN = drwho-client drwho-server +BUILD = $(BIN) +VLDLIBS = $(LDLIBS:%=%$(VAR)) +VBIN = $(BIN:%=%$(VAR)) + +#---------------------------------------------------------------------------- +# Include macros and targets +#---------------------------------------------------------------------------- + +include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU +include $(ACE_ROOT)/include/makeinclude/macros.GNU +include $(ACE_ROOT)/include/makeinclude/rules.common.GNU +include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU +include $(ACE_ROOT)/include/makeinclude/rules.lib.GNU +include $(ACE_ROOT)/include/makeinclude/rules.local.GNU + +#---------------------------------------------------------------------------- +# Local targets +#---------------------------------------------------------------------------- + +drwho-client: $(addprefix $(VDIR),$(CLIENT-OBJ)) $(addprefix $(VDIR),$(SHARED-OBJ)) + $(LINK.cc) $(LDFLAGS) -o $@ $^ $(VLDLIBS) + +drwho-server: $(addprefix $(VDIR),$(SERVER-OBJ)) $(addprefix $(VDIR),$(SHARED-OBJ)) + $(LINK.cc) $(LDFLAGS) -o $@ $^ $(VLDLIBS) + +#---------------------------------------------------------------------------- +# Dependencies +#---------------------------------------------------------------------------- + +# DO NOT DELETE THIS LINE -- g++dep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. + +.obj/client.o .obj/client.so .shobj/client.o .shobj/client.so: client.cpp \ + $(ACE_ROOT)/ace/OS.h \ + $(ACE_ROOT)/ace/inc_user_config.h \ + $(ACE_ROOT)/ace/config.h \ + $(ACE_ROOT)/ace/config-g++-common.h \ + $(ACE_ROOT)/ace/streams.h \ + $(ACE_ROOT)/ace/Basic_Types.h \ + $(ACE_ROOT)/ace/Basic_Types.i \ + $(ACE_ROOT)/ace/OS.i \ + $(ACE_ROOT)/ace/Trace.h \ + $(ACE_ROOT)/ace/Log_Msg.h \ + $(ACE_ROOT)/ace/Log_Record.h \ + $(ACE_ROOT)/ace/ACE.h \ + $(ACE_ROOT)/ace/ACE.i \ + $(ACE_ROOT)/ace/Log_Priority.h \ + $(ACE_ROOT)/ace/Log_Record.i \ + Options.h SML_Client.h SM_Client.h PM_Client.h Protocol_Manager.h \ + Search_Struct.h Protocol_Record.h Drwho_Node.h global.h CM_Client.h \ + Select_Manager.h SML_Server.h SM_Server.h PM_Server.h CM_Server.h \ + Comm_Manager.h SMR_Client.h +.obj/server.o .obj/server.so .shobj/server.o .shobj/server.so: server.cpp \ + $(ACE_ROOT)/ace/OS.h \ + $(ACE_ROOT)/ace/inc_user_config.h \ + $(ACE_ROOT)/ace/config.h \ + $(ACE_ROOT)/ace/config-g++-common.h \ + $(ACE_ROOT)/ace/streams.h \ + $(ACE_ROOT)/ace/Basic_Types.h \ + $(ACE_ROOT)/ace/Basic_Types.i \ + $(ACE_ROOT)/ace/OS.i \ + $(ACE_ROOT)/ace/Trace.h \ + $(ACE_ROOT)/ace/Log_Msg.h \ + $(ACE_ROOT)/ace/Log_Record.h \ + $(ACE_ROOT)/ace/ACE.h \ + $(ACE_ROOT)/ace/ACE.i \ + $(ACE_ROOT)/ace/Log_Priority.h \ + $(ACE_ROOT)/ace/Log_Record.i \ + Options.h SMR_Server.h SM_Server.h PM_Server.h Protocol_Manager.h \ + Search_Struct.h Protocol_Record.h Drwho_Node.h global.h CM_Server.h \ + Comm_Manager.h Select_Manager.h +.obj/Protocol_Manager.o .obj/Protocol_Manager.so .shobj/Protocol_Manager.o .shobj/Protocol_Manager.so: Protocol_Manager.cpp Options.h new.h \ + Protocol_Manager.h \ + $(ACE_ROOT)/ace/OS.h \ + $(ACE_ROOT)/ace/inc_user_config.h \ + $(ACE_ROOT)/ace/config.h \ + $(ACE_ROOT)/ace/config-g++-common.h \ + $(ACE_ROOT)/ace/streams.h \ + $(ACE_ROOT)/ace/Basic_Types.h \ + $(ACE_ROOT)/ace/Basic_Types.i \ + $(ACE_ROOT)/ace/OS.i \ + $(ACE_ROOT)/ace/Trace.h \ + $(ACE_ROOT)/ace/Log_Msg.h \ + $(ACE_ROOT)/ace/Log_Record.h \ + $(ACE_ROOT)/ace/ACE.h \ + $(ACE_ROOT)/ace/ACE.i \ + $(ACE_ROOT)/ace/Log_Priority.h \ + $(ACE_ROOT)/ace/Log_Record.i \ + Search_Struct.h Protocol_Record.h Drwho_Node.h global.h +.obj/Drwho_Node.o .obj/Drwho_Node.so .shobj/Drwho_Node.o .shobj/Drwho_Node.so: Drwho_Node.cpp Drwho_Node.h \ + $(ACE_ROOT)/ace/OS.h \ + $(ACE_ROOT)/ace/inc_user_config.h \ + $(ACE_ROOT)/ace/config.h \ + $(ACE_ROOT)/ace/config-g++-common.h \ + $(ACE_ROOT)/ace/streams.h \ + $(ACE_ROOT)/ace/Basic_Types.h \ + $(ACE_ROOT)/ace/Basic_Types.i \ + $(ACE_ROOT)/ace/OS.i \ + $(ACE_ROOT)/ace/Trace.h \ + $(ACE_ROOT)/ace/Log_Msg.h \ + $(ACE_ROOT)/ace/Log_Record.h \ + $(ACE_ROOT)/ace/ACE.h \ + $(ACE_ROOT)/ace/ACE.i \ + $(ACE_ROOT)/ace/Log_Priority.h \ + $(ACE_ROOT)/ace/Log_Record.i \ + global.h +.obj/Protocol_Record.o .obj/Protocol_Record.so .shobj/Protocol_Record.o .shobj/Protocol_Record.so: Protocol_Record.cpp Options.h Protocol_Record.h \ + Drwho_Node.h $(ACE_ROOT)/ace/OS.h \ + $(ACE_ROOT)/ace/inc_user_config.h \ + $(ACE_ROOT)/ace/config.h \ + $(ACE_ROOT)/ace/config-g++-common.h \ + $(ACE_ROOT)/ace/streams.h \ + $(ACE_ROOT)/ace/Basic_Types.h \ + $(ACE_ROOT)/ace/Basic_Types.i \ + $(ACE_ROOT)/ace/OS.i \ + $(ACE_ROOT)/ace/Trace.h \ + $(ACE_ROOT)/ace/Log_Msg.h \ + $(ACE_ROOT)/ace/Log_Record.h \ + $(ACE_ROOT)/ace/ACE.h \ + $(ACE_ROOT)/ace/ACE.i \ + $(ACE_ROOT)/ace/Log_Priority.h \ + $(ACE_ROOT)/ace/Log_Record.i \ + global.h +.obj/File_Manager.o .obj/File_Manager.so .shobj/File_Manager.o .shobj/File_Manager.so: File_Manager.cpp global.h \ + $(ACE_ROOT)/ace/Mem_Map.h \ + $(ACE_ROOT)/ace/ACE.h \ + $(ACE_ROOT)/ace/OS.h \ + $(ACE_ROOT)/ace/inc_user_config.h \ + $(ACE_ROOT)/ace/config.h \ + $(ACE_ROOT)/ace/config-g++-common.h \ + $(ACE_ROOT)/ace/streams.h \ + $(ACE_ROOT)/ace/Basic_Types.h \ + $(ACE_ROOT)/ace/Basic_Types.i \ + $(ACE_ROOT)/ace/OS.i \ + $(ACE_ROOT)/ace/Trace.h \ + $(ACE_ROOT)/ace/Log_Msg.h \ + $(ACE_ROOT)/ace/Log_Record.h \ + $(ACE_ROOT)/ace/ACE.i \ + $(ACE_ROOT)/ace/Log_Priority.h \ + $(ACE_ROOT)/ace/Log_Record.i \ + $(ACE_ROOT)/ace/Mem_Map.i \ + File_Manager.h +.obj/Hash_Table.o .obj/Hash_Table.so .shobj/Hash_Table.o .shobj/Hash_Table.so: Hash_Table.cpp Options.h new.h Hash_Table.h \ + Search_Struct.h Protocol_Record.h Drwho_Node.h \ + $(ACE_ROOT)/ace/OS.h \ + $(ACE_ROOT)/ace/inc_user_config.h \ + $(ACE_ROOT)/ace/config.h \ + $(ACE_ROOT)/ace/config-g++-common.h \ + $(ACE_ROOT)/ace/streams.h \ + $(ACE_ROOT)/ace/Basic_Types.h \ + $(ACE_ROOT)/ace/Basic_Types.i \ + $(ACE_ROOT)/ace/OS.i \ + $(ACE_ROOT)/ace/Trace.h \ + $(ACE_ROOT)/ace/Log_Msg.h \ + $(ACE_ROOT)/ace/Log_Record.h \ + $(ACE_ROOT)/ace/ACE.h \ + $(ACE_ROOT)/ace/ACE.i \ + $(ACE_ROOT)/ace/Log_Priority.h \ + $(ACE_ROOT)/ace/Log_Record.i \ + global.h +.obj/Binary_Search.o .obj/Binary_Search.so .shobj/Binary_Search.o .shobj/Binary_Search.so: Binary_Search.cpp Options.h Binary_Search.h +.obj/Search_Struct.o .obj/Search_Struct.so .shobj/Search_Struct.o .shobj/Search_Struct.so: Search_Struct.cpp Options.h Search_Struct.h \ + Protocol_Record.h Drwho_Node.h \ + $(ACE_ROOT)/ace/OS.h \ + $(ACE_ROOT)/ace/inc_user_config.h \ + $(ACE_ROOT)/ace/config.h \ + $(ACE_ROOT)/ace/config-g++-common.h \ + $(ACE_ROOT)/ace/streams.h \ + $(ACE_ROOT)/ace/Basic_Types.h \ + $(ACE_ROOT)/ace/Basic_Types.i \ + $(ACE_ROOT)/ace/OS.i \ + $(ACE_ROOT)/ace/Trace.h \ + $(ACE_ROOT)/ace/Log_Msg.h \ + $(ACE_ROOT)/ace/Log_Record.h \ + $(ACE_ROOT)/ace/ACE.h \ + $(ACE_ROOT)/ace/ACE.i \ + $(ACE_ROOT)/ace/Log_Priority.h \ + $(ACE_ROOT)/ace/Log_Record.i \ + global.h +.obj/new.o .obj/new.so .shobj/new.o .shobj/new.so: new.cpp \ + \ + $(ACE_ROOT)/ace/OS.h \ + $(ACE_ROOT)/ace/inc_user_config.h \ + $(ACE_ROOT)/ace/config.h \ + $(ACE_ROOT)/ace/config-g++-common.h \ + $(ACE_ROOT)/ace/streams.h \ + $(ACE_ROOT)/ace/Basic_Types.h \ + $(ACE_ROOT)/ace/Basic_Types.i \ + $(ACE_ROOT)/ace/OS.i \ + $(ACE_ROOT)/ace/Trace.h \ + $(ACE_ROOT)/ace/Log_Msg.h \ + $(ACE_ROOT)/ace/Log_Record.h \ + $(ACE_ROOT)/ace/ACE.h \ + $(ACE_ROOT)/ace/ACE.i \ + $(ACE_ROOT)/ace/Log_Priority.h \ + $(ACE_ROOT)/ace/Log_Record.i \ + Options.h +.obj/CM_Client.o .obj/CM_Client.so .shobj/CM_Client.o .shobj/CM_Client.so: CM_Client.cpp global.h Options.h Multicast_Manager.h \ + $(ACE_ROOT)/ace/OS.h \ + $(ACE_ROOT)/ace/inc_user_config.h \ + $(ACE_ROOT)/ace/config.h \ + $(ACE_ROOT)/ace/config-g++-common.h \ + $(ACE_ROOT)/ace/streams.h \ + $(ACE_ROOT)/ace/Basic_Types.h \ + $(ACE_ROOT)/ace/Basic_Types.i \ + $(ACE_ROOT)/ace/OS.i \ + $(ACE_ROOT)/ace/Trace.h \ + $(ACE_ROOT)/ace/Log_Msg.h \ + $(ACE_ROOT)/ace/Log_Record.h \ + $(ACE_ROOT)/ace/ACE.h \ + $(ACE_ROOT)/ace/ACE.i \ + $(ACE_ROOT)/ace/Log_Priority.h \ + $(ACE_ROOT)/ace/Log_Record.i \ + CM_Client.h +.obj/BS_Client.o .obj/BS_Client.so .shobj/BS_Client.o .shobj/BS_Client.so: BS_Client.cpp Options.h new.h File_Manager.h \ + $(ACE_ROOT)/ace/OS.h \ + $(ACE_ROOT)/ace/inc_user_config.h \ + $(ACE_ROOT)/ace/config.h \ + $(ACE_ROOT)/ace/config-g++-common.h \ + $(ACE_ROOT)/ace/streams.h \ + $(ACE_ROOT)/ace/Basic_Types.h \ + $(ACE_ROOT)/ace/Basic_Types.i \ + $(ACE_ROOT)/ace/OS.i \ + $(ACE_ROOT)/ace/Trace.h \ + $(ACE_ROOT)/ace/Log_Msg.h \ + $(ACE_ROOT)/ace/Log_Record.h \ + $(ACE_ROOT)/ace/ACE.h \ + $(ACE_ROOT)/ace/ACE.i \ + $(ACE_ROOT)/ace/Log_Priority.h \ + $(ACE_ROOT)/ace/Log_Record.i \ + BS_Client.h Binary_Search.h +.obj/SM_Client.o .obj/SM_Client.so .shobj/SM_Client.o .shobj/SM_Client.so: SM_Client.cpp Options.h new.h PMC_All.h PM_Client.h \ + Protocol_Manager.h \ + $(ACE_ROOT)/ace/OS.h \ + $(ACE_ROOT)/ace/inc_user_config.h \ + $(ACE_ROOT)/ace/config.h \ + $(ACE_ROOT)/ace/config-g++-common.h \ + $(ACE_ROOT)/ace/streams.h \ + $(ACE_ROOT)/ace/Basic_Types.h \ + $(ACE_ROOT)/ace/Basic_Types.i \ + $(ACE_ROOT)/ace/OS.i \ + $(ACE_ROOT)/ace/Trace.h \ + $(ACE_ROOT)/ace/Log_Msg.h \ + $(ACE_ROOT)/ace/Log_Record.h \ + $(ACE_ROOT)/ace/ACE.h \ + $(ACE_ROOT)/ace/ACE.i \ + $(ACE_ROOT)/ace/Log_Priority.h \ + $(ACE_ROOT)/ace/Log_Record.i \ + Search_Struct.h Protocol_Record.h Drwho_Node.h global.h PMC_Flo.h \ + PMC_Usr.h PMC_Ruser.h SM_Client.h CM_Client.h Select_Manager.h +.obj/SMR_Client.o .obj/SMR_Client.so .shobj/SMR_Client.o .shobj/SMR_Client.so: SMR_Client.cpp Options.h new.h PMC_All.h PM_Client.h \ + Protocol_Manager.h \ + $(ACE_ROOT)/ace/OS.h \ + $(ACE_ROOT)/ace/inc_user_config.h \ + $(ACE_ROOT)/ace/config.h \ + $(ACE_ROOT)/ace/config-g++-common.h \ + $(ACE_ROOT)/ace/streams.h \ + $(ACE_ROOT)/ace/Basic_Types.h \ + $(ACE_ROOT)/ace/Basic_Types.i \ + $(ACE_ROOT)/ace/OS.i \ + $(ACE_ROOT)/ace/Trace.h \ + $(ACE_ROOT)/ace/Log_Msg.h \ + $(ACE_ROOT)/ace/Log_Record.h \ + $(ACE_ROOT)/ace/ACE.h \ + $(ACE_ROOT)/ace/ACE.i \ + $(ACE_ROOT)/ace/Log_Priority.h \ + $(ACE_ROOT)/ace/Log_Record.i \ + Search_Struct.h Protocol_Record.h Drwho_Node.h global.h PMC_Flo.h \ + PMC_Usr.h PMC_Ruser.h SMR_Client.h SM_Client.h CM_Client.h \ + Select_Manager.h +.obj/SML_Client.o .obj/SML_Client.so .shobj/SML_Client.o .shobj/SML_Client.so: SML_Client.cpp Options.h SML_Client.h SM_Client.h \ + PM_Client.h Protocol_Manager.h \ + $(ACE_ROOT)/ace/OS.h \ + $(ACE_ROOT)/ace/inc_user_config.h \ + $(ACE_ROOT)/ace/config.h \ + $(ACE_ROOT)/ace/config-g++-common.h \ + $(ACE_ROOT)/ace/streams.h \ + $(ACE_ROOT)/ace/Basic_Types.h \ + $(ACE_ROOT)/ace/Basic_Types.i \ + $(ACE_ROOT)/ace/OS.i \ + $(ACE_ROOT)/ace/Trace.h \ + $(ACE_ROOT)/ace/Log_Msg.h \ + $(ACE_ROOT)/ace/Log_Record.h \ + $(ACE_ROOT)/ace/ACE.h \ + $(ACE_ROOT)/ace/ACE.i \ + $(ACE_ROOT)/ace/Log_Priority.h \ + $(ACE_ROOT)/ace/Log_Record.i \ + Search_Struct.h Protocol_Record.h Drwho_Node.h global.h CM_Client.h \ + Select_Manager.h SML_Server.h SM_Server.h PM_Server.h CM_Server.h \ + Comm_Manager.h +.obj/CM_Server.o .obj/CM_Server.so .shobj/CM_Server.o .shobj/CM_Server.so: CM_Server.cpp global.h Options.h CM_Server.h \ + $(ACE_ROOT)/ace/OS.h \ + $(ACE_ROOT)/ace/inc_user_config.h \ + $(ACE_ROOT)/ace/config.h \ + $(ACE_ROOT)/ace/config-g++-common.h \ + $(ACE_ROOT)/ace/streams.h \ + $(ACE_ROOT)/ace/Basic_Types.h \ + $(ACE_ROOT)/ace/Basic_Types.i \ + $(ACE_ROOT)/ace/OS.i \ + $(ACE_ROOT)/ace/Trace.h \ + $(ACE_ROOT)/ace/Log_Msg.h \ + $(ACE_ROOT)/ace/Log_Record.h \ + $(ACE_ROOT)/ace/ACE.h \ + $(ACE_ROOT)/ace/ACE.i \ + $(ACE_ROOT)/ace/Log_Priority.h \ + $(ACE_ROOT)/ace/Log_Record.i \ + Comm_Manager.h +.obj/BS_Server.o .obj/BS_Server.so .shobj/BS_Server.o .shobj/BS_Server.so: BS_Server.cpp BS_Server.h Binary_Search.h new.h +.obj/SM_Server.o .obj/SM_Server.so .shobj/SM_Server.o .shobj/SM_Server.so: SM_Server.cpp new.h Options.h PMS_All.h PM_Server.h \ + Protocol_Manager.h \ + $(ACE_ROOT)/ace/OS.h \ + $(ACE_ROOT)/ace/inc_user_config.h \ + $(ACE_ROOT)/ace/config.h \ + $(ACE_ROOT)/ace/config-g++-common.h \ + $(ACE_ROOT)/ace/streams.h \ + $(ACE_ROOT)/ace/Basic_Types.h \ + $(ACE_ROOT)/ace/Basic_Types.i \ + $(ACE_ROOT)/ace/OS.i \ + $(ACE_ROOT)/ace/Trace.h \ + $(ACE_ROOT)/ace/Log_Msg.h \ + $(ACE_ROOT)/ace/Log_Record.h \ + $(ACE_ROOT)/ace/ACE.h \ + $(ACE_ROOT)/ace/ACE.i \ + $(ACE_ROOT)/ace/Log_Priority.h \ + $(ACE_ROOT)/ace/Log_Record.i \ + Search_Struct.h Protocol_Record.h Drwho_Node.h global.h PMS_Flo.h \ + PMS_Usr.h PMS_Ruser.h SM_Server.h CM_Server.h Comm_Manager.h \ + Select_Manager.h +.obj/SMR_Server.o .obj/SMR_Server.so .shobj/SMR_Server.o .shobj/SMR_Server.so: SMR_Server.cpp Options.h SMR_Server.h SM_Server.h \ + PM_Server.h Protocol_Manager.h \ + $(ACE_ROOT)/ace/OS.h \ + $(ACE_ROOT)/ace/inc_user_config.h \ + $(ACE_ROOT)/ace/config.h \ + $(ACE_ROOT)/ace/config-g++-common.h \ + $(ACE_ROOT)/ace/streams.h \ + $(ACE_ROOT)/ace/Basic_Types.h \ + $(ACE_ROOT)/ace/Basic_Types.i \ + $(ACE_ROOT)/ace/OS.i \ + $(ACE_ROOT)/ace/Trace.h \ + $(ACE_ROOT)/ace/Log_Msg.h \ + $(ACE_ROOT)/ace/Log_Record.h \ + $(ACE_ROOT)/ace/ACE.h \ + $(ACE_ROOT)/ace/ACE.i \ + $(ACE_ROOT)/ace/Log_Priority.h \ + $(ACE_ROOT)/ace/Log_Record.i \ + Search_Struct.h Protocol_Record.h Drwho_Node.h global.h CM_Server.h \ + Comm_Manager.h Select_Manager.h +.obj/SMR_Client.o .obj/SMR_Client.so .shobj/SMR_Client.o .shobj/SMR_Client.so: SMR_Client.cpp Options.h new.h PMC_All.h PM_Client.h \ + Protocol_Manager.h \ + $(ACE_ROOT)/ace/OS.h \ + $(ACE_ROOT)/ace/inc_user_config.h \ + $(ACE_ROOT)/ace/config.h \ + $(ACE_ROOT)/ace/config-g++-common.h \ + $(ACE_ROOT)/ace/streams.h \ + $(ACE_ROOT)/ace/Basic_Types.h \ + $(ACE_ROOT)/ace/Basic_Types.i \ + $(ACE_ROOT)/ace/OS.i \ + $(ACE_ROOT)/ace/Trace.h \ + $(ACE_ROOT)/ace/Log_Msg.h \ + $(ACE_ROOT)/ace/Log_Record.h \ + $(ACE_ROOT)/ace/ACE.h \ + $(ACE_ROOT)/ace/ACE.i \ + $(ACE_ROOT)/ace/Log_Priority.h \ + $(ACE_ROOT)/ace/Log_Record.i \ + Search_Struct.h Protocol_Record.h Drwho_Node.h global.h PMC_Flo.h \ + PMC_Usr.h PMC_Ruser.h SMR_Client.h SM_Client.h CM_Client.h \ + Select_Manager.h + +# IF YOU PUT ANYTHING HERE IT WILL GO AWAY diff --git a/apps/drwho/Multicast_Manager.cpp b/apps/drwho/Multicast_Manager.cpp new file mode 100644 index 00000000000..11a3b5a742f --- /dev/null +++ b/apps/drwho/Multicast_Manager.cpp @@ -0,0 +1,170 @@ +// $Id$ +#include "ACE_Mem_Map.h" +#include "new.h" +#include "Multicast_Manager.h" +#include "global.h" + +// Initialize all the static member vars. +int Multicast_Manager::received_host_count = 0; +Multicast_Manager::Host_Elem *Multicast_Manager::drwho_list = 0; +Multicast_Manager::Host_Elem *Multicast_Manager::current_ptr = 0; + +/* Names of hosts to query for friend info. */ +char *Multicast_Manager::host_names[] = +{ + "mabillon.ics.uci.edu", /* "128.195.14.4", */ + "beaver.ics.uci.edu", /* "128.195.2.1", */ + "convention.ics.uci.edu", /* "128.195.8.9", */ + "valentine.ics.uci.edu", /* "128.200.38.10", */ + "abp.ics.uci.edu", /* "128.200.39.23", */ + "cress.ics.uci.edu", /* "128.195.5.8", */ +#if 0 + "murphy.ics.uci.edu", /* "128.195.4.11", */ + "madeleine.ics.uci.edu", /* "128.200.32.2", */ + "liege.ics.uci.edu", /* "128.195.13.1", */ + "ics.uci.edu", /* "128.195.1.1", */ + "128.195.10.16", /* vlsi.ics.uci.edu */ +#endif + 0 /* The NULL entry... ;-) */ +}; + +void +Multicast_Manager::insert_default_hosts (void) +{ + /* Enter the static list of hosts into the dynamic table! */ + + for (char **np = host_names; *np != 0; np++) + Multicast_Manager::add_host (*np); +} + +/* Inserts all the names in FILENAME into the list of hosts to contact. */ + +int +Multicast_Manager::insert_hosts_from_file (char *filename) +{ + ACE_Mem_Map mmap (filename); + char *host_ptr = mmap.addr (); + + if (host_ptr == 0) + return -1; + else + { + + for (char *end_ptr = host_ptr + mmap.size (); host_ptr < end_ptr; ) + { + Multicast_Manager::add_host (host_ptr); + + while (*host_ptr != '\n') + host_ptr++; + + *host_ptr++ = '\0'; + } + + return 0; + } +} + +/* Returns the IP host address for the next unexamined host in the list. + If no more unexamined hosts remain a 0 is returned, else a 1. */ + +int +Multicast_Manager::get_next_host_addr (in_addr &host_addr) +{ + for (Multicast_Manager::current_ptr = Multicast_Manager::current_ptr == 0 ? Multicast_Manager::drwho_list : Multicast_Manager::current_ptr->next; + Multicast_Manager::current_ptr != 0; + Multicast_Manager::current_ptr = Multicast_Manager::current_ptr->next) + + { + hostent *hp; + char *host_name = Multicast_Manager::current_ptr->host_name; + + if ((hp = Multicast_Manager::get_host_entry (host_name)) == 0) + { + fprintf (stderr, "%s: host unknown.\n", host_name); + continue; + } + + Multicast_Manager::received_host_count++; + ACE_OS::memcpy (&host_addr, + hp->h_addr, + sizeof host_addr); + ACE_OS::memcpy (&Multicast_Manager::current_ptr->host_addr, + hp->h_addr, + sizeof host_addr); + return 1; + } + + return 0; +} + +/* This function attempts to get the internet address for either a + hostname or hostnumber. The function makes the simplifying + assumption that hostnames begin with an alphabetic character! */ + +hostent * +Multicast_Manager::get_host_entry (char *host) +{ + static hostent host_entry; + auto hostent *hp; + + if (isdigit (*host)) /* IP address. */ + { + unsigned long ia = inet_addr (host); + + hp = ia == (unsigned long) -1 ? 0 : gethostbyaddr ((char *) &ia, sizeof ia, AF_INET); + } + else /* Host name. */ + hp = gethostbyname (host); + + return hp == 0 ? 0 : (hostent *) memcpy (&host_entry, hp, sizeof *hp); +} + +/* Adds an additional new host to the list of host machines. */ + +void +Multicast_Manager::add_host (char *host_name) +{ + Multicast_Manager::drwho_list = new (PRIVATE_POOL) Host_Elem (host_name, Multicast_Manager::drwho_list); +} + +void +Multicast_Manager::checkoff_host (in_addr host_addr) +{ + for (Host_Elem *tmp = Multicast_Manager::drwho_list; tmp != 0; tmp = tmp->next) + if (ACE_OS::memcmp (&tmp->host_addr.s_addr, + &host_addr.s_addr, + sizeof host_addr.s_addr) == 0) + { + tmp->checked_off = 1; + Multicast_Manager::received_host_count--; + return; + } +} + +int +Multicast_Manager::get_next_non_responding_host (char *&host_name) +{ + for (Multicast_Manager::current_ptr = Multicast_Manager::current_ptr == 0 ? Multicast_Manager::drwho_list : Multicast_Manager::current_ptr->next; + Multicast_Manager::current_ptr != 0; + Multicast_Manager::current_ptr = Multicast_Manager::current_ptr->next) + if (!Multicast_Manager::current_ptr->checked_off) + { + host_name = Multicast_Manager::current_ptr->host_name; + return 1; + } + + return 0; +} + +#if !defined (__OPTIMIZE__) +Multicast_Manager::Host_Elem::Host_Elem (char *h_name, Multicast_Manager::Host_Elem *n) +: host_name (h_name), checked_off (0), next (n) +{ +} + +int +Multicast_Manager::outstanding_hosts_remain (void) +{ + return Multicast_Manager::received_host_count > 0; +} +#endif /* __OPTIMIZE__ */ diff --git a/apps/drwho/Multicast_Manager.h b/apps/drwho/Multicast_Manager.h new file mode 100644 index 00000000000..e0b97de488a --- /dev/null +++ b/apps/drwho/Multicast_Manager.h @@ -0,0 +1,55 @@ +/* -*- C++ -*- */ +// $Id$ + +/* This file handles all the operations upon host machines names + and addresses. */ + +#ifndef _HOST_MANAGER_H +#define _HOST_MANAGER_H + +#include "ace/OS.h" + +struct Host_Elem +{ + char *host_name; + in_addr host_addr; + int checked_off; + Host_Elem *next; + + Host_Elem (char *h_name, Host_Elem *n); +}; + +class Multicast_Manager +{ +public: + static void add_host (char *host_name); + static void checkoff_host (in_addr host_addr); + static int get_next_host_addr (in_addr &host_addr); + static int outstanding_hosts_remain (void); + static int get_next_non_responding_host (char *&host_name); + static int insert_hosts_from_file (char *filename); + static void insert_default_hosts (void); + +private: + static hostent *get_host_entry (char *host); + + static int received_host_count; + static char *host_names[]; + static Host_Elem *drwho_list; + static Host_Elem *current_ptr; +}; + +#ifdef __OPTIMIZE__ +inline +Multicast_Manager::Host_Elem::Host_Elem (char *h_name, Multicast_Manager::Host_Elem *n) + : host_name (h_name), checked_off (0), next (n) +{ +} + +inline int +Multicast_Manager::outstanding_hosts_remain (void) +{ + return Multicast_Manager::received_host_count > 0; +} +#endif /* __OPTIMIZE__ */ +#endif /* _HOST_MANAGER_H */ diff --git a/apps/drwho/Options.cpp b/apps/drwho/Options.cpp new file mode 100644 index 00000000000..bb102b3f6b1 --- /dev/null +++ b/apps/drwho/Options.cpp @@ -0,0 +1,152 @@ +// $Id$ +#include "global.h" +#include "new.h" +#include "Multicast_Manager.h" +#include "ace/Get_Opt.h" +#include "Options.h" + +/* Initialize all the static variables. */ + +/* Contains bit-mask for options. */ +unsigned int Options::option_word = 0; + +/* Which protocol are we using? */ +Options::Protocol_Types Options::protocol_type = Options::PROTO_FLO; + +/* User name for quick lookups. */ +char *Options::user_name = 0; + +/* Port number for client/server. */ +short Options::port_number = PORT_NUMBER; + +/* Maximum time the client waits for servers to timeout. */ +int Options::max_server_timeout = 5; + +/* Name of the program. */ +char *Options::program_name; + +/* Default name of file that stores friend info. */ +char *Options::friend_file = FRIEND_FILE; + +void +Options::print_usage_and_die (int long_msg) +{ + fprintf (stderr, "usage: %s %s", program_name, + long_msg + ? "\n" + "-?\tprints a short usage message\n" + "-A\tappend the following hostname to the list of predefined hostnames.\n" + "-a\treturn information on *all* users remotely logged in (uses yp passwd).\n" + "-b\trun the server in the background (i.e., as a daemon).\n" + "-d\tturn on debugging.\n" + "-F\tuse the following file contents to initialize the host list.\n" + "-f\tuse the following file contents to initialize the friends database.\n" + "-H\tuse the following hostname as part of the new list of hostnames.\n" + "\t(this option overwrites the existing default names).\n" + "-h\tprint a long usage message.\n" + "-L\tprint the login name rather than the real name (which is the default).\n" + "-l\tprint information in long format (works for all protocols).\n" + "-p\tset the port number (server must correspond).\n" + "-r\tdo the remote lookups (i.e., local operations are the default).\n" + "-R\tprint info using the rusers format.\n" + "-s\tsort the output by login name.\n" + "-S\tsort the output by real name.\n" + "-t\tset the amount of time we wait for servers to timeout.\n" + "-w\treturn information on just one user.\n" + : "[-?haAbdfFHhLlpRrtw]\n"); + exit (1); +} + +#ifndef __OPTIMIZE__ +void +Options::set_opt (Option_Types opt) +{ + Options::option_word |= opt; +} + +int +Options::get_opt (Option_Types opt) +{ + return (Options::option_word & opt) != 0; +} +#endif /* __OPTIMIZE__ */ + +void +Options::set_options (int argc, char *argv[]) +{ + int c; + int add_default_hosts = 1; + + Options::program_name = argv[0]; + Get_Opt getopt (argc, argv, "?aA:bdF:f:hH:Llp:rRsSt:w:"); + + while ((c = getopt ()) != -1) + { + switch (c) + { + case '?': + Options::print_usage_and_die (0); + /* NOTREACHED */ + case 'A': + Multicast_Manager::add_host (getopt.optarg); + break; + case 'a': + Options::protocol_type = PROTO_ALL; + break; + case 'b': + Options::set_opt (Options::BE_A_DAEMON); + break; + case 'd': + Options::set_opt (Options::DEBUG); + break; + case 'f': + Options::friend_file = getopt.optarg; + break; + case 'F': + if (Multicast_Manager::insert_hosts_from_file (getopt.optarg) < 0) + perror (Options::program_name), exit (1); + add_default_hosts = 0; + break; + case 'H': + Multicast_Manager::add_host (getopt.optarg); + add_default_hosts = 0; + break; + case 'h': + Options::print_usage_and_die (1); + /* NOTREACHED */ + case 'L': + Options::set_opt (Options::PRINT_LOGIN_NAME); + break; + case 'l': + Options::set_opt (Options::USE_VERBOSE_FORMAT); + break; + case 'p': + Options::port_number = atoi (getopt.optarg); + break; + case 'R': + Options::protocol_type = PROTO_RUSER; + break; + case 'r': + Options::set_opt (Options::REMOTE_USAGE); + break; + case 's': + Options::set_opt (Options::SORT_BY_LOGIN_NAME); + break; + case 'S': + Options::set_opt (Options::SORT_BY_REAL_NAME); + break; + case 't': + Options::max_server_timeout = atoi (getopt.optarg); + break; + case 'w': + Options::user_name = getopt.optarg; + Options::protocol_type = PROTO_USR; + break; + default: + break; + } + } + + if (Options::get_opt (Options::REMOTE_USAGE) && add_default_hosts) + Multicast_Manager::insert_default_hosts (); +} diff --git a/apps/drwho/Options.h b/apps/drwho/Options.h new file mode 100644 index 00000000000..1d9153cc974 --- /dev/null +++ b/apps/drwho/Options.h @@ -0,0 +1,71 @@ +/* -*- C++ -*- */ +// $Id$ + +/* This file is used to provide a consolidated Options.handling facility. */ + +#ifndef _OPTIONS_H +#define _OPTIONS_H + +/* Silly macros for handling message types. */ +#define GET_PACKET_TYPE(P) (ntohs (*((short *) P))) +#define SET_PACKET_TYPE(P,T) ((*(short *) P) = ntohs (T)) +#define SKIP_PACKET_TYPE(P) ((P) + sizeof (short)) +#define SUBTRACT_PACKET_TYPE(L) ((L) - sizeof (short)) + +class Options +{ + static void print_usage_and_die (int long_msg); + static unsigned int option_word; + +public: + enum Option_Types + { + REMOTE_USAGE = 01, + PRINT_LOGIN_NAME = 02, + DEBUG = 04, + STAND_ALONE_SERVER = 010, + SORT_BY_LOGIN_NAME = 020, + SORT_BY_REAL_NAME = 040, + USE_VERBOSE_FORMAT = 0100, + BE_A_DAEMON = 0200 + }; + + /* Different types of messages. */ + enum Protocol_Types + { + PROTO_USR = 1, /* Only return info on one user. */ + PROTO_ALL = 2, /* Return info on all users logged in around the system. */ + PROTO_FLO = 3, /* Return info on friends logged in. */ + PROTO_RUSER = 4, /* Return info in ruser format! */ + + PROTO_RWHO = 5, /* Return info in rwho format. */ + PROTO_WHO = 6, /* Return info in who format. */ + PROTO_RUPTIME = 7 /* Return info in ruptime format. */ + }; + + static void set_options (int argc, char *argv[]); + static void set_opt (Option_Types opt); + static int get_opt (Option_Types opt); + + static short port_number; + static Protocol_Types protocol_type; + static int max_server_timeout; + static char *program_name; + static char *friend_file; + static char *user_name; +}; + +#ifdef __OPTIMIZE__ +inline void +Options::set_opt (Option_Types opt) +{ + Options::option_word |= opt; +} + +inline int +Options::get_opt (Option_Types opt) +{ + return Options::option_word & opt; +} +#endif /* __OPTIMIZE__ */ +#endif /* _OPTIONS_H */ diff --git a/apps/drwho/PMC_All.cpp b/apps/drwho/PMC_All.cpp new file mode 100644 index 00000000000..9758c6c0625 --- /dev/null +++ b/apps/drwho/PMC_All.cpp @@ -0,0 +1,85 @@ +// $Id$ +#include "global.h" +#include "new.h" +#include "Options.h" +#include "HT_Client.h" +#include "PMC_All.h" + +/* This function is pretty much a no-op that just sets up the appropriate + lookup function to use. */ + +int +PMC_All::encode (char *packet, int &packet_length) +{ + if (Options::get_opt (Options::DEBUG) != 0) + fprintf (stderr, "in PMC_All::encode\n"); + + this->ss = new (PRIVATE_POOL) HT_Client; + + SET_PACKET_TYPE (packet, Options::PROTO_ALL); + + char *buf_ptr = SKIP_PACKET_TYPE (packet); + + packet_length = buf_ptr - packet; + return 1; +} + +/* This method is responsible for transforming the msg from the server + back into a form usable by the client. Note that it reads the REAL_NAME + from the packet (since the server placed it there)... */ + +int +PMC_All::decode (char *packet, int &packet_length) +{ + if (Options::get_opt (Options::DEBUG) != 0) + { + fprintf (stderr, "in PMC_All::decode, packet_length = %d\n", packet_length); + write (2, packet, packet_length); + putc ('\n', stderr); + } + char *cp = packet; + int remote_users = 0; + + sscanf (cp, "Users %d", &remote_users); + + this->increment_total_users (remote_users); + + for (cp = ACE::strend (cp); *cp != '\n'; cp++) + { + /* Skip over the LOGIN_NAME. */ + + char *login_name = cp; + char *real_name = cp = ACE::strend (cp); + + for (cp = ACE::strend (cp); + *(cp = this->handle_protocol_entries (cp, login_name, real_name)) != '\t' + ;) + ; + } + + return 1; +} + +Protocol_Record * +PMC_All::insert_protocol_info (Protocol_Record &protocol_record) +{ + Protocol_Record *frp = PM_Client::insert_protocol_info (protocol_record); + int length = strlen (frp->set_real (ACE::strnew (protocol_record.get_real ()))); + + if (length > this->max_key_length) + this->max_key_length = length; + + return frp; +} + +void +PMC_All::process (void) +{ + printf ("remote users logged on\n"); + PM_Client::process (); +} + +#ifndef __OPTIMIZE__ +PMC_All::PMC_All (void) +{} +#endif /* __OPTIMIZE__ */ diff --git a/apps/drwho/PMC_All.h b/apps/drwho/PMC_All.h new file mode 100644 index 00000000000..0fd2a1e6192 --- /dev/null +++ b/apps/drwho/PMC_All.h @@ -0,0 +1,28 @@ +/* -*- C++ -*- */ +// $Id$ + +/* Provides the client's lookup table abstraction for `all' users... */ + +#ifndef _FMC_ALL_H +#define _FMC_ALL_H + +#include "PM_Client.h" + +class PMC_All : public PM_Client +{ +protected: + Protocol_Record *insert_protocol_info (Protocol_Record &protocol_record); + virtual int encode (char *packet, int &total_bytes); + virtual int decode (char *packet, int &total_bytes); + +public: + PMC_All (void); + virtual void process (void); +}; + +#ifdef __OPTIMIZE__ +inline +PMC_All::PMC_All (void) +{} +#endif /* __OPTIMIZE__ */ +#endif /* _FMC_ALL_H */ diff --git a/apps/drwho/PMC_Flo.cpp b/apps/drwho/PMC_Flo.cpp new file mode 100644 index 00000000000..13dd5206934 --- /dev/null +++ b/apps/drwho/PMC_Flo.cpp @@ -0,0 +1,99 @@ +// $Id$ +#include "Options.h" +#include "new.h" +#include "BS_Client.h" +#include "PMC_Flo.h" + +/* This function "encodes" a list of friends by putting the userid's in + a contiguous block. This block can then be transmitted over to the + network to servers on other subnets. Several things are added to + make decoding easier on the other end: + + * A count of the number of friends is prepended (assumption: there + are no more than 9999999 friends... ;-)) + * The login userids are separated by a single space. */ + +int +PMC_Flo::encode (char *packet, int &packet_length) +{ + if (Options::get_opt (Options::DEBUG) != 0) + fprintf (stderr, "in PMC_Flo::encode"); + + this->ss = new (PRIVATE_POOL) BS_Client; + + SET_PACKET_TYPE (packet, Options::PROTO_FLO); + char *buf_ptr = SKIP_PACKET_TYPE (packet); + + sprintf (buf_ptr, "%d", this->friend_count ()); + + buf_ptr += MAXUSERIDNAMELEN; + + /* Loop through all the friends, copying them into the packet buffer. */ + + for (Protocol_Record *frp; (frp = this->get_next_friend ()) != 0; ) + buf_ptr = ACE::strecpy (buf_ptr, frp->get_login ()); + + packet_length = buf_ptr - packet; + + if (Options::get_opt (Options::DEBUG) != 0) + { + fprintf (stderr, ", packet_length = %d\n", packet_length); + write (2, packet, packet_length); + putc ('\n', stderr); + } + return 1; +} + +/* This method is responsible for transforming the msg from the server + back into a form usable by the client. */ + +int +PMC_Flo::decode (char *packet, int &packet_length) +{ + if (Options::get_opt (Options::DEBUG) != 0) + { + fprintf (stderr, "in PMC_Flo::decode, packet_length = %d\n", packet_length); + write (2, packet, packet_length); + putc ('\n', stderr); + } + char *cp = packet; + int remote_users = 0; + + sscanf (cp, "Users %d", &remote_users); + + this->increment_total_users (remote_users); + + for (cp = ACE::strend (cp); *cp != '\n'; cp++) + { + char *login_name = cp; + + for (cp = ACE::strend (cp); *(cp = this->handle_protocol_entries (cp, login_name)) != '\t'; ) + ; + } + + return 1; +} + +Protocol_Record * +PMC_Flo::insert_protocol_info (Protocol_Record &protocol_record) +{ + Protocol_Record *frp = PM_Client::insert_protocol_info (protocol_record); + int length = strlen (frp->get_real ()); + + if (length > this->max_key_length) + this->max_key_length = length; + + return frp; +} + +void +PMC_Flo::process (void) +{ + printf ("remote friends logged on\n"); + PM_Client::process (); +} + +#ifndef __OPTIMIZE__ +PMC_Flo::PMC_Flo (void) +{} +#endif /* __OPTIMIZE__ */ diff --git a/apps/drwho/PMC_Flo.h b/apps/drwho/PMC_Flo.h new file mode 100644 index 00000000000..06ef2295495 --- /dev/null +++ b/apps/drwho/PMC_Flo.h @@ -0,0 +1,28 @@ +/* -*- C++ -*- */ +// $Id$ + +/* Provides the client's lookup table abstraction for `flo' users... */ + +#ifndef _FMC_FLO_H +#define _FMC_FLO_H + +#include "PM_Client.h" + +class PMC_Flo : public PM_Client +{ +protected: + virtual Protocol_Record *insert_protocol_info (Protocol_Record &protocol_record); + virtual int encode (char *packet, int &total_bytes); + virtual int decode (char *packet, int &total_bytes); + +public: + PMC_Flo (void); + virtual void process (void); +}; + +#ifdef __OPTIMIZE__ +inline +PMC_Flo::PMC_Flo (void) +{} +#endif /* __OPTIMIZE__ */ +#endif /* _FMC_FLO_H */ diff --git a/apps/drwho/PMC_Ruser.cpp b/apps/drwho/PMC_Ruser.cpp new file mode 100644 index 00000000000..de71941f940 --- /dev/null +++ b/apps/drwho/PMC_Ruser.cpp @@ -0,0 +1,137 @@ +// $Id$ +#include "global.h" +#include "new.h" +#include "Options.h" +#include "HT_Client.h" +#include "PMC_Ruser.h" + +/* This function is pretty much a no-op that just sets up the appropriate + lookup function to use. */ + +int +PMC_Ruser::encode (char *packet, int &packet_length) +{ + if (Options::get_opt (Options::DEBUG) != 0) + fprintf (stderr, "in PMC_Ruser::encode\n"); + + this->ss = new (PRIVATE_POOL) HT_Client; + + SET_PACKET_TYPE (packet, Options::PROTO_RUSER); + + char *buf_ptr = SKIP_PACKET_TYPE (packet); + + *buf_ptr++ = char (Options::get_opt (Options::PRINT_LOGIN_NAME)); + + packet_length = buf_ptr - packet; + return 1; +} + +/* This method is responsible for transforming the msg from the server + back into a form usable by the client. Note that it reads the REAL_NAME + from the packet (since the server placed it there)... */ + +int +PMC_Ruser::decode (char *packet, int &packet_length) +{ + if (Options::get_opt (Options::DEBUG) != 0) + { + fprintf (stderr, "in PMC_Ruser::decode, packet_length = %d\n", packet_length); + write (2, packet, packet_length); + putc ('\n', stderr); + } + char *cp = packet; + int remote_users = 0; + + sscanf (cp, "Users %d", &remote_users); + + this->increment_total_users (remote_users); + + for (cp = ACE::strend (cp); *cp != '\n'; cp++) + { + char *host_name = cp; + + for (cp = ACE::strend (cp); *(cp = this->handle_protocol_entries (cp, host_name)) != '\t'; ) + ; + } + + return 1; +} + +Protocol_Record * +PMC_Ruser::insert_protocol_info (Protocol_Record &protocol_record) +{ + Protocol_Record *frp = this->ss->insert (protocol_record.get_host (), MAXHOSTNAMELEN); + Drwho_Node *current_node = protocol_record.get_drwho_list (); + Drwho_Node *np = this->get_drwho_node (ACE::strnnew (current_node->get_login_name (), MAXUSERIDNAMELEN), frp->drwho_list); + int length = strlen (frp->get_host ()); + + np->set_real_name (ACE::strnew (current_node->get_real_name ())); + + if (np->get_active_count () < current_node->get_active_count ()) + np->set_active_count (current_node->get_active_count ()); + if (np->get_inactive_count () < current_node->get_inactive_count()) + np->set_inactive_count (current_node->get_inactive_count ()); + + if (length > this->max_key_length) + this->max_key_length = length; + + return frp; +} + +char * +PMC_Ruser::handle_protocol_entries (char *cp, char *host_name, char *) +{ + static Protocol_Record protocol_record (1); + auto Drwho_Node *current_node = protocol_record.get_drwho_list (); + + protocol_record.set_host (host_name); + current_node->set_inactive_count (atoi (cp)); + current_node->set_active_count (atoi (cp = strchr (cp, ' ') + 1)); + current_node->set_login_name (cp = strchr (cp, ' ') + 1); + current_node->set_real_name (cp = strchr (cp, '\0') + 1); + + this->insert_protocol_info (protocol_record); + + return ACE::strend (cp); +} + +void +PMC_Ruser::process (void) +{ + auto char *(Drwho_Node::*get_name)(void) = + Options::get_opt (Options::PRINT_LOGIN_NAME) ? &Drwho_Node::get_login_name : &Drwho_Node::get_real_name; + + for (Protocol_Record *frp; (frp = this->Protocol_Manager::get_each_friend ()) != 0; ) + { + printf ("%-*s ", this->max_key_length, frp->get_host ()); + + for (Drwho_Node *np = frp->get_drwho_list (); ;) + { + fputs ((np->*get_name) (), stdout); + + if (np->get_inactive_count () != 0) + { + if (np->get_active_count () != 0) + printf ("*(%d)", np->get_active_count ()); + } + else if (np->get_active_count () > 1) + printf ("*(%d)", np->get_active_count ()); + else if (np->get_active_count () == 1) + putchar ('*'); + + if ((np = np->next) == 0) + break; + else if (Options::get_opt (Options::PRINT_LOGIN_NAME)) + putchar (' '); + else + printf (", "); + } + + putchar ('\n'); + } +} + +#ifndef __OPTIMIZE__ +PMC_Ruser::PMC_Ruser (void) +{} +#endif /* __OPTIMIZE__ */ diff --git a/apps/drwho/PMC_Ruser.h b/apps/drwho/PMC_Ruser.h new file mode 100644 index 00000000000..936f29854d0 --- /dev/null +++ b/apps/drwho/PMC_Ruser.h @@ -0,0 +1,29 @@ +/* -*- C++ -*- */ +// $Id$ + +/* Provides the client's lookup table abstraction for `ruser' users... */ + +#ifndef _FMC_RUSER_H +#define _FMC_RUSER_H + +#include "PM_Client.h" + +class PMC_Ruser : public PM_Client +{ +protected: + char *handle_protocol_entries (char *cp, char *host_name, char * = 0); + Protocol_Record *insert_protocol_info (Protocol_Record &protocol_record); + virtual int encode (char *packet, int &total_bytes); + virtual int decode (char *packet, int &total_bytes); + +public: + PMC_Ruser (void); + virtual void process (void); +}; + +#ifdef __OPTIMIZE__ +inline +PMC_Ruser::PMC_Ruser (void) +{} +#endif /* __OPTIMIZE__ */ +#endif /* _FMC_RUSER_H */ diff --git a/apps/drwho/PMC_Usr.cpp b/apps/drwho/PMC_Usr.cpp new file mode 100644 index 00000000000..f6a1a7d2d33 --- /dev/null +++ b/apps/drwho/PMC_Usr.cpp @@ -0,0 +1,93 @@ +// $Id$ +#include "Options.h" +#include "new.h" +#include "SL_Client.h" +#include "PMC_Usr.h" + +int +PMC_Usr::encode (char *packet, int &packet_length) +{ + if (Options::get_opt (Options::DEBUG) != 0) + fprintf (stderr, "in PMC_Usr::encode"); + + this->ss = new (PRIVATE_POOL) SL_Client (this->usr_name); + + SET_PACKET_TYPE (packet, Options::PROTO_USR); + + char *buf_ptr = SKIP_PACKET_TYPE (packet); + + buf_ptr = ACE::strecpy (buf_ptr, this->get_next_friend ()->get_login ()); + + packet_length = buf_ptr - packet; + + if (Options::get_opt (Options::DEBUG) != 0) + { + fprintf (stderr, ", packet_length = %d\n", packet_length); + write (2, packet, packet_length); + putc ('\n', stderr); + } + return 1; +} + +/* This method is responsible for transforming the msg from the server + back into a form usable by the client. */ + +int +PMC_Usr::decode (char *packet, int &packet_length) +{ + if (Options::get_opt (Options::DEBUG) != 0) + { + fprintf (stderr, "in PMC_Usr::decode, packet_length = %d\n", packet_length); + write (2, packet, packet_length); + putc ('\n', stderr); + } + + char *cp = packet; + + if (*cp != '\n') + { + char *login_name = cp; + + for (cp = ACE::strend (cp); *(cp = this->handle_protocol_entries (cp, login_name)) != '\t'; ) + ; + } + return 1; +} + +void +PMC_Usr::process (void) +{ + Protocol_Record *frp = this->get_each_friend (); + Drwho_Node *np = frp->get_drwho_list (); + + if (np == 0) + fputs ("<unknown>", stdout); + else + { + + /* First try to get a login session that is active... */ + + for (; np != 0; np = np->next) + if (np->active_count > 0) + { + printf ("%s ", np->get_host_name ()); + + if (Options::get_opt (Options::USE_VERBOSE_FORMAT) == 0) + return; + } + + for (np = frp->get_drwho_list (); np != 0; np = np->next) + if (np->active_count == 0) + { + printf ("%s ", np->get_host_name ()); + + if (Options::get_opt (Options::USE_VERBOSE_FORMAT) == 0) + return; + } + } +} + +#ifndef __OPTIMIZE__ +PMC_Usr::PMC_Usr (char *u_name): usr_name (u_name) +{} +#endif /* __OPTIMIZE__ */ diff --git a/apps/drwho/PMC_Usr.h b/apps/drwho/PMC_Usr.h new file mode 100644 index 00000000000..03195f12586 --- /dev/null +++ b/apps/drwho/PMC_Usr.h @@ -0,0 +1,30 @@ +/* -*- C++ -*- */ +// $Id$ + +/* Provides the client's lookup table abstraction for `Usr' users... */ + +#ifndef _FMC_USR_H +#define _FMC_USR_H + +#include "PM_Client.h" + +class PMC_Usr : public PM_Client +{ +private: + char *usr_name; + +protected: + virtual int encode (char *packet, int &total_bytes); + virtual int decode (char *packet, int &total_bytes); + +public: + PMC_Usr (char *usr_name); + virtual void process (void); +}; + +#ifdef __OPTIMIZE__ +inline +PMC_Usr::PMC_Usr (char *u_name): usr_name (u_name) +{} +#endif /* __OPTIMIZE__ */ +#endif /* _FMC_USR_H */ diff --git a/apps/drwho/PMS_All.cpp b/apps/drwho/PMS_All.cpp new file mode 100644 index 00000000000..d28f21f9bcc --- /dev/null +++ b/apps/drwho/PMS_All.cpp @@ -0,0 +1,76 @@ +// $Id$ +#include "Options.h" +#include "new.h" +#include "HT_Server.h" +#include "PMS_All.h" + +/* This function packs the located friends userids, plus the machines + they are logged into (along with the inactive and active counts on + each machine) into a buffer that is subsequently transmitted back + to the client across the network. Note that this function encodes + the REAL_NAME of the user in the packet. */ + +int +PMS_All::encode (char *packet, int &packet_length) +{ + if (Options::get_opt (Options::DEBUG) != 0) + fprintf (stderr, "in PMS_All::encode"); + + Protocol_Record *frp; + char *buf_ptr = packet; + + sprintf (buf_ptr, "Users %d", this->get_total_users ()); + buf_ptr += strlen (buf_ptr) + 1; + + /* We only send back info on friends that we actually see logged in. */ + + for (; (frp = this->get_next_friend ()) != 0; *buf_ptr++ = '\t') + buf_ptr = this->handle_protocol_entries (ACE::strecpy (ACE::strecpy (buf_ptr, frp->get_login ()), frp->get_real ()), frp->get_drwho_list ()); + + *buf_ptr++ = '\n'; + packet_length = buf_ptr - packet; + + if (Options::get_opt (Options::DEBUG) != 0) + { + fprintf (stderr, ", packet_length = %d\n", packet_length); + write (2, packet, packet_length); + putc ('\n', stderr); + } + return 1; +} + +/* This function takes a packet received from the client and calls + the appropriate Protocol_Manager routine to build the local table of + friends. */ + +int +PMS_All::decode (char *, int &packet_length) +{ + if (Options::get_opt (Options::DEBUG) != 0) + fprintf (stderr, "in PMS_All::decode, packet_length = %d\n", packet_length); + + this->ss = new (PRIVATE_POOL) HT_Server; + return 1; +} + +/* We only want the user's real name, not the gecos junk after the first leading ','. + However, if the real-name is not in the password file, just return the login name + instead. */ + +Protocol_Record * +PMS_All::insert_protocol_info (Protocol_Record &protocol_record) +{ + Protocol_Record *frp = PM_Server::insert_protocol_info (protocol_record); + passwd *pwent = getpwnam (frp->get_login ()); + char *cp; + + if ((cp = strchr (frp->set_real (pwent == 0 ? frp->get_login () : ACE::strnew (pwent->pw_gecos)), ',')) != 0) + *cp = '\0'; + + return frp; +} + +#ifndef __OPTIMIZE__ +PMS_All::PMS_All (void) +{} +#endif /* __OPTIMIZE__ */ diff --git a/apps/drwho/PMS_All.h b/apps/drwho/PMS_All.h new file mode 100644 index 00000000000..559e7674eea --- /dev/null +++ b/apps/drwho/PMS_All.h @@ -0,0 +1,27 @@ +/* -*- C++ -*- */ +// $Id$ + +/* Provides the server's lookup table abstraction for `all' users... */ + +#ifndef _FMS_ALL_H +#define _FMS_ALL_H + +#include "PM_Server.h" + +class PMS_All : public PM_Server +{ +protected: + virtual Protocol_Record *insert_protocol_info (Protocol_Record &protocol_record); + virtual int encode (char *packet, int &total_bytes); + virtual int decode (char *packet, int &total_bytes); + +public: + PMS_All (void); +}; + +#ifdef __OPTIMIZE__ +inline +PMS_All::PMS_All (void) +{} +#endif /* __OPTIMIZE__ */ +#endif /* _FMS_ALL_H */ diff --git a/apps/drwho/PMS_Flo.cpp b/apps/drwho/PMS_Flo.cpp new file mode 100644 index 00000000000..692d316b7cf --- /dev/null +++ b/apps/drwho/PMS_Flo.cpp @@ -0,0 +1,58 @@ +// $Id$ +#include "Options.h" +#include "new.h" +#include "BS_Server.h" +#include "PMS_Flo.h" + +/* This function packs the located friends userids, plus the machines + they are logged into (along with the inactive and active counts on + each machine) into a buffer that is subsequently transmitted back + to the client across the network. */ + +int +PMS_Flo::encode (char *packet, int &packet_length) +{ + if (Options::get_opt (Options::DEBUG) != 0) + fprintf (stderr, "in PMS_Flo::encode"); + + Protocol_Record *frp; + char *buf_ptr = packet; + + sprintf (buf_ptr, "Users %d", this->get_total_users ()); + buf_ptr += strlen (buf_ptr) + 1; + + /* We only send back info on friends that we actually see logged in. */ + + for (; (frp = this->get_next_friend ()) != 0; *buf_ptr++ = '\t') + buf_ptr = this->handle_protocol_entries (ACE::strecpy (buf_ptr, frp->get_login ()), frp->get_drwho_list ()); + + *buf_ptr++ = '\n'; + packet_length = buf_ptr - packet; + + if (Options::get_opt (Options::DEBUG) != 0) + { + fprintf (stderr, ", packet_length = %d\n", packet_length); + write (2, packet, packet_length); + putc ('\n', stderr); + } + return 1; +} + +/* This function takes a packet received from the client and calls + the appropriate Protocol_Manager routine to build the local table of + friends. */ + +int +PMS_Flo::decode (char *packet, int &packet_length) +{ + if (Options::get_opt (Options::DEBUG) != 0) + fprintf (stderr, "in PMS_Flo::decode, packet_length = %d\n", packet_length); + + this->ss = new (PRIVATE_POOL) BS_Server (packet); + return 1; +} + +#ifndef __OPTIMIZE__ +PMS_Flo::PMS_Flo (void) +{} +#endif /* __OPTIMIZE__ */ diff --git a/apps/drwho/PMS_Flo.h b/apps/drwho/PMS_Flo.h new file mode 100644 index 00000000000..e095b5f4ec6 --- /dev/null +++ b/apps/drwho/PMS_Flo.h @@ -0,0 +1,26 @@ +/* -*- C++ -*- */ +// $Id$ + +/* Provides the server's lookup table abstraction for `flo' users... */ + +#ifndef _FMS_FLO_H +#define _FMS_FLO_H + +#include "PM_Server.h" + +class PMS_Flo : public PM_Server +{ +protected: + virtual int encode (char *packet, int &total_bytes); + virtual int decode (char *packet, int &total_bytes); + +public: + PMS_Flo (void); +}; + +#ifdef __OPTIMIZE__ +inline +PMS_Flo::PMS_Flo (void) +{} +#endif /* __OPTIMIZE__ */ +#endif diff --git a/apps/drwho/PMS_Ruser.cpp b/apps/drwho/PMS_Ruser.cpp new file mode 100644 index 00000000000..ca49e998a3c --- /dev/null +++ b/apps/drwho/PMS_Ruser.cpp @@ -0,0 +1,103 @@ +// $Id$ +#include "Options.h" +#include "new.h" +#include "HT_Server.h" +#include "PMS_Ruser.h" + +/* This function packs the located friends userids, plus the machines + they are logged into (along with the inactive and active counts on + each machine) into a buffer that is subsequently transmitted back + to the client across the network. Note that this function encodes + the REAL_NAME of the user in the packet. */ + +int +PMS_Ruser::encode (char *packet, int &packet_length) +{ + if (Options::get_opt (Options::DEBUG) != 0) + fprintf (stderr, "in PMS_Ruser::encode"); + + Protocol_Record *frp; + char *buf_ptr = packet; + + sprintf (buf_ptr, "Users %d", this->get_total_users ()); + buf_ptr += strlen (buf_ptr) + 1; + + /* We only send back info on hosts that we actually see. */ + + for (; (frp = this->get_next_friend ()) != 0; *buf_ptr++ = '\t') + buf_ptr = this->handle_protocol_entries (ACE::strecpy (buf_ptr, frp->get_host ()), frp->get_drwho_list ()); + + *buf_ptr++ = '\n'; + packet_length = buf_ptr - packet; + + if (Options::get_opt (Options::DEBUG) != 0) + { + fprintf (stderr, ", packet_length = %d\n", packet_length); + write (2, packet, packet_length); + putc ('\n', stderr); + } + return 1; +} + +/* This function takes a packet received from the client and crusers + the appropriate Protocol_Manager routine to build the local table of + friends. */ + +int +PMS_Ruser::decode (char *packet, int &packet_length) +{ + if (Options::get_opt (Options::DEBUG) != 0) + fprintf (stderr, "in PMS_Ruser::decode, packet_length = %d\n", packet_length); + + if (*packet) + Options::set_opt (Options::PRINT_LOGIN_NAME); + + this->ss = new (PRIVATE_POOL) HT_Server; + return 1; +} + +Protocol_Record * +PMS_Ruser::insert_protocol_info (Protocol_Record &protocol_record) +{ + Drwho_Node *current_node = protocol_record.get_drwho_list (); + Protocol_Record *frp = this->ss->insert (current_node->get_host_name (), MAXHOSTNAMELEN); + Drwho_Node *np = this->get_drwho_node (ACE::strnnew (protocol_record.get_login (), MAXUSERIDNAMELEN), frp->drwho_list); + + if (Options::get_opt (Options::PRINT_LOGIN_NAME)) + np->set_real_name (""); + else + { + passwd *pwent = getpwnam (np->get_login_name ()); + char *cp; + + if ((cp = strchr (np->set_real_name (pwent == 0 ? np->get_login_name () : ACE::strnew (pwent->pw_gecos)), ',')) != 0) + *cp = '\0'; + } + + if (current_node->get_idle_time () >= MAX_USER_TIMEOUT) + np->inactive_count++; + else + np->active_count++; + + return frp; +} + +char * +PMS_Ruser::handle_protocol_entries (char *buf_ptr, Drwho_Node *np) +{ + + for (; np != 0; np = np->next) + { + sprintf (buf_ptr, "%d %d ", np->get_inactive_count (), np->get_active_count ()); + buf_ptr += strlen (buf_ptr); + + buf_ptr = ACE::strecpy (ACE::strecpy (buf_ptr, np->get_login_name ()), np->get_real_name ()); + } + + return buf_ptr; +} + +#ifndef __OPTIMIZE__ +PMS_Ruser::PMS_Ruser (void) +{} +#endif /* __OPTIMIZE__ */ diff --git a/apps/drwho/PMS_Ruser.h b/apps/drwho/PMS_Ruser.h new file mode 100644 index 00000000000..0111580c3f9 --- /dev/null +++ b/apps/drwho/PMS_Ruser.h @@ -0,0 +1,28 @@ +/* -*- C++ -*- */ +// $Id$ + +/* Provides the server's lookup table abstraction for `ruser' users... */ + +#ifndef _FMS_RUSER_H +#define _FMS_RUSER_H + +#include "PM_Server.h" + +class PMS_Ruser : public PM_Server +{ +protected: + virtual char *handle_protocol_entries (char *bp, Drwho_Node *hp); + virtual Protocol_Record *insert_protocol_info (Protocol_Record &protocol_record); + virtual int encode (char *packet, int &total_bytes); + virtual int decode (char *packet, int &total_bytes); + +public: + PMS_Ruser (void); +}; + +#ifdef __OPTIMIZE__ +inline +PMS_Ruser::PMS_Ruser (void) +{} +#endif /* __OPTIMIZE__ */ +#endif /* _FMS_RUSER_H */ diff --git a/apps/drwho/PMS_Usr.cpp b/apps/drwho/PMS_Usr.cpp new file mode 100644 index 00000000000..900bec14dfa --- /dev/null +++ b/apps/drwho/PMS_Usr.cpp @@ -0,0 +1,66 @@ +// $Id$ +#include "Options.h" +#include "new.h" +#include "SL_Server.h" +#include "PMS_Usr.h" + +/* This function "encodes" a list of friends by putting the userid's in + a contiguous block. This block can then be transmitted over to the + network to servers on other subnets. Several things are added to + make decoding easier on the other end: + + * A count of the number of friends is prepended (assumption: there + are no more than 9999999 friends... ;-)) + * The login userids are separated by a single space. */ + +int +PMS_Usr::encode (char *packet, int &packet_length) +{ + if (Options::get_opt (Options::DEBUG) != 0) + fprintf (stderr, "in PMS_Usr::encode"); + + char *buf_ptr = packet; + + /* We only send back info on friend that is actually logged in. */ + + Protocol_Record *frp = this->get_next_friend (); + + if (frp) + { + buf_ptr = this->handle_protocol_entries (ACE::strecpy (buf_ptr, frp->get_login ()), frp->get_drwho_list ()); + *buf_ptr++ = '\t'; + } + + *buf_ptr++ = '\n'; + packet_length = buf_ptr - packet; + + if (Options::get_opt (Options::DEBUG) != 0) + { + fprintf (stderr, ", packet_length = %d\n", packet_length); + write (2, packet, packet_length); + putc ('\n', stderr); + } + return 1; +} + +/* This function takes a packet received from the client and calls + the appropriate Protocol_Manager routine to build the local table of + friends. */ + +int +PMS_Usr::decode (char *packet, int &packet_length) +{ + if (Options::get_opt (Options::DEBUG) != 0) + { + fprintf (stderr, "in PMS_Usr::decode, packet_length = %d\n", packet_length); + write (2, packet, packet_length); + putc ('\n', stderr); + } + this->ss = new (PRIVATE_POOL) SL_Server (packet); + return 1; +} + +#ifndef __OPTIMIZE__ +PMS_Usr::PMS_Usr (void) +{} +#endif /* __OPTIMIZE__ */ diff --git a/apps/drwho/PMS_Usr.h b/apps/drwho/PMS_Usr.h new file mode 100644 index 00000000000..d9cd7094da1 --- /dev/null +++ b/apps/drwho/PMS_Usr.h @@ -0,0 +1,26 @@ +/* -*- C++ -*- */ +// $Id$ + +/* Provides the client's lookup table abstraction for `Usr' users... */ + +#ifndef _FMS_USR_H +#define _FMS_USR_H + +#include "PM_Server.h" + +class PMS_Usr : public PM_Server +{ +protected: + virtual int encode (char *packet, int &total_bytes); + virtual int decode (char *packet, int &total_bytes); + +public: + PMS_Usr (void); +}; + +#ifdef __OPTIMIZE__ +inline +PMS_Usr::PMS_Usr (void) +{} +#endif /* __OPTIMIZE__ */ +#endif /* _FMS_USR_H */ diff --git a/apps/drwho/PM_Client.cpp b/apps/drwho/PM_Client.cpp new file mode 100644 index 00000000000..ba37746484f --- /dev/null +++ b/apps/drwho/PM_Client.cpp @@ -0,0 +1,106 @@ +// $Id$ +#include "Options.h" +#include "PM_Server.h" +#include "PM_Client.h" + +/* This function is used to merge the LOGIN_NAME from server HOST_NAME + into the userids kept on the client's side. Note that we must + allocate memory for HOST_NAME... */ + +Protocol_Record * +PM_Client::insert_protocol_info (Protocol_Record &protocol_record) +{ + Protocol_Record *frp = this->ss->insert (protocol_record.get_login ()); + Drwho_Node *current_node = protocol_record.get_drwho_list (); + Drwho_Node *np = this->get_drwho_node (ACE::strnew (current_node->get_host_name ()), frp->drwho_list); + + /* Update the active and inactive counts. */ + + if (np->get_active_count () < current_node->get_active_count ()) + { + np->set_active_count (current_node->get_active_count ()); + frp->is_active = 1; + } + if (np->get_inactive_count () < current_node->get_inactive_count()) + np->set_inactive_count (current_node->get_inactive_count ()); + + return frp; +} + +/* This routine does all the dirty work, and actually prints out the + friends info in a nicely formatted manner. */ + +void +PM_Client::process (void) +{ + char *(Protocol_Record::*get_name)(void) = Options::get_opt (Options::PRINT_LOGIN_NAME) ? &Protocol_Record::get_login : &Protocol_Record::get_real; + + int active_friends = 0; + int users = this->Protocol_Manager::get_total_users (); + + printf ("------------------------\n"); + + if (Options::get_opt (Options::PRINT_LOGIN_NAME)) + this->max_key_length = MAXUSERIDNAMELEN; + + /* Goes through the queue of all the logged in friends and prints + out the associated information. */ + + for (Protocol_Record *frp; (frp = this->Protocol_Manager::get_each_friend ()) != 0; ) + { + printf ("%c%-*s [", (frp->is_active != 0 ? '*' : ' '), + this->max_key_length, (frp->*get_name) ()); + + for (Drwho_Node *np = frp->get_drwho_list (); ;) + { + fputs (np->get_host_name (), stdout); + + active_friends += np->get_active_count (); + + if (np->get_inactive_count () != 0) + { + if (np->get_active_count () != 0) + printf ("*(%d)", np->get_active_count ()); + } + else if (np->get_active_count () > 1) + printf ("*(%d)", np->get_active_count ()); + else if (np->get_active_count () == 1) + putchar ('*'); + + if ((np = np->next) == 0) + break; + else + putchar (' '); + } + + printf ("]\n"); + } + + printf ("------------------------\n"); + printf ("friends: %d\tusers: %d\n", active_friends, users); +} + +char * +PM_Client::handle_protocol_entries (char *cp, char *login_name, char *real_name) +{ + static Protocol_Record protocol_record (1); + Drwho_Node *current_node = protocol_record.get_drwho_list (); + + protocol_record.set_login (login_name); + protocol_record.set_real (real_name); + current_node->set_inactive_count (atoi (cp)); + current_node->set_active_count (atoi (cp = strchr (cp, ' ') + 1)); + current_node->set_host_name (cp = strchr (cp, ' ') + 1); + + this->insert_protocol_info (protocol_record); + + return ACE::strend (cp); +} + +#ifndef __OPTIMIZE__ +PM_Client::PM_Client (void): max_key_length (0) +{} + +PM_Client::~PM_Client (void) +{} +#endif /* __OPTIMIZE__ */ diff --git a/apps/drwho/PM_Client.h b/apps/drwho/PM_Client.h new file mode 100644 index 00000000000..ff1c20f32fa --- /dev/null +++ b/apps/drwho/PM_Client.h @@ -0,0 +1,37 @@ +/* -*- C++ -*- */ +// $Id$ + +/* Provides the client side of the friend manager lookup table abstraction. */ + +#ifndef _PM_CLIENT_H +#define _PM_CLIENT_H + +#include "Protocol_Manager.h" + +class PM_Client : public Protocol_Manager +{ +protected: + int max_key_length; + + virtual char *handle_protocol_entries (char *cp, char *key_name1, char *key_name2 = 0); + virtual Protocol_Record *insert_protocol_info (Protocol_Record &protocol_record); +public: + PM_Client (void); + virtual ~PM_Client (void); + + virtual int encode (char *packet, int &total_bytes) = 0; + virtual int decode (char *packet, int &total_bytes) = 0; + virtual void process (void); +}; + +#ifdef __OPTIMIZE__ +inline +PM_Client::PM_Client (void): max_key_length (0) +{} + +inline +PM_Client::~PM_Client (void) +{} +#endif /* __OPTIMIZE__ */ +#endif /* _PM_CLIENT_H */ + diff --git a/apps/drwho/PM_Server.cpp b/apps/drwho/PM_Server.cpp new file mode 100644 index 00000000000..bd47013606b --- /dev/null +++ b/apps/drwho/PM_Server.cpp @@ -0,0 +1,72 @@ +// $Id$ +#include "Options.h" +#include "Rwho_DB_Manager.h" +#include "PM_Server.h" + +/* This is the main method for the server side of things. It + reads the RWHO file on the local machine and inserts HOST_NAME + information for each LOGIN_NAME that is a friend into the DRWHO_LIST. + This function is also responsible for determining whether a given + LOGIN_NAME is currently idle or not. */ + +int +PM_Server::process (void) +{ + RWho_DB_Manager ru; + Protocol_Record protocol_record (1); + + while (ru.get_next_user (protocol_record) > 0) + this->insert_protocol_info (protocol_record); + + return 1; +} + +/* Insert the HOST_NAME into the server's lookup table on behalf of + user LOGIN_NAME. Note that we need to allocate memory for + HOST_NAME... */ + +Protocol_Record * +PM_Server::insert_protocol_info (Protocol_Record &protocol_record) +{ + Protocol_Record *frp = this->ss->insert (protocol_record.get_login ()); + + Drwho_Node *current_node = protocol_record.get_drwho_list (); + + if (current_node->get_idle_time () < MAX_USER_TIMEOUT) + this->increment_total_users (); + + if (frp) + { + Drwho_Node *np = this->get_drwho_node (ACE::strnew (current_node->get_host_name ()), frp->drwho_list); + + if (current_node->get_idle_time () >= MAX_USER_TIMEOUT) + np->inactive_count++; + else + np->active_count++; + } + + return frp; +} + +/* Put the inactive and active counts, plus the hostname into the packet. */ + +char * +PM_Server::handle_protocol_entries (char *buf_ptr, Drwho_Node *np) +{ + + for (; np != 0; np = np->next) + { + sprintf (buf_ptr, "%d %d %s", np->get_inactive_count (), np->get_active_count (), np->get_host_name ()); + buf_ptr += strlen (buf_ptr) + 1; + } + + return buf_ptr; +} + +#ifndef __OPTIMIZE__ +PM_Server::PM_Server (void) +{} + +PM_Server::~PM_Server (void) +{} +#endif /* __OPTIMIZE__ */ diff --git a/apps/drwho/PM_Server.h b/apps/drwho/PM_Server.h new file mode 100644 index 00000000000..2b9b497aee4 --- /dev/null +++ b/apps/drwho/PM_Server.h @@ -0,0 +1,35 @@ +/* -*- C++ -*- */ +// $Id$ + +/* Handle the server's lookup table abstraction. */ + +#ifndef _PM_SERVER_H +#define _PM_SERVER_H + +#include "Protocol_Manager.h" + +class PM_Server : public Protocol_Manager +{ +protected: + virtual char *handle_protocol_entries (char *bp, Drwho_Node *hp); + virtual Protocol_Record *insert_protocol_info (Protocol_Record &protocol_record); + +public: + PM_Server (void); + virtual ~PM_Server (void); + + virtual int encode (char *packet, int &total_bytes) = 0; + virtual int decode (char *packet, int &total_bytes) = 0; + virtual int process (void); +}; + +#ifdef __OPTIMIZE__ +inline +PM_Server::PM_Server (void) +{} + +inline +PM_Server::~PM_Server (void) +{} +#endif /* __OPTIMIZE__ */ +#endif diff --git a/apps/drwho/Protocol_Manager.cpp b/apps/drwho/Protocol_Manager.cpp new file mode 100644 index 00000000000..a31f4041d10 --- /dev/null +++ b/apps/drwho/Protocol_Manager.cpp @@ -0,0 +1,83 @@ +// $Id$ +#include "Options.h" +#include "new.h" +#include "Protocol_Manager.h" + +#if 0 +/* Static initializers. */ +int Protocol_Manager::total_users = 0; +Search_Struct *Protocol_Manager::ss = 0; +#endif + +/* Functions shared between client and server. */ + +/* Returns a pointer to the Drwho_Node associated with HOST_NAME (if + it exists, otherwise a new node is created. Note that if a + Drwho_Node is found it is moved to the front of the list so that + subsequent finds are faster (i.e., self-organizing!) */ + +Drwho_Node * +Protocol_Manager::get_drwho_node (char *key_name, Drwho_Node *&head) +{ + for (Drwho_Node **temp = &head; *temp != 0; temp = &(*temp)->next) + if (strcmp (key_name, (*temp)->get_login_name ()) == 0) + break; + + if (*temp == 0) + return head = new (PRIVATE_POOL) Drwho_Node (key_name, head); + else + { + Drwho_Node *t = *temp; + + *temp = (*temp)->next; + t->next = head; + return head = t; + } +} + +#ifndef __OPTIMIZE__ +Protocol_Manager::Protocol_Manager (void): total_users (0) +{} + +Protocol_Manager::~Protocol_Manager (void) +{ + if (Options::get_opt (Options::DEBUG)) + fprintf (stderr, "disposing Protocol_Manager\n"); +} + +/* Returns the next friend in the sequence of sorted friends. */ + +Protocol_Record * +Protocol_Manager::get_next_friend (void) +{ + return this->ss->get_next_entry (); +} + +Protocol_Record * +Protocol_Manager::get_each_friend (void) +{ + return this->ss->get_each_entry (); +} + +/* Returns the number of friends. */ + +int +Protocol_Manager::friend_count (void) +{ + return this->ss->n_elems (); +} + +/* Returns total number of users logged in throughout the system. */ + +int +Protocol_Manager::get_total_users (void) +{ + return Protocol_Manager::total_users; +} + +void +Protocol_Manager::increment_total_users (int remote_users) +{ + Protocol_Manager::total_users += remote_users; +} +#endif /* __OPTIMIZE__ */ diff --git a/apps/drwho/Protocol_Manager.h b/apps/drwho/Protocol_Manager.h new file mode 100644 index 00000000000..705a1e81657 --- /dev/null +++ b/apps/drwho/Protocol_Manager.h @@ -0,0 +1,86 @@ +/* -*- C++ -*- */ +// $Id$ + +/* A base class that consolidates friend management functionality + shared by both clients and servers. */ + +#ifndef _FRIEND_MANAGER_H +#define _FRIEND_MANAGER_H + +#include "ace/OS.h" +#include "Options.h" +#include "Search_Struct.h" +#include "Protocol_Record.h" + +class Protocol_Manager +{ +protected: + int total_users; + Search_Struct *ss; + + int friend_count (void); + + Drwho_Node *get_drwho_node (char *host_name, Drwho_Node *&head); + int get_total_users (void); + void increment_total_users (int remote_users = 1); + + Protocol_Record *get_next_friend (void); + Protocol_Record *get_each_friend (void); + + virtual Protocol_Record *insert_protocol_info (Protocol_Record &protocol_record) = 0; + +public: + Protocol_Manager (void); + virtual ~Protocol_Manager (void); + + virtual int encode (char *packet, int &total_bytes) = 0; + virtual int decode (char *packet, int &total_bytes) = 0; +}; + +#ifdef __OPTIMIZE__ +inline +Protocol_Manager::Protocol_Manager (void): total_users (0) +{} + +inline +Protocol_Manager::~Protocol_Manager (void) +{ + if (Options::DEBUG) + fprintf (stderr, "disposing Protocol_Manager\n"); +} + +/* Returns the next friend in the sequence of sorted friends. */ + +inline Protocol_Record * +Protocol_Manager::get_next_friend (void) +{ + return this->ss->get_next_entry (); +} + +inline Protocol_Record * +Protocol_Manager::get_each_friend (void) +{ + return this->ss->get_each_entry (); +} + +/* Returns the number of friends. */ + +inline int +Protocol_Manager::friend_count (void) +{ + return this->ss->n_elems (); +} + +inline int +Protocol_Manager::get_total_users (void) +{ + return this->total_users; +} + +inline void +Protocol_Manager::increment_total_users (int remote_users) +{ + this->total_users += remote_users; +} +#endif /* __OPTIMIZE__ */ +#endif /* _FRIEND_MANAGER_H */ diff --git a/apps/drwho/Protocol_Record.cpp b/apps/drwho/Protocol_Record.cpp new file mode 100644 index 00000000000..c62350f03ff --- /dev/null +++ b/apps/drwho/Protocol_Record.cpp @@ -0,0 +1,79 @@ +// $Id$ +#include "Options.h" +#include "Protocol_Record.h" + +/* Static initialization. */ + +Drwho_Node Protocol_Record::drwho_node; + +Protocol_Record::~Protocol_Record (void) +{ + if (Options::get_opt (Options::DEBUG)) + fprintf (stderr, "disposing Protocol_Record\n"); + + for (Drwho_Node *np = this->get_drwho_list (); np != 0; ) + { + Drwho_Node *t = np; + np = np->next; + } +} + +#ifndef __OPTIMIZE__ +Protocol_Record::Protocol_Record (void) + : is_active (0), drwho_list (0), key_name1 (0), key_name2 (0), next (0) +{} + +Protocol_Record::Protocol_Record (int) + : is_active (0), drwho_list (&Protocol_Record::drwho_node), key_name1 (0), key_name2 (0), next (0) +{} + + +Protocol_Record::Protocol_Record (char *kn1, Protocol_Record *next) + : is_active (0), drwho_list (0), key_name2 (0) +{ + this->key_name1 = kn1; + this->next = next; +} + +char * +Protocol_Record::get_login (void) +{ + return this->key_name1; +} + +char * +Protocol_Record::set_login (char *str) +{ + return this->key_name1 = str; +} + +char * +Protocol_Record::get_real (void) +{ + return this->key_name2; +} + +char * +Protocol_Record::get_host (void) +{ + return this->key_name1; +} + +char * +Protocol_Record::set_host (char *str) +{ + return this->key_name1 = str; +} + +char * +Protocol_Record::set_real (char *str) +{ + return this->key_name2 = str; +} + +Drwho_Node * +Protocol_Record::get_drwho_list (void) +{ + return this->drwho_list; +} +#endif /* __OPTIMIZE__ */ diff --git a/apps/drwho/Protocol_Record.h b/apps/drwho/Protocol_Record.h new file mode 100644 index 00000000000..05afa16f8e6 --- /dev/null +++ b/apps/drwho/Protocol_Record.h @@ -0,0 +1,95 @@ +/* -*- C++ -*- */ +// $Id$ + +/* Stores information about a single friend's status. */ + +#ifndef _FRIEND_RECORD_H +#define _FRIEND_RECORD_H + +#include "Drwho_Node.h" + +class Protocol_Record +{ +public: + static Drwho_Node drwho_node; + char *key_name1; + char *key_name2; + Drwho_Node *drwho_list; + Protocol_Record *next; + int is_active; + + Protocol_Record (void); + Protocol_Record (int use_dummy); + Protocol_Record (char *key_name1, Protocol_Record *next = 0); + ~Protocol_Record (void); + char *get_host (void); + char *set_host (char *str); + char *get_login (void); + char *set_login (char *str); + char *get_real (void); + char *set_real (char *str); + Drwho_Node *get_drwho_list (void); +}; + +#ifdef __OPTIMIZE__ +inline +Protocol_Record::Protocol_Record (void) + : is_active (0), drwho_list (0), key_name1 (0), key_name2 (0), next (0) +{} + +inline +Protocol_Record::Protocol_Record (int use_dummy) + : is_active (0), drwho_list (&Protocol_Record::drwho_node), key_name1 (0), key_name2 (0), next (0) +{} + +inline +Protocol_Record::Protocol_Record (char *key_name1, Protocol_Record *next) + : is_active (0), drwho_list (0), key_name2 (0) +{ + this->key_name1 = key_name1; + this->next = next; +} + +inline char * +Protocol_Record::get_login (void) +{ + return this->key_name1; +} + +inline char * +Protocol_Record::set_login (char *str) +{ + return this->key_name1 = str; +} + +inline char * +Protocol_Record::get_real (void) +{ + return this->key_name2; +} + +inline char * +Protocol_Record::get_host (void) +{ + return this->key_name1; +} + +inline char * +Protocol_Record::set_host (char *str) +{ + return this->key_name1 = str; +} + +inline char * +Protocol_Record::set_real (char *str) +{ + return this->key_name2 = str; +} + +inline Drwho_Node * +Protocol_Record::get_drwho_list (void) +{ + return this->drwho_list; +} +#endif /* __OPTIMIZE__ */ +#endif /* _FRIEND_RECORD_H */ diff --git a/apps/drwho/Rwho_DB_Manager.cpp b/apps/drwho/Rwho_DB_Manager.cpp new file mode 100644 index 00000000000..e67d6ded666 --- /dev/null +++ b/apps/drwho/Rwho_DB_Manager.cpp @@ -0,0 +1,104 @@ +// $Id$ +#include "global.h" +#include "Options.h" +#include "Rwho_DB_Manager.h" + +/* Change to the RWHO directory to speed up and simplify later + processing. This requires opening the directory + for reading with the directory iterator abstraction and then + skipping the first two files in the directory, which are assumed to + be "." and ".." (this function needs to be changed if this + assumption does not hold!) */ + +RWho_DB_Manager::RWho_DB_Manager (void) + : number_of_users (0), current_user (0), rwho_dir_name (RWHODIR), + WHOD_HEADER_SIZE (sizeof host_data - sizeof host_data.wd_we) +{ + if (getcwd (this->original_pathname, MAXPATHLEN + 1) == 0) + perror (Options::program_name), exit (1); + + if (chdir (this->rwho_dir_name) < 0) + perror (this->rwho_dir_name), exit (1); + + this->rwho_dir.opendir (this->rwho_dir_name); + + /* Skip "." and ".." */ + this->rwho_dir.readdir (); + this->rwho_dir.readdir (); +} + +/* The destructor cleans up the RWHOD_DIR handle. */ + +RWho_DB_Manager::~RWho_DB_Manager (void) +{ + if (chdir (this->original_pathname) < 0) + perror (Options::program_name), exit (1); + + if (Options::get_opt (Options::DEBUG)) + fprintf (stderr, "disposing the RWho-Manager\n"); +} + +/* This procedure looks through the rwhod directory until it finds the next + valid user file. + + The requirements for user files are: + 1) The file is at least MIN_HOST_DATA_SIZE bytes long + 2) It was received within the last MAX_HOST_TIMEOUT seconds + + Return: + Are there any more hosts? */ + +int +RWho_DB_Manager::get_next_host (void) +{ + dirent *dir_ptr; + long current_time; + + time (¤t_time); + + /* Go through each file in the directory looking for valid entries */ + + while ((dir_ptr = this->rwho_dir.readdir ()) != 0) + { + int user_file; + int host_data_length; + + if ((user_file = open (dir_ptr->d_name, O_RDONLY)) < 0) + return -1; + + host_data_length = read (user_file, (char *) &this->host_data, sizeof this->host_data); + + if (host_data_length > WHOD_HEADER_SIZE && current_time - this->host_data.wd_recvtime < MAX_HOST_TIMEOUT) + { + this->current_user = 0; + this->number_of_users = (host_data_length - WHOD_HEADER_SIZE) / sizeof *this->host_data.wd_we; + close (user_file); + return 1; /* We found a good host, so return it */ + } + else + close (user_file); + } + + return 0; /* There are no more hosts, so return False */ +} + +/* Returns the next user's information. Note that for efficiency + only pointers are copied, i.e., this info must be used before we + call this function again. */ + +int +RWho_DB_Manager::get_next_user (Protocol_Record &protocol_record) +{ + /* Get the next host file if necessary */ + if (this->current_user >= this->number_of_users && this->get_next_host () == 0) + return 0; + + Drwho_Node *current_node = protocol_record.get_drwho_list (); + + protocol_record.set_login (this->host_data.wd_we[current_user].we_utmp.out_name); + current_node->set_host_name (this->host_data.wd_hostname); + current_node->set_idle_time (this->host_data.wd_we[current_user].we_idle); + this->current_user++; + + return 1; +} diff --git a/apps/drwho/Rwho_DB_Manager.h b/apps/drwho/Rwho_DB_Manager.h new file mode 100644 index 00000000000..7925c695bd5 --- /dev/null +++ b/apps/drwho/Rwho_DB_Manager.h @@ -0,0 +1,31 @@ +/* -*- C++ -*- */ +// $Id$ + +/* This class returns the user/machine pairs one at a time from the rwho database. */ + +#ifndef _RWHO_DB_MANAGER_H +#define _RWHO_DB_MANAGER_H + +#include "rwhod.h" +#include "Dirent.h" +#include "Protocol_Record.h" + +class RWho_DB_Manager +{ +private: + Dirent rwho_dir; + whod host_data; + int number_of_users; + int current_user; + const int WHOD_HEADER_SIZE; + char original_pathname[MAXPATHLEN + 1]; + char *rwho_dir_name; + + int get_next_host (void); + +public: + RWho_DB_Manager (void); + ~RWho_DB_Manager (void); + int get_next_user (Protocol_Record &protocol_record); +}; +#endif /* _RWHO_DB_MANAGER_H */ diff --git a/apps/drwho/SL_Client.cpp b/apps/drwho/SL_Client.cpp new file mode 100644 index 00000000000..d2c62c942c6 --- /dev/null +++ b/apps/drwho/SL_Client.cpp @@ -0,0 +1,14 @@ +// $Id$ +#include "Options.h" +#include "SL_Client.h" + +#ifndef __OPTIMIZE__ +SL_Client::SL_Client (char *usr_name): Single_Lookup (usr_name) +{} + +Protocol_Record * +SL_Client::insert (char *, int) +{ + return this->frp; +} +#endif /* __OPTIMIZE__ */ diff --git a/apps/drwho/SL_Client.h b/apps/drwho/SL_Client.h new file mode 100644 index 00000000000..f00e9939f02 --- /dev/null +++ b/apps/drwho/SL_Client.h @@ -0,0 +1,29 @@ +/* -*- C++ -*- */ +// $Id$ + +/* Provides the client's single user lookup table abstraction. */ + +#ifndef _SL_CLIENT_H +#define _SL_CLIENT_H + +#include "Single_Lookup.h" + +class SL_Client : public Single_Lookup +{ +public: + SL_Client (char *usr_name); + virtual Protocol_Record *insert (char *key_name, int max_len = MAXUSERIDNAMELEN); +}; + +#ifdef __OPTIMIZE__ +inline +SL_Client::SL_Client (char *usr_name): Single_Lookup (usr_name) +{} + +inline Protocol_Record * +SL_Client::insert (char *key_name, int) +{ + return this->frp; +} +#endif /* __OPTIMIZE__ */ +#endif /* _SL_CLIENT_H */ diff --git a/apps/drwho/SL_Server.cpp b/apps/drwho/SL_Server.cpp new file mode 100644 index 00000000000..a55a02323c6 --- /dev/null +++ b/apps/drwho/SL_Server.cpp @@ -0,0 +1,21 @@ +// $Id$ +#include "global.h" +#include "SL_Server.h" + +#ifndef __OPTIMIZE__ +SL_Server::SL_Server (char *usr_name): Single_Lookup (usr_name) +{} + +Protocol_Record * +SL_Server::get_each_entry (void) +{ + Protocol_Record *frp = Single_Lookup::get_each_entry (); + return frp->get_drwho_list () == 0 ? 0 : frp; +} + +Protocol_Record * +SL_Server::insert (char *key_name, int max_len) +{ + return strncmp (key_name, this->frp->get_login (), max_len) == 0 ? this->frp : 0; +} +#endif /* __OPTIMIZE__ */ diff --git a/apps/drwho/SL_Server.h b/apps/drwho/SL_Server.h new file mode 100644 index 00000000000..55738c554e1 --- /dev/null +++ b/apps/drwho/SL_Server.h @@ -0,0 +1,37 @@ +/* -*- C++ -*- */ +// $Id$ + +/* Provides the server's single user lookup table abstraction. */ + +#ifndef _SL_SERVER_H +#define _SL_SERVER_H + +#include "Single_Lookup.h" + +class SL_Server : public Single_Lookup +{ +public: + SL_Server (char *packet); + virtual Protocol_Record *insert (char *key_name, int max_len = MAXUSERIDNAMELEN); + virtual Protocol_Record *get_each_entry (void); +}; + +#ifdef __OPTIMIZE__ +inline +SL_Server::SL_Server (char *usr_name): Single_Lookup (usr_name) +{} + +inline Protocol_Record * +SL_Server::get_each_entry (void) +{ + Protocol_Record *frp = Single_Lookup::get_each_entry (); + return frp->get_drwho_list () == 0 ? 0 : frp; +} + +inline Protocol_Record * +SL_Server::insert (char *key_name, int max_len) +{ + return strncmp (key_name, this->frp->get_login (), max_len) == 0 ? this->frp : 0; +} +#endif /* __OPTIMIZE__ */ +#endif /* _SL_SERVER_H */ diff --git a/apps/drwho/SML_Client.cpp b/apps/drwho/SML_Client.cpp new file mode 100644 index 00000000000..b097064e156 --- /dev/null +++ b/apps/drwho/SML_Client.cpp @@ -0,0 +1,35 @@ +// $Id$ +#include "Options.h" +#include "SML_Client.h" + +int +SML_Client::receive (int) +{ + if (sml_server.mux (this->recv_packet, this->packet_length) < 0) + return -1; + + if (this->demux (this->recv_packet, this->packet_length) < 0) + return -1; + + return 1; +} + +int +SML_Client::send (void) +{ + if (this->mux (this->send_packet, this->packet_length) < 0) + return -1; + + if (sml_server.demux (this->send_packet, this->packet_length) < 0) + return -1; + + return 1; +} + +#ifndef __OPTIMIZE__ +SML_Client::SML_Client (void) +{} + +SML_Client::~SML_Client (void) +{} +#endif /* __OPTIMIZE__ */ diff --git a/apps/drwho/SML_Client.h b/apps/drwho/SML_Client.h new file mode 100644 index 00000000000..462310b99a8 --- /dev/null +++ b/apps/drwho/SML_Client.h @@ -0,0 +1,32 @@ +/* -*- C++ -*- */ +// $Id$ + +#ifndef _SML_CLIENT_H +#define _SML_CLIENT_H + +#include "SM_Client.h" +#include "SML_Server.h" + +class SML_Client : public SM_Client +{ +private: + SML_Server sml_server; + int packet_length; + +public: + SML_Client (void); + virtual ~SML_Client (void); + virtual int receive (int timeout = 0); + virtual int send (void); +}; + +#ifdef __OPTIMIZE__ +inline +SML_Client::SML_Client (void) +{} + +inline +SML_Client::~SML_Client (void) +{} +#endif /* __OPTIMIZE__ */ +#endif /* _SML_CLIENT_H */ diff --git a/apps/drwho/SML_Server.cpp b/apps/drwho/SML_Server.cpp new file mode 100644 index 00000000000..e1ddcb83990 --- /dev/null +++ b/apps/drwho/SML_Server.cpp @@ -0,0 +1,10 @@ +// $Id$ +#include "SML_Server.h" + +#ifndef __OPTIMIZE__ +SML_Server::SML_Server (void) +{} + +SML_Server::~SML_Server (void) +{} +#endif /* __OPTIMIZE__ */ diff --git a/apps/drwho/SML_Server.h b/apps/drwho/SML_Server.h new file mode 100644 index 00000000000..b5ab3474a80 --- /dev/null +++ b/apps/drwho/SML_Server.h @@ -0,0 +1,25 @@ +/* -*- C++ -*- */ +// $Id$ + +#ifndef _SML_SERVER_H +#define _SML_SERVER_H + +#include "SM_Server.h" + +class SML_Server : public SM_Server +{ +public: + SML_Server (void); + virtual ~SML_Server (void); +}; + +#ifdef __OPTIMIZE__ +inline +SML_Server::SML_Server (void) +{} + +inline +SML_Server::~SML_Server (void) +{} +#endif /* __OPTIMIZE__ */ +#endif /* _SML_SERVER_H */ diff --git a/apps/drwho/SMR_Client.cpp b/apps/drwho/SMR_Client.cpp new file mode 100644 index 00000000000..cd3d97717d5 --- /dev/null +++ b/apps/drwho/SMR_Client.cpp @@ -0,0 +1,19 @@ +// $Id$ +#include "Options.h" +#include "new.h" +#include "PMC_All.h" +#include "PMC_Flo.h" +#include "PMC_Usr.h" +#include "PMC_Ruser.h" +#include "SMR_Client.h" + +#ifndef __OPTIMIZE__ +SMR_Client::SMR_Client (short port_number) +{ + if (CM_Client::open (port_number) < 0) + perror (Options::program_name), exit (1); +} + +SMR_Client::~SMR_Client (void) +{} +#endif /* __OPTIMIZE__ */ diff --git a/apps/drwho/SMR_Client.h b/apps/drwho/SMR_Client.h new file mode 100644 index 00000000000..11a8b7cbf9b --- /dev/null +++ b/apps/drwho/SMR_Client.h @@ -0,0 +1,28 @@ +/* -*- C++ -*- */ +// $Id$ + +#ifndef _SMR_CLIENT_H +#define _SMR_CLIENT_H + +#include "SM_Client.h" + +class SMR_Client : public SM_Client +{ +public: + SMR_Client (short port_number); + virtual ~SMR_Client (void); +}; + +#ifdef __OPTIMIZE__ +inline +SMR_Client::SMR_Client (short port_number) +{ + if (CM_Client::open (port_number) < 0) + perror (Options::program_name), exit (1); +} + +inline +SMR_Client::~SMR_Client (void) +{} +#endif /* __OPTIMIZE__ */ +#endif /* _SMR_CLIENT_H */ diff --git a/apps/drwho/SMR_Server.cpp b/apps/drwho/SMR_Server.cpp new file mode 100644 index 00000000000..0c43d480b86 --- /dev/null +++ b/apps/drwho/SMR_Server.cpp @@ -0,0 +1,14 @@ +// $Id$ +#include "Options.h" +#include "SMR_Server.h" + +#ifndef __OPTIMIZE__ +SMR_Server::SMR_Server (short port_number) +{ + if (CM_Server::open (port_number) < 0) + perror (Options::program_name), exit (1); +} + +SMR_Server::~SMR_Server (void) +{} +#endif /* __OPTIMIZE__ */ diff --git a/apps/drwho/SMR_Server.h b/apps/drwho/SMR_Server.h new file mode 100644 index 00000000000..29c4281af7d --- /dev/null +++ b/apps/drwho/SMR_Server.h @@ -0,0 +1,28 @@ +/* -*- C++ -*- */ +// $Id$ + +#ifndef _SMR_SERVER_H +#define _SMR_SERVER_H + +#include "SM_Server.h" + +class SMR_Server : public SM_Server +{ +public: + SMR_Server (short port_number); + ~SMR_Server (void); +}; + +#ifdef __OPTIMIZE__ +inline +SMR_Server::SMR_Server (short port_number) +{ + if (CM_Server::open (port_number) < 0) + perror (Options::program_name), exit (1); +} + +inline +SMR_Server::~SMR_Server (void) +{} +#endif /* __OPTIMIZE__ */ +#endif /* _SMR_SERVER_H */ diff --git a/apps/drwho/SM_Client.cpp b/apps/drwho/SM_Client.cpp new file mode 100644 index 00000000000..074684076c0 --- /dev/null +++ b/apps/drwho/SM_Client.cpp @@ -0,0 +1,61 @@ +// $Id$ +#include "Options.h" +#include "new.h" +#include "PMC_All.h" +#include "PMC_Flo.h" +#include "PMC_Usr.h" +#include "PMC_Ruser.h" +#include "SM_Client.h" + +/* Call-back function that invokes the appropriate decode function. */ + +int +SM_Client::demux (char *packet, int &packet_length) +{ + if (this->pm_client->decode (packet, packet_length) < 0) + return -1; + return 1; +} + +/* Call-back function that invokes the appropriate encode function. */ + +int +SM_Client::mux (char *packet, int &packet_length) +{ + switch (Options::protocol_type) + { + case Options::PROTO_USR: + this->pm_client = new (PRIVATE_POOL) PMC_Usr (Options::user_name); + break; + case Options::PROTO_ALL: + this->pm_client = new (PRIVATE_POOL) PMC_All; + break; + case Options::PROTO_FLO: + this->pm_client = new (PRIVATE_POOL) PMC_Flo; + break; + case Options::PROTO_RUSER: + this->pm_client = new (PRIVATE_POOL) PMC_Ruser; + break; + default: + fprintf (stderr, "%s: bad protocol\n", Options::program_name); + return -1; + } + + if (this->pm_client->encode (packet, packet_length) < 0) + return -1; + return 1; +} + +#ifndef __OPTIMIZE__ +SM_Client::SM_Client (void) +{} + +SM_Client::~SM_Client (void) +{} + +void +SM_Client::process (void) +{ + this->pm_client->process (); +} +#endif /* __OPTIMIZE__ */ diff --git a/apps/drwho/SM_Client.h b/apps/drwho/SM_Client.h new file mode 100644 index 00000000000..3c33f3bd45e --- /dev/null +++ b/apps/drwho/SM_Client.h @@ -0,0 +1,39 @@ +/* -*- C++ -*- */ +// $Id$ + +#ifndef _SM_CLIENT_H +#define _SM_CLIENT_H + +#include "PM_Client.h" +#include "CM_Client.h" +#include "Select_Manager.h" + +class SM_Client : public Select_Manager, public CM_Client +{ +private: + PM_Client *pm_client; + +public: + SM_Client (void); + virtual int mux (char *packet, int &packet_length); + virtual int demux (char *packet, int &packet_length); + virtual void process (void); + virtual ~SM_Client (void); +}; + +#ifdef __OPTIMIZE__ +inline +SM_Client::SM_Client (void) +{} + +inline +SM_Client::~SM_Client (void) +{} + +inline void +SM_Client::process (void) +{ + this->pm_client->process (); +} +#endif /* __OPTIMIZE__ */ +#endif /* _SM_CLIENT_H */ diff --git a/apps/drwho/SM_Server.cpp b/apps/drwho/SM_Server.cpp new file mode 100644 index 00000000000..8709f6132d4 --- /dev/null +++ b/apps/drwho/SM_Server.cpp @@ -0,0 +1,59 @@ +// $Id$ +#include "new.h" +#include "Options.h" +#include "PMS_All.h" +#include "PMS_Flo.h" +#include "PMS_Usr.h" +#include "PMS_Ruser.h" +#include "SM_Server.h" + +int +SM_Server::demux (char *packet, int &packet_length) +{ + /* SUPPRESS 112 */ + switch (GET_PACKET_TYPE (packet)) + { + case Options::PROTO_USR: + this->pm_server = new (PRIVATE_POOL) PMS_Usr; + break; + case Options::PROTO_ALL: + this->pm_server = new (PRIVATE_POOL) PMS_All; + break; + case Options::PROTO_FLO: + this->pm_server = new (PRIVATE_POOL) PMS_Flo; + break; + case Options::PROTO_RUSER: + this->pm_server = new (PRIVATE_POOL) PMS_Ruser; + break; + default: + return -1; + } + + if (pm_server->decode (SKIP_PACKET_TYPE (packet), SUBTRACT_PACKET_TYPE (packet_length)) < 0) + return -1; + + if (pm_server->process () < 0) + return -1; + + return 1; +} + +int +SM_Server::mux (char *packet, int &packet_length) +{ + int status = pm_server->encode (packet, packet_length); + + /* Hum... should this really go here? */ + if (Options::get_opt (Options::STAND_ALONE_SERVER)) + release_memory (); + return status; +} + +#ifndef __OPTIMIZE__ +SM_Server::SM_Server (void) +{} + +SM_Server::~SM_Server (void) +{} +#endif /* __OPTIMIZE__ */ + diff --git a/apps/drwho/SM_Server.h b/apps/drwho/SM_Server.h new file mode 100644 index 00000000000..fbad338adf9 --- /dev/null +++ b/apps/drwho/SM_Server.h @@ -0,0 +1,32 @@ +/* -*- C++ -*- */ +// $Id$ + +#ifndef _SM_SERVER_H +#define _SM_SERVER_H + +#include "PM_Server.h" +#include "CM_Server.h" +#include "Select_Manager.h" + +class SM_Server : public Select_Manager, public CM_Server +{ +private: + PM_Server *pm_server; + +public: + SM_Server (void); + virtual ~SM_Server (void); + virtual int mux (char *packet, int &packet_length); + virtual int demux (char *packet, int &packet_length); +}; + +#ifdef __OPTIMIZE__ +inline +SM_Server::SM_Server (void) +{} + +inline +SM_Server::~SM_Server (void) +{} +#endif /* __OPTIMIZE__ */ +#endif /* _SM_SERVER_H */ diff --git a/apps/drwho/Search_Struct.cpp b/apps/drwho/Search_Struct.cpp new file mode 100644 index 00000000000..eb1a52ba71e --- /dev/null +++ b/apps/drwho/Search_Struct.cpp @@ -0,0 +1,20 @@ +// $Id$ +#include "Options.h" +#include "Search_Struct.h" + +#ifndef __OPTIMIZE__ +Search_Struct::~Search_Struct (void) +{ + if (Options::get_opt (Options::DEBUG)) + fprintf (stderr, "disposing Search_Struct\n"); +} + +Search_Struct::Search_Struct (void): count (0) +{} + +int +Search_Struct::n_elems (void) +{ + return this->count; +} +#endif /* __OPTIMIZE__ */ diff --git a/apps/drwho/Search_Struct.h b/apps/drwho/Search_Struct.h new file mode 100644 index 00000000000..e8f8e6b0a48 --- /dev/null +++ b/apps/drwho/Search_Struct.h @@ -0,0 +1,42 @@ +/* -*- C++ -*- */ +// $Id$ + +/* Provides an "Abstract Base Class" lookup table abstraction that + stores and manipulates friend records. */ + +#ifndef _SEARCH_STRUCT_H +#define _SEARCH_STRUCT_H + +#include "Protocol_Record.h" + +class Search_Struct +{ +protected: + int count; + +public: + Search_Struct (void); + virtual ~Search_Struct (void); + virtual int n_elems (void); + + virtual Protocol_Record *insert (char *key_name, int max_len = MAXUSERIDNAMELEN) = 0; + virtual Protocol_Record *get_next_entry (void) = 0; + virtual Protocol_Record *get_each_entry (void) = 0; +}; + +#ifdef __OPTIMIZE__ +inline +Search_Struct::~Search_Struct (void) +{} + +inline +Search_Struct::Search_Struct (void): count (0) +{} + +inline int +Search_Struct::n_elems (void) +{ + return this->count; +} +#endif /* __OPTIMIZE__ */ +#endif /* _SEARCH_STRUCT_H */ diff --git a/apps/drwho/Select_Manager.h b/apps/drwho/Select_Manager.h new file mode 100644 index 00000000000..0c06d47dc3f --- /dev/null +++ b/apps/drwho/Select_Manager.h @@ -0,0 +1,12 @@ +// $Id$ +/* -*- C++ -*- */ +#ifndef _SELECT_MANAGER_H +#define _SELECT_MANAGER_H + +class Select_Manager +{ +public: + virtual int mux (char *packet, int &packet_length) = 0 ; + virtual int demux (char *packet, int &packet_length) = 0; +}; +#endif /* _SELECT_MANAGER_H */ diff --git a/apps/drwho/Single_Lookup.cpp b/apps/drwho/Single_Lookup.cpp new file mode 100644 index 00000000000..55751170bc9 --- /dev/null +++ b/apps/drwho/Single_Lookup.cpp @@ -0,0 +1,29 @@ +// $Id$ +#include "Options.h" +#include "new.h" +#include "Single_Lookup.h" + +#ifndef __OPTIMIZE__ +Single_Lookup::Single_Lookup (char *usr_name) +{ + this->frp = new (PRIVATE_POOL) Protocol_Record (ACE::strnew (usr_name)); +} + +Single_Lookup::~Single_Lookup (void) +{ + if (Options::get_opt (Options::DEBUG)) + fprintf (stderr, "disposing Single_Lookup\n"); +} + +Protocol_Record * +Single_Lookup::get_each_entry (void) +{ + return this->frp; +} + +Protocol_Record * +Single_Lookup::get_next_entry (void) +{ + return this->get_each_entry (); +} +#endif /* __OPTIMIZE__ */ diff --git a/apps/drwho/Single_Lookup.h b/apps/drwho/Single_Lookup.h new file mode 100644 index 00000000000..e114b172656 --- /dev/null +++ b/apps/drwho/Single_Lookup.h @@ -0,0 +1,51 @@ +/* -*- C++ -*- */ +// $Id$ + +/* Provides the client's single user lookup table abstraction. */ + +#ifndef _SINGLE_LOOKUP_H +#define _SINGLE_LOOKUP_H + +#include "Options.h" +#include "Search_Struct.h" + +class Single_Lookup : public Search_Struct +{ +protected: + Protocol_Record *frp; + +public: + Single_Lookup (char *usr_name); + virtual ~Single_Lookup (void); + virtual Protocol_Record *insert (char *key_name, int max_len = MAXUSERIDNAMELEN) = 0; + virtual Protocol_Record *get_next_entry (void); + virtual Protocol_Record *get_each_entry (void); +}; + +#ifdef __OPTIMIZE__ +inline +Single_Lookup::Single_Lookup (char *usr_name) +{ + this->frp = new Protocol_Record (ACE::strnew (usr_name)); +} + +inline +Single_Lookup::~Single_Lookup (void) +{ + if (Options::DEBUG) + fprintf (stderr, "disposing Single_Lookup\n"); +} + +inline Protocol_Record * +Single_Lookup::get_each_entry (void) +{ + return this->frp; +} + +inline Protocol_Record * +Single_Lookup::get_next_entry (void) +{ + return this->get_each_entry (); +} +#endif /* __OPTIMIZE__ */ +#endif /* _SINGLE_LOOKUP_H */ diff --git a/apps/drwho/client.cpp b/apps/drwho/client.cpp new file mode 100644 index 00000000000..f1b51483a1e --- /dev/null +++ b/apps/drwho/client.cpp @@ -0,0 +1,61 @@ +// $Id$ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// drwho +// +// = FILENAME +// client.cpp +// +// = DESCRIPTION +// Client driver program for drwho. +// +// = AUTHOR +// Douglas C. Schmidt +// +// ============================================================================ + +#include "ace/OS.h" +#include "Options.h" +#include "new.h" +#include "SML_Client.h" +#include "SMR_Client.h" + +// Factory function. + +static SM_Client * +make_client (void) +{ + if (Options::get_opt (Options::REMOTE_USAGE) == 0) + return new (PRIVATE_POOL) SML_Client; + else + return new (PRIVATE_POOL) SMR_Client (Options::port_number); +} + +int +main (int argc, char *argv[]) +{ + Options::set_options (argc, argv); + + mark_memory (); + + SM_Client *sm_client = make_client (); + + if (sm_client->send () < 0) + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n", + Options::program_name), + -1); + + if (sm_client->receive (Options::max_server_timeout) < 0) + ACE_ERROR_RETURN ((LM_ERROR, + "%p\n", + Options::program_name), + -1); + + sm_client->process (); + + return 0; +} diff --git a/apps/drwho/global.h b/apps/drwho/global.h new file mode 100644 index 00000000000..0352ca36e31 --- /dev/null +++ b/apps/drwho/global.h @@ -0,0 +1,35 @@ +/* -*- C++ -*- */ +// $Id$ + +/* Here are all the declarations that are needed throughout the program. */ + +#ifndef _GLOBAL_H +#define _GLOBAL_H + +/* These constants are used throughout the program... */ + +enum +{ + MAXUSERIDNAMELEN = 8, + MAX_USER_TIMEOUT = 300, + MAX_HOST_TIMEOUT = 300, +#ifdef i386 + UDP_PACKET_SIZE = 0x2000, +#else + UDP_PACKET_SIZE = 0x4000, +#endif + PORT_NUMBER = 12344 +/* MAXPATHLEN = 1024, + MAXHOSTNAMELEN = 64 + 1 */ +}; + +/* Default name of file where friends info is stored. */ +#define FRIEND_FILE ".friends.dta" + +/* Default name where rwho info is stored. */ +#define RWHODIR "/usr/spool/rwho" + +/* Daemon creator. */ +extern void daemon_start (int ignsigcld); + +#endif /* _GLOBAL_H */ diff --git a/apps/drwho/new.cpp b/apps/drwho/new.cpp new file mode 100644 index 00000000000..eb0668290d1 --- /dev/null +++ b/apps/drwho/new.cpp @@ -0,0 +1,215 @@ +// $Id$ +/* Provide a very fast dynamic memory management abstraction tuned for + drwho server characteristics. */ + +#include "assert.h" +#include "ace/OS.h" +#include "Options.h" +#include "new.h" + +#if 0 +/* Determine default alignment. If your C++ compiler does not + like this then try something like #define ALIGNMENT 8. */ + +struct fooalign {char x; double d;}; + +static int ALIGNMENT = ((char *)&((struct fooalign *) 0)->d - (char *)0); +static int PAGE_SIZE = getpagesize (); +#endif + +static const int ALIGNMENT = 8; +static const int PAGE_SIZE = 4096; +static const int debug = 1; +static int use_pool = 0; + +static inline int +max (int a, int b) +{ + return a >= b ? a : b; +} + +/* The ALIGNMENT argument must be a power of two... */ + +static inline int +round (size_t size, int alignment) +{ + return size + alignment - 1 & ~(alignment - 1); +} + +class Chunk_Manager +{ +private: + struct Chunk + { + Chunk *next; + char *buf_cur; + char *buf_end; + int buf_size; + char buf_start[1]; + + int chunk_must_grow (size_t size); + void *get_n_bytes (size_t size); + int chunk_size (void); + void print_stats (int); + }; + + static void insert_free_chunk (Chunk *ptr); + static Chunk *check_free_list (size_t size); + static Chunk *make_new_chunk (size_t size, Chunk *next = 0); + static Chunk *free_list; + static Chunk *head; + static size_t default_chunk_size; + +public: + static void *alloc_bytes (size_t size); + static void release_chunks (void); +}; + +size_t Chunk_Manager::default_chunk_size = 4 * PAGE_SIZE; +Chunk_Manager::Chunk *Chunk_Manager::free_list = 0; +Chunk_Manager::Chunk *Chunk_Manager::head = 0; + +void +#if defined (__GNUG__) || defined (SunOS5) +Chunk_Manager::Chunk::print_stats (int size) +#else +Chunk::print_stats (int size) +#endif +{ + fprintf (stderr, "buf_size = %d, bytes left = %d, bytes used = %d, bytes requested = %d\n", + this->buf_size, this->buf_end - this->buf_cur, this->buf_cur - this->buf_start, size); +} + +int +#if defined (__GNUG__) || defined (SunOS5) +Chunk_Manager::Chunk::chunk_must_grow (size_t size) +#else +Chunk::chunk_must_grow (size_t size) +#endif +{ + return this->buf_end - this->buf_cur < size; +} + +void * +#if defined (__GNUG__) || defined (SunOS5) +Chunk_Manager::Chunk::get_n_bytes (size_t size) +#else +Chunk::get_n_bytes (size_t size) +#endif +{ + void *temp = this->buf_cur; + this->buf_cur += size; + return temp; +} + +int +#if defined (__GNUG__) || defined (SunOS5) +Chunk_Manager::Chunk::chunk_size (void) +#else +Chunk::chunk_size (void) +#endif +{ + return this->buf_size; +} + +void +Chunk_Manager::insert_free_chunk (Chunk *ptr) +{ + for (Chunk **flpp = &Chunk_Manager::free_list; (*flpp) != 0 && (*flpp)->buf_size < ptr->buf_size; flpp = &(*flpp)->next) + ; + + ptr->next = *flpp; + *flpp = ptr; +} + +Chunk_Manager::Chunk * +Chunk_Manager::check_free_list (size_t size) +{ + + for (Chunk **flpp = &Chunk_Manager::free_list; (*flpp) != 0 && (*flpp)->buf_size < size; flpp = &(*flpp)->next) + ; + + if (*flpp == 0) + return 0; + else + { + Chunk *flp = *flpp; + *flpp = (*flpp)->next; + return flp; + } +} + +void +Chunk_Manager::release_chunks (void) +{ + Chunk *tmp = Chunk_Manager::head; + + while (tmp != 0) + { + Chunk *t = tmp; + tmp = tmp->next; + insert_free_chunk (t); + } + + Chunk_Manager::head = 0; +} + +Chunk_Manager::Chunk * +Chunk_Manager::make_new_chunk (size_t size, Chunk *n) +{ + Chunk *free_chunk = Chunk_Manager::check_free_list (size = round (size, Chunk_Manager::default_chunk_size)); + + if (free_chunk == 0) + { + if ((free_chunk = (Chunk *) malloc (sizeof *free_chunk + size)) == 0) + return 0; + + free_chunk->buf_size = size; + free_chunk->buf_end = free_chunk->buf_start + free_chunk->buf_size; + } + free_chunk->buf_cur = free_chunk->buf_start; + free_chunk->next = n; + return free_chunk; +} + +void * +Chunk_Manager::alloc_bytes (size_t size) +{ + size = round (size, ALIGNMENT); + + if (Chunk_Manager::head == 0) + Chunk_Manager::head = Chunk_Manager::make_new_chunk (size); + else if (Chunk_Manager::head->chunk_must_grow (size)) + Chunk_Manager::head = Chunk_Manager::make_new_chunk (max (Chunk_Manager::head->chunk_size () * 2, size), Chunk_Manager::head); + +// Chunk_Manager::head->print_stats (size); + + return Chunk_Manager::head->get_n_bytes (size); +} + +void * +operator new (size_t size, New_Pool new_pool) +{ + if (::use_pool || new_pool == PRIVATE_POOL) + return Chunk_Manager::alloc_bytes (size); + else + return (void *) malloc (size); +} +void +mark_memory (int start_using_the_pool) +{ + ::use_pool = start_using_the_pool; +} + +void +release_memory (void) +{ + Chunk_Manager::release_chunks (); +} + +/* We need this deletion operator in order to make the linker happy. */ + +void +operator delete (void *) +{ +} diff --git a/apps/drwho/new.h b/apps/drwho/new.h new file mode 100644 index 00000000000..6ad5eb11442 --- /dev/null +++ b/apps/drwho/new.h @@ -0,0 +1,27 @@ +/* -*- C++ -*- */ +// $Id$ + +/* Provides a fast, fixed-sized pool of memory. */ + +#ifndef _NEW_H +#define _NEW_H + +#include <stddef.h> + +enum New_Pool +{ + MALLOC_POOL = 1, + PRIVATE_POOL = 2 +}; + +void *operator new (size_t size, New_Pool new_pool); + +void operator delete (void *); + +/* Release all the memory... */ +void release_memory (void); + +/* Set the mark for future memory allocation... */ +void mark_memory (int start_using_the_pool = 1); + +#endif /* _NEW_H */ diff --git a/apps/drwho/rwhod.h b/apps/drwho/rwhod.h new file mode 100644 index 00000000000..d884f5cd27a --- /dev/null +++ b/apps/drwho/rwhod.h @@ -0,0 +1,38 @@ +/* -*- C++ -*- */ +// $Id$ + +/* The /usr/include/protocols/rwhod.h header breaks cfront 2.0... */ + +#ifndef _RWHOD_H +#define _RWHOD_H + +struct outmp +{ + char out_line[8]; /* tty name */ + char out_name[8]; /* user id */ + long out_time; /* time on */ +}; + +struct whoent +{ + outmp we_utmp; /* active tty info */ + int we_idle; /* tty idle time */ +}; + +struct whod +{ + char wd_vers; /* protocol version # */ + char wd_type; /* packet type, see below */ + char wd_pad[2]; + int wd_sendtime; /* time stamp by sender */ + int wd_recvtime; /* time stamp applied by receiver */ + char wd_hostname[32]; /* hosts's name */ + int wd_loadav[3]; /* load average as in uptime */ + int wd_boottime; /* time system booted */ + whoent wd_we[1024 / sizeof (struct whoent)]; +}; + +#define WHODVERSION 1 +#define WHODTYPE_STATUS 1 /* host status */ + +#endif /* _RWHOD_H */ diff --git a/apps/drwho/server.cpp b/apps/drwho/server.cpp new file mode 100644 index 00000000000..3ae1adb6919 --- /dev/null +++ b/apps/drwho/server.cpp @@ -0,0 +1,96 @@ +// $Id$ +/* Driver program for the server. Note that it is easy to reuse the + server for other distributed programs. Pretty much all that must + change are the functions registered with the communciations + manager. */ + +#include "ace/OS.h" +#include "Options.h" +#include "new.h" +#include "SMR_Server.h" + +static char * +tstamp (void) +{ + long time_now; + char *temp; + + time_now = time (0); + temp = asctime (localtime (&time_now)); + temp[12] = 0; + return temp; +} + +/* Catch the obvious signals and die with dignity... */ + +static void +exit_server (int sig) +{ + char buffer[80]; + sprintf (buffer, "%s exiting on signal", tstamp ()); + psignal (sig, buffer); + monitor (0); + exit (0); +} + +/* Returns TRUE if the program was started by INETD. */ + +static int +started_by_inetd (void) +{ + /* SUPPRESS 175 */ + sockaddr_in sin; + int size = sizeof sin; + + return getsockname (0, (sockaddr *) &sin, &size) == 0; +} + +/* Does the drwho service. */ + +static void +do_drwho (SMR_Server &smr_server) +{ + if (smr_server.receive () == -1) + perror (Options::program_name); + + if (smr_server.send () == -1) + perror (Options::program_name); +} + +/* If the server is started with any argument at all then it doesn't + fork off a child process to do the work. This is useful when + debugging! */ + +int +main (int argc, char *argv[]) +{ + signal (SIGTERM, SIG_PF (exit_server)); + signal (SIGINT, SIG_PF (exit_server)); + signal (SIGQUIT, SIG_PF (exit_server)); + + Options::set_options (argc, argv); + Options::set_opt (Options::STAND_ALONE_SERVER); + + int inetd_controlled = started_by_inetd (); + + if (!inetd_controlled && Options::get_opt (Options::BE_A_DAEMON)) + daemon_start (1); + + mark_memory (); + + SMR_Server smr_server (Options::port_number); + + /* I'm not sure what this should do yet... */ + + if (inetd_controlled) + do_drwho (smr_server); + else + { + + for (;;) + do_drwho (smr_server); + + /* NOTREACHED */ + } + exit (0); +} |