14

mbd.c

  1. #include "mbd.h"
  2. #include "mbd_kbd.h"
  3.  
  4. #include "mb_sio.h"
  5.  
  6. #include "mbdef.h"
  7.  
  8. #include "ctk/shell.h"
  9.  
  10. #include <sys/types.h>
  11. #include <sys/socket.h>
  12.  
  13. #if defined( LINUX ) || defined (HPUX)
  14. #include <sys/time.h>
  15. #else
  16. #include <sys/select.h>
  17. #endif
  18.  
  19. #include <sys/file.h>
  20. #include <sys/ioctl.h>
  21. #include <sys/param.h>
  22.  
  23. #include <stdlib.h>
  24. #include <string.h>
  25.  
  26. #if defined( SUN ) || defined( LINUX )
  27. #include <netinet/in.h>
  28. #include <unistd.h>
  29. #endif
  30. #include <netdb.h>
  31.  
  32. #include <signal.h>
  33. #include <time.h>
  34.  
  35. #include <errno.h>
  36.  
  37. #include "ctk/debug.h"
  38.  
  39. #if defined( DEBUG )
  40. #include "ctk/dump.h"
  41. int debug = 0;
  42. #endif
  43.  
  44. #ifndef MIN
  45. #define MIN(x, y) ((x) < (y) ? (x) : (y))
  46. #endif
  47. #ifndef MAX
  48. #define MAX(x, y) ((x) < (y) ? (y) : (x))
  49. #endif
  50.  
  51. struct magicbus mb; /* application object */
  52.  
  53. static int mb_write( int s, u_char *buf, int len );
  54.    
  55. static void mb_watch_socket( int socket ) {
  56.     struct mb_socket *s_in;
  57.  
  58.     ONDEBUG2( fprintf( stdout, "\n[accept=%i]", socket ) );
  59.  
  60.     s_in = (struct mb_socket *)malloc( sizeof ( struct mb_socket ));
  61.     s_in->n_sent = s_in->n_recv = 0;
  62.     s_in->s_socket = socket;
  63.     s_in->s_name = 0;
  64.  
  65.     list_put( mb.in_sockets, -1, s_in );
  66.  
  67.     /* accounting */
  68.     mb.n_conn++;
  69. }
  70.  
  71. static void mb_drop_socket( int socket ) {
  72.     struct mb_socket *s_in;
  73.     struct mb_toreq *to_r;
  74.  
  75.     int i, len;
  76.  
  77.     ONDEBUG2( fprintf( stdout, "\n[drop=%i]", socket ) );
  78.  
  79.     for ( i = 0, len = list_length( mb.in_sockets ); i < len; i++ ) {
  80.         s_in = (struct mb_socket *)list_get( mb.in_sockets, i );
  81.         if ( s_in->s_socket == socket ) {
  82.             list_delete( mb.in_sockets, i );
  83.             if ( s_in->s_name )
  84.                 free( s_in->s_name );
  85.             free( s_in );
  86.             break;
  87.         }
  88.     }
  89.  
  90.     for ( i = 0, len = list_length( mb.to_reqs ); i < len; i++ ) {
  91.         to_r = (struct mb_toreq *)list_get( mb.to_reqs, i );
  92.         /* lost a requester? */
  93.         if ( to_r->r_sin == socket ) {
  94.             list_delete( mb.to_reqs, i );
  95.             free( to_r );
  96.             break;
  97.         }
  98.         /* lost a responder? */
  99.         if ( to_r->r_sout == socket ) {
  100.             list_delete( mb.to_reqs, i );
  101.             if ( to_r->r_sin ) {
  102.                 char rsp[ 64 ];
  103.                 int n;
  104.                 /* notify requester */
  105.                 n = sprintf( rsp, "%c%c%u%c", MB_STAMP, MB_TIMEOUT, to_r->r_msg_id, 0 );
  106.                 mb_write( to_r->r_sin, (u_char *)rsp, n );
  107.                 ONDEBUG1( fprintf( stdout, "reply_type=%c msg_id=%u\n", MB_TIMEOUT, to_r->r_msg_id );
  108.                         dump( (u_char *)rsp, MIN(n, mb.dump_size), stdout ) );
  109.             }
  110.             free( to_r );
  111.             break;
  112.         }
  113.     }
  114. }
  115.  
  116. static struct mb_socket *mb_find_socket( int socket ) {
  117.     int i, len = list_length( mb.in_sockets );
  118.     struct mb_socket *s_in;
  119.  
  120.     for ( i = 0; i < len; i++ ) {
  121.         s_in = (struct mb_socket *)list_get( mb.in_sockets, i );
  122.         if ( s_in->s_socket == socket )
  123.             return s_in;
  124.     }
  125.     return 0;
  126. }
  127.  
  128. static int mb_count_socket_name( char *s_name ) {
  129.     int i, len = list_length( mb.in_sockets );
  130.     struct mb_socket *s_in;
  131.     int n = 0;
  132.  
  133.     for ( i = 0; i < len; i++ ) {
  134.         s_in = (struct mb_socket *)list_get( mb.in_sockets, i );
  135.         if ( s_in->s_name && strcmp( s_in->s_name, s_name ) == 0 )
  136.             n++;
  137.     }
  138.     return n;
  139. }
  140.  
  141. static int mb_read( int s, u_char *buf, int len ) {
  142.     int r = s_read( s, buf, len );
  143.  
  144.     if ( r < 0 )
  145.         mb_drop_socket( s );
  146.  
  147.     return r;
  148. }
  149.  
  150. static int mb_write( int s, u_char *buf, int len ) {
  151.     int w = s_write( s, buf, len );
  152.  
  153.     if ( w < 0 )
  154.         mb_drop_socket( s );
  155.  
  156.     return w;
  157. }
  158.  
  159. static int mb_getc( int s ) {
  160.     int c = s_getc( s );
  161.  
  162.     if ( c < 0 )
  163.         mb_drop_socket( s );
  164.  
  165.     return c;
  166. }
  167.  
  168. static int mb_getuint( int s ) {
  169.     int i = s_getuint( s );
  170.  
  171.     if ( i < 0 )
  172.         mb_drop_socket( s );
  173.  
  174.     return i;
  175. }
  176.  
  177. static char *mb_getident( int s ) {
  178.     char *p = s_getident( s );
  179.  
  180.     if ( !p )
  181.         mb_drop_socket( s );
  182.  
  183.     return p;
  184. }
  185.  
  186. static int mb_add_toreq( int msg_id, int sin, int sout, int timeout ) {
  187.     struct mb_toreq *to_r;
  188.     int i, len;
  189.  
  190.     time_t attime = time( 0 ) + timeout;
  191.  
  192.     static int r_id = 0;
  193.  
  194.     if ( ++r_id < 0 )
  195.         r_id = 1;
  196.  
  197.     for ( i = 0, len = list_length( mb.to_reqs ); i < len; i++ ) {
  198.         to_r = (struct mb_toreq *)list_get( mb.to_reqs, i );
  199.         if ( to_r->r_attime > attime )
  200.             break;
  201.     }
  202.  
  203.     to_r = (struct mb_toreq *)malloc( sizeof (struct mb_toreq) );
  204.     to_r->r_id = r_id;
  205.     to_r->r_msg_id = msg_id;
  206.     to_r->r_sout = sout;
  207.     to_r->r_sin = sin;
  208.     to_r->r_attime = attime;
  209.  
  210.     list_insert( mb.to_reqs, i, to_r );
  211.  
  212.     return r_id;
  213. }
  214.  
  215. static time_t mb_check_toreqs( ) {
  216.     struct mb_toreq *to_r;
  217.     time_t now;
  218.  
  219.     char rsp[ 64 ];
  220.     int n;
  221.  
  222.     if ( list_length( mb.to_reqs ) == 0 )
  223.         /* be quick */
  224.         return 0;
  225.  
  226.     now = time( 0 );
  227.  
  228.     while ( (to_r = (struct mb_toreq *)list_get( mb.to_reqs, 0 )) ) {
  229.         if ( to_r->r_attime > now )
  230.             break;
  231.         if ( to_r->r_sin ) {
  232.             n = sprintf( rsp, "%c%c%u%c", MB_STAMP, MB_TIMEOUT, to_r->r_msg_id, 0 );
  233.             mb_write( to_r->r_sin, (u_char *)rsp, n );
  234.             ONDEBUG1( fprintf( stdout, "reply_type=%c msg_id=%u\n", MB_TIMEOUT, to_r->r_msg_id );
  235.                     dump( (u_char *)rsp, MIN(n, mb.dump_size), stdout ) );
  236.             free( to_r );
  237.         }
  238.         list_delete( mb.to_reqs, 0 );
  239.     }
  240.  
  241.     to_r = list_get( mb.to_reqs, 0 );
  242.  
  243.     return to_r ? to_r->r_attime : 0;
  244. }
  245.  
  246. int mb_getpagesize( ) {
  247.     return mb.page_size;
  248. }
  249.  
  250. int mb_setpagesize( int pagesize ) {
  251.     if ( pagesize > 0 )
  252.         mb.page_size = pagesize;
  253.  
  254.     return mb.page_size;
  255. }
  256.  
  257. int mb_gettimeout( ) {
  258.     return mb.timeout;
  259. }
  260.  
  261. int mb_settimeout( int to ) {
  262.     if ( to > 0 )
  263.         mb.timeout = to;
  264.  
  265.     return mb.timeout;
  266. }
  267.  
  268. void mb_register( int socket ) {
  269.     struct mb_socket *s_in = mb_find_socket( socket );
  270.     int msg_id;
  271.     char *s_name;
  272.  
  273.     char msg[ 32 ];
  274.     int msg_len;
  275.  
  276.     char rsp[ 64 ];
  277.  
  278.     int n;
  279.  
  280.     if ( (msg_id = mb_getuint( socket )) < 0 )
  281.         return;
  282.     ONDEBUG1( fprintf( stdout, " msg_id=%u", msg_id ) );
  283.  
  284.     if ( (s_name = mb_getident( socket )) == 0 )
  285.         return;
  286.     ONDEBUG1( fprintf( stdout, " domain=%s\n", s_name ) );
  287.  
  288.     if ( s_in->s_name ) {   /* already named? */
  289.         free( s_in->s_name );
  290.         s_in->s_name = 0;
  291.     }
  292.  
  293.     /* change socket's name */
  294.     if ( (s_in->s_name = (char *)malloc( strlen( s_name ) + 1 )) == 0 ) {
  295.         mb_drop_socket( socket );
  296.         close( socket );    /* be tough */
  297.         return;
  298.     }
  299.     strcpy( s_in->s_name, s_name );
  300.  
  301.     /* reply with a '\0' terminated formatted number */
  302.     msg_len = sprintf( msg, "%u", mb_count_socket_name( s_name ) );
  303.     n = sprintf( rsp, "%c%c%u%c%u%c%s%c", MB_STAMP, MB_REGISTER, msg_id, 0, msg_len + 1, 0, msg, 0 );
  304.     mb_write( socket, (u_char *)rsp, n );
  305.     ONDEBUG1( fprintf( stdout, "reply_type=%c msg_id=%u n=%i\n", MB_REGISTER, msg_id, mb_count_socket_name( s_name ) );
  306.             dump( (u_char *)rsp, MIN(n, mb.dump_size), stdout ) );
  307. }
  308.  
  309. void mb_probe( int socket ) {
  310.     int msg_id;
  311.     char *s_name;
  312.  
  313.     char msg[ 32 ];
  314.     int msg_len;
  315.  
  316.     char rsp[ 64 ];
  317.  
  318.     int n;
  319.  
  320.     if ( (msg_id = mb_getuint( socket )) < 0 )
  321.         return;
  322.     ONDEBUG1( fprintf( stdout, " msg_id=%u", msg_id ) );
  323.  
  324.     if ( (s_name = mb_getident( socket )) == 0 )
  325.         return;
  326.     ONDEBUG1( fprintf( stdout, " domain=%s\n", s_name ) );
  327.  
  328.     /* reply with a '\0' terminated formatted number */
  329.     msg_len = sprintf( msg, "%u", mb_count_socket_name( s_name ) );
  330.     n = sprintf( rsp, "%c%c%u%c%u%c%s%c", MB_STAMP, MB_PROBE, msg_id, 0, msg_len + 1, 0, msg, 0 );
  331.     mb_write( socket, (u_char *)rsp, n );
  332.     ONDEBUG1( fprintf( stdout, "reply_type=%c msg_id=%u n=%i\n", MB_REGISTER, msg_id, mb_count_socket_name( s_name ) );
  333.             dump( (u_char *)rsp, MIN(n, mb.dump_size), stdout ) );
  334. }
  335.  
  336. void mb_send( int socket, int how ) {
  337.     struct mb_socket *s_in = mb_find_socket( socket );
  338.     struct mb_socket *s_out;
  339.     char *s_name;
  340.  
  341.     int msg_id, msg_len;
  342.  
  343.     char rsp[ 64 ];
  344.     int n;
  345.  
  346.     list s_list;
  347.     int i, len;
  348.  
  349.     int r;
  350.  
  351.     if ( (s_name = mb_getident( socket )) == 0 )
  352.         return;
  353.     ONDEBUG1( fprintf( stdout, " domain=%s", s_name ) );
  354.  
  355.     if ( (msg_id = mb_getuint( socket )) < 0 )
  356.         return;
  357.     ONDEBUG1( fprintf( stdout, " msg_id=%u", msg_id ) );
  358.  
  359.     if ( (msg_len = mb_getuint( socket )) < 0 )
  360.         return;
  361.     ONDEBUG1( fprintf( stdout, " msg_len=%u\n", msg_len ) );
  362.  
  363.     /* find peer */
  364.     for ( s_list = list_new(), i = 0, len = list_length( mb.in_sockets ); i < len; i++ ) {
  365.         s_out = (struct mb_socket *)list_get( mb.in_sockets, i );
  366.         if ( s_out->s_socket != socket && s_out->s_name && strcmp( s_out->s_name, s_name ) == 0 ) {
  367.             list_put( s_list, -1, (void *)s_out->s_socket );
  368.             s_out->n_recv++;
  369.             if ( how != MB_MULTIWAY )
  370.                 break;  /* only one */
  371.         }
  372.     }
  373.  
  374.     /* read data */
  375.     if ( msg_len > 0 ) {
  376.         u_char *msg = (u_char *)alloca( mb.page_size );
  377.         int s, r_id;
  378.  
  379.         /* send header */
  380.         for ( i = 0; i < list_length( s_list ); i++ ) {
  381.             s = (int)list_get( s_list, i );
  382.             r_id = how == MB_TWOWAY ? mb_add_toreq( msg_id, socket, s, mb_gettimeout() ) : 0;
  383.  
  384.             n = sprintf( rsp, "%c%c%u%c%u%c", MB_STAMP, how, r_id, 0, msg_len, 0 );
  385.  
  386.             if ( mb_write( s, (u_char *)rsp, n ) < 0 )
  387.                 /* lost peer */
  388.                 list_delete( s_list, i );
  389.         }
  390.  
  391.         /* transmit data */
  392.         do {
  393.             n = MIN( msg_len, mb.page_size );
  394.             r = socket != -1 ? mb_read( socket, msg, n ) : n;
  395.             if ( r < 0 ) {
  396.                 /* lost sender */
  397.                 memset( msg, 0, r = n );
  398.                 socket = -1;
  399.             }
  400.             for ( i = 0; i < list_length( s_list ); i++ ) {
  401.                 s = (int)list_get( s_list, i );
  402.                 if ( mb_write( s, msg, r ) < 0 )
  403.                     /* lost peer */
  404.                     list_delete( s_list, i );
  405.             }
  406.             ONDEBUG1( dump( msg, MIN(r, mb.dump_size), stdout );
  407.             fprintf( stdout, "to_send=%i\n", msg_len - r ) );
  408.         }
  409.         while ( msg_len -= r );
  410.     }
  411.  
  412.     /* acknowledge */
  413.     if ( socket != -1 ) {
  414.         if ( list_length( s_list ) > 0 ) {
  415.             if ( how != MB_TWOWAY ) {
  416.                 n = sprintf( rsp, "%c%c%u%c%c", MB_STAMP, MB_REPLY, msg_id, 0, 0 );
  417.                 mb_write( socket, (u_char *)rsp, n );
  418.                 ONDEBUG1( fprintf( stdout, "reply_type=%c msg_id=%u\n", MB_REPLY, msg_id );
  419.                         dump( (u_char *)rsp, MIN(n, mb.dump_size), stdout ) );
  420.             }
  421.         }
  422.         else {
  423.             n = sprintf( rsp, "%c%c%u%c", MB_STAMP, MB_NOBODY, msg_id, 0 );
  424.             mb_write( socket, (u_char *)rsp, n );
  425.             ONDEBUG1( fprintf( stdout, "reply_type=%c msg_id=%u\n", MB_NOBODY, msg_id );
  426.                     dump( (u_char *)rsp, MIN(n, mb.dump_size), stdout ) );
  427.         }
  428.     }
  429.     /* accouting */
  430.     s_in->n_sent++;
  431.     mb.n_msgs++;
  432.  
  433.     /* recycle memory */
  434.     list_free( s_list );
  435. }
  436.  
  437. void mb_recv( int socket ) {
  438.     int msg_id, msg_len;
  439.  
  440.     char rsp[ 64 ];
  441.     int n;
  442.  
  443.     int s;
  444.  
  445.     struct mb_toreq *to_r;
  446.     int i, len;
  447.  
  448.     int r;
  449.  
  450.     if ( (msg_id = mb_getuint( socket )) < 0 )
  451.         return;
  452.  
  453.     if ( (msg_len = mb_getuint( socket )) < 0 )
  454.         return;
  455.     ONDEBUG1( fprintf( stdout, " msg_len=%u\n", msg_len ) );
  456.  
  457.     /* find request */
  458.     for ( i = 0, len = list_length( mb.to_reqs ); i < len; i++ ) {
  459.         to_r = (struct mb_toreq *)list_get( mb.to_reqs, i );
  460.         if ( to_r->r_id == msg_id ) {
  461.             list_delete( mb.to_reqs, i );
  462.             break;
  463.         }
  464.     }
  465.  
  466.     if ( i < len ) {
  467.         s = to_r->r_sin;   
  468.  
  469.         /* send header */
  470.         if ( s != -1 ) {
  471.             msg_id = to_r->r_msg_id;
  472.             n = sprintf( rsp, "%c%c%u%c%u%c", MB_STAMP, MB_REPLY, msg_id, 0, msg_len, 0 );
  473.             if ( mb_write( s, (u_char *)rsp, n ) < 0 )
  474.                 /* lost requester */
  475.                 s = -1;
  476.             ONDEBUG1( fprintf( stdout, "reply_type=%c msg_id=%u msg_len=%u\n", MB_REPLY, msg_id, msg_len );
  477.                     dump( (u_char *)rsp, MIN(n, mb.dump_size), stdout ) );
  478.         }
  479.         /* recycle memory */
  480.         free( to_r );
  481.     }
  482.     else
  483.         s = -1; /* too late */
  484.  
  485.     /* read data */
  486.     if ( msg_len > 0 ) {
  487.         u_char *msg = (u_char *)alloca( mb.page_size );
  488.         /* transmit data */
  489.         do {
  490.             n = MIN( msg_len, mb.page_size );
  491.             r = socket != -1 ? mb_read( socket, msg, n ) : n;
  492.             if ( r < 0 ) {
  493.                 /* lost responder */
  494.                 memset( msg, 0, r = n );
  495.                 socket = -1;
  496.             }
  497.             if ( s != -1 ) {
  498.                 if ( mb_write( s, msg, n ) < 0 )
  499.                 /* lost requester */
  500.                 s = -1;
  501.             }
  502.             ONDEBUG1( dump( msg, MIN(n, mb.dump_size) , stdout );
  503.                     fprintf( stdout, "to_send=%i\n", msg_len - r ) );
  504.         }
  505.         while ( msg_len -= r );
  506.     }
  507. }
  508.  
  509. static void mb_input( int socket ) {
  510.     int msg_type;
  511.     int c;
  512.  
  513.     if ( (c = mb_getc( socket )) == MB_STAMP ) {
  514.         ONDEBUG1( fprintf( stdout, "\n%c", c ) );
  515.         msg_type = mb_getc( socket );
  516.         ONDEBUG1( fprintf( stdout, " msg_type=%c", msg_type ) );
  517.         switch ( msg_type ) {
  518.         case MB_ONEWAY:
  519.         case MB_TWOWAY:
  520.         case MB_MULTIWAY:
  521.             mb_send( socket, msg_type );
  522.             return;
  523.         case MB_REPLY:
  524.             mb_recv( socket );
  525.             return;
  526.         case MB_REGISTER:
  527.             mb_register( socket );
  528.             return;
  529.         case MB_PROBE:
  530.             mb_probe( socket );
  531.             return;
  532.         default:
  533.             /* error */
  534.             break;
  535.         }
  536.     }
  537.     /* protocol error */
  538.     mb_drop_socket( socket );
  539.     close( socket );
  540. }
  541.  
  542. int mb_accept( int socket ) {
  543.     int sd;
  544.  
  545.     union {
  546.         struct sockaddr unix_addr;
  547.         struct sockaddr_in in_addr;
  548.     } in_address;
  549.     socklen_t addrlen = sizeof ( in_address );
  550.  
  551.     sd = accept( socket, (struct sockaddr *)&in_address, &addrlen );
  552.     if ( sd == -1 ) {
  553.         fprintf( stderr, "%s\n", strerror( errno ) );
  554.         return -1;
  555.     }
  556.  
  557.     mb_watch_socket( sd );
  558.  
  559.     return 0;
  560. }
  561.  
  562. int mb_open_unix( ) {
  563.     int sd;
  564.     struct sockaddr sd_address;
  565.     char pathname[ MAXPATHLEN ];
  566.  
  567.     if ( (sd = socket( PF_UNIX, SOCK_STREAM, 0 )) == -1 ) {
  568.         fprintf( stderr, "%s\n", strerror( errno ) );
  569.         return -1;
  570.     }
  571.  
  572.     sd_address.sa_family = AF_UNIX;
  573.     sprintf( pathname, "%s/%s", MB_UNIX, mb.port_name );
  574.     (void)strcpy( sd_address.sa_data, pathname );
  575.  
  576.     if ( bind( sd, &sd_address, sizeof ( sd_address )) != 0 ){
  577.         fprintf( stderr, "%s\n", strerror( errno ) );
  578.         close( sd );
  579.         return -1;
  580.     }
  581.    
  582.     if ( listen( sd, 5 ) != 0) {
  583.         fprintf( stderr, "%s\n", strerror( errno ) );
  584.         close( sd );
  585.         return -1;
  586.     }
  587.  
  588.     mb.socket_unix = sd;
  589.  
  590.     return 0;
  591. }
  592.  
  593. int mb_open_inet( ) {
  594.     int sd;
  595.     struct sockaddr_in sd_address;
  596.     struct servent *serv;
  597.  
  598.     if ( (serv = getservbyname( mb.port_name, "tcp" )) == 0 ) {
  599.         fprintf( stderr, "Service not found\n" );
  600.         return -1;
  601.     }
  602.     endservent();
  603.  
  604.     if ( (sd = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP )) == -1 ) {
  605.         fprintf( stderr, "%s\n", strerror( errno ) );
  606.         return -1;
  607.     }
  608.     sd_address.sin_family = AF_INET;
  609.     sd_address.sin_addr.s_addr = htonl( INADDR_ANY );
  610.     sd_address.sin_port = serv->s_port;
  611.  
  612.     if ( bind( sd, (struct sockaddr *)&sd_address, sizeof ( sd_address )) != 0 ){
  613.         fprintf( stderr, "%s\n", strerror( errno ) );
  614.         close( sd );
  615.         return -1;
  616.     }
  617.    
  618.     if ( listen( sd, 5 ) != 0) {
  619.         fprintf( stderr, "%s\n", strerror( errno ) );
  620.         close( sd );
  621.         return -1;
  622.     }
  623.  
  624.     mb.socket_inet = sd;
  625.  
  626.     return 0;
  627. }
  628.  
  629. void mb_open( void ) {
  630.     mb_open_unix( );
  631.     mb_open_inet( );
  632. }
  633.  
  634. void mb_close_unix( void ) {
  635.     char pathname[ MAXPATHLEN ];
  636.  
  637.     if ( mb.socket_unix != -1 ) {
  638.         close( mb.socket_unix );
  639.         mb.socket_unix = -1;
  640.         /* free local address */
  641.         sprintf( pathname, "%s/%s", MB_UNIX, mb.port_name );
  642.         unlink( pathname );
  643.     }
  644. }
  645.  
  646. void mb_close_inet( void ) {
  647.     if ( mb.socket_inet != -1 ) {
  648.         close( mb.socket_inet );
  649.         mb.socket_inet = -1;
  650.     }
  651. }
  652.  
  653. void mb_close( void ) {
  654.     struct mb_socket *s_in;
  655.  
  656.     while ( (s_in = (struct mb_socket *)list_delete( mb.in_sockets, -1 )) ) {
  657.         close( s_in->s_socket );
  658.         if ( s_in->s_name )
  659.             free( s_in->s_name );
  660.         free( s_in );
  661.     }
  662.     mb_close_inet( );
  663.     mb_close_unix( );
  664. }
  665.  
  666. void mb_intr( int sig ) {
  667.     mb_exit( 1 );
  668. }
  669.  
  670. void mb_exit( int status ) {
  671.     mb_close( );
  672.     exit( status );
  673. }
  674.  
  675. static void startup( ) {
  676.     if ( mb.interactive ) {
  677.         mb.kbd_shell = shell_new( );
  678.  
  679.         shell_addcmd( mb.kbd_shell, "open",     "open [unix | inet]",   kbd_open );
  680.         shell_addcmd( mb.kbd_shell, "close",    "close [unix | inet]",  kbd_close);
  681.         shell_addcmd( mb.kbd_shell, "pagesize", "pagesize [nbytes]",    kbd_pagesize);
  682.         shell_addcmd( mb.kbd_shell, "timeout",  "timeout [nsecs]",      kbd_timeout);
  683. #if defined( DEBUG )
  684.         shell_addcmd( mb.kbd_shell, "dumpsize", "dumpsize [n_octets]",  kbd_dumpsize);
  685.         shell_addcmd( mb.kbd_shell, "debug",    "debug [level]",        kbd_debug);
  686. #endif
  687.         shell_addcmd( mb.kbd_shell, "info",     "info",                 kbd_info);
  688.         shell_addcmd( mb.kbd_shell, "exit",     "exit | quit",          kbd_exit);
  689.         shell_addcmd( mb.kbd_shell, "quit",     "quit | exit",          kbd_exit);
  690.  
  691. #ifdef SIGTTOU
  692.         signal( SIGTTOU, SIG_IGN );
  693. #endif
  694. #ifdef SIGTTIN
  695.         signal( SIGTTIN, SIG_IGN );
  696. #endif
  697. #ifdef SIGTSTP
  698.         signal( SIGTSTP, SIG_IGN );
  699. #endif
  700.  
  701.         signal( SIGPIPE, SIG_IGN ); /* raised if broken stream on write */
  702.  
  703.         signal( SIGHUP, mb_intr );
  704.         signal( SIGINT, mb_intr );
  705.         signal( SIGTERM, mb_intr );
  706.  
  707.         fprintf( stdout, "MagicBus %s(%s)\n", MB_VERSION, MB_REVISION);
  708.         fprintf( stdout, "(C)2010 frasq.org.\n" );
  709.         fprintf( stdout, "%s", mb.kbd_prompt );
  710.         fflush( stdout );
  711.     }
  712.     else {
  713.         int pid;
  714.  
  715.         pid = fork ();
  716.         if ( pid == -1 ) {
  717.             fprintf( stderr, "%s\n", strerror( errno ) );
  718.             exit( 1 );
  719.         }
  720.         if ( pid == 0 )
  721.             /* parent */
  722.             exit( 0 );
  723.  
  724.         pid = fork ();
  725.         if ( pid == -1 ) {
  726.             fprintf( stderr, "%s\n", strerror( errno ) );
  727.             exit( 1 );
  728.         }
  729.         if ( pid > 0 )
  730.             /* child */
  731.             exit( 0 );
  732.  
  733. #ifdef SIGTTOU
  734.         signal( SIGTTOU, SIG_IGN );
  735. #endif
  736. #ifdef SIGTTIN
  737.         signal( SIGTTIN, SIG_IGN );
  738. #endif
  739. #ifdef SIGTSTP
  740.         signal( SIGTSTP, SIG_IGN );
  741. #endif
  742.  
  743.         signal( SIGPIPE, SIG_IGN ); /* raised if broken stream on write */
  744.  
  745.         signal( SIGHUP, mb_intr );
  746.         signal( SIGINT, mb_intr );
  747.         signal( SIGTERM, mb_intr );
  748.  
  749.         if ( mb_open_unix( ) == -1 )
  750.             exit( 1 );
  751.  
  752.         if ( !mb.local )
  753.             if ( mb_open_inet( ) == -1 )
  754.                 exit( 1 );
  755.     }
  756. }
  757.  
  758. static void main_loop( ) {
  759.     fd_set read_fds;
  760.     int n_fds;
  761.     int i;
  762.  
  763.     struct timeval time_out, *tp = 0;
  764.     time_t next_time;
  765.  
  766.     long delay = 0L;
  767.     struct mb_socket *s_in;
  768.     int nb_in_sockets;
  769.  
  770.     for ( ;; ) {    /* forever */
  771.         FD_ZERO( &read_fds );
  772.         n_fds = FD_SETSIZE;
  773.  
  774.         nb_in_sockets = list_length( mb.in_sockets );
  775.  
  776.         if ( mb.interactive )
  777.             FD_SET( 0, &read_fds );
  778.  
  779.         if ( mb.socket_inet != -1 )
  780.             FD_SET( mb.socket_inet, &read_fds );
  781.  
  782.         if ( mb.socket_unix != -1 )
  783.             FD_SET( mb.socket_unix, &read_fds );
  784.  
  785.         for ( i = 0; i < nb_in_sockets; i++ ) {
  786.             s_in = (struct mb_socket *)list_get( mb.in_sockets, i );
  787.             FD_SET( s_in->s_socket, &read_fds );
  788.         }
  789.  
  790.         switch ( select( n_fds, &read_fds, 0, 0, tp )) {
  791.         case -1:    /* trouble */
  792.             if ( errno != EINTR )
  793.                 mb_exit( 1 );
  794.             break;
  795.  
  796.         case 0: /* time out */
  797.             break;
  798.  
  799.         default:    /* event */
  800.             if ( mb.interactive && FD_ISSET( 0, &read_fds ))
  801.                 /* from operator */
  802.                 shell_input( mb.kbd_shell, mb.kbd_prompt );
  803.             if ( mb.socket_unix != -1 && FD_ISSET( mb.socket_unix, &read_fds ))
  804.                 /* from here */
  805.                 mb_accept( mb.socket_unix );
  806.             if ( mb.socket_inet != -1 && FD_ISSET( mb.socket_inet, &read_fds ))
  807.                 /* from afar */
  808.                 mb_accept( mb.socket_inet );
  809.  
  810.             for ( i = 0; i < list_length( mb.in_sockets ); i++ ) {
  811.                 s_in = (struct mb_socket *)list_get( mb.in_sockets, i );
  812.                 if ( FD_ISSET( s_in->s_socket, &read_fds ))
  813.                     mb_input( s_in->s_socket );
  814.             }
  815.             break;
  816.         }
  817.         /* check timers */
  818.         if( (next_time = mb_check_toreqs( )) ) {
  819.             /* wake up for next timer */
  820.             if( (delay = next_time - time( (time_t *)0 )) < 0 )
  821.                 delay = 0;  /* just to be sure */
  822.             ONDEBUG2( fprintf( stdout, "\n[delay=%ld]", delay ));
  823.             time_out.tv_sec = delay;
  824.             time_out.tv_usec = 0L;
  825.             tp = &time_out;
  826.         }
  827.         else
  828.             tp = 0;
  829.     }
  830. }
  831.  
  832. int main( int argc, char **argv ) {
  833.     extern int opterr;
  834.  
  835.     int c;
  836.  
  837.     mb.local = 0;
  838.     mb.interactive = 0;
  839.     mb.kbd_prompt = MBD_PROMPT;
  840.     mb.port_name = MB_INET;
  841.     mb.socket_inet = -1;
  842.     mb.socket_unix = -1;
  843.     mb.in_sockets = list_new();
  844.     mb.to_reqs = list_new();
  845.     mb.page_size = MB_PAGESIZE;
  846.     mb.timeout = 60;
  847.     mb.dump_size = 16;
  848.  
  849.     opterr = 0;
  850.  
  851. #if defined( DEBUG )
  852.     while ( (c = getopt( argc, argv, "D:d:P:ip:lt:" )) != -1 )
  853. #else
  854.     while ( (c = getopt( argc, argv, "P:ip:lt:" )) != -1 )
  855. #endif
  856.         switch ( c ) {
  857. #if defined( DEBUG )
  858.         case 'D':
  859.             debug = atoi( optarg );
  860.             break;
  861.         case 'd': {
  862.             int dump_size = atoi( optarg );
  863.             if ( dump_size >= 16 )
  864.                 mb.dump_size = dump_size;
  865.             break;
  866.         }
  867. #endif
  868.         case 'P':
  869.             mb.kbd_prompt = optarg;
  870.             break;
  871.         case 'i':
  872.             mb.interactive = 1;
  873.             break;
  874.         case 'p': {
  875.             int page_size = atoi( optarg );
  876.             if ( page_size > 0 )
  877.                 mb.page_size = page_size;
  878.             break;
  879.         }
  880.         case 'l':
  881.             mb.local = 1;
  882.             break;
  883.         case 't': {
  884.             int to = atoi( optarg );
  885.             if ( to > 0 )
  886.                 mb.timeout = to;
  887.             break;
  888.         }
  889.         case '?':
  890.         default:
  891.         error:
  892. #if defined( DEBUG )
  893.             fprintf( stderr, "%s [-D level] [-d dump_size] [-P prompt] [-i] [-l] [-p page_size] [-t time_out] [port_name]\n", argv[ 0 ] );
  894. #else
  895.             fprintf( stderr, "%s [-P prompt] [-i] [-l] [-p page_size] [-t time_out] [port_name]\n", argv[ 0 ] );
  896. #endif
  897.             exit( 1 );
  898.         }
  899.  
  900.     switch ( argc - optind ) {
  901.     case 0:
  902.         break;
  903.     case 1:
  904.         mb.port_name = argv[ optind ];
  905.         break;
  906.     default:
  907.         goto error;
  908.     }
  909.  
  910.     /* check options */
  911.     if ( mb.interactive )
  912.         mb.local = 0;
  913.  
  914. #if defined( DEBUG )
  915.     setbuf( stdout, 0 );
  916. #endif
  917.  
  918.     startup( );
  919.     main_loop( );
  920. }

Comments

Your comment:
[p] [b] [i] [u] [s] [quote] [pre] [br] [code] [url] [email] strip help 2000

Enter a maximum of 2000 characters.
Improve the presentation of your text with the following formatting tags:
[p]paragraph[/p], [b]bold[/b], [i]italics[/i], [u]underline[/u], [s]strike[/s], [quote]citation[/quote], [pre]as is[/pre], [br]line break,
[url]http://www.izend.org[/url], [url=http://www.izend.org]site[/url], [email]izend@izend.org[/email], [email=izend@izend.org]izend[/email],
[code]command[/code], [code=language]source code in c, java, php, html, javascript, xml, css, sql, bash, dos, make, etc.[/code].