Fetch Flex from Sourceforge.
[AROS-Contrib.git] / regina / rxqueue.c
blob57ecdcde21eed1cc62d404f872d10320da4ae98a
1 #ifndef lint
2 static char *RCSid = "$Id$";
3 #endif
5 /*
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.
24 #include "rexx.h"
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #else
29 # include "configur.h"
30 #endif
32 #ifdef WIN32
33 # if defined(_MSC_VER)
34 # if _MSC_VER >= 1100
35 /* Stupid MSC can't compile own headers without warning at least in VC 5.0 */
36 # pragma warning(disable: 4115 4201 4214)
37 # endif
38 # include <windows.h>
39 # if _MSC_VER >= 1100
40 # pragma warning(default: 4115 4201 4214)
41 # endif
42 # else
43 # include <windows.h>
44 # endif
45 # include <io.h>
46 #else
47 # ifdef HAVE_SYS_SOCKET_H
48 # include <sys/socket.h>
49 # endif
50 # ifdef HAVE_NETINET_IN_H
51 # include <netinet/in.h>
52 # endif
53 # ifdef HAVE_SYS_SELECT_H
54 # include <sys/select.h>
55 # endif
56 # ifdef HAVE_NETDB_H
57 # include <netdb.h>
58 # endif
59 # ifdef HAVE_ARPA_INET_H
60 # include <arpa/inet.h>
61 # endif
62 #endif
64 #include <string.h>
66 #ifdef HAVE_UNISTD_H
67 #include <unistd.h>
68 #endif
70 #ifdef HAVE_ERRNO_H
71 #include <errno.h>
72 #endif
74 #ifdef HAVE_SIGNAL_H
75 #include <signal.h>
76 #endif
78 #include "extstack.h"
80 #define SUCCESS(a) ((a)&&(a)->value[0] == '0')
82 #ifndef NDEBUG
83 # define DEBUGDUMP(x) {x;}
84 #else
85 # define DEBUGDUMP(x) {}
86 #endif
88 char *buff=NULL;
89 unsigned int bufflen=0;
91 #if !defined(HAVE_STRERROR)
93 * Sigh! This must probably be done this way, although it's incredibly
94 * backwards. Some versions of gcc comes with a complete set of ANSI C
95 * include files, which contains the definition of strerror(). However,
96 * that function does not exist in the default libraries of SunOS.
97 * To circumvent that problem, strerror() is #define'd to get_sys_errlist()
98 * in config.h, and here follows the definition of that function.
99 * Originally, strerror() was #defined to sys_errlist[x], but that does
100 * not work if string.h contains a declaration of the (non-existing)
101 * function strerror().
103 * So, this is a mismatch between the include files and the library, and
104 * it should not create problems for Regina. However, the _user_ will not
105 * encounter any problems until he compiles Regina, so we'll have to
106 * clean up after a buggy installation of the C compiler!
108 const char *get_sys_errlist( int num )
110 extern char *sys_errlist[] ;
111 return sys_errlist[num] ;
113 #endif
115 int send_all( int sock, char *action )
118 * Send everything in stdin to the socket. Each LF encountered
119 * results in a send.
120 * This code borrowed from rxstack.c in REXX/imc
122 int c,rc;
123 unsigned int len;
124 streng *result;
126 for ( ; ; )
128 len = 0;
129 while ( ( c = getchar() ) != EOF && c != '\n' )
131 if ( len >= bufflen
132 && (( buff = realloc( buff, bufflen <<= 1 ) ) == NULL ) )
134 showerror( ERR_STORAGE_EXHAUSTED, 0, ERR_STORAGE_EXHAUSTED_TMPL );
135 exit( ERR_STORAGE_EXHAUSTED );
137 buff[len++] = (char)c;
139 if ( (c == EOF || feof(stdin) )
140 && !len)
141 break;
142 DEBUGDUMP(printf("--- Queue %s ---\n", action[0] == RXSTACK_QUEUE_FIFO ? "FIFO" : "LIFO"););
143 rc = send_command_to_rxstack( NULL, sock, action, buff, len );
144 if ( rc != -1 )
146 result = read_result_from_rxstack( NULL, sock, RXSTACK_HEADER_SIZE );
147 DROPSTRENG( result );
150 return 0;
153 char *get_unspecified_queue( void )
155 char *rxq = getenv( "RXQUEUE" );
157 if ( rxq == NULL )
158 rxq = "SESSION";
159 return rxq;
162 char *get_action( char *parm )
164 char *action=NULL;
166 if ( strcmp( parm, "/fifo" ) == 0 )
167 action = RXSTACK_QUEUE_FIFO_STR;
168 else if ( strcmp( parm, "/lifo" ) == 0 )
169 action = RXSTACK_QUEUE_LIFO_STR;
170 else if ( strcmp( parm, "/clear" ) == 0 )
171 action = RXSTACK_EMPTY_QUEUE_STR;
172 else if ( strcmp( parm, "/pull" ) == 0 )
173 action = RXSTACK_PULL_STR;
174 else if ( strcmp( parm, "/queued" ) == 0 )
175 action = RXSTACK_NUMBER_IN_QUEUE_STR;
176 else
178 showerror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_INVALID_SWITCH, ERR_RXSTACK_INVALID_SWITCH_TMPL, "/fifo, /lifo, /clear, /queued, /pull" );
179 /* not setting action will exit */
181 return action;
184 void junk_return_from_rxstack( int sock, streng *header )
186 int length;
187 streng *result;
189 length = get_length_from_header( NULL, header );
190 if ( length )
192 result = read_result_from_rxstack( NULL, sock, length );
193 if ( result )
194 DROPSTRENG( result );
199 int cleanup( void )
201 #ifdef WIN32
202 WSACleanup();
203 #endif
204 if ( buff )
205 free( buff );
206 return 0;
209 int main( int argc, char *argv[])
211 int sock,portno,rc=0,i,num;
212 char *action;
213 streng *queue=NULL,*server_name=NULL;
214 char *in_queue=NULL;
215 int server_address;
216 streng *result;
217 #ifdef WIN32
218 WORD wsver = (WORD)MAKEWORD(1,1);
219 WSADATA wsaData;
220 #endif
222 #ifdef WIN32
223 if ( WSAStartup( wsver, &wsaData ) != 0 )
225 showerror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_NO_WINSOCK, ERR_RXSTACK_NO_WINSOCK_TMPL, WSAGetLastError() );
226 exit(ERR_RXSTACK_NO_WINSOCK);
228 #endif
230 action = NULL;
232 * Process the command line
234 if ( argc == 1 )
237 * "rxqueue"
239 action = RXSTACK_QUEUE_FIFO_STR;
240 in_queue = get_unspecified_queue();
242 else if ( argc == 2 )
245 * "rxqueue queue"
246 * or
247 * "rxqueue /switch"
249 if ( argv[1][0] == '/' )
252 * Only parameter is a switch
254 in_queue = get_unspecified_queue();
255 action = get_action( argv[1] );
257 else
260 * Only parameter is a queue name
262 in_queue = argv[1];
263 action = RXSTACK_QUEUE_FIFO_STR;
266 else if ( argc == 3 )
269 * "rxqueue queue /switch"
271 in_queue = argv[1];
272 if ( argv[2][0] == '/' )
275 * Parameter is a switch
277 action = get_action( argv[2] );
280 else
283 * ERROR
285 fprintf(stderr, "Invalid number of parameters\n");
286 rc = 1;
288 if ( action )
290 queue = MAKESTRENG( strlen( in_queue ) );
291 if ( queue == NULL )
293 showerror( ERR_STORAGE_EXHAUSTED, 0, ERR_STORAGE_EXHAUSTED_TMPL );
294 exit(ERR_STORAGE_EXHAUSTED);
296 memcpy( PSTRENGVAL( queue ), in_queue, PSTRENGLEN( queue ) );
298 * Parse the queue to determine server address
299 * and queue name
301 if ( parse_queue( NULL, queue, &server_name, &server_address, &portno ) == 0 )
303 if ( PSTRENGLEN( queue ) == 0 )
305 DROPSTRENG( queue );
306 queue = MAKESTRENG( strlen( in_queue ) );
307 if ( queue == NULL )
309 showerror( ERR_STORAGE_EXHAUSTED, 0, ERR_STORAGE_EXHAUSTED_TMPL );
310 exit(ERR_STORAGE_EXHAUSTED);
312 memcpy( PSTRENGVAL( queue ), "SESSION", PSTRENGLEN( queue ) );
314 DEBUGDUMP(printf( "queue: <%s> server: %s<%d> Port:%d\n", PSTRENGVAL( queue ), PSTRENGVAL( server_name ), server_address,portno ););
315 sock = connect_to_rxstack( NULL, portno, server_name, server_address );
316 if ( sock < 0 )
318 cleanup();
319 exit(ERR_RXSTACK_CANT_CONNECT);
322 * Now process the actual command
324 switch( action[0] )
326 case RXSTACK_QUEUE_FIFO:
327 case RXSTACK_QUEUE_LIFO:
328 DEBUGDUMP(printf("--- Queue %s ", action[0] == RXSTACK_QUEUE_FIFO ? "FIFO" : "LIFO"););
330 * Allocate the initial buffer
332 if (( buff = (char *)malloc( bufflen = 256 ) ) == NULL )
334 showerror( ERR_STORAGE_EXHAUSTED, 0, ERR_STORAGE_EXHAUSTED_TMPL );
335 rc = ERR_STORAGE_EXHAUSTED;
336 break;
339 * Set the current queue
341 DEBUGDUMP(printf("(Set Queue) ---\n"););
342 rc = send_command_to_rxstack( NULL, sock, RXSTACK_SET_QUEUE_STR, PSTRENGVAL( queue) , PSTRENGLEN( queue ) );
343 if ( rc == -1 )
345 showerror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_INTERNAL, ERR_RXSTACK_INTERNAL_TMPL, rc, "Setting default queue" );
346 rc = ERR_RXSTACK_INTERNAL;
347 break;
349 result = read_result_from_rxstack( NULL, sock, RXSTACK_HEADER_SIZE );
350 if ( !SUCCESS( result ) )
352 showerror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_INTERNAL, ERR_RXSTACK_INTERNAL_TMPL, rc, "Setting default queue" );
353 DROPSTRENG( result );
354 rc = ERR_RXSTACK_INTERNAL;
355 break;
358 * Success. We need to throw away the returned queue name. We
359 * don't need it.
361 junk_return_from_rxstack( sock, result );
362 send_all( sock, action );
363 DROPSTRENG( result );
364 rc = 0;
365 break;
366 case RXSTACK_EMPTY_QUEUE:
367 DEBUGDUMP(printf("--- Empty Queue ---\n"););
368 rc = send_command_to_rxstack( NULL, sock, action, PSTRENGVAL( queue) , PSTRENGLEN( queue ) );
369 if ( rc == -1 )
371 showerror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_INTERNAL, ERR_RXSTACK_INTERNAL_TMPL, rc, "Emptying queue" );
372 rc = ERR_RXSTACK_INTERNAL;
373 break;
375 result = read_result_from_rxstack( NULL, sock, RXSTACK_HEADER_SIZE );
376 if ( !SUCCESS( result ) )
378 showerror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_INTERNAL, ERR_RXSTACK_INTERNAL_TMPL, rc, "Emptying queue" );
379 DROPSTRENG( result );
380 rc = ERR_RXSTACK_INTERNAL;
381 break;
383 DROPSTRENG( result );
384 rc = 0;
385 break;
386 case RXSTACK_NUMBER_IN_QUEUE:
388 * Set the current queue
390 DEBUGDUMP(printf("--- Set Queue ---\n"););
391 rc = send_command_to_rxstack( NULL, sock, RXSTACK_SET_QUEUE_STR, PSTRENGVAL( queue ), PSTRENGLEN( queue ) );
392 if ( rc == -1 )
394 showerror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_INTERNAL, ERR_RXSTACK_INTERNAL_TMPL, rc, "Setting default queue" );
395 rc = ERR_RXSTACK_INTERNAL;
396 break;
399 * Read the return response header
401 result = read_result_from_rxstack( NULL, sock, RXSTACK_HEADER_SIZE );
402 if ( !SUCCESS( result ) )
404 showerror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_INTERNAL, ERR_RXSTACK_INTERNAL_TMPL, rc, "Setting default queue" );
405 DROPSTRENG( result );
406 rc = ERR_RXSTACK_INTERNAL;
407 break;
410 * Success. We need to throw away the returned queue name. We
411 * don't need it.
413 junk_return_from_rxstack( sock, result );
414 DROPSTRENG( result );
415 DEBUGDUMP(printf("--- Number in Queue ---\n"););
416 num = get_number_in_queue_from_rxstack( NULL, sock );
417 printf("%d\n", num );
418 rc = 0;
419 break;
420 case RXSTACK_PULL:
422 * Set the current queue
424 DEBUGDUMP(printf("--- Set Queue ---\n"););
425 rc = send_command_to_rxstack( NULL, sock, RXSTACK_SET_QUEUE_STR, PSTRENGVAL( queue ), PSTRENGLEN( queue ) );
426 if ( rc == -1 )
428 showerror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_INTERNAL, ERR_RXSTACK_INTERNAL_TMPL, rc, "Setting default queue" );
429 rc = ERR_RXSTACK_INTERNAL;
430 break;
432 result = read_result_from_rxstack( NULL, sock, RXSTACK_HEADER_SIZE );
433 if ( !SUCCESS( result ) )
435 showerror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_INTERNAL, ERR_RXSTACK_INTERNAL_TMPL, rc, "Setting default queue" );
436 DROPSTRENG( result );
437 rc = ERR_RXSTACK_INTERNAL;
438 break;
441 * Success. We need to throw away the returned queue name. We
442 * don't need it.
444 junk_return_from_rxstack( sock, result );
445 DROPSTRENG( result );
447 * Loop until the number of lines on the queue is zero
449 for ( ; ; )
451 DEBUGDUMP(printf("--- Pull ---\n"););
452 rc = get_line_from_rxstack( NULL, sock, &result );
453 if ( rc == 0 )
455 for ( i = 0; i < PSTRENGLEN( result ); i++ )
457 putchar( result->value[i] );
459 putchar( '\n' );
461 else if ( rc == 2 )
463 showerror( ERR_EXTERNAL_QUEUE, ERR_RXSTACK_INTERNAL, ERR_RXSTACK_INTERNAL_TMPL, rc, "Getting line from queue" );
464 rc = ERR_RXSTACK_INTERNAL;
465 break;
467 else
470 * Queue empty.
472 rc = 0;
473 break;
475 DROPSTRENG( result );
477 break;
480 * Tell the server we want to disconnect
481 * Don't expect any return result.
483 DEBUGDUMP(printf("--- Exit ---\n"););
484 send_command_to_rxstack( NULL, sock, RXSTACK_EXIT_STR, NULL, 0 );
485 close(sock);
487 else
489 DEBUGDUMP(printf( "queue: <%s> server: %s<%d> Port:%d\n", PSTRENGVAL( queue ), PSTRENGVAL( server_name ), server_address,portno ););
492 DROPSTRENG( server_name );
493 DROPSTRENG( queue );
494 cleanup();
495 return rc;