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 #define NO_CTYPE_REPLACEMENT
26 # include "configur.h"
30 # if defined(_MSC_VER)
32 /* Stupid MSC can't compile own headers without warning at least in VC 5.0 */
33 # pragma warning(disable: 4115 4201 4214 4514)
37 # 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>
62 # include <winsock2.h>
85 #define SUCCESS(a) ((a)&&(a)->value[0] == '0')
88 * debugging is turned off. You can turn it on by the command line option "-D".
90 static int debug
= 0 ;
91 #define DEBUGDUMP(x) { if ( debug ) \
96 unsigned int bufflen
=0;
98 #if !defined(HAVE_STRERROR)
100 * Sigh! This must probably be done this way, although it's incredibly
101 * backwards. Some versions of gcc comes with a complete set of ANSI C
102 * include files, which contains the definition of strerror(). However,
103 * that function does not exist in the default libraries of SunOS.
104 * To circumvent that problem, strerror() is #define'd to get_sys_errlist()
105 * in config.h, and here follows the definition of that function.
106 * Originally, strerror() was #defined to sys_errlist[x], but that does
107 * not work if string.h contains a declaration of the (non-existing)
108 * function strerror().
110 * So, this is a mismatch between the include files and the library, and
111 * it should not create problems for Regina. However, the _user_ will not
112 * encounter any problems until he compiles Regina, so we'll have to
113 * clean up after a buggy installation of the C compiler!
115 const char *get_sys_errlist( int num
)
117 extern char *sys_errlist
[] ;
118 return sys_errlist
[num
] ;
122 streng
*Str_upper( streng
*str
)
126 for ( i
= 0; i
< PSTRENGLEN( str
); i
++ )
128 if ( islower( str
->value
[i
] ) )
129 str
->value
[i
] = (char)toupper( str
->value
[i
] );
134 int send_all( int sock
, char *action
)
137 * Send everything in stdin to the socket. Each LF encountered
139 * This code borrowed from rxstack.c in REXX/imc
148 while ( ( c
= getchar() ) != EOF
)
150 if ( c
== REGINA_EOL
)
152 #if defined(DOS) || defined(OS2) || defined(WIN32)
153 if (len
&& ( buff
[len
-1] == REGINA_CR
) )
159 && (( buff
= (char *)realloc( buff
, bufflen
<<= 1 ) ) == NULL
) )
161 showerror( ERR_STORAGE_EXHAUSTED
, 0, ERR_STORAGE_EXHAUSTED_TMPL
);
162 exit( ERR_STORAGE_EXHAUSTED
);
164 buff
[len
++] = (char)c
;
166 if ( (c
== EOF
|| feof(stdin
) )
169 DEBUGDUMP(printf("--- Queue %s ---\n", action
[0] == RXSTACK_QUEUE_FIFO
? "FIFO" : "LIFO"););
170 rc
= send_command_to_rxstack( NULL
, sock
, action
, buff
, len
);
173 result
= read_result_from_rxstack( NULL
, sock
, RXSTACK_HEADER_SIZE
);
174 DROPSTRENG( result
);
180 char *get_unspecified_queue( void )
182 char *rxq
= getenv( "RXQUEUE" );
189 char *force_remote( char *rxq
)
193 if ( strchr(rxq
, '@' ) == NULL
)
195 if ( ( h
= (char *)malloc( strlen( rxq
) + 2 ) ) != NULL
)
205 char *get_action( char *parm
)
209 if ( strcmp( parm
, "/fifo" ) == 0 )
210 action
= RXSTACK_QUEUE_FIFO_STR
;
211 else if ( strcmp( parm
, "/lifo" ) == 0 )
212 action
= RXSTACK_QUEUE_LIFO_STR
;
213 else if ( strcmp( parm
, "/clear" ) == 0 )
214 action
= RXSTACK_EMPTY_QUEUE_STR
;
215 else if ( strcmp( parm
, "/pull" ) == 0 )
216 action
= RXSTACK_PULL_STR
;
217 else if ( strcmp( parm
, "/queued" ) == 0 )
218 action
= RXSTACK_NUMBER_IN_QUEUE_STR
;
221 showerror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_INVALID_SWITCH
, ERR_RXSTACK_INVALID_SWITCH_TMPL
, "/fifo, /lifo, /clear, /queued, /pull" );
222 /* not setting action will exit */
227 void junk_return_from_rxstack( int sock
, streng
*header
)
232 length
= get_length_from_header( NULL
, header
);
235 result
= read_result_from_rxstack( NULL
, sock
, length
);
237 DROPSTRENG( result
);
252 int main( int argc
, char *argv
[])
256 streng
*queue
=NULL
,*server_name
=NULL
;
261 WORD wsver
= (WORD
)MAKEWORD(1,1);
266 if ( WSAStartup( wsver
, &wsaData
) != 0 )
268 showerror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_NO_WINSOCK
, ERR_RXSTACK_NO_WINSOCK_TMPL
, WSAGetLastError() );
269 exit(ERR_RXSTACK_NO_WINSOCK
);
276 if ( getenv( "RXDEBUG" ) != NULL
)
280 && ( ( strcmp( *argv
, "-D" ) == 0 ) || ( strcmp( *argv
, "/D" ) == 0 ) ) )
283 putenv( "RXDEBUG=1" ) ;
290 * Process the command line
297 action
= RXSTACK_QUEUE_FIFO_STR
;
298 in_queue
= get_unspecified_queue();
300 else if ( argc
== 1 )
307 if ( argv
[0][0] == '/' )
310 * Only parameter is a switch
312 in_queue
= get_unspecified_queue();
313 action
= get_action( argv
[0] );
318 * Only parameter is a queue name
321 action
= RXSTACK_QUEUE_FIFO_STR
;
324 else if ( argc
== 2 )
327 * "rxqueue queue /switch"
330 if ( argv
[1][0] == '/' )
333 * Parameter is a switch
335 action
= get_action( argv
[1] );
343 fprintf(stderr
, "Invalid number of parameters\n");
346 in_queue
= force_remote( in_queue
) ;
349 queue
= MAKESTRENG( strlen( in_queue
) );
352 showerror( ERR_STORAGE_EXHAUSTED
, 0, ERR_STORAGE_EXHAUSTED_TMPL
);
353 exit(ERR_STORAGE_EXHAUSTED
);
355 memcpy( PSTRENGVAL( queue
), in_queue
, PSTRENGLEN( queue
) );
356 queue
->len
= strlen( in_queue
) ;
358 * Parse the queue to determine server address
361 if ( parse_queue( NULL
, queue
, &q
) == 1 )
363 if ( PSTRENGLEN( queue
) == 0 )
366 queue
= MAKESTRENG( 7 );
369 showerror( ERR_STORAGE_EXHAUSTED
, 0, ERR_STORAGE_EXHAUSTED_TMPL
);
370 exit(ERR_STORAGE_EXHAUSTED
);
372 memcpy( PSTRENGVAL( queue
), "SESSION", 7 );
375 DEBUGDUMP(printf( "queue: <%.*s> server: %.*s<%d> Port:%d\n", PSTRENGLEN( queue
), PSTRENGVAL( queue
), PSTRENGLEN( q
.u
.e
.name
), PSTRENGVAL( q
.u
.e
.name
), q
.u
.e
.address
, q
.u
.e
.portno
););
376 sock
= connect_to_rxstack( NULL
, &q
);
380 exit(ERR_RXSTACK_CANT_CONNECT
);
383 * Now process the actual command
387 case RXSTACK_QUEUE_FIFO
:
388 case RXSTACK_QUEUE_LIFO
:
389 DEBUGDUMP(printf("--- Queue %s ", action
[0] == RXSTACK_QUEUE_FIFO
? "FIFO" : "LIFO"););
391 * Allocate the initial buffer
393 if (( buff
= (char *)malloc( bufflen
= 256 ) ) == NULL
)
395 showerror( ERR_STORAGE_EXHAUSTED
, 0, ERR_STORAGE_EXHAUSTED_TMPL
);
396 rc
= ERR_STORAGE_EXHAUSTED
;
400 * Set the current queue
402 DEBUGDUMP(printf("(Set Queue) ---\n"););
403 rc
= send_command_to_rxstack( NULL
, sock
, RXSTACK_SET_QUEUE_STR
, PSTRENGVAL( queue
) , PSTRENGLEN( queue
) );
406 showerror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_INTERNAL
, ERR_RXSTACK_INTERNAL_TMPL
, rc
, "Setting default queue" );
407 rc
= ERR_RXSTACK_INTERNAL
;
410 result
= read_result_from_rxstack( NULL
, sock
, RXSTACK_HEADER_SIZE
);
411 if ( !SUCCESS( result
) )
413 showerror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_INTERNAL
, ERR_RXSTACK_INTERNAL_TMPL
, rc
, "Setting default queue" );
414 DROPSTRENG( result
);
415 rc
= ERR_RXSTACK_INTERNAL
;
419 * Success. We need to throw away the returned queue name. We
422 junk_return_from_rxstack( sock
, result
);
423 send_all( sock
, action
);
424 DROPSTRENG( result
);
427 case RXSTACK_EMPTY_QUEUE
:
428 DEBUGDUMP(printf("--- Empty Queue ---\n"););
429 rc
= send_command_to_rxstack( NULL
, sock
, action
, PSTRENGVAL( queue
) , PSTRENGLEN( queue
) );
432 showerror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_INTERNAL
, ERR_RXSTACK_INTERNAL_TMPL
, rc
, "Emptying queue" );
433 rc
= ERR_RXSTACK_INTERNAL
;
436 result
= read_result_from_rxstack( NULL
, sock
, RXSTACK_HEADER_SIZE
);
437 if ( !SUCCESS( result
) )
439 showerror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_INTERNAL
, ERR_RXSTACK_INTERNAL_TMPL
, rc
, "Emptying queue" );
440 DROPSTRENG( result
);
441 rc
= ERR_RXSTACK_INTERNAL
;
444 DROPSTRENG( result
);
447 case RXSTACK_NUMBER_IN_QUEUE
:
449 * Set the current queue
451 DEBUGDUMP(printf("--- Set Queue ---\n"););
452 rc
= send_command_to_rxstack( NULL
, sock
, RXSTACK_SET_QUEUE_STR
, PSTRENGVAL( queue
), PSTRENGLEN( queue
) );
455 showerror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_INTERNAL
, ERR_RXSTACK_INTERNAL_TMPL
, rc
, "Setting default queue" );
456 rc
= ERR_RXSTACK_INTERNAL
;
460 * Read the return response header
462 result
= read_result_from_rxstack( NULL
, sock
, RXSTACK_HEADER_SIZE
);
463 if ( !SUCCESS( result
) )
465 showerror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_INTERNAL
, ERR_RXSTACK_INTERNAL_TMPL
, rc
, "Setting default queue" );
466 DROPSTRENG( result
);
467 rc
= ERR_RXSTACK_INTERNAL
;
471 * Success. We need to throw away the returned queue name. We
474 junk_return_from_rxstack( sock
, result
);
475 DROPSTRENG( result
);
476 DEBUGDUMP(printf("--- Number in Queue ---\n"););
477 num
= get_number_in_queue_from_rxstack( NULL
, sock
, &rc
);
479 printf("%d\n", num
);
483 * Set the current queue
485 DEBUGDUMP(printf("--- Set Queue ---\n"););
486 rc
= send_command_to_rxstack( NULL
, sock
, RXSTACK_SET_QUEUE_STR
, PSTRENGVAL( queue
), PSTRENGLEN( queue
) );
489 showerror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_INTERNAL
, ERR_RXSTACK_INTERNAL_TMPL
, rc
, "Setting default queue" );
490 rc
= ERR_RXSTACK_INTERNAL
;
493 result
= read_result_from_rxstack( NULL
, sock
, RXSTACK_HEADER_SIZE
);
494 if ( !SUCCESS( result
) )
496 showerror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_INTERNAL
, ERR_RXSTACK_INTERNAL_TMPL
, rc
, "Setting default queue" );
497 DROPSTRENG( result
);
498 rc
= ERR_RXSTACK_INTERNAL
;
502 * Success. We need to throw away the returned queue name. We
505 junk_return_from_rxstack( sock
, result
);
506 DROPSTRENG( result
);
508 * Loop until the number of lines on the queue is zero
512 DEBUGDUMP(printf("--- Pull ---\n"););
513 rc
= get_line_from_rxstack( NULL
, sock
, &result
, 0 );
516 printf( "%.*s\n", PSTRENGLEN( result
), PSTRENGVAL( result
) ) ;
518 else if ( ( rc
== 1 ) || ( rc
== 4 ) )
528 showerror( ERR_EXTERNAL_QUEUE
, ERR_RXSTACK_INTERNAL
, ERR_RXSTACK_INTERNAL_TMPL
, rc
, "Getting line from queue" );
529 rc
= ERR_RXSTACK_INTERNAL
;
532 DROPSTRENG( result
);
537 * Tell the server we want to disconnect
538 * Don't expect any return result.
540 DEBUGDUMP(printf("--- Exit ---\n"););
541 send_command_to_rxstack( NULL
, sock
, RXSTACK_EXIT_STR
, NULL
, 0 );
546 DEBUGDUMP(printf( "queue: <%.*s>\n", PSTRENGLEN( queue
), PSTRENGVAL( queue
) ););
550 DROPSTRENG( server_name
);