135 lines
3.7 KiB
C++
135 lines
3.7 KiB
C++
// examples/inc_daemon.cc
|
|
// This file is part of libpbe; see http://decimail.org
|
|
// (C) 2004 Philip Endecott
|
|
|
|
// This program is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation; either version 2 of the License, or
|
|
// any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program; if not, write to the Free Software
|
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
// Demo program for Daemon class
|
|
|
|
// The Daemon class does the mucky stuff needed to implement a
|
|
// "daemon" (i.e. a server, e.g. imapd, httpd etc) process.
|
|
|
|
// You make a subclass of Daemon that:
|
|
// * Provides "void session(int in_fd, int out_fd)" that does the work.
|
|
// File descriptors for input and output to the connection are supplied.
|
|
// * Calls the Daemon base class constructor with port number, program
|
|
// name (used in syslog calls) and optional syslog "facility" code (see
|
|
// man syslog).
|
|
//
|
|
// Your main program then creates an instance of your Daemon subclass and
|
|
// invokes one of three run_*() methods, as shown below.
|
|
|
|
// This example implements a trivial "inc" daemon that reads a number
|
|
// from the user, increments it, and returns the incremented value.
|
|
|
|
|
|
// libpbe includes:
|
|
|
|
#include "Daemon.hh"
|
|
#include "Exception.hh"
|
|
|
|
// Standard includes:
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <iostream>
|
|
using namespace std;
|
|
|
|
|
|
// To demonstrate exception handling, if the user enters 666 this
|
|
// exception is thrown.
|
|
class NumberOfTheBeast: public Exception {
|
|
public:
|
|
void report(ostream& s) {
|
|
s << "The number of the beast!" << endl;
|
|
}
|
|
};
|
|
|
|
|
|
class IncDaemon: public Daemon {
|
|
|
|
public:
|
|
IncDaemon(void): Daemon(1705,"inc_daemon") {}
|
|
|
|
|
|
// Here is the session function that is called to handle a new
|
|
// connection. It is run in its own thread.
|
|
void session(int in_fd, int out_fd)
|
|
{
|
|
// I don't know how to make a C++ stream from a file descriptor.
|
|
FILE* inf = fdopen(in_fd,"r");
|
|
FILE* outf = fdopen(out_fd,"w");
|
|
|
|
fprintf(outf,"Please enter numbers to increment.\n");
|
|
int r=1;
|
|
// check for EOF is important - it indicates connection is closed
|
|
while(!feof(inf) && !ferror(inf) && !ferror(outf)) {
|
|
fprintf(outf,"> ");
|
|
fflush(outf);
|
|
int n;
|
|
r = fscanf(inf,"%d",&n);
|
|
if (r==0 || r==EOF) {
|
|
break;
|
|
}
|
|
if (n==666) {
|
|
throw NumberOfTheBeast();
|
|
}
|
|
fprintf(outf,"--->%d<---\n",n+1);
|
|
}
|
|
if (r==0) {
|
|
fprintf(outf,"fscanf() didn't get a number\n");
|
|
}
|
|
if (r==EOF) {
|
|
fprintf(outf,"fscanf() returned EOF\n");
|
|
}
|
|
if (feof(inf)) {
|
|
fprintf(outf,"EOF on input\n");
|
|
}
|
|
if (ferror(inf)) {
|
|
fprintf(outf,"Error on input(!)\n");
|
|
}
|
|
if (ferror(outf)) {
|
|
fprintf(outf,"Error on output(!)\n");
|
|
}
|
|
fflush(outf);
|
|
}
|
|
};
|
|
|
|
|
|
|
|
int main(int argc, char* argv[])
|
|
{
|
|
IncDaemon d;
|
|
if (argc==1) {
|
|
// Guess whether to run in interactive or daemon mode based on isatty(0)
|
|
d.run_default();
|
|
} else if (argc==2) {
|
|
string a(argv[1]);
|
|
if (a=="-i") {
|
|
// Run interactively, i.e. not a daemon at all
|
|
d.run_interactively();
|
|
} else if (a=="-d") {
|
|
// Run as a daemon
|
|
cout << "Daemon about to start. Telnet to port 1705." << endl;
|
|
d.run_as_daemon();
|
|
} else {
|
|
cerr << "Unrecognised option '" << a << "'" << endl;
|
|
exit(1);
|
|
}
|
|
} else {
|
|
cerr << "Too many options" << endl;
|
|
exit(1);
|
|
}
|
|
}
|