We can't link with bz2 anymore because it's now a shared
[AROS-Contrib.git] / regina / rxqueue.c
blobedd45831919e9b992d30d4631a0ea965f9080873
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 #define NO_CTYPE_REPLACEMENT
21 #include "rexx.h"
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #else
26 # include "configur.h"
27 #endif
29 #ifdef WIN32
30 # if defined(_MSC_VER)
31 # if _MSC_VER >= 1100
32 /* Stupid MSC can't compile own headers without warning at least in VC 5.0 */
33 # pragma warning(disable: 4115 4201 4214 4514)
34 # endif
35 # include <windows.h>
36 # if _MSC_VER >= 1100
37 # pragma warning(default: 4115 4201 4214)
38 # endif
39 # else
40 # include <windows.h>
41 # endif
42 # include <io.h>
43 #else
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 #ifdef __LCC__
62 # include <winsock2.h>
63 #endif
65 #include <string.h>
67 #ifdef HAVE_UNISTD_H
68 #include <unistd.h>
69 #endif
71 #ifdef HAVE_ERRNO_H
72 #include <errno.h>
73 #endif
75 #ifdef HAVE_SIGNAL_H
76 #include <signal.h>
77 #endif
79 #ifdef HAVE_CTYPE_H
80 #include <ctype.h>
81 #endif
83 #include "extstack.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 ) \
92 {x;} \
95 char *buff=NULL;
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] ;
120 #endif
122 streng *Str_upper( streng *str )
124 int i;
126 for ( i = 0; i < PSTRENGLEN( str ); i++ )
128 if ( islower( str->value[i] ) )
129 str->value[i] = (char)toupper( str->value[i] );
131 return str;
134 int send_all( int sock, char *action )
137 * Send everything in stdin to the socket. Each LF encountered
138 * results in a send.
139 * This code borrowed from rxstack.c in REXX/imc
141 int c,rc;
142 unsigned int len;
143 streng *result;
145 for ( ; ; )
147 len = 0;
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 ) )
154 len--;
155 #endif
156 break;
158 if ( len >= bufflen
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) )
167 && !len)
168 break;
169 DEBUGDUMP(printf("--- Queue %s ---\n", action[0] == RXSTACK_QUEUE_FIFO ? "FIFO" : "LIFO"););
170 rc = send_command_to_rxstack( NULL, sock, action, buff, len );
171 if ( rc != -1 )
173 result = read_result_from_rxstack( NULL, sock, RXSTACK_HEADER_SIZE );
174 DROPSTRENG( result );
177 return 0;
180 char *get_unspecified_queue( void )
182 char *rxq = getenv( "RXQUEUE" );
184 if ( rxq == NULL )
185 rxq = "SESSION";
186 return rxq;
189 char *force_remote( char *rxq )
191 char *h ;
193 if ( strchr(rxq, '@' ) == NULL )
195 if ( ( h = (char *)malloc( strlen( rxq ) + 2 ) ) != NULL )
197 strcpy( h, rxq ) ;
198 strcat( h, "@" ) ;
199 return h ;
202 return rxq ;
205 char *get_action( char *parm )
207 char *action=NULL;
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;
219 else
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 */
224 return action;
227 void junk_return_from_rxstack( int sock, streng *header )
229 int length;
230 streng *result;
232 length = get_length_from_header( NULL, header );
233 if ( length )
235 result = read_result_from_rxstack( NULL, sock, length );
236 if ( result )
237 DROPSTRENG( result );
242 int cleanup( void )
244 #ifdef WIN32
245 WSACleanup();
246 #endif
247 if ( buff )
248 free( buff );
249 return 0;
252 int main( int argc, char *argv[])
254 int sock,rc=0,num;
255 char *action;
256 streng *queue=NULL,*server_name=NULL;
257 char *in_queue=NULL;
258 streng *result;
259 Queue q;
260 #ifdef WIN32
261 WORD wsver = (WORD)MAKEWORD(1,1);
262 WSADATA wsaData;
263 #endif
265 #ifdef WIN32
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);
271 #endif
273 argv++ ;
274 argc-- ;
276 if ( getenv( "RXDEBUG" ) != NULL )
277 debug = 1 ;
279 if ( ( argc >= 1 )
280 && ( ( strcmp( *argv, "-D" ) == 0 ) || ( strcmp( *argv, "/D" ) == 0 ) ) )
282 debug = 1 ;
283 putenv( "RXDEBUG=1" ) ;
284 argc-- ;
285 argv++ ;
288 action = NULL;
290 * Process the command line
292 if ( argc == 0 )
295 * "rxqueue"
297 action = RXSTACK_QUEUE_FIFO_STR;
298 in_queue = get_unspecified_queue();
300 else if ( argc == 1 )
303 * "rxqueue queue"
304 * or
305 * "rxqueue /switch"
307 if ( argv[0][0] == '/' )
310 * Only parameter is a switch
312 in_queue = get_unspecified_queue();
313 action = get_action( argv[0] );
315 else
318 * Only parameter is a queue name
320 in_queue = argv[0];
321 action = RXSTACK_QUEUE_FIFO_STR;
324 else if ( argc == 2 )
327 * "rxqueue queue /switch"
329 in_queue = argv[0];
330 if ( argv[1][0] == '/' )
333 * Parameter is a switch
335 action = get_action( argv[1] );
338 else
341 * ERROR
343 fprintf(stderr, "Invalid number of parameters\n");
344 rc = 1;
346 in_queue = force_remote( in_queue ) ;
347 if ( action )
349 queue = MAKESTRENG( strlen( in_queue ) );
350 if ( queue == NULL )
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
359 * and queue name
361 if ( parse_queue( NULL, queue, &q ) == 1 )
363 if ( PSTRENGLEN( queue ) == 0 )
365 DROPSTRENG( queue );
366 queue = MAKESTRENG( 7 );
367 if ( queue == NULL )
369 showerror( ERR_STORAGE_EXHAUSTED, 0, ERR_STORAGE_EXHAUSTED_TMPL );
370 exit(ERR_STORAGE_EXHAUSTED);
372 memcpy( PSTRENGVAL( queue ), "SESSION", 7 );
373 queue->len = 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 );
377 if ( sock < 0 )
379 cleanup();
380 exit(ERR_RXSTACK_CANT_CONNECT);
383 * Now process the actual command
385 switch( action[0] )
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;
397 break;
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 ) );
404 if ( rc == -1 )
406 showerror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_INTERNAL, ERR_RXSTACK_INTERNAL_TMPL, rc, "Setting default queue" );
407 rc = ERR_RXSTACK_INTERNAL;
408 break;
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;
416 break;
419 * Success. We need to throw away the returned queue name. We
420 * don't need it.
422 junk_return_from_rxstack( sock, result );
423 send_all( sock, action );
424 DROPSTRENG( result );
425 rc = 0;
426 break;
427 case RXSTACK_EMPTY_QUEUE:
428 DEBUGDUMP(printf("--- Empty Queue ---\n"););
429 rc = send_command_to_rxstack( NULL, sock, action, PSTRENGVAL( queue) , PSTRENGLEN( queue ) );
430 if ( rc == -1 )
432 showerror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_INTERNAL, ERR_RXSTACK_INTERNAL_TMPL, rc, "Emptying queue" );
433 rc = ERR_RXSTACK_INTERNAL;
434 break;
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;
442 break;
444 DROPSTRENG( result );
445 rc = 0;
446 break;
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 ) );
453 if ( rc == -1 )
455 showerror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_INTERNAL, ERR_RXSTACK_INTERNAL_TMPL, rc, "Setting default queue" );
456 rc = ERR_RXSTACK_INTERNAL;
457 break;
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;
468 break;
471 * Success. We need to throw away the returned queue name. We
472 * don't need it.
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 );
478 if ( rc == 0 )
479 printf("%d\n", num );
480 break;
481 case RXSTACK_PULL:
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 ) );
487 if ( rc == -1 )
489 showerror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_INTERNAL, ERR_RXSTACK_INTERNAL_TMPL, rc, "Setting default queue" );
490 rc = ERR_RXSTACK_INTERNAL;
491 break;
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;
499 break;
502 * Success. We need to throw away the returned queue name. We
503 * don't need it.
505 junk_return_from_rxstack( sock, result );
506 DROPSTRENG( result );
508 * Loop until the number of lines on the queue is zero
510 for ( ; ; )
512 DEBUGDUMP(printf("--- Pull ---\n"););
513 rc = get_line_from_rxstack( NULL, sock, &result, 0 );
514 if ( rc == 0 )
516 printf( "%.*s\n", PSTRENGLEN( result ), PSTRENGVAL( result ) ) ;
518 else if ( ( rc == 1 ) || ( rc == 4 ) )
521 * Queue empty.
523 rc = 0;
524 break;
526 else
528 showerror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_INTERNAL, ERR_RXSTACK_INTERNAL_TMPL, rc, "Getting line from queue" );
529 rc = ERR_RXSTACK_INTERNAL;
530 break;
532 DROPSTRENG( result );
534 break;
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 );
542 close(sock);
544 else
546 DEBUGDUMP(printf( "queue: <%.*s>\n", PSTRENGLEN( queue ), PSTRENGVAL( queue ) ););
547 rc = 1;
550 DROPSTRENG( server_name );
551 DROPSTRENG( queue );
552 cleanup();
553 return rc;