2 static char *RCSid
= "$Id$";
6 * The Regina Rexx Interpreter
7 * Copyright (C) 1992-1994 Anders Christensen <anders@pvv.unit.no>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the Free
21 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #ifdef EXTERNAL_TO_REGINA
28 /* tmpstr_of must be defined before the inclusion of extstack.h since it
29 * redefines tsd_t (grrr) */
30 volatile char *tmpstr_of( tsd_t
*TSD
, const streng
*input
)
32 /* even exiterror isn't permitted at this point. */
33 assert(0); /* hint while debugging */
34 return((volatile char *) input
->value
);
40 # if defined(_MSC_VER)
42 /* Stupid MSC can't compile own headers without warning at least in VC 5.0 */
43 # pragma warning(disable: 4115 4201 4214)
47 # pragma warning(default: 4115 4201 4214)
54 # ifdef HAVE_SYS_SOCKET_H
55 # include <sys/socket.h>
57 # ifdef HAVE_NETINET_IN_H
58 # include <netinet/in.h>
60 # ifdef HAVE_SYS_SELECT_H
61 # include <sys/select.h>
66 # ifdef HAVE_ARPA_INET_H
67 # include <arpa/inet.h>
81 # define DEBUGDUMP(x) {x;}
83 # define DEBUGDUMP(x) {}
86 void showerror( int err
, int suberr
, char *tmpl
, ...)
90 fprintf( stderr
, "Error:%d.%d - ", err
, suberr
);
92 fprintf( stderr
, "Error:%d - ", err
);
93 va_start( argptr
, tmpl
);
94 vfprintf( stderr
, tmpl
, argptr
);
96 fprintf( stderr
, "\n" );
99 int init_external_queue( const tsd_t
*TSD
)
103 WORD wsver
= (WORD
)MAKEWORD(1,1);
105 if ( WSAStartup( wsver
, &wsaData
) != 0 )
107 /* TSD can be NULL when called from rxqueue or rxstack */
108 if ( TSD
== NULL
|| TSD
->called_from_saa
)
109 showerror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_NO_WINSOCK
, ERR_RXSTACK_NO_WINSOCK_TMPL
, WSAGetLastError() );
111 exiterror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_NO_WINSOCK
, WSAGetLastError() );
115 TSD
= TSD
; /* keep compiler happy */
120 void term_external_queue( void )
127 int get_default_port_number( void )
130 char *port
= getenv("RXSTACK");
143 int get_length_from_header( const tsd_t
*TSD
, streng
*header
)
148 result
= MAKESTRENG( RXSTACK_HEADER_SIZE
- 1 );
151 result
->len
= RXSTACK_HEADER_SIZE
- 1;
152 memcpy( result
->value
, header
->value
+1, RXSTACK_HEADER_SIZE
-1 );
153 DEBUGDUMP(printf("Hex value: %s\n", result
->value
););
154 length
= REXX_X2D( result
);
155 DROPSTRENG( result
);
160 #if !defined(NO_EXTERNAL_QUEUES)
162 int get_default_server_address( void )
164 return inet_addr( "127.0.0.1" );
167 int connect_to_rxstack( tsd_t
*TSD
, int portno
, streng
*server_name
, int server_address
)
169 struct sockaddr_in server
;
172 * Connect to external rxstack process/daemon/service
174 memset( &server
, 0, sizeof(server
) );
175 server
.sin_family
= AF_INET
;
176 server
.sin_addr
.s_addr
= server_address
;
177 server
.sin_port
= htons((unsigned short) portno
);
179 sock
= socket( AF_INET
, SOCK_STREAM
, 0 );
182 if ( connect( sock
, (struct sockaddr
*)&server
, sizeof(server
) ) < 0 )
184 /* TSD can be NULL when called from rxqueue or rxstack */
185 if ( TSD
== NULL
|| TSD
->called_from_saa
)
186 showerror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_CANT_CONNECT
, ERR_RXSTACK_CANT_CONNECT_TMPL
, server_name
->value
, portno
, strerror ( errno
) );
188 exiterror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_CANT_CONNECT
, tmpstr_of( (void *) TSD
, server_name
), portno
, strerror ( errno
) );
195 #if !defined(NO_EXTERNAL_QUEUES)
196 int disconnect_from_rxstack( const tsd_t
*TSD
, int sock
)
200 DEBUGDUMP(printf("Diconnecting from socket %d\n", sock
););
201 rc
= send_command_to_rxstack( TSD
, sock
, RXSTACK_EXIT_STR
, NULL
, 0 );
207 #if !defined(NO_EXTERNAL_QUEUES)
208 int send_command_to_rxstack( const tsd_t
*TSD
, int sock
, char *action
, char *str
, int len
)
210 streng
*qlen
, *header
;
213 DEBUGDUMP(printf("Sending to %d Action: %s <%s> Len:%d\n", sock
, action
, (str
) ? str
: "", len
););
214 qlen
= REXX_D2X( len
);
217 header
= REXX_RIGHT( qlen
, RXSTACK_HEADER_SIZE
, '0');
221 header
->value
[0] = action
[0];
222 rc
= send( sock
, PSTRENGVAL(header
), PSTRENGLEN(header
), 0 );
223 DEBUGDUMP(printf("Send length: %s(%d) rc %d\n", PSTRENGVAL(header
),PSTRENGLEN(header
),rc
););
224 if ( str
&& rc
!= -1 )
226 rc
= send( sock
, str
, len
, 0 );
227 DEBUGDUMP(printf("Send str length: %d\n", rc
););
229 DROPSTRENG( header
);
236 #if !defined(NO_EXTERNAL_QUEUES)
237 streng
*read_result_from_rxstack( const tsd_t
*TSD
, int sock
, int result_size
)
240 * Creates a streng of length 'result_size' and if non-zero,
241 * reads this many characters from the socket.
242 * The caller MUST DROPSTRENG this streng.
247 result
= MAKESTRENG( result_size
);
250 result
->len
= result_size
;
253 rc
= recv( sock
, PSTRENGVAL(result
), PSTRENGLEN(result
), 0 );
254 DEBUGDUMP(printf("Recv result: %s(%d) length: %d\n", PSTRENGVAL(result
),PSTRENGLEN(result
), rc
););
261 #if !defined(NO_EXTERNAL_QUEUES)
262 int parse_queue( tsd_t
*TSD
, streng
*queue
, streng
**server_name
, int *server_address
, int *portno
)
265 * Validate the queue name. Format is [queue][@host[:port]]
267 int num_colons
=0,num_ats
=0,num_dots
=0,i
,colon_pos
=-1,at_pos
=-1;
268 char *tmp_server
=NULL
,*tmp_port
=NULL
;
269 int len
=PSTRENGLEN( queue
);
270 struct hostent
*host
;
274 * Find the optional '@' and ':'...
276 for ( i
= 0; i
< len
; i
++ )
278 if ( queue
->value
[i
] == '@' )
282 tmp_server
= queue
->value
+at_pos
+1;
283 queue
->value
[at_pos
] = '\0';
285 else if ( queue
->value
[i
] == ':' )
289 tmp_port
= queue
->value
+colon_pos
+1;
290 queue
->value
[colon_pos
] = '\0';
297 && at_pos
> colon_pos
) )
299 /* TSD can be NULL when called from rxqueue or rxstack */
300 if ( TSD
== NULL
|| TSD
->called_from_saa
)
301 showerror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_INVALID_QUEUE
, ERR_RXSTACK_INVALID_QUEUE_TMPL
, queue
->value
);
303 exiterror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_INVALID_QUEUE
, tmpstr_of( (void *) TSD
, queue
) );
307 * Sort out the port number portion...
309 if ( num_colons
== 1 )
311 *portno
= atoi( tmp_port
);
312 queue
->len
= colon_pos
;
316 *portno
= get_default_port_number();
318 DEBUGDUMP(printf("port <%d>\n", *portno
););
320 * Sort out server_name portion...
325 * Get the length of the server portion of the specified queue
326 * If 3 dots, we have an IP address for the server address and queue name
328 len
= strlen( tmp_server
);
329 for( i
= 0, num_dots
= 0; i
< len
; i
++ )
331 if ( tmp_server
[i
] == '.' )
336 host
= gethostbyname( tmp_server
);
339 ptr
= (struct in_addr
*)host
->h_addr
;
340 *server_address
= ptr
->s_addr
;
341 *server_name
= MAKESTRENG( len
+1 );
342 if ( *server_name
== NULL
)
344 /* TSD can be NULL when called from rxqueue or rxstack */
345 if ( TSD
== NULL
|| TSD
->called_from_saa
)
346 showerror( ERR_STORAGE_EXHAUSTED
, 0, ERR_STORAGE_EXHAUSTED_TMPL
);
348 exiterror( ERR_STORAGE_EXHAUSTED
, 0 );
351 (*server_name
)->len
= len
;
352 memcpy( (*server_name
)->value
, tmp_server
, len
);
353 (*server_name
)->value
[len
] = '\0';
357 /* TSD can be NULL when called from rxqueue or rxstack */
358 if ( TSD
== NULL
|| TSD
->called_from_saa
)
359 showerror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_NO_IP
, ERR_RXSTACK_NO_IP_TMPL
, tmp_server
);
361 exiterror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_NO_IP
, tmp_server
);
365 else if ( num_dots
== 3 )
367 *server_address
= inet_addr( tmp_server
);
368 *server_name
= MAKESTRENG( len
+1 );
369 if ( *server_name
== NULL
)
371 /* TSD can be NULL when called from rxqueue or rxstack */
372 if ( TSD
== NULL
|| TSD
->called_from_saa
)
373 showerror( ERR_STORAGE_EXHAUSTED
, 0, ERR_STORAGE_EXHAUSTED_TMPL
);
375 exiterror( ERR_STORAGE_EXHAUSTED
, 0 );
378 (*server_name
)->len
= len
;
379 memcpy( (*server_name
)->value
, tmp_server
, len
);
380 (*server_name
)->value
[len
] = '\0';
384 /* TSD can be NULL when called from rxqueue or rxstack */
385 if ( TSD
== NULL
|| TSD
->called_from_saa
)
386 showerror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_INVALID_SERVER
, ERR_RXSTACK_INVALID_SERVER_TMPL
, tmp_server
);
388 exiterror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_INVALID_SERVER
, tmp_server
);
395 *server_address
= inet_addr("127.0.0.1");
396 *server_name
= MAKESTRENG( 10 );
397 if ( *server_name
== NULL
)
399 /* TSD can be NULL when called from rxqueue or rxstack */
400 if ( TSD
== NULL
|| TSD
->called_from_saa
)
401 showerror( ERR_STORAGE_EXHAUSTED
, 0, ERR_STORAGE_EXHAUSTED_TMPL
);
403 exiterror( ERR_STORAGE_EXHAUSTED
, 0 );
406 (*server_name
)->len
= 10;
407 memcpy( (*server_name
)->value
, "127.0.0.1", 9 );
408 (*server_name
)->value
[9] = '\0';
410 DEBUGDUMP(printf("server <%s>\n", (*server_name
)->value
););
415 int delete_queue_from_rxstack( const tsd_t
*TSD
, int sock
, streng
*queue_name
)
420 rc
= send_command_to_rxstack( TSD
, sock
, RXSTACK_DELETE_QUEUE_STR
, PSTRENGVAL( queue_name
), PSTRENGLEN( queue_name
) );
423 result
= read_result_from_rxstack( TSD
, sock
, RXSTACK_HEADER_SIZE
);
426 rc
= result
->value
[0]-'0';
427 DROPSTRENG( result
);
433 int timeout_queue_on_rxstack( const tsd_t
*TSD
, int sock
, long timeout
)
436 streng
*result
,*qtimeout
, *hex_timeout
;
438 qtimeout
= REXX_D2X( timeout
);
441 hex_timeout
= REXX_RIGHT( qtimeout
, RXSTACK_TIMEOUT_SIZE
, '0');
442 DROPSTRENG( qtimeout
);
445 DEBUGDUMP(printf("Send timeout: %s(%d) rc %d\n", PSTRENGVAL(hex_timeout
),PSTRENGLEN(hex_timeout
),rc
););
446 rc
= send_command_to_rxstack( TSD
, sock
, RXSTACK_TIMEOUT_QUEUE_STR
, PSTRENGVAL(hex_timeout
), PSTRENGLEN(hex_timeout
) );
447 DROPSTRENG( hex_timeout
);
450 result
= read_result_from_rxstack( TSD
, sock
, RXSTACK_HEADER_SIZE
);
453 rc
= result
->value
[0]-'0';
454 DROPSTRENG( result
);
462 int get_number_in_queue_from_rxstack( const tsd_t
*TSD
, int sock
)
467 rc
= send_command_to_rxstack( TSD
, sock
, RXSTACK_NUMBER_IN_QUEUE_STR
, NULL
, 0 );
470 header
= read_result_from_rxstack( TSD
, sock
, RXSTACK_HEADER_SIZE
);
473 rc
= header
->value
[0]-'0';
477 * now get the length from the header
479 DEBUGDUMP(printf("before get_length_from_header: %s\n", header
->value
););
480 length
= get_length_from_header( TSD
, header
);
484 /* TSD can be NULL when called from rxqueue or rxstack */
485 if ( TSD
== NULL
|| TSD
->called_from_saa
)
486 showerror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_INTERNAL
, ERR_RXSTACK_INTERNAL_TMPL
, rc
, "Getting number in queue" );
488 exiterror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_INTERNAL
, rc
, "Getting number in queue" );
490 DROPSTRENG( header
);
496 int get_queue_from_rxstack( const tsd_t
*TSD
, int sock
, streng
**result
)
501 rc
= send_command_to_rxstack( TSD
, sock
, RXSTACK_GET_QUEUE_STR
, NULL
, 0 );
504 header
= read_result_from_rxstack( TSD
, sock
, RXSTACK_HEADER_SIZE
);
507 rc
= header
->value
[0]-'0';
511 * now get the length from the header and get that many characters...
513 length
= get_length_from_header( TSD
, header
);
514 *result
= read_result_from_rxstack( TSD
, sock
, length
);
518 /* TSD can be NULL when called from rxqueue or rxstack */
519 if ( TSD
== NULL
|| TSD
->called_from_saa
)
520 showerror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_INTERNAL
, ERR_RXSTACK_INTERNAL_TMPL
, rc
, "Getting queue from stack" );
522 exiterror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_INTERNAL
, rc
, "Getting queue from stack" );
524 DROPSTRENG( header
);
530 int get_line_from_rxstack( const tsd_t
*TSD
, int sock
, streng
**result
)
535 rc
= send_command_to_rxstack( TSD
, sock
, RXSTACK_PULL_STR
, NULL
, 0 );
538 header
= read_result_from_rxstack( TSD
, sock
, RXSTACK_HEADER_SIZE
);
541 rc
= header
->value
[0]-'0';
545 * now get the length from the header and get that many characters...
547 length
= get_length_from_header( TSD
, header
);
548 *result
= read_result_from_rxstack( TSD
, sock
, length
);
550 else if ( rc
== 1 || rc
== 4 )
553 * queue is empty - return a NULL
559 /* TSD can be NULL when called from rxqueue or rxstack */
560 if ( TSD
== NULL
|| TSD
->called_from_saa
)
561 showerror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_INTERNAL
, ERR_RXSTACK_INTERNAL_TMPL
, rc
, "Getting line from queue" );
563 exiterror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_INTERNAL
, rc
, "Getting line from queue" );
565 DROPSTRENG( header
);
571 int create_queue_on_rxstack( const tsd_t
*TSD
, int sock
, streng
*queue
, streng
**result
)
576 rc
= send_command_to_rxstack( TSD
, sock
, RXSTACK_CREATE_QUEUE_STR
, (queue
) ? PSTRENGVAL( queue
) : NULL
, (queue
) ? PSTRENGLEN( queue
) : 0 );
579 header
= read_result_from_rxstack( TSD
, sock
, RXSTACK_HEADER_SIZE
);
582 rc
= header
->value
[0]-'0';
586 * the requested queue name was created, so put the input
587 * value into the result
589 *result
= MAKESTRENG( PSTRENGLEN( queue
) );
590 if ( *result
== NULL
)
592 /* TSD can be NULL when called from rxqueue or rxstack */
593 if ( TSD
== NULL
|| TSD
->called_from_saa
)
594 showerror( ERR_STORAGE_EXHAUSTED
, 0, ERR_STORAGE_EXHAUSTED_TMPL
);
596 exiterror( ERR_STORAGE_EXHAUSTED
, 0 );
600 (*result
)->len
= PSTRENGLEN( queue
);
601 memcpy( (*result
)->value
, PSTRENGVAL( queue
), PSTRENGLEN( queue
) );
607 * now get the length from the header and get that many characters...
609 length
= get_length_from_header( TSD
, header
);
610 *result
= read_result_from_rxstack( TSD
, sock
, length
);
614 /* TSD can be NULL when called from rxqueue or rxstack */
615 if ( TSD
== NULL
|| TSD
->called_from_saa
)
616 showerror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_INTERNAL
, ERR_RXSTACK_INTERNAL_TMPL
, rc
, "Creating queue" );
618 exiterror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_INTERNAL
, rc
, "Creating queue" );
620 DROPSTRENG( header
);
626 int set_queue_in_rxstack( const tsd_t
*TSD
, int sock
, streng
*queue_name
, streng
**result
)
631 rc
= send_command_to_rxstack( TSD
, sock
, RXSTACK_SET_QUEUE_STR
, PSTRENGVAL( queue_name
), PSTRENGLEN( queue_name
) );
634 header
= read_result_from_rxstack( TSD
, sock
, RXSTACK_HEADER_SIZE
);
637 rc
= header
->value
[0]-'0';
641 * now get the length from the header and get that many characters...
643 length
= get_length_from_header( TSD
, header
);
644 *result
= read_result_from_rxstack( TSD
, sock
, length
);
648 /* TSD can be NULL when called from rxqueue or rxstack */
649 if ( TSD
== NULL
|| TSD
->called_from_saa
)
650 showerror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_INTERNAL
, ERR_RXSTACK_INTERNAL_TMPL
, rc
, "Setting quueue" );
652 exiterror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_INTERNAL
, rc
, "Setting quueue" );
654 DROPSTRENG( header
);
660 int queue_line_fifo_to_rxstack( const tsd_t
*TSD
, int sock
, streng
*line
)
665 rc
= send_command_to_rxstack( TSD
, sock
, RXSTACK_QUEUE_FIFO_STR
, PSTRENGVAL( line
), PSTRENGLEN( line
) );
668 header
= read_result_from_rxstack( TSD
, sock
, RXSTACK_HEADER_SIZE
);
671 rc
= header
->value
[0]-'0';
674 /* TSD can be NULL when called from rxqueue or rxstack */
675 if ( TSD
== NULL
|| TSD
->called_from_saa
)
676 showerror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_INTERNAL
, ERR_RXSTACK_INTERNAL_TMPL
, rc
, "Queueing line" );
678 exiterror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_INTERNAL
, rc
, "Queueing line" );
680 DROPSTRENG( header
);
686 int queue_line_lifo_to_rxstack( const tsd_t
*TSD
, int sock
, streng
*line
)
691 rc
= send_command_to_rxstack( TSD
, sock
, RXSTACK_QUEUE_LIFO_STR
, PSTRENGVAL( line
), PSTRENGLEN( line
) );
694 header
= read_result_from_rxstack( TSD
, sock
, RXSTACK_HEADER_SIZE
);
697 rc
= header
->value
[0]-'0';
700 /* TSD can be NULL when called from rxqueue or rxstack */
701 if ( TSD
== NULL
|| TSD
->called_from_saa
)
702 showerror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_INTERNAL
, ERR_RXSTACK_INTERNAL_TMPL
, rc
, "Queueing line" );
704 exiterror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_INTERNAL
, rc
, "Queueing line" );
706 DROPSTRENG( header
);