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>
26 # if defined(_MSC_VER)
28 /* Stupid MSC can't compile own headers without warning at least in VC 5.0 */
29 # pragma warning(disable: 4115 4201 4214 4514)
33 # pragma warning(default: 4115 4201 4214)
44 # ifdef HAVE_SYS_SOCKET_H
45 # include <sys/socket.h>
47 # ifdef HAVE_NETINET_IN_H
48 # include <netinet/in.h>
50 # ifdef HAVE_SYS_SELECT_H
51 # include <sys/select.h>
56 # ifdef HAVE_ARPA_INET_H
57 # include <arpa/inet.h>
69 #ifdef EXTERNAL_TO_REGINA
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
);
81 static int debug
= -1 ;
82 #define DEBUGDUMP(x) { \
85 debug = ( getenv( "RXDEBUG" ) == NULL ) ? 0 : 1 ; \
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
, ...)
102 fprintf( stderr
, "Error:%d.%d - ", err
, suberr
);
104 fprintf( stderr
, "Error:%d - ", err
);
105 va_start( argptr
, tmpl
);
106 vfprintf( stderr
, tmpl
, argptr
);
108 fprintf( stderr
, "\n" );
111 int init_external_queue( const tsd_t
*TSD
)
115 WORD wsver
= (WORD
)MAKEWORD(1,1);
117 if ( WSAStartup( wsver
, &wsaData
) != 0 )
119 /* TSD will be NULL when called from rxqueue or rxstack */
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() );
127 TSD
= TSD
; /* keep compiler happy */
132 void term_external_queue( void )
139 int get_length_from_header( const tsd_t
*TSD
, const streng
*header
)
141 int length
=0,error
=1;
144 result
= MAKESTRENG( RXSTACK_HEADER_SIZE
- 1 );
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 )
161 char *port
= getenv("RXSTACK"); /* FIXME: May be overwritten by VALUE-BIF */
165 if ( sscanf( port
, "%d %c", &portno
, &dummy
) == 1 )
166 if ( (portno
> 1) && (portno
< 0xFFFF) )
172 int default_external_address( void )
174 return inet_addr( ReginaLocalHost
);
177 streng
*default_external_name( const tsd_t
*TSD
)
182 len
= sizeof(ReginaLocalHost
); /* includes the term. \0 */
183 result
= MAKESTRENG( len
);
184 result
->len
= len
- 1;
185 memcpy( result
->value
, ReginaLocalHost
, len
) ;
189 int connect_to_rxstack( tsd_t
*TSD
, Queue
*q
)
191 struct sockaddr_in server
;
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
);
214 close(q
->u
.e
.socket
);
218 /* TSD will be NULL when called from rxqueue or rxstack */
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
) );
227 int disconnect_from_rxstack( const tsd_t
*TSD
, Queue
*q
)
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
);
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
;
247 int send_command_to_rxstack( const tsd_t
*TSD
, int sock
, const char *action
, const char *str
, int len
)
249 streng
*qlen
, *header
;
252 DEBUGDUMP(printf("\n--> Sending to %d Action: %s <%.*s> Len:%d\n", sock
, action
, len
, (str
) ? str
: "", len
););
253 qlen
= REXX_D2X( len
);
256 header
= REXX_RIGHT( qlen
, RXSTACK_HEADER_SIZE
, '0');
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
);
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
279 * returns the result from recv.
283 rc
= recv( sock
, PSTRENGVAL(str
) + PSTRENGLEN(str
), size
, 0 );
285 DEBUGDUMP(printf("<-- Recv result: %.*s(%d) rc %d\n", size
, PSTRENGVAL(str
) + PSTRENGLEN(str
), PSTRENGLEN(str
), 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.
299 result
= MAKESTRENG( result_size
);
304 result
->len
= 0 ; /* MAKESTRENG sets ->len to nonzero sometimes */
305 rc
= inject_result_from_rxstack( sock
, result
, result_size
);
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.
318 * -code: error detected (exiterror() is thrown normally!), code is one
321 * 1: queue is parsed successfully, either with or without host part.
323 int parse_queue( tsd_t
*TSD
, streng
*queue
, Queue
*q
)
329 q
->type
= QisExternal
;
330 q
->u
.e
.portno
= 0; /* Good practise for initialisation */
338 len
= PSTRENGLEN( queue
);
339 if (( h
= (char *)memchr( PSTRENGVAL( queue
), '@', len
) ) == NULL
)
342 AtPos
= (int) ( h
- PSTRENGVAL( queue
) ) ;
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 */
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();
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 )
374 if ( ( q
->u
.e
.portno
< 1 ) || ( q
->u
.e
.portno
> 0xFFFF ) )
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
) ;
382 return -5; /* RXQUEUE_BADQNAME */
386 h
= PSTRENGVAL( q
->u
.e
.name
) ;
389 q
->u
.e
.address
= default_external_address();
390 DROPSTRENG( q
->u
.e
.name
);
391 q
->u
.e
.name
= default_external_name( TSD
);
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
) ;
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 */
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
) ;
415 return -5; /* RXQUEUE_BADQNAME */
420 queue
->len
= AtPos
; /* chop off the host part */
424 int delete_queue_from_rxstack( const tsd_t
*TSD
, int sock
, const streng
*queue_name
)
429 rc
= send_command_to_rxstack( TSD
, sock
, RXSTACK_DELETE_QUEUE_STR
, PSTRENGVAL( queue_name
), PSTRENGLEN( queue_name
) );
432 result
= read_result_from_rxstack( TSD
, sock
, RXSTACK_HEADER_SIZE
);
435 rc
= result
->value
[0]-'0';
436 DROPSTRENG( result
);
442 int timeout_queue_on_rxstack( const tsd_t
*TSD
, int sock
, long timeout
)
445 streng
*result
,*qtimeout
, *hex_timeout
;
447 qtimeout
= REXX_D2X( timeout
);
450 hex_timeout
= REXX_RIGHT( qtimeout
, RXSTACK_TIMEOUT_SIZE
, '0');
451 DROPSTRENG( qtimeout
);
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
);
459 result
= read_result_from_rxstack( TSD
, sock
, RXSTACK_HEADER_SIZE
);
462 rc
= result
->value
[0]-'0';
463 DROPSTRENG( result
);
471 int get_number_in_queue_from_rxstack( const tsd_t
*TSD
, int sock
, int *errcode
)
476 rc
= send_command_to_rxstack( TSD
, sock
, RXSTACK_NUMBER_IN_QUEUE_STR
, NULL
, 0 );
479 header
= read_result_from_rxstack( TSD
, sock
, RXSTACK_HEADER_SIZE
);
482 rc
= header
->value
[0]-'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
);
493 /* TSD will be NULL when called from rxqueue or rxstack */
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
);
508 int clear_queue_on_rxstack( const tsd_t
*TSD
, int sock
)
513 rc
= send_command_to_rxstack( TSD
, sock
, RXSTACK_EMPTY_QUEUE_STR
, NULL
, 0 );
516 result
= read_result_from_rxstack( TSD
, sock
, RXSTACK_HEADER_SIZE
);
519 rc
= result
->value
[0]-'0';
520 DROPSTRENG( result
);
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.
534 assert( q
->type
== QisExternal
) ;
535 if ( q
->u
.e
.name
!= 0 )
536 len
= PSTRENGLEN( q
->u
.e
.name
) ;
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 */
546 showerror( ERR_STORAGE_EXHAUSTED
, 0, ERR_STORAGE_EXHAUSTED_TMPL
);
547 else if ( !TSD
->called_from_saa
)
548 exiterror( ERR_STORAGE_EXHAUSTED
, 0 );
551 retval
->len
= 0 ; /* MAKESTRENG sets ->len to nonzero sometimes */
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
563 char *ptr
= PSTRENGVAL( str
) ;
567 assert( q
->type
== QisExternal
) ;
568 ptr
+= PSTRENGLEN( str
) ;
571 if ( q
->u
.e
.name
!= 0 )
573 len
= PSTRENGLEN( q
->u
.e
.name
) ;
574 memcpy( ptr
, PSTRENGVAL( q
->u
.e
.name
), 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
) ;
587 /* finally add the port */
588 sum
+= sprintf( ptr
, ":%u", (unsigned) q
->u
.e
.portno
) ;
592 int get_queue_from_rxstack( const tsd_t
*TSD
, const Queue
*q
, streng
**result
)
597 assert( q
->type
== QisExternal
) ;
598 rc
= send_command_to_rxstack( TSD
, q
->u
.e
.socket
, RXSTACK_GET_QUEUE_STR
, NULL
, 0 );
601 header
= read_result_from_rxstack( TSD
, q
->u
.e
.socket
, RXSTACK_HEADER_SIZE
);
604 rc
= header
->value
[0]-'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
);
617 rc
= 4; /* RXQUEUE_NOEMEM, not really used */
621 /* TSD will be NULL when called from rxqueue or rxstack */
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
);
633 int get_line_from_rxstack( const tsd_t
*TSD
, int sock
, streng
**result
, int nowait
)
638 rc
= send_command_to_rxstack( TSD
, sock
, (nowait
) ? RXSTACK_FETCH_STR
: RXSTACK_PULL_STR
, NULL
, 0 );
641 header
= read_result_from_rxstack( TSD
, sock
, RXSTACK_HEADER_SIZE
);
644 rc
= header
->value
[0]-'0';
645 DEBUGDUMP(printf("rc from read_result_from_rxstack=%d\n", rc
););
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
);
655 case RXSTACK_TIMEOUT
:
658 * queue is empty - return a NULL
663 /* TSD will be NULL when called from rxqueue or rxstack */
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" );
670 DROPSTRENG( header
);
676 int create_queue_on_rxstack( const tsd_t
*TSD
, const Queue
*q
, const streng
*queue
, streng
**result
)
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 );
685 header
= read_result_from_rxstack( TSD
, q
->u
.e
.socket
, RXSTACK_HEADER_SIZE
);
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
);
701 rc
= 4; /* RXQUEUE_NOEMEM */
705 /* TSD will be NULL when called from rxqueue or rxstack */
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" );
712 case 2: rc
= 5; break; /* RXQUEUE_BADQNAME */
713 case 3: rc
= 4; break; /* RXQUEUE_NOEMEM */
714 case 6: rc
= 1; break; /* RXQUEUE_STORAGE */
718 DROPSTRENG( header
);
724 int set_queue_in_rxstack( const tsd_t
*TSD
, int sock
, const streng
*queue_name
)
727 streng
*header
, *dummy
;
729 rc
= send_command_to_rxstack( TSD
, sock
, RXSTACK_SET_QUEUE_STR
, PSTRENGVAL( queue_name
), PSTRENGLEN( queue_name
) );
732 header
= read_result_from_rxstack( TSD
, sock
, RXSTACK_HEADER_SIZE
);
735 rc
= header
->value
[0]-'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
) ;
748 /* TSD will be NULL when called from rxqueue or rxstack */
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" );
755 case 3: rc
= 4; break; /* RXQUEUE_NOEMEM */
756 case 6: rc
= 1; break; /* RXQUEUE_STORAGE */
760 DROPSTRENG( header
);
764 rc
= 100; /* RXQUEUE_NETERROR */
768 int queue_line_fifo_to_rxstack( const tsd_t
*TSD
, int sock
, const streng
*line
)
773 rc
= send_command_to_rxstack( TSD
, sock
, RXSTACK_QUEUE_FIFO_STR
, PSTRENGVAL( line
), PSTRENGLEN( line
) );
776 header
= read_result_from_rxstack( TSD
, sock
, RXSTACK_HEADER_SIZE
);
779 rc
= header
->value
[0]-'0';
782 /* TSD will be NULL when called from rxqueue or rxstack */
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" );
789 case 2: rc
= 5; break; /* RXQUEUE_BADQNAME */
790 case 3: rc
= 4; break; /* RXQUEUE_NOEMEM */
791 case 6: rc
= 1; break; /* RXQUEUE_STORAGE */
795 DROPSTRENG( header
);
801 int queue_line_lifo_to_rxstack( const tsd_t
*TSD
, int sock
, const streng
*line
)
806 rc
= send_command_to_rxstack( TSD
, sock
, RXSTACK_QUEUE_LIFO_STR
, PSTRENGVAL( line
), PSTRENGLEN( line
) );
809 header
= read_result_from_rxstack( TSD
, sock
, RXSTACK_HEADER_SIZE
);
812 rc
= header
->value
[0]-'0';
815 /* TSD will be NULL when called from rxqueue or rxstack */
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" );
822 case 2: rc
= 5; break; /* RXQUEUE_BADQNAME */
823 case 3: rc
= 4; break; /* RXQUEUE_NOEMEM */
824 case 6: rc
= 1; break; /* RXQUEUE_STORAGE */
828 DROPSTRENG( header
);