server/bed.cxx

Go to the documentation of this file.
00001 /**********************************************************************
00002  * Copyright 2002 Jeff Rush <jrush@taupro.com>
00003  * Original Copyright 1979-2002 Udanax.com
00004  *
00005  * This file is part of the Udanax xanalogical storage system.
00006  *
00007  * Udanax is free software; you can redistribute it and/or modify it
00008  * under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * Udanax is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with Udanax; if not, write to the Free Software Foundation,
00019  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  **********************************************************************/
00021 
00030 /* Modification History:
00031  * $Log: bed.cxx,v $
00032  * Revision 1.17  2004/09/11 15:02:00  jrush
00033  * Fixed Doxygen tags on all Session parameter arguments.
00034  *
00035  * Revision 1.16  2004/09/11 13:59:21  jrush
00036  * Changed all fprintf's to stderr to use the Nana library L() macro.  Also
00037  * removed a 2-3 minor compiler warnings.
00038  *
00039  * Revision 1.15  2004/09/04 16:02:18  jrush
00040  * Added Doxygen headers before each and every function definition.
00041  *
00042  * Revision 1.14  2004/08/28 13:35:26  jrush
00043  * Catching up CVS to various incomplete versions on local disk.
00044  *
00045  * Revision 1.13  2002/07/26 04:33:47  jrush
00046  * Replaced gerror() with assert()
00047  *
00048  * Revision 1.12  2002/05/28 03:58:42  jrush
00049  * Sources modified to comply with GPL licensing.
00050  *
00051  * Revision 1.11  2002/04/12 11:48:50  jrush
00052  * Major reorganization of includes into a single base-include style.
00053  *
00054  * Revision 1.10  2002/04/09 21:45:46  jrush
00055  * Renamed class 'tumbler' to 'Tumbler', for consistency with Python sources,
00056  * and changed typeisa from typedef to a subclass, in preparation for cleaning
00057  * up the type/class tree.
00058  *
00059  * Revision 1.9  2002/04/08 18:55:56  jrush
00060  * Switched from using global variable 'user' to object 'Session' as a
00061  * connection for tracking open document descriptors in the bert table.
00062  *
00063  * Revision 1.8  2002/04/06 19:51:30  jrush
00064  * Renamed TRUE/FALSE constant use to the C++ standard of true/false.
00065  *
00066  * Revision 1.7  2002/04/06 17:05:57  jrush
00067  * Switched from referring to 'task' for a client connection to 'session',
00068  * and converted the typetask typedef/struct into a Session C++ class.
00069  *
00070  * Revision 1.6  2002/04/06 15:01:44  jrush
00071  * Changed INT to just 'int'.
00072  *
00073  * Revision 1.5  2002/04/02 17:43:10  jrush
00074  * Fixed select() and FD_SET to work with Gnu C under Linux; added debugging
00075  * msgs, some cosmetic cleanup.
00076  *
00077  * Revision 1.4  2002/02/14 10:08:25  jrush
00078  * Cleaned up source:
00079  *
00080  * 1. ran thru the indent tool to achieve a standard look,
00081  * 2. added structured comments at top for use with DOxygen reporting
00082  *    as well as CVS keywords,
00083  * 3. centralized prototypes in protos.h, removing incomplete ones,
00084  * 4. cleaned up use of bool/BOOLEAN type to suit C++ type,
00085  * 5. fixed initializer nesting in tumbler constants,
00086  * 6. converted select() int bits into ANSI fd_set type,
00087  * 7. added Makefile.am for use by automake.
00088  *
00089  */
00090 
00091 int backenddaemon;       /* backend version */
00092 
00093 #include <errno.h>
00094 #include <setjmp.h>                    /* an easy way to deal with unexpected EOF on frontend input */
00095 #include <stdlib.h>
00096 #include <signal.h>
00097 #include <sys/time.h>                  /* includes <time.h> */
00098 #ifndef sun
00099 #include <time.h>
00100 #endif                                 /* sun */
00101 #include "udanax.h"
00102 #include "players.h"
00103 #include "requests.h"
00104 
00105 jmp_buf frontendeof;
00106 
00107 int user = 0;   /* Global current user ID */
00108 
00109 extern int             errno;
00110        FILE           *logfile;
00111        FILE           *nulllog;
00112        FILE           *reallog;
00113        char            outputbuffer[BUFSIZ];
00114        char            inputbuffer[BUFSIZ];
00115        bool            logstuff;
00116        FILE           *interfaceinput;
00117 extern FILE           *febelog;
00118        struct timeval  timeout;
00119 extern int             main_socket;
00120 static Tumbler         currentaccount;
00121        bool            quitafteruser = false;
00122        bool            mightbeblocked = false;
00123 
00124 extern bool getrequest(Session *sess, typerequest *requestptr);
00125 extern void sendresultoutput(Session * session);
00126 extern void xuputstring(char *string, FILE * fd);
00127 extern void processrcfile();
00128 extern void crash(int /*sigarg*/);
00129 extern void leave(PLAYER player[], int * xn_players);
00130 extern int  open_sock();
00131 extern void new_players(PLAYER player[], int * n_playersp, int block, Session * sess);
00132 extern void logaccount(Tumbler * tp);
00133 
00141     void
00142 xanadu(
00143     Session *sess)    
00144 {
00145     L("Entering xanadu()\n");
00146 
00147     typerequest request;
00148 
00149     logstuff = false;
00150     if (setjmp(frontendeof)) {
00151         closeberts(sess);
00152         player[user].wantsout = true;
00153 
00154     } else if (getrequest(sess, &request)) {
00155 
00156         (*requestfns[request]) (sess);
00157         sendresultoutput(sess);
00158 
00159         if (request == QUIT)
00160             player[user].wantsout = true;
00161     }
00162 
00163     sess->free();
00164 
00165     if (interfaceinput && interfaceinput != nulllog)
00166         fflush(interfaceinput);
00167 
00168     logstuff = false;
00169     L("Leaving xanadu()\n");
00170 }
00171 
00179     void
00180 flagquitting(
00181     int /*sigarg*/)
00182 {
00183     signal(SIGINT, SIG_IGN);           /* Don't die too early */
00184     if (mightbeblocked) {
00185         if (interfaceinput) {
00186             fprintf(interfaceinput, "%d~\n", QUIT);
00187             fclose(interfaceinput);
00188         }
00189         writeenfilades();
00190         closediskfile();
00191         exit(0);
00192     } else
00193         quitafteruser = true;          /* Flag to stop backend after current request */
00194 }
00195 
00203     int
00204 main(
00205     int   argc,
00206     char *argv[])
00207 {                                      /* inside temporary */
00208     Session sess;    
00209     char buf[100];
00210     //UNUSED FILE *fd;
00211     struct tm *local;
00212     long clock;
00213 
00214 /* extern void crash();* *//* if broken pipe, release port (I hope) */
00215 
00216     //UNUSED int s;      /* for socket */
00217     fd_set inputfds2;
00218     int i;
00219 
00220     freopen("backenderror", "w", stderr);
00221     setbuf(stderr, NULL);
00222 
00223     backenddaemon = 1;
00224 
00225     FD_ZERO(&inputfds);
00226 
00227     processrcfile();
00228 
00229     signal(SIGPIPE, crash);
00230     signal(SIGHUP, crash);
00231     signal(SIGXCPU, SIG_IGN);
00232     signal(SIGINT, flagquitting);
00233 
00234     febelog = interfaceinput = reallog = logfile = nulllog = fopen("/dev/null", "a");
00235 
00236     clock = time(0);
00237     local = localtime(&clock);
00238     sprintf(buf, "ln%d.%d.%d:%d", local->tm_mon + 1, local->tm_mday, local->tm_hour, local->tm_min);
00239     interfaceinput = fopen(buf, "w");
00240 
00241 #ifndef DISTRIBUTION
00242     sprintf(buf, "febe%d.%d.%d:%d", local->tm_mon + 1, local->tm_mday, local->tm_hour, local->tm_min);
00243     febelog = fopen(buf, "w");
00244     setbuf(febelog, NULL);
00245 #endif
00246 
00247     setbuf(stdin, inputbuffer);
00248     setbuf(stdout, outputbuffer);
00249     debug = 0;
00250     init(1);
00251     //now uses a ctor:: inittask(&sess);
00252     errno = 0;
00253     initsession("enf.enf");
00254     main_socket = open_sock();
00255 
00256     if (n_players < 1) {
00257         mightbeblocked = true;
00258         new_players(player, &n_players, true, &sess);   /* wait for fe to talk to */
00259         mightbeblocked = false;
00260     }
00261 
00262     for (;;) {
00263         if (n_players < 1) {
00264             diskflush();               /* Write out everything when no one around */
00265             mightbeblocked = true;
00266             new_players(player, &n_players, true, &sess);       /* wait for fe to talk to */
00267             mightbeblocked = false;
00268         }
00269 
00270         inputfds2       = inputfds;
00271         timeout.tv_sec  = 2;                /* wait 2 seconds on a select, then look for a new user */
00272         timeout.tv_usec = 0;
00273 
00274         int nevents = select(nfds + 1, &inputfds2, 0, 0, &timeout);
00275         if (nevents < 0) {
00276             if (errno == EINTR) {
00277                 continue;
00278             }
00279             perror("select");
00280             assert(0); // select in main
00281         } else {
00282 
00283             if (nevents)
00284                 L("Somone connected to our main socket\n");
00285 
00286             for (i = 0; i <= nfds; i++) {
00287                 if (FD_ISSET(i, &inputfds2)) {
00288 //OBSOLETE                if ((1 << i) & inputfds2) {
00289                     L("Read-Event on socket %d\n", i);
00290 
00291                     user         = fdtoplayer[i];
00292                     sess.inp     = player[user].inp;
00293                     sess.outp    = player[user].outp;
00294                     sess.account = player[user].account;
00295 
00296                     if (!tumblereq(&currentaccount, &sess.account)) {
00297                         currentaccount = sess.account;
00298                         logaccount(&sess.account);
00299                     }
00300 
00301                     xanadu(&sess);
00302 
00303                     if (quitafteruser) {
00304                         if (interfaceinput) {
00305                             fprintf(interfaceinput, "%d~\n", QUIT);
00306                             fclose(interfaceinput);
00307                         }
00308                         writeenfilades();
00309                         closediskfile();
00310                         exit(0);
00311                     }
00312 /* testforreservedness("main"); */
00313 /* logfile = nulllog; */
00314                     nsessorcommand++;
00315                 }
00316             }
00317         }
00318 
00319         leave(player, &n_players);
00320         mightbeblocked = true;
00321         new_players(player, &n_players, false, &sess);
00322         mightbeblocked = false;
00323     }
00324     return 0;
00325 }
00326 
00334     bool
00335 establishprotocol(
00336     FILE *inp,
00337     FILE *outp)
00338 {
00339     L("Entering establishprotocol()\n");
00340 
00341     metachar ch;
00342 
00343 /* This is the metaprotocol for the time being */
00344     while ((ch = getc(inp)) != '\n')
00345         putc((ch > ' ' ? ch : '.'), stderr);
00346 
00347     while ((ch = getc(inp)) == '\n')
00348         putc(ch, stderr);
00349 
00350     L("establishprotocol: synced up\n");
00351 
00352     if (ch == 'P' && getc(inp) == '0' && getc(inp) == '~') {
00353         if (!feof(inp)) {              /* Don't send to a dead pipe */
00354             xuputstring("\nP0~", outp);
00355             fflush(outp);
00356             L("Leaving establishprotocol(), SUCCESS\n");
00357             return true;
00358         }
00359     } else {
00360         if (!feof(inp)) {              /* Don't send to a dead pipe */
00361             xuputstring("\nP?~", outp);
00362             fflush(outp);
00363         }
00364     }
00365     L("Leaving establishprotocol(), FAIL\n");
00366     return false;
00367 }
00368 
00376     void
00377 frontenddied()
00378 {
00379     longjmp(frontendeof, 1);
00380 }
00381 
00389 /* for linker until we get this cleaned up */
00390     void
00391 setmaximumsetupsize(
00392     Session *sess)    
00393 {
00394 }
00395 
00403     void
00404 sourceunixcommand(
00405     Session *sess)    
00406 {
00407 }
00408 
00416     bool
00417 decrementusers()
00418 {
00419     if (n_players > 1) {
00420         player[user].wantsout = 1;
00421     }
00422     return (n_players > 1);
00423 }

Generated on Sun Aug 21 04:18:15 2005 for Udanax-Green by doxygen1.3.4