forgotten commit. disabled until egl is adapted.
[AROS-Contrib.git] / regina / extstack.c
blobec236e42e93e9dae9978e024454336d1974262c7
1 /*
2 * The Regina Rexx Interpreter
3 * Copyright (C) 1992-1994 Anders Christensen <anders@pvv.unit.no>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the Free
17 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #if defined(__WATCOMC__) && defined(OS2)
21 # include <os2/types.h>
22 #endif
23 #include "rexx.h"
25 #if defined(WIN32)
26 # if defined(_MSC_VER)
27 # if _MSC_VER >= 1100
28 /* Stupid MSC can't compile own headers without warning at least in VC 5.0 */
29 # pragma warning(disable: 4115 4201 4214 4514)
30 # endif
31 # include <windows.h>
32 # if _MSC_VER >= 1100
33 # pragma warning(default: 4115 4201 4214)
34 # endif
35 # else
36 # include <windows.h>
37 # include <winsock.h>
38 # endif
39 # include <io.h>
40 #else
41 # ifdef HAVE_TYPES_H
42 # include <types.h>
43 # endif
44 # ifdef HAVE_SYS_SOCKET_H
45 # include <sys/socket.h>
46 # endif
47 # ifdef HAVE_NETINET_IN_H
48 # include <netinet/in.h>
49 # endif
50 # ifdef HAVE_SYS_SELECT_H
51 # include <sys/select.h>
52 # endif
53 # ifdef HAVE_NETDB_H
54 # include <netdb.h>
55 # endif
56 # ifdef HAVE_ARPA_INET_H
57 # include <arpa/inet.h>
58 # endif
59 #endif
61 #include <stdio.h>
62 #include <stdlib.h>
63 #include <string.h>
64 #include <assert.h>
65 #include <stdarg.h>
67 #include "extstack.h"
69 #ifdef EXTERNAL_TO_REGINA
70 # include <assert.h>
71 /* tmpstr_of must be defined before the inclusion of extstack.h since it
72 * redefines tsd_t (grrr) */
73 volatile char *tmpstr_of( dummy_tsd_t *TSD, const streng *input )
75 /* even exiterror isn't permitted at this point. */
76 assert(0); /* hint while debugging */
77 return((volatile char *) input->value);
79 #endif
81 static int debug = -1 ;
82 #define DEBUGDUMP(x) { \
83 if ( debug == -1 ) \
84 { \
85 debug = ( getenv( "RXDEBUG" ) == NULL ) ? 0 : 1 ; \
86 } \
87 if ( debug ) \
88 { \
89 x ; \
90 } \
93 /* "localhost" maps to "127.0.0.1" on most systems but it may use DNS on
94 * badly configured systems. Use "127.0.0.1" to bypass any errors.
96 static const char ReginaLocalHost[] = "127.0.0.1";
98 void showerror( int err, int suberr, char *tmpl, ...)
100 va_list argptr;
101 if ( suberr )
102 fprintf( stderr, "Error:%d.%d - ", err, suberr );
103 else
104 fprintf( stderr, "Error:%d - ", err );
105 va_start( argptr, tmpl );
106 vfprintf( stderr, tmpl, argptr );
107 va_end( argptr );
108 fprintf( stderr, "\n" );
111 int init_external_queue( const tsd_t *TSD )
113 int rc=0;
114 #ifdef WIN32
115 WORD wsver = (WORD)MAKEWORD(1,1);
116 WSADATA wsaData;
117 if ( WSAStartup( wsver, &wsaData ) != 0 )
119 /* TSD will be NULL when called from rxqueue or rxstack */
120 if ( TSD == NULL )
121 showerror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_NO_WINSOCK, ERR_RXSTACK_NO_WINSOCK_TMPL, WSAGetLastError() );
122 else if ( !TSD->called_from_saa )
123 exiterror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_NO_WINSOCK, WSAGetLastError() );
124 rc = 1;
126 #else
127 TSD = TSD; /* keep compiler happy */
128 #endif
129 return rc;
132 void term_external_queue( void )
134 #ifdef WIN32
135 WSACleanup();
136 #endif
139 int get_length_from_header( const tsd_t *TSD, const streng *header )
141 int length=0,error=1;
142 streng *result=NULL;
144 result = MAKESTRENG( RXSTACK_HEADER_SIZE - 1 );
145 if ( result )
147 result->len = RXSTACK_HEADER_SIZE - 1;
148 memcpy( result->value, header->value+1, RXSTACK_HEADER_SIZE-1 );
149 DEBUGDUMP(printf("Hex value: %.*s\n", PSTRENGLEN(result),PSTRENGVAL(result)););
150 length = REXX_X2D( result, &error );
151 DROPSTRENG( result );
153 return ( error ) ? 0 : length;
156 #if !defined(NO_EXTERNAL_QUEUES)
157 int default_port_number( void )
159 int portno;
160 char dummy;
161 char *port = getenv("RXSTACK"); /* FIXME: May be overwritten by VALUE-BIF */
163 if ( port != NULL )
165 if ( sscanf( port, "%d %c", &portno, &dummy ) == 1 )
166 if ( (portno > 1) && (portno < 0xFFFF) )
167 return portno;
169 return RXSOCKET;
172 int default_external_address( void )
174 return inet_addr( ReginaLocalHost );
177 streng *default_external_name( const tsd_t *TSD )
179 int len;
180 streng *result;
182 len = sizeof(ReginaLocalHost); /* includes the term. \0 */
183 result = MAKESTRENG( len );
184 result->len = len - 1;
185 memcpy( result->value, ReginaLocalHost, len ) ;
186 return result ;
189 int connect_to_rxstack( tsd_t *TSD, Queue *q )
191 struct sockaddr_in server;
192 int eno;
195 * Connect to external rxstack process/daemon/service
197 assert( q->type == QisExternal ) ;
198 DEBUGDUMP(printf("In connect_to_rxstack: q = {name=%.*s, address=%08X, portno=%d}\n", q->u.e.name->len, q->u.e.name->value, q->u.e.address, q->u.e.portno););
199 memset( &server, 0, sizeof(server) );
200 server.sin_family = AF_INET;
201 server.sin_addr.s_addr = q->u.e.address;
202 server.sin_port = htons((unsigned short) q->u.e.portno);
204 q->u.e.socket = socket( AF_INET, SOCK_STREAM, 0 );
205 if ( q->u.e.socket >= 0 )
208 if ( connect( q->u.e.socket, (struct sockaddr *)&server, sizeof(server) ) >= 0 )
210 DEBUGDUMP(printf("In connect_to_rxstack: socket=%d\n", q->u.e.socket););
211 return(q->u.e.socket);
213 eno = errno;
214 close(q->u.e.socket);
215 q->u.e.socket = -1;
216 errno = eno;
218 /* TSD will be NULL when called from rxqueue or rxstack */
219 if ( TSD == NULL )
220 showerror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_CANT_CONNECT, ERR_RXSTACK_CANT_CONNECT_TMPL, q->u.e.name, q->u.e.portno, strerror ( errno ) );
221 else if ( !TSD->called_from_saa )
222 exiterror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_CANT_CONNECT, tmpstr_of( TSD, q->u.e.name ), q->u.e.portno, strerror ( errno ) );
224 return -1;
227 int disconnect_from_rxstack( const tsd_t *TSD, Queue *q )
229 int rc;
231 assert( q->type == QisExternal ) ;
232 if (q->u.e.socket != -1)
234 DEBUGDUMP(printf("Disconnecting from socket %d\n", q->u.e.socket ););
235 rc = send_command_to_rxstack( TSD, q->u.e.socket, RXSTACK_EXIT_STR, NULL, 0 );
236 close( q->u.e.socket );
238 else
239 rc = 0; /* success: 0 bytes transfered */
240 if (q->u.e.name != NULL)
241 DROPSTRENG( q->u.e.name );
242 memset( q, 0, sizeof(Queue) ) ;
243 q->type = QisUnused ;
244 return rc;
247 int send_command_to_rxstack( const tsd_t *TSD, int sock, const char *action, const char *str, int len )
249 streng *qlen, *header;
250 int rc=-1;
252 DEBUGDUMP(printf("\n--> Sending to %d Action: %s <%.*s> Len:%d\n", sock, action, len, (str) ? str : "", len););
253 qlen = REXX_D2X( len );
254 if ( qlen )
256 header = REXX_RIGHT( qlen, RXSTACK_HEADER_SIZE, '0');
257 DROPSTRENG( qlen );
258 if ( header )
260 header->value[0] = action[0];
261 rc = send( sock, PSTRENGVAL(header), PSTRENGLEN(header), 0 );
262 DEBUGDUMP(printf("Send length: %.*s(%d) rc %d\n", PSTRENGLEN(header),PSTRENGVAL(header),PSTRENGLEN(header),rc););
263 if ( str && rc != -1 )
265 rc = send( sock, str, len, 0 );
266 DEBUGDUMP(printf("Send str length: %d\n", rc););
268 DROPSTRENG( header );
271 return rc;
274 static int inject_result_from_rxstack( int sock, streng *str, int size )
277 * Reads size bytes from sock and adds them to str. No overflow checking
278 * is performed.
279 * returns the result from recv.
281 int rc;
283 rc = recv( sock, PSTRENGVAL(str) + PSTRENGLEN(str), size, 0 );
284 str->len += size;
285 DEBUGDUMP(printf("<-- Recv result: %.*s(%d) rc %d\n", size, PSTRENGVAL(str) + PSTRENGLEN(str), PSTRENGLEN(str), rc ); );
286 return rc;
289 streng *read_result_from_rxstack( const tsd_t *TSD, int sock, int result_size )
292 * Creates a streng of length 'result_size' and if non-zero,
293 * reads this many characters from the socket.
294 * The caller MUST DROPSTRENG this streng.
296 streng *result;
297 int rc;
299 result = MAKESTRENG( result_size );
300 if ( result )
302 if ( result_size )
304 result->len = 0 ; /* MAKESTRENG sets ->len to nonzero sometimes */
305 rc = inject_result_from_rxstack( sock, result, result_size );
308 return result;
311 /* parse_queue validates the queue name. The format is [queue][@host[:port]]
312 * *eq is filled and may contain default values.
313 * queue may be empty to designate the current/default queue.
314 * host may be empty to designate the local host. It has to be either a
315 * IPv4 hostname or a IPv4 IP address.
316 * The [@host[:port]] part is chopped off and the pure queue name remains.
317 * return values:
318 * -code: error detected (exiterror() is thrown normally!), code is one
319 * or RXQUEUE_...
320 * 0: queue is NULL
321 * 1: queue is parsed successfully, either with or without host part.
323 int parse_queue( tsd_t *TSD, streng *queue, Queue *q )
325 int len, AtPos;
326 char *h, dummy;
327 struct hostent *he;
329 q->type = QisExternal ;
330 q->u.e.portno = 0; /* Good practise for initialisation */
331 q->u.e.socket = -1;
332 q->u.e.address = 0;
333 q->u.e.name = NULL;
335 if ( queue == NULL )
336 return 0 ;
338 len = PSTRENGLEN( queue );
339 if (( h = (char *)memchr( PSTRENGVAL( queue ), '@', len ) ) == NULL )
340 return 1 ;
342 AtPos = (int) ( h - PSTRENGVAL( queue ) ) ;
343 h++ ;
344 len -= AtPos + 1 ;
346 /* h is at host, len contains its length. We now do a trick. We copy the
347 * complete host part into q->u.e.name, but a '\0' appended. We can simply
348 * check out the portno part and we can apply sscanf() on it. Working with
349 * a temporary buffer for the portno has no benefit, we can save 5 byte
350 * per connection with a maximum of 1 permanent connection ==> 5 byte
352 q->u.e.name = MAKESTRENG( len + 1 ) ;
353 if (q->u.e.name == NULL )
355 /* TSD will be NULL when called from rxqueue or rxstack */
356 if ( TSD == NULL )
357 showerror( ERR_STORAGE_EXHAUSTED, 0, ERR_STORAGE_EXHAUSTED_TMPL );
358 else if ( !TSD->called_from_saa )
359 exiterror( ERR_STORAGE_EXHAUSTED, 0 );
360 return -4; /* RXQUEUE_NOEMEM */
362 memcpy( PSTRENGVAL( q->u.e.name ), h, len ) ;
363 PSTRENGVAL( q->u.e.name )[len] = '\0' ;
364 q->u.e.name->len = len ;
366 if (( h = (char *)memchr( PSTRENGVAL( q->u.e.name ), ':', len ) ) == NULL )
367 q->u.e.portno = default_port_number();
368 else
370 q->u.e.name->len = (int) ( h - PSTRENGVAL( q->u.e.name ) ) ;
371 *h++ = '\0' ; /* chop off the portno part and jump over ':' */
372 if ( sscanf( h, "%d %c", &q->u.e.portno, &dummy ) != 1 )
373 q->u.e.portno = 0;
374 if ( ( q->u.e.portno < 1 ) || ( q->u.e.portno > 0xFFFF ) )
376 if ( TSD == NULL )
377 showerror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_INVALID_QUEUE, ERR_RXSTACK_INVALID_QUEUE_TMPL, PSTRENGVAL( queue ) );
378 else if ( !TSD->called_from_saa )
379 exiterror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_INVALID_QUEUE, tmpstr_of( TSD, queue ) );
380 DROPSTRENG( q->u.e.name ) ;
381 q->u.e.name = NULL ;
382 return -5; /* RXQUEUE_BADQNAME */
386 h = PSTRENGVAL( q->u.e.name ) ;
387 if ( *h == '\0' )
389 q->u.e.address = default_external_address();
390 DROPSTRENG( q->u.e.name );
391 q->u.e.name = default_external_name( TSD );
393 else
395 /* h is either a dotted name or a host name, always try the dotted one
396 * first. It's MUCH faster.
398 q->u.e.address = inet_addr( h );
399 if ( ( q->u.e.address == 0 ) || ( q->u.e.address == -1 ) ) /* various errors */
401 he = gethostbyname( h ) ;
402 if ( ( he != NULL )
403 && ( he->h_addr != NULL )
404 && ( he->h_addrtype == AF_INET ) )
405 q->u.e.address = ( ( struct in_addr * ) he->h_addr )->s_addr;
406 if ( ( q->u.e.address == 0 ) || ( q->u.e.address == -1 ) )
408 /* TSD will be NULL when called from rxqueue or rxstack */
409 if ( TSD == NULL )
410 showerror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_NO_IP, ERR_RXSTACK_NO_IP_TMPL, PSTRENGVAL( q->u.e.name ) );
411 else if ( !TSD->called_from_saa )
412 exiterror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_NO_IP, tmpstr_of( TSD, q->u.e.name ) );
413 DROPSTRENG( q->u.e.name ) ;
414 q->u.e.name = NULL ;
415 return -5; /* RXQUEUE_BADQNAME */
420 queue->len = AtPos ; /* chop off the host part */
421 return 1 ;
424 int delete_queue_from_rxstack( const tsd_t *TSD, int sock, const streng *queue_name )
426 int rc;
427 streng *result;
429 rc = send_command_to_rxstack( TSD, sock, RXSTACK_DELETE_QUEUE_STR, PSTRENGVAL( queue_name ), PSTRENGLEN( queue_name ) );
430 if ( rc != -1 )
432 result = read_result_from_rxstack( TSD, sock, RXSTACK_HEADER_SIZE );
433 if ( result )
435 rc = result->value[0]-'0';
436 DROPSTRENG( result );
439 return rc;
442 int timeout_queue_on_rxstack( const tsd_t *TSD, int sock, long timeout )
444 int rc=0;
445 streng *result,*qtimeout, *hex_timeout;
447 qtimeout = REXX_D2X( timeout );
448 if ( qtimeout )
450 hex_timeout = REXX_RIGHT( qtimeout, RXSTACK_TIMEOUT_SIZE, '0');
451 DROPSTRENG( qtimeout );
452 if ( hex_timeout )
454 DEBUGDUMP(printf("Send timeout: %.*s(%d) rc %d\n", PSTRENGLEN(hex_timeout),PSTRENGVAL(hex_timeout),PSTRENGLEN(hex_timeout),rc););
455 rc = send_command_to_rxstack( TSD, sock, RXSTACK_TIMEOUT_QUEUE_STR, PSTRENGVAL(hex_timeout), PSTRENGLEN(hex_timeout) );
456 DROPSTRENG( hex_timeout );
457 if ( rc != -1 )
459 result = read_result_from_rxstack( TSD, sock, RXSTACK_HEADER_SIZE );
460 if ( result )
462 rc = result->value[0]-'0';
463 DROPSTRENG( result );
468 return rc;
471 int get_number_in_queue_from_rxstack( const tsd_t *TSD, int sock, int *errcode )
473 int rc,length=0;
474 streng *header;
476 rc = send_command_to_rxstack( TSD, sock, RXSTACK_NUMBER_IN_QUEUE_STR, NULL, 0 );
477 if ( rc != -1 )
479 header = read_result_from_rxstack( TSD, sock, RXSTACK_HEADER_SIZE );
480 if ( header )
482 rc = header->value[0]-'0';
483 if ( rc == 0 )
486 * now get the length from the header
488 DEBUGDUMP(printf("before get_length_from_header: %.*s\n", header->len, header->value););
489 length = get_length_from_header( TSD, header );
491 else
493 /* TSD will be NULL when called from rxqueue or rxstack */
494 if ( TSD == NULL )
495 showerror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_INTERNAL, ERR_RXSTACK_INTERNAL_TMPL, rc, "Getting number in queue" );
496 else if ( !TSD->called_from_saa )
497 exiterror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_INTERNAL, rc, "Getting number in queue" );
498 rc = 9; /* RXQUEUE_NOTREG */
500 DROPSTRENG( header );
503 if ( errcode )
504 *errcode = rc;
505 return length;
508 int clear_queue_on_rxstack( const tsd_t *TSD, int sock )
510 int rc ;
511 streng *result ;
513 rc = send_command_to_rxstack( TSD, sock, RXSTACK_EMPTY_QUEUE_STR, NULL, 0 );
514 if ( rc != -1 )
516 result = read_result_from_rxstack( TSD, sock, RXSTACK_HEADER_SIZE );
517 if ( result )
519 rc = result->value[0]-'0';
520 DROPSTRENG( result );
523 return rc ;
526 static streng *init_connect_string( const tsd_t *TSD, const Queue *q, int addlength )
528 /* Determines the length of the connect string of eq and sums up
529 * addlength. A streng of that size is created and returned.
531 streng *retval ;
532 int len = 0 ;
534 assert( q->type == QisExternal ) ;
535 if ( q->u.e.name != 0 )
536 len = PSTRENGLEN( q->u.e.name ) ;
537 if ( len == 0 )
538 len = 15 ; /* enough for "xxx.xxx.xxx.xxx" */
539 len += 8 ; /* enough for "@" and ":65535" and a terminating 0 */
541 retval = MAKESTRENG( len + addlength ) ;
542 if ( retval == NULL )
544 /* TSD will be NULL when called from rxqueue or rxstack */
545 if ( TSD == NULL )
546 showerror( ERR_STORAGE_EXHAUSTED, 0, ERR_STORAGE_EXHAUSTED_TMPL );
547 else if ( !TSD->called_from_saa )
548 exiterror( ERR_STORAGE_EXHAUSTED, 0 );
550 else
551 retval->len = 0 ; /* MAKESTRENG sets ->len to nonzero sometimes */
552 return retval ;
555 static void add_connect_string( const Queue *q, streng *str )
557 /* Adds the connect string of eq to str.
558 * This may be "@localhost:5757"
559 * We always add the port. It may be redefined in between by a call to
560 * the VALUE BIF.
562 int sum = 0, len ;
563 char *ptr = PSTRENGVAL( str ) ;
564 char *addr ;
565 struct in_addr ia ;
567 assert( q->type == QisExternal ) ;
568 ptr += PSTRENGLEN( str ) ;
569 *ptr++ = '@' ;
570 sum++ ;
571 if ( q->u.e.name != 0 )
573 len = PSTRENGLEN( q->u.e.name ) ;
574 memcpy( ptr, PSTRENGVAL( q->u.e.name ), len ) ;
575 ptr += len ;
576 sum += len ;
578 if ( sum == 1 ) /* no q->u.e.name? use the dotted IP address */
580 ia.s_addr = q->u.e.address ;
581 addr = inet_ntoa( ia ) ;
582 len = strlen( addr ) ;
583 memcpy( ptr, addr, len ) ;
584 ptr += len ;
585 sum += len ;
587 /* finally add the port */
588 sum += sprintf( ptr, ":%u", (unsigned) q->u.e.portno ) ;
589 str->len += sum ;
592 int get_queue_from_rxstack( const tsd_t *TSD, const Queue *q, streng **result )
594 int rc,length;
595 streng *header;
597 assert( q->type == QisExternal ) ;
598 rc = send_command_to_rxstack( TSD, q->u.e.socket, RXSTACK_GET_QUEUE_STR, NULL, 0 );
599 if ( rc != -1 )
601 header = read_result_from_rxstack( TSD, q->u.e.socket, RXSTACK_HEADER_SIZE );
602 if ( header )
604 rc = header->value[0]-'0';
605 if ( rc == 0 )
608 * now get the length from the header and get that many characters...
610 length = get_length_from_header( TSD, header );
611 if ( ( *result = init_connect_string( TSD, q, length ) ) != NULL )
613 inject_result_from_rxstack( q->u.e.socket, *result, length ) ;
614 add_connect_string( q, *result );
616 else
617 rc = 4; /* RXQUEUE_NOEMEM, not really used */
619 else
621 /* TSD will be NULL when called from rxqueue or rxstack */
622 if ( TSD == NULL )
623 showerror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_INTERNAL, ERR_RXSTACK_INTERNAL_TMPL, rc, "Getting queue from stack" );
624 else if ( !TSD->called_from_saa )
625 exiterror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_INTERNAL, rc, "Getting queue from stack" );
627 DROPSTRENG( header );
630 return rc;
633 int get_line_from_rxstack( const tsd_t *TSD, int sock, streng **result, int nowait )
635 int rc,length;
636 streng *header;
638 rc = send_command_to_rxstack( TSD, sock, (nowait) ? RXSTACK_FETCH_STR : RXSTACK_PULL_STR, NULL, 0 );
639 if ( rc != -1 )
641 header = read_result_from_rxstack( TSD, sock, RXSTACK_HEADER_SIZE );
642 if ( header )
644 rc = header->value[0]-'0';
645 DEBUGDUMP(printf("rc from read_result_from_rxstack=%d\n", rc););
646 switch( rc )
648 case RXSTACK_OK:
650 * now get the length from the header and get that many characters...
652 length = get_length_from_header( TSD, header );
653 *result = read_result_from_rxstack( TSD, sock, length );
654 break;
655 case RXSTACK_TIMEOUT:
656 case RXSTACK_EMPTY:
658 * queue is empty - return a NULL
660 *result = NULL;
661 break;
662 default:
663 /* TSD will be NULL when called from rxqueue or rxstack */
664 if ( TSD == NULL )
665 showerror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_INTERNAL, ERR_RXSTACK_INTERNAL_TMPL, rc, "Getting line from queue" );
666 else if ( !TSD->called_from_saa )
667 exiterror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_INTERNAL, rc, "Getting line from queue" );
668 break;
670 DROPSTRENG( header );
673 return rc;
676 int create_queue_on_rxstack( const tsd_t *TSD, const Queue *q, const streng *queue, streng **result )
678 int rc,length;
679 streng *header;
681 assert( q->type == QisExternal ) ;
682 rc = send_command_to_rxstack( TSD, q->u.e.socket, RXSTACK_CREATE_QUEUE_STR, (queue) ? PSTRENGVAL( queue ) : NULL, (queue) ? PSTRENGLEN( queue ) : 0 );
683 if ( rc != -1 )
685 header = read_result_from_rxstack( TSD, q->u.e.socket, RXSTACK_HEADER_SIZE );
686 if ( header )
688 rc = header->value[0]-'0';
689 if ( ( rc == 0 ) || ( rc == 1 ) )
692 * now get the length from the header and get that many characters...
694 length = get_length_from_header( TSD, header );
695 if ( ( *result = init_connect_string( TSD, q, length ) ) != NULL )
697 inject_result_from_rxstack( q->u.e.socket, *result, length ) ;
698 add_connect_string( q, *result );
700 else
701 rc = 4; /* RXQUEUE_NOEMEM */
703 else
705 /* TSD will be NULL when called from rxqueue or rxstack */
706 if ( TSD == NULL )
707 showerror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_INTERNAL, ERR_RXSTACK_INTERNAL_TMPL, rc, "Creating queue" );
708 else if ( !TSD->called_from_saa )
709 exiterror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_INTERNAL, rc, "Creating queue" );
710 switch ( rc )
712 case 2: rc = 5; break; /* RXQUEUE_BADQNAME */
713 case 3: rc = 4; break; /* RXQUEUE_NOEMEM */
714 case 6: rc = 1; break; /* RXQUEUE_STORAGE */
715 default:;
718 DROPSTRENG( header );
721 return rc;
724 int set_queue_in_rxstack( const tsd_t *TSD, int sock, const streng *queue_name )
726 int rc,length;
727 streng *header, *dummy;
729 rc = send_command_to_rxstack( TSD, sock, RXSTACK_SET_QUEUE_STR, PSTRENGVAL( queue_name ), PSTRENGLEN( queue_name ) );
730 if ( rc != -1 )
732 header = read_result_from_rxstack( TSD, sock, RXSTACK_HEADER_SIZE );
733 if ( header )
735 rc = header->value[0]-'0';
736 if ( rc == 0 )
739 * now get the length from the header and get that many characters...
741 length = get_length_from_header( TSD, header );
742 dummy = read_result_from_rxstack( TSD, sock, length );
743 /* dummy is no longer used */
744 DROPSTRENG( dummy ) ;
746 else
748 /* TSD will be NULL when called from rxqueue or rxstack */
749 if ( TSD == NULL )
750 showerror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_INTERNAL, ERR_RXSTACK_INTERNAL_TMPL, rc, "Setting queue" );
751 else if ( !TSD->called_from_saa )
752 exiterror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_INTERNAL, rc, "Setting queue" );
753 switch ( rc )
755 case 3: rc = 4; break; /* RXQUEUE_NOEMEM */
756 case 6: rc = 1; break; /* RXQUEUE_STORAGE */
757 default:;
760 DROPSTRENG( header );
763 else
764 rc = 100; /* RXQUEUE_NETERROR */
765 return rc;
768 int queue_line_fifo_to_rxstack( const tsd_t *TSD, int sock, const streng *line )
770 int rc;
771 streng *header;
773 rc = send_command_to_rxstack( TSD, sock, RXSTACK_QUEUE_FIFO_STR, PSTRENGVAL( line ), PSTRENGLEN( line ) );
774 if ( rc != -1 )
776 header = read_result_from_rxstack( TSD, sock, RXSTACK_HEADER_SIZE );
777 if ( header )
779 rc = header->value[0]-'0';
780 if ( rc != 0 )
782 /* TSD will be NULL when called from rxqueue or rxstack */
783 if ( TSD == NULL )
784 showerror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_INTERNAL, ERR_RXSTACK_INTERNAL_TMPL, rc, "Queueing line" );
785 else if ( !TSD->called_from_saa )
786 exiterror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_INTERNAL, rc, "Queueing line" );
787 switch ( rc )
789 case 2: rc = 5; break; /* RXQUEUE_BADQNAME */
790 case 3: rc = 4; break; /* RXQUEUE_NOEMEM */
791 case 6: rc = 1; break; /* RXQUEUE_STORAGE */
792 default:;
795 DROPSTRENG( header );
798 return rc;
801 int queue_line_lifo_to_rxstack( const tsd_t *TSD, int sock, const streng *line )
803 int rc;
804 streng *header;
806 rc = send_command_to_rxstack( TSD, sock, RXSTACK_QUEUE_LIFO_STR, PSTRENGVAL( line ), PSTRENGLEN( line ) );
807 if ( rc != -1 )
809 header = read_result_from_rxstack( TSD, sock, RXSTACK_HEADER_SIZE );
810 if ( header )
812 rc = header->value[0]-'0';
813 if ( rc != 0 )
815 /* TSD will be NULL when called from rxqueue or rxstack */
816 if ( TSD == NULL )
817 showerror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_INTERNAL, ERR_RXSTACK_INTERNAL_TMPL, rc, "Queueing line" );
818 else if ( !TSD->called_from_saa )
819 exiterror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_INTERNAL, rc, "Queueing line" );
820 switch ( rc )
822 case 2: rc = 5; break; /* RXQUEUE_BADQNAME */
823 case 3: rc = 4; break; /* RXQUEUE_NOEMEM */
824 case 6: rc = 1; break; /* RXQUEUE_STORAGE */
825 default:;
828 DROPSTRENG( header );
831 return rc;
833 #endif