home *** CD-ROM | disk | FTP | other *** search
- #ifdef RCSID
- static char *RCSid =
- "$Header: readpipe.c 7010300.1 94/02/24 18:40:31 snataraj Generic<base> $ ";
- #endif /* RCSID */
-
- /* Copyright (c) 1991 by Oracle Corporation */
- /*
- NAME
- readpipe.c - read a server named pipe
- NOTES
- described in ORACLE7 Server Application Developer's Guide
- MODIFIED (MM/DD/YY)
- emendez 02/02/94 - Fix for bug 157576
- gdoherty 01/31/94 - make oci header inclusion for ansi or k+r adaptive
- rkooi 12/15/92 - add some comments
- tssmith 12/15/92 - Added break in for(;;) loop
- tssmith 12/12/92 - Creation
- */
-
- /*
- * readpipe.c
- *
- * This OCI program demonstrates how to read messages from
- * a named pipe. This program can be run in
- * a window or terminal session, and be used to print messages
- * from a PL/SQL source program (an anonymous block or a
- * stored procedure).
- *
- * This is very useful in debugging PL/SQL programs.
- *
- * First, you must create a PL/SQL package and package body that packs
- * your message(s) and sends them to a named pipe.
- * In the example below, two 'put' procedures are implemented,
- * overloaded by type: VARCHAR2 and NUMBER. This you can extend
- * as required for additional types.
- *
- * Store this package in the server in an appropriate schema,
- * and grant execute privilege on it to the users who require it.
- *
- * You will need to grant execute privilege on the dbms_pipe package
- * to the owner of the plsdbg package below.
- *
- * Note that this example uses only a single named pipe. It could
- * be confusing if more than one PL/SQL program were writing to
- * the same pipe (unless some identifying protocol is established).
- * It would certainly be confusing if several OCI programs like
- * the one below were reading the same pipe.
- *
- * Here is the example package:
- *
- * create or replace package plsdbg as
- * -- the procedure put is overloaded for varchar strings
- * -- and numbers. extend as needed.
- * procedure put(info varchar2);
- * procedure put(n number);
- * end;
- * /
- *
- * create or replace package body plsdbg as
- *
- * procedure put(info varchar2) is
- * status integer; -- ret. val. required for the
- * -- send_message function, not used here
- * begin
- * dbms_pipe.pack_message(info);
- * status := dbms_pipe.send_message('ora$plsql_debug');
- * end;
- *
- * procedure put(n number) is
- * chr varchar2(44);
- * status integer;
- * begin
- * chr := to_char(n);
- * dbms_pipe.pack_message(chr);
- * status := dbms_pipe.send_message('ora$plsql_debug');
- * end;
- * end;
- * /
- *
- * In a PL/SQL program, you call plsdbg to write messages to the
- * pipe 'ora$plsql_debug' like this:
- * ...
- * declare
- * my_var integer;
- * ...
- * begin
- * my_var := 42;
- * ... -- program procedes until debug output is needed
- * plsdbg.put('Hmm, my_var is--');
- * plsdbg.put(my_var);
- * -- and the OCI program reading ora$plsql_debug will
- * -- print the text message, and the value of my_var
- * ...
- */
-
- #include <stdio.h>
- #include <string.h>
-
- /* These header files must be included for the
- type information, and #defined constants. */
- #include <oratypes.h>
- #include <ocidfn.h>
- #ifdef __STDC__
- #include <ociapr.h>
- #else
- #include <ocikpr.h>
- #endif
-
- /* demo constants and structs */
- #include <ocidem.h>
-
- /* Declare the CDA, LDA, and HDA. */
- Cda_Def lda;
- ub1 hda[HDA_SIZE];
- Cda_Def cda;
-
- /* Define a string that holds the anonymous PL/SQL block.
- The block calls the DBMS_PIPE procedures to get messages
- written to the pipe named ora$plsql_debug. */
-
- #define GETNEXTITEM "\
- declare\
- s integer;\
- chr varchar2(200);\
- begin\
- chr := '';\
- s := dbms_pipe.receive_message('ora$plsql_debug');\
- if s = 0 then\
- dbms_pipe.unpack_message(chr);\
- end if;\
- :status := s;\
- :retval := chr;\
- end;"
-
- /* Error-handling function */
- void errrpt();
-
-
- main(argc, argv)
- sword argc;
- text **argv;
- {
- text username[128];
- ub1 retval[132];
- sword status;
-
- /* Prepare username/password, from command line or
- else use scott/tiger as the default if none given on
- the command line. */
-
- if (argc > 1)
- strncpy((char *) username, (char *) argv[1],
- (sword) sizeof (username) - 1);
- else
- strcpy((char *) username, "SCOTT/TIGER");
-
- /* Connect to ORACLE. */
- if (orlon(&lda, hda, username, -1,
- (text *) 0, -1, 0))
- {
- printf("Cannot connect as %s. Exiting...\n", username);
- exit(1);
- }
- else
- printf("connected\n");
-
- /* Open the cursor -- must quit if we cannot. */
- if (oopen(&cda, &lda, (text *) 0, -1, -1, (text *) 0, -1))
- {
- printf("Error opening cursor. Exiting...\n");
- exit(1);
- }
-
- /* Parse the anonymous PL/SQL block. */
- if (oparse(&cda, (text *) GETNEXTITEM,
- (sb4) -1, 0, (ub4) 2))
- {
- errrpt();
- exit(1);
- }
-
- /* Bind the status program variable. */
- if (obndrv(&cda, (text *) ":status", -1, (ub1 *) &status,
- (sword) sizeof (sword), SQLT_INT,
- -1, (sb2 *) 0, (text *) 0, -1, -1))
- {
- errrpt();
- exit(1);
- }
-
- /* Bind the return string (retval). */
- if (obndrv(&cda, (text *) ":retval", -1, (ub1 *) retval,
- (sword) sizeof (retval), SQLT_STR,
- -1, (sb2 *) 0, (text *) 0, -1, -1))
- {
- errrpt();
- exit(1);
- }
-
- /* Loop to look for print messages on the pipe */
- printf("listening...\n");
- for (;;)
- {
- if (oexec(&cda))
- {
- errrpt();
- break;
- }
-
- if (status != 0)
- printf("Abnormal pipe status: %d\n\r", status);
- else
- printf("%s\n\r", retval);
- }
- }
-
-
- /* Report errors. */
- void errrpt()
- {
- sword rv;
- text msg[1024];
-
- /* use oerhms to get error messages longer than 70 characters */
- rv = oerhms(&lda, cda.rc, msg, (sword) sizeof (msg));
- printf("ORACLE ERROR\n");
- printf("%.*s\n", rv, msg);
- }
-
-
-
-