/* File: aceclient.c * Author: Jean Thierry-Mieg (mieg@kaa.cnrs-mop.fr) * Copyright (C) J Thierry-Mieg and R Durbin, 1992 * ------------------------------------------------------------------- * Acedb is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * or see the on-line version at http://www.gnu.org/copyleft/gpl.txt * ------------------------------------------------------------------- * This file is part of the ACEDB genome database package, written by * Richard Durbin (MRC LMB, UK) rd@mrc-lmb.cam.ac.uk, and * Jean Thierry-Mieg (CRBM du CNRS, France) mieg@kaa.cnrs-mop.fr * * * Description: * I started from a sample code generated by rpcgen on Solaris * and a first version by Peter Kocab. * * Exported functions: * HISTORY: * Last edited: Jul 11 14:31 2000 (edgrif) * * Nov 4 17:22 1999 (fw): switched input to ACEIN * * Dec 2 15:55 1998 (edgrif): Correct decl. of main, add code to * record build time of this module. * Created: Wed Nov 25 20:02:45 1992 (mieg) *------------------------------------------------------------------- */ /* $Id: aceclient.c,v 1.41 2003/07/04 01:50:14 mieg Exp $ */ #include #include #include #include #include #include static int nAceIn = 0; static int chunkSize = 10; extern int accessDebug ; /* in aceclientlib.c */ /****************************************************************/ static char* getAceLevel (ACEIN fi, char *prompt, int limit, BOOL mask) /* read */ { static Stack s = 0 ; BOOL in = FALSE ; char *cp, cutter ; int nn = 1 ; s = stackReCreate (s, 30000) ; /* If mask is true then "parse =" is pushed on to the front of whatever */ /* the user enters at the command line. This is all implicit and horrible, */ /* we already have one mechanism for passing pure ace data to the server, */ /* why do we need another one ???????? uuuggggghhhhh....... */ if (mask) pushText (s, "parse = ") ; while (aceInPrompt (fi, prompt)) { cp = aceInWordCut (fi, "\n" ,&cutter) ; if (cp && *cp) { if (!in) { nn++ ; nAceIn++ ; in = TRUE ; } catText (s, cp) ; if (mask) catText (s, "\\n") ; else catText (s, "\n") ; } else { if (mask) catText (s, "\\n") ; else catText (s, "\n") ; in = FALSE ; if (limit && !(nn % limit)) break ; } } if (nn > 1) return stackText (s, 0); return NULL; } /* getAceLevel */ /*****************************************************************/ static char* getAceData (char *prompt) { ACEIN fi; char *cp ; fi = aceInCreateFromStdin (TRUE, "", 0); /* do NOT test stdinIsInteractive(), * this would changes the behaviour of the * code in pipe calls */ aceInSpecial (fi, "\n/\\\t@") ; cp = getAceLevel (fi, prompt, 0, TRUE) ; aceInDestroy (fi); return cp ; } /* getAceData */ /*****************************************************************/ static char* getOrder (ACEIN fi, char *prompt, BOOL silent, BOOL isAceIn, BOOL isAceOut, BOOL isReport) { static Stack s = 0 ; char *cp = 0, cutter, *errtext; int np ; if (isAceIn) return getAceLevel (fi, prompt, 500, FALSE) ; lao: cutter = 0 ; cp = aceInWordCut (fi, isReport ? "#" : "" ,&cutter) ; if ((!cp && !cutter) || (cp && *cp == '/' && *(cp+1) == '/')) { if (!aceInPrompt(fi, prompt)) return 0 ; /* just get a card */ if (isReport && (!cp || *cp != '/')) { putchar ('\n'); fflush(stdout); } goto lao ; } if (!silent || isAceOut) return cp ; /* the whole line will be processed by the server */ /* Now silent = TRUE and we are in report mode*/ if (!cutter) /* just print out the line */ { if (cp) { printf("%s",cp); fflush(stdout); } goto lao ; } if (cp) { printf("%s",cp) ; /* print the beginning */ fflush(stdout); } s = stackReCreate(s, 50) ; s->textOnly = TRUE ; pushText(s,"") ; if (!freestep('(')) { putchar (cutter) ; goto lao ; } np = 1 ; while (np && (cp = aceInWordCut(fi, "()" ,&cutter))) { catText(s, cp) ; switch (cutter) { case '(': catText(s,"(") ; np++ ; break ; case ')': np-- ; if (np) catText(s,")") ; break ; case 0: if (np) { errtext = "Missing right parenthese" ; goto error ; } } } cp = stackText(s,0) ; return cp ; /* let the server process this command */ error: printf("//! %s after %% in %s\n", errtext, stackText(s,0)) ; cp = aceInPos(fi) ; if (cp) printf("//! %s",cp) ; fflush(stdout); goto lao ; } /* getOrder */ /*********************************************************************/ static void signalHandler (int sig) { if (sig == SIGINT) messExit ("SIGINT"); else if (sig == SIGQUIT) messExit ("SIGQUIT"); } /* signalHandler */ /*********************************************************************/ /* Defines a routine to return the compile date of this file. */ UT_MAKE_GETCOMPILEDATEROUTINE() int main (int argc, char *argv[]) { void *handle; /* JC do not need to know what it is */ char *host; char *prompt; unsigned char *answer; int n, retval, length, t, timeOut = 300 , encore = 0 ; unsigned long port = DEFAULT_PORT; unsigned long p; BOOL silent = FALSE, doWrite = TRUE , isReport = FALSE, encoring, isAceIn = FALSE, isAceOut = FALSE, isQuit = FALSE, isShutdown = FALSE ; char *cp ; ACEIN fi = 0; Stack s = 0 ; struct sigaction sa; /* Does not return if user typed "-version" option. checkForCmdlineVersion(&argc, argv) ; */ memset (&sa, 0, sizeof(struct sigaction)); sa.sa_handler = signalHandler; sigemptyset(&sa.sa_mask); if (sigaction(SIGINT, &sa, 0) != 0 || /* Ctrl-C */ sigaction(SIGQUIT, &sa, 0) != 0) /* Ctrl-\ */ messerror ("Signal handler initialisation failed (%s)", messSysErrorText()); if ( argc < 2 ) goto abort ; host = argv[1] ; prompt = strnew(messprintf("acedb@%s> ", host), 0); n = 2 ; if (argc > n + 1 && strcmp("-port", argv[n]) == 0) { if (sscanf(argv[n+1],"%lu",&p)== 1) { port = p ; n += 2 ; } else goto abort ; } if (argc > n + 1 && strcmp("-time_out", argv[n]) == 0) { if (sscanf(argv[n+1],"%ic",&t)== 1) { timeOut = t ; n += 2 ; } else goto abort ; } if (argc > n && (strcmp("-access_info", argv[n]) == 0 || strcmp("access_info", argv[n]) == 0)) { accessDebug = TRUE ; n++ ; } if (argc > n && (strcmp("-ace_out", argv[n]) == 0 || strcmp("ace_out", argv[n]) == 0)) { isAceOut = TRUE ; silent = TRUE ; n++ ; } if (argc > n && (strcmp("-ace_in", argv[n]) == 0 || strcmp("ace_in", argv[n]) == 0)) { isAceIn = TRUE ; encore = 3 ; fi = aceInCreateFromStdin (FALSE, "", 0);/* non-interactive */ n++ ; } if (argc > n) { if (!strcmp("-f", argv[n])) { n++ ; isReport = TRUE ; silent = TRUE; fi = aceInCreateFromFile (argv[n], "r", "", 0); if (!fi) { printf ("//! Cannot open file %s given on command line\n", argv[n]) ; fflush(stdout); goto abort ; } } else goto abort ; } s = stackReCreate(s,50) ; pushText(s,"") ; if (argc > n) { int i ; n++ ; for (i= n ; i < argc ; i++) { catText(s, argv[i]) ; catText(s, " ") ; } } if (!fi) { if (silent) /* non-interactive input */ fi = aceInCreateFromStdin (FALSE, "", 0); else fi = aceInCreateFromStdin (TRUE, "", 0); /* do NOT test stdinIsInteractive(), * this would changes the behaviour of the * code in pipe calls */ } if (isReport) aceInSpecial (fi, "\n\t\\@%$") ; /* no // (to echo empty lines), allow client-side sub shells */ else aceInSpecial (fi, "\n\t\\/@%$") ; /* allow client-side sub shells */ if ((handle = openServer(host, port, timeOut)) == NULL) { printf("//! cannot establish connection\n") ; fflush(stdout); goto abort; } #ifdef DEBUG else printf("opened connection to %s on port %lu\n\n",host,port); #endif while((cp = getOrder(fi, prompt, silent, isAceIn, isAceOut, isReport))) { if (strncasecmp(cp, "query", 5) != 0 && freelower(*cp) == 'q') /* quit command */ { cp = "quit" ; isQuit = TRUE ; /* transmit the quit to the server */ } if (strncasecmp(cp, "shutdown", 8) == 0) isShutdown = TRUE ; else isShutdown = FALSE ; doWrite = TRUE ; if (isAceOut && strncasecmp(cp,"Write",5) && strncasecmp (cp, "Table", 5)) doWrite = FALSE ; /* If someone just enters "parse" then get the ace data from stdin. */ if (!strncasecmp(cp, "parse", 5) && strNumWords(cp) == 1) { cp = getAceData ("parse> ") ; if (!cp) continue; } /* For requests that generate large responses from the server, this */ /* gets set TRUE and we have an inner loop with goto suiteReponse. */ encoring = FALSE ; suiteReponse: retval = askServerBinary (handle, cp, &answer, &length, &encore, chunkSize) ; if (isShutdown && retval == 5) { printf("// The server has disconnected\n\n") ; /* DWB - report error code */ exit (0) ; } if (isQuit) break ; /* reply is null */ if (retval > 0) /* error handling */ { printf("//! Null answer - Error Code: %d\n", retval) ; /* DWB - report error code */ printf("//! You may have timed out") ; break ; continue ; } if (!encore && !answer) /* error handling */ { printf("//! Null reponse, you may have timed out \n") ; if (silent || messQuery("// Do you want to quit (y/n) ?")) break ; continue ; } if (length && !encoring && !silent) printf ("// Reponse: %d bytes.\n", length) ; s = stackReCreate(s,length) ; stackTextForceFeed(s, length) ; memcpy(stackText(s,0), answer, length) ; free(answer); stackCursor(s, 0) ; if (doWrite) { while ((cp = stackNextText(s))) { if ((silent || (encore && encore != 3)) && (!*cp || *cp == '/')) continue ; if (silent) /* jump // lines */ { register char *cp1 = cp, *cp2, cc ; while (*cp1) { cp2 = cp1 ; while (*cp2 && *cp2 != '\n') cp2++ ; cc = *cp2 ; *cp2 = 0 ; if (!(*cp1 == '/' && *(cp1 + 1) == '/')) puts (cp1) ; if (cc) *cp2++ = cc ; cp1 = cp2 ; } } else { if (*cp) { register char *cp1 = cp + strlen(cp) - 1 ; if (cp1 >= cp && *cp1 == '\n') *cp1 = 0 ; /* because puts adds a terminal \n */ if (*cp) puts (cp) ; else putchar('\n') ; } } } } if (isAceIn) continue ; if (encore) { encoring = TRUE ; cp = "encore" ; goto suiteReponse ; /* get rest of data */ } } closeServer(handle); if (!silent) printf("\n" "// Please report problems to mieg@kaa.crbm.cnrs-mop.fr\n" "// Bye\n" "\n") ; if (isAceIn) printf ("\n// Passed %d objects to the server, \n// ciao bye \n\n", nAceIn) ; return(EXIT_SUCCESS) ; abort: fprintf(stderr, "//! usage: aceclient host [-port number] [-time_out secs] " "[-access_info] [-ace_out] [-ace_in] [-f reportfile parameters]\n") ; return(EXIT_FAILURE) ; } /* main */ /*********************** eof ********************************/