home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 11 / 11.iso / n / n001 / 1.ddi / SCP / MAIN_SC.C < prev   
Encoding:
C/C++ Source or Header  |  1989-10-17  |  10.4 KB  |  396 lines

  1.  
  2. /*                                                                            */
  3. /*                                                                            */
  4. /*                  Copyright 1987, 1988, 1989 Netwise, Inc.                  */
  5. /*                              All Rights Reserved                           */
  6. /*   This software contains information which is proprietary to and a trade   */
  7. /*   secret of Netwise, Inc. It is not to be used, reproduced, or disclosed   */
  8. /*   except as authorized in your license agreement.                          */
  9. /*                                                                            */
  10. /*                          Restricted Rights Legend                          */
  11. /*   Use, duplication,  or  disclosure  by the  Government  is  subject  to   */
  12. /*   restrictions as set forth in subparagraph (c)(1)(ii) of the Rights  in   */
  13. /*   Technical Data and  Computer Software clause  at 252.227-7013, or  the   */
  14. /*   equivalent Government clause for other agencies.                         */
  15. /*   Contractor: Netwise, Inc., Boulder, CO 80301 USA                         */
  16. /*                                                                            */
  17. /*                                                                            */
  18.  
  19. #include <stdio.h>
  20. #include <stdarg.h>
  21. #include <rpchdr.h>
  22. #include <nwnet.h>
  23. #include <signal.h>
  24.  
  25. #ifdef __TURBOC__
  26. #pragma warn -par
  27. #endif
  28.  
  29. /*
  30.  * Error severity codes (passed to eprt).
  31.  */
  32. #define    NONFATAL    0
  33. #define    FATAL        1
  34.  
  35. #ifdef SERV_DEF
  36. #include "serv_def.h"        /* get macro definitions from this file */
  37. #endif
  38.  
  39. /*
  40.  * Main routine for servers to handle one-shot or persistent
  41.  * connections for a single client at a time.
  42.  */
  43.  
  44. /* Macro: Dispatcher  (Required)
  45.  *
  46.  * The 'Dispatcher' macro is the name of the dispatcher procedure
  47.  * for your RPC server. The name of the dispatcher procedure depends on
  48.  * the interface name given in the RPC specification file, or on the
  49.  * name of your RPC specification file if no interface name was given.
  50.  */
  51. /*
  52. #define    Dispatcher    dispatcher_proc_name
  53.  */
  54.  
  55. /* Macro: Server_Name  (Required)
  56.  *
  57.  * The 'Server_Name' macro must contain the name of your server as it
  58.  * should be registered in your environment. The name clients use to
  59.  * locate the server will be based on this.
  60.  */
  61. /*
  62. #define    Server_Name    "server_name"
  63.  */
  64.  
  65. /* Macro: Server_Init  (Optional)
  66.  *
  67.  * The macro 'Server_Init' may contain code to be executed when the
  68.  * server is started. This may be useful for opening files, or other
  69.  * operations that only need to be done once before any remote procedure
  70.  * calls are serviced. If 'Server_Init' is not defined, no such
  71.  * initialization is performed.
  72.  *
  73.  * Command line arguments can be accessed by using argc and argv.
  74.  */
  75. /*
  76. #define Server_Init    server_init_routine();
  77.  */
  78.  
  79. /* Macro: Server_Term  (Optional)
  80.  *
  81.  * The macro 'Server_Term' may contain the name of a termination
  82.  * procedure to be called when the server encounters an error. If
  83.  * present, this routine, will be called with the code of the most
  84.  * recent error, or zero if the server is terminating normally. If
  85.  * not defined, the server just calls exit with an appropriate code.
  86.  */
  87. /*
  88. #define    Server_Term    term_routine_name
  89.  */
  90.  
  91. /* Macro: Poll_Loop  (Optional)
  92.  *
  93.  * The macro 'Poll_Loop' may contain code to be executed from within
  94.  * the server's polling loop.  This code is placed at the end of the
  95.  * polling loop and can be used to insert delays or to poll for
  96.  * additional events.
  97.  */
  98. /*
  99. #define Poll_Loop    poll_loop_routine();
  100.  */
  101.  
  102. /* Macro: Server_Loop  (Optional)
  103.  *
  104.  * The macro 'Server_Loop' may contain code to be executed from
  105.  * within the server's primary loop.  This code is executed prior to
  106.  * accepting the next client connection. It can be used to allocate
  107.  * resources in preparation for this client's connection.
  108.  */
  109. /*
  110. #define    Server_Loop        server_loop_routine();
  111.  */
  112.  
  113. /* Macro: Dispatcher_Loop  (Optional)
  114.  *
  115.  * The macro 'Dispatcher_Loop' may contain code to be executed from
  116.  * within the server's primary loop.  This code is executed prior to
  117.  * servicing the next remote procedure and can be used to allocate
  118.  * resources in preparation for this remote procedure.
  119.  */
  120. /*
  121. #define    Dispatcher_Loop        dispatcher_loop_routine();
  122.  */
  123.  
  124. /* Macro: DEBUG  (Optional)
  125.  *
  126.  * The following define controls the inclusion of optional debugging code
  127.  * within the server. If defined, various debugging messages will be
  128.  * printed to 'stderr' as the server executes.
  129.  */
  130. /*
  131. #define    DEBUG
  132.  */
  133.  
  134. /* Macro: DPRT  (Optional)
  135.  *
  136.  * The DPRT macro may be defined if you want to use your own "dprt" routine.
  137.  * The default routine in this file prints a debug message to stderr. In
  138.  * certain environments it may be desirable to generate this output through
  139.  * some other means. If the default "dprt" is used, it is only enabled if
  140.  * DEBUG is defined.
  141.  */
  142. /*
  143. #define    DPRT
  144.  */
  145.  
  146. /* Macro: EPRT  (Optional)
  147.  *
  148.  * The EPRT macro may be defined to replace the default error handler with
  149.  * your own. The default routine prints a message to stderr.
  150.  */
  151. /*
  152. #define    EPRT
  153.  */
  154.  
  155. /* Variable: shut_down  (Optional)
  156.  *
  157.  * Set this variable from within a remote procedure to tell the main
  158.  * routine to shutdown gracefully after the current RPC call is serviced.
  159.  */
  160. int shut_down = 0;
  161.  
  162. /* Variable: _scp_v2r1_  (Required)
  163.  *
  164.  * This variable is used to insure that compatible pieces are linked
  165.  * together. It is not referenced during execution.
  166.  */
  167. int _scp_v2r1_ = 0;
  168.  
  169. /*
  170.  * Exit codes used by servers
  171.  */
  172. #define    EXIT_OK        0    /* normal termination */
  173. #define    EXIT_ERR    1    /* an error occurred */
  174.  
  175. /*ARGSUSED*/
  176. main(argc, argv)
  177. int    argc;
  178. char    *argv[];
  179. {
  180.     void    finish(), dprt();
  181.     int    eprt();
  182.     struct    nl_info    info;
  183.     connection_id    lid, aid;
  184.     network_addr    adx;
  185.     struct    dscp_t    dscp;
  186.     int    erc;
  187.     int    ch;
  188.  
  189.     if ( (erc = nl_init(&info)) != 0 ) {
  190.         if (eprt("nl_init", FATAL, erc, &dscp, __LINE__))
  191.             finish(erc);
  192.     }
  193.  
  194.     if ( (erc = nl_open(&lid)) != 0 ) {
  195.         if (eprt("nl_open", FATAL, erc, &dscp, __LINE__))
  196.             finish(erc);
  197.     }
  198.  
  199.     adx.len = info.addr_len;
  200.     if ( (adx.value = _allo_(adx.len)) == NULL ) {
  201.         eprt("malloc", FATAL, -1, &dscp, __LINE__);
  202.         finish(-1);
  203.     }
  204.  
  205.     if ( (erc = nl_getaddr(adx.value, &adx.len)) != 0 ) {
  206.         if (eprt("nl_getaddr", FATAL, erc, &dscp, __LINE__))
  207.             finish(erc);
  208.     }
  209.  
  210. #ifndef    Server_Interrupt_Control
  211.     /*
  212.      * The default server interrupt code for DOS sets up the program
  213.      * to ignore the control-C interrupt. This prevents uncontrolled
  214.      * program termination. The server can then be directed to perform an
  215.      * orderly shutdown by pressing the ESC key.
  216.      * If this default server interrupt code is not desired,
  217.      * Server_Interrupt_Control should be defined.
  218.      */
  219.     printf("Press ESC key to shut down the server:\n"); 
  220.     signal(SIGINT, SIG_IGN);
  221. #endif
  222.  
  223. #ifdef    Server_Init
  224.     Server_Init        /* server-specific initialization code */
  225. #endif
  226.  
  227.     dprt("Registering");
  228.     erc = nl_register(Server_Name, adx.value, &adx.len, lid);
  229.     if ( erc != 0 ) {
  230.         if (eprt("nl_register", FATAL, erc, &dscp, __LINE__))
  231.             finish(erc);
  232.     }
  233.  
  234.     while ( shut_down == 0 ) {
  235.  
  236. #ifdef    Server_Loop
  237.         Server_Loop
  238. #endif
  239.         dprt("Waiting for a connection");
  240.  
  241.         for (;;) {
  242.             struct    nl_stats stat;
  243.  
  244.             if ( (erc = nl_status(lid, &stat)) != 0 ) {
  245.                 if (eprt("nl_status",FATAL,erc,&dscp,__LINE__)){
  246.                     nl_close(lid);
  247.                     finish(erc);
  248.                 }
  249.             }
  250.             if (stat.read_ready == 1)
  251.                 break;
  252.  
  253. #ifndef    Server_Interrupt_Control
  254.             /*
  255.              * The server can be directed to perform an orderly
  256.              * shutdown by pressing the ESC key.
  257.              * If this default server interrupt code is not desired,
  258.              * Server_Interrupt_Control should be defined.
  259.              */
  260. #define ESCKEY    '\033'
  261.             if (kbhit() && (ch=getch()) == ESCKEY) {
  262.                 dprt("Server shutting down\n");
  263.                 nl_close(lid);
  264.                 finish(erc);
  265.             }
  266. #endif
  267.  
  268. #ifdef    Poll_Loop
  269.             Poll_Loop
  270. #endif
  271.         }
  272.  
  273.         if ( (erc = nl_open(&aid)) != 0 ) {
  274.             if (eprt("nl_open", FATAL, erc, &dscp, __LINE__)) {
  275.                 nl_close(lid);
  276.                 finish(erc);
  277.             }
  278.         }
  279.  
  280.         if ( (erc = nl_accept(lid, aid, NULL, NULL)) != 0 ) {
  281.             if (eprt("nl_accept", FATAL, erc, &dscp, __LINE__)) {
  282.                 nl_close(lid);
  283.                 nl_close(aid);
  284.                 finish(erc);
  285.             }
  286.         }
  287.         dprt("Connection accepted");
  288.  
  289.         /*
  290.          * Accept RPC calls on this connection until DSCP_CLOSE
  291.          * or DSCP_ABORT is set or an error occurs.
  292.          */
  293.         do {
  294.  
  295. #ifdef    Dispatcher_Loop
  296.             Dispatcher_Loop
  297. #endif
  298.             dscp.iflags = dscp.cflags = 0L;
  299.  
  300.             if ( (erc = Dispatcher( lid, &dscp )) != 0 ) {
  301.                 if (eprt("dispatcher", NONFATAL, erc, &dscp, __LINE__)) {
  302.                     nl_close(lid);
  303.                     nl_close(aid);
  304.                     finish(erc);
  305.                 }
  306.             }
  307.         } while ((dscp.cflags & (DSCP_CLOSE|DSCP_ABORT)) == 0 &&
  308.                                 !shut_down);
  309.  
  310.         if ( dscp.cflags & DSCP_ABORT ) {
  311.             if ( (erc = nl_abort( lid )) != 0 ) {
  312.                 if (eprt("nl_abort", FATAL, erc, &dscp, __LINE__)) {
  313.                     nl_close(aid);
  314.                     finish(erc);
  315.                 }
  316.             }
  317.         } else if ( dscp.cflags & DSCP_CLOSE ) {
  318.             if ( (erc = nl_close( lid )) != 0 ) {
  319.                 if (eprt("nl_close", FATAL, erc, &dscp, __LINE__)) {
  320.                     nl_close(aid);
  321.                     finish(erc);
  322.                 }
  323.             }
  324.         }
  325.         lid = aid;
  326.         dprt("Connection terminated");
  327.     }
  328.  
  329.     dprt("Server shutting down");
  330.     if ( (erc = nl_close( aid )) != 0 ) {
  331.         if (eprt("nl_close", FATAL, erc, &dscp, __LINE__))
  332.             finish(erc);
  333.     }
  334.  
  335.     finish(0);
  336. }
  337.  
  338. void
  339. finish(error)
  340. int    error;
  341. {
  342. #ifdef    Server_Term
  343.     Server_Term(error);
  344. #endif
  345.  
  346.     /*
  347.      * Exit here with a reasonable code in case the user didn't
  348.      * didn't define Server_Term or didn't call exit there.
  349.      */
  350.     exit( error ? EXIT_ERR : EXIT_OK );
  351. }
  352.  
  353. #ifndef    EPRT
  354. /*ARGSUSED*/
  355. int
  356. eprt(func, severity, error, dscp, line)
  357. char    *func;
  358. int    severity;
  359. int    error;
  360. struct    dscp_t    *dscp;
  361. int    line;
  362. {
  363.     /*
  364.      * Errors can be downgraded from FATAL to NONFATAL if the error
  365.      * occurred in a Network Library routine, and the error code we
  366.      * got indicates an "informational" error.
  367.      */
  368.     if (severity == FATAL) {
  369.         if ((strncmp(func, "nl_", 3) == 0) && ((error & 1) == 0))
  370.             severity = NONFATAL;
  371.     }
  372.  
  373.     (void) fprintf(stderr, "%s failed (%d) on line %d -- %s\n",
  374.         func, error, line,
  375.         severity == FATAL ? "fatal" : "non-fatal");
  376.  
  377.     return severity;
  378. }
  379. #endif
  380.  
  381. #ifndef    DPRT
  382. /*VARARGS0*/
  383. void
  384. dprt(char *format, ...)
  385. {
  386. #ifdef    DEBUG
  387.     va_list args;
  388.  
  389.     va_start(args,format);
  390.     (void) vfprintf(stderr, format, args);
  391.     (void) fputc('\n', stderr);
  392.     va_end(args);
  393. #endif
  394. }
  395. #endif
  396.