_INSIDE THE SYSTEM LIBRARY_ by Michael J. Vilot Listing One rionb04p30.unisys.com.br - - [22/Mar/1996:18:12:46 -0500] "GET /ooad.html HTTP/1.0" 200 2006 "http://www.objects.destek.com/" "Mozilla/1.22 (Windows; I; 16bit)" Listing Two #include #include #include // should be #include // for map<>, pair<>, make_pair() #include typedef pair Pairtype; typedef set > Settype; typedef map > Maptype; static Maptype m; // shared by input() and output() static Pairtype parse(istream& file, unsigned long& line); static string empty; // returned as "browser" @ eof unsigned long input(istream& file) throw(unsigned long) { unsigned long line = 1; while (file && !file.eof()) { Pairtype p = parse(file,line); string& browser = p.first; string& site = p.second; if (browser != empty) { Settype& set = m[browser]; set.insert(site); } } if ( !file.eof() ) throw line; return line; } static void quoted_string(istream&, unsigned long); static char buffer[512]; // shared static Pairtype parse(istream& file, unsigned long& line) { string site; file >> site; // 1st field if (file.eof()) return make_pair(empty,site); // ignore through date (4th field) file.getline(buffer, sizeof buffer, ']'); // ignore command (5th field) quoted_string(file, line); // ignore 6th & 7th fields int n1; file >> n1 >> buffer; // ignore referrer URL (8th field) quoted_string(file, line); // get browser info (9th/last field) file.getline(buffer, sizeof buffer); ++line; string browser(buffer); return make_pair(browser, site); } static void quoted_string(istream& file, unsigned long line) { char x = ' '; file >> ws; // skip whitespace file.get(x); if (x != '"') throw line; file.get(buffer, sizeof buffer, '"'); file.get(x); if (x != '"') throw line; } void output(ostream& out) { out << "Browsers (and their sites): " << endl; out.flags( out.flags() | ios::left ); Maptype::iterator it; for (it = m.begin(); it != m.end(); ++it) { out << (*it).first << endl; Settype& set = (*it).second; Settype::iterator i2; for (i2 = set.begin(); i2 != set.end(); ++i2) { out << '\t' << *i2 << endl; } } } Listing Three "Infoseek Robot 1.17" homer-bbn.infoseek.com homer.infoseek.com "Lycos Spider (Rex)/TEST v1.0 libwww/3.1" fourteen.srv.lycos.com qe20.lycos.com "Mozilla/1.1 (Windows; U; 32bit)" mail.jabil.com "Mozilla/1.1N (Macintosh; I; PPC)" box772.labs.cis.pitt.edu gate.cs.auckland.ac.nz ... "Mozilla/2.01 (X11; I; OSF1 V3.2 alpha)" picasso.idt-isep.ipp.pt "Mozilla/2.0GoldB1 (Win95; I)" 206.15.181.148 ad05-103.compuserve.com barredu207.k12.vt.us dd35-188.compuserve.com fairisaac.com hd63-109.compuserve.com ... Listing Four (Connect to site on "well known" port # 119, using TCP/IP) 200 quartz.mv.com NNTP[auth] server version 1.5.12.1 ready (posting ok). list active 215 Newsgroups in form "group high low flags". ... . (final output line) quit Listing Five #include #include // for priority_queue #include // should be simply #include #include #include // for os_event typedef priority_queue< deque< string >, greater< string > > Qtype; static void open(iostream&) throw(const char*); static void input(iostream&, Qtype&); static void output(Qtype&); int main(int argc, char *argv[]) // list active newsgroups { try { // Attach a socket to the NNTP server (well-known port #119) const char* name = (argc != 2) ? "news.mv.com" : argv[1]; os_socket_address nntp_server( os_ip_address(name), 119 ); // Create an input stream attached to the socket os_tcp_socket socket; socket.connect_to( nntp_server ); os_tstream stream( socket ); open(stream); // Check login, send list command // Create a priority_queue to sort the names Qtype queue; input(stream, queue); // Gather names stream << "quit" << endl; // Close connection output(queue); // Display the results } catch(os_event& ev) { cerr << "ObjectSpace exception: " << ev << endl; return 1; } catch(const char* msg) { cerr << "NNTP Server Error: " << msg << endl; return 1; } return 0; } static void open(iostream& stream) throw(const char*) { // Read login information static char buffer[256]; stream.getline( buffer, sizeof buffer ); if ( buffer[0] != '2' ) throw "NNTP not found on port"; // Send request to list active newsgroups stream << "list active" << endl; // Check status (200+) stream.getline( buffer, sizeof buffer ); if ( buffer[0] != '2' ) throw "list command failed"; } static void input(iostream& stream, Qtype& q) { unsigned long count = 0; while ( !stream.eof() ) { string s; stream >> s; // read 1st string (newsgroup) // Check for end of listing if (s[0] == '.') break; q.push(s); // save the result // Skip past remainder of line static char buffer[256]; stream.getline( buffer, sizeof buffer ); // Note progress ++count; if ( (count % 100) == 0 ) cout << "Read " << count << " so far." << endl; } } static void output(Qtype& q) { cout << "========== " << q.size() << " ACTIVE NEWSGROUPS ==========" << endl; while (q.size()) { cout << q.top() << endl; q.pop(); } cout << "=============================================" << endl; } Listing Six (connect_to news.mv.com) Read 100 so far. ... Read 7300 so far. Send: quit ========== 7394 ACTIVE NEWSGROUPS ========== alt.0d alt.1d alt.2600 alt.2600.hope.announce alt.2600.hope.d alt.2600.hope.tech alt.2600hz alt.3d ... t.unix vt.uucp vt.vtuug wash.general wash.politics wash.test wi.forsale wpi.clubs.hsa