svc99() — Access supervisor call

Standards

Standards / Extensions C or C++ Dependencies
Language Environment® both  

Format

#include <stdio.h>

int svc99(__S99parms *string);

General description

Provides access to SVC99 on z/OS®, which provides ability to:
  • Dynamically allocate or deallocate a resource
  • Dynamically concatenate or deconcatenate data sets
  • Dynamically retrieve information on data sets

To avoid infringing on the user's name space, this nonstandard function has two names. One name is prefixed with two underscore characters, and one name is not. The name without the prefix underscore characters is exposed only when Start of changeusing the runtime library extensionsEnd of change.

The __S99parms structure must be in 31-bit addressable storage. A call to svc99() with 64-bit addressable storage will result in -1 return code.

The __S99TXTPP element needs to be a 32-bits wide pointer to 31-bit addressable storage containing an array of text unit pointers. Each of the text unit pointers must be a 32-bits wide pointer, each pointing to 31-bit addressable storage containing a text unit, or can be a NULL pointer. The last text unit pointer must have its high bit (traditional 31-bit amode high bit) turned on to denote the end of text units has been reached.

The __S99S99X element needs to be a 32-bits wide pointer to 31-bit addressable storage containing the __S99rbx structure, when needed. This is consistent with the __dyn_t structure element __rbx requirement outlined above.

The __S99parms structure is defined in stdio.h. It has been changed to include the address of the Request Block Extension. The Request Block Extension and the Error Message Parameter list can be used to process the messages returned by SVC99 when an error occurs. To use this feature, you must allocate and initialize these structures.

Table 1. Elements Contained by __S99parms Structure
Field Type Value Stored
__S99RBLN unsigned char SVC99 length of request block
__S99VERB unsigned char SVC99 verb code
__S99FLAG1 unsigned short SVC99 Flags 1 field
__S99ERROR unsigned short SVC99 error code field
__S99INFO unsigned short SVC99 information code
__S99TXTPP void * __ptr32 SVC99 pointer to a list of text unit pointers
__S99S99X void * __ptr32 SVC99 pointer to the Request Extension Block
__S99FLAG2 unsigned int SVC99 Flags 2 field for APF authorized programs

Returned value

If the input pointer is NULL, svc99() returns 0 if running under CICS® and nonzero otherwise. The nonzero value indicates that svc99() is supported under the current operating system (that is, z/OS non-CICS). If the input is not NULL, svc99() returns -1 if running under CICS (to indicate an error), otherwise it returns a code that results from svc99().

If the input is not NULL, and svc99() is not supported on the system, it returns -1.

Example

CELEBS58
/* CELEBS58

   This example uses the svc99() function to dynamically allocate a data
   set called USERID.EXAMPLE.

 */
#define MASK 0x80000000
#define _EXT

#include <stdio.h>
#include <string.h>

int main(void)
{
    int rc;
    struct __S99struc parmlist;
    char *s[10] = {                      /* array of text pointers */
    /* text units follow */
        "\0\x02\0\x01\0\x0E""USERID.EXAMPLE", /* DSN=EXAMPLE */
        "\0\x05\0\x01\0\x01\x02",             /* DISP=(,CATLG) */
        "\0\x07\0\0",                         /* SPACE=(TRK,.. */
        "\0\x0A\0\x01\0\x03\0\0\x14",         /* primary=20 */
        "\0\x0B\0\x01\0\x03\0\0\x01",         /* secondary=1 */
        "\0\x15\0\x01\0\x05SYSDA",            /* UNIT=SYSDA */
        "\0\x30\0\x01\0\x02\0\x50",           /* BLKSIZE=80 */
        "\0\x3C\0\x01\0\x02\x40\0",           /* DSORG=PS */
        "\0\x42\0\x01\0\x02\0\x50",           /* LRECL=80 */
        "\0\x49\0\x01\0\x01\x80"};            /* RECFM=F */

    memset(&parmlist, 0, sizeof(parmlist));
    parmlist.__S99RBLN = 20;
    parmlist.__S99VERB = 1;            /* verb for dsname allocation       */
    parmlist.__S99FLAG1 = 0x4000;      /* do not use existing allocation   */
    parmlist.__S99TXTPP = s;           /* pointer to pointer to text units */
    s[9] = (char *)((long unsigned) (s[9]) | MASK);

    rc = svc99(&parmlist);
    if (rc != 0)
       printf(" Error code = %d   Information code = %d\n",
           parmlist.__S99ERROR, parmlist.__S99INFO);
}

If your user ID starts with one of the letters A-F, you must add two double quotation marks (") before the user ID so that the first letter of the user ID is interpreted as a character rather than as a hexadecimal digit.

The preceding example can be made more readable by using symbolic names and data structures as demonstrated in the example below. The members IEFZB4DB, IEFZB4D0 and IEFZB4D2 of SYS1.MACLIB contain symbolic names that will be familiar to most assembler language programmers.

This next example uses symbolic names taken from these members to define, in z/OS XL C/C++ the text unit representing primary=20 or s[3]. Similar definitions can be made for the remaining text units but will not be given here.
#include <stdio.h>
#include <string.h>

#define MASK 0x80000000
#define CHAR_BIT 4
/* Defines one text unit with an integer of size 'bytes' */

#define __S99TUNIT_INT(bytes) struct {
    short unsigned __S99TUKEY;    /* KEY                        */
    short unsigned __S99TUNUM;    /* NO. OF LENGTH+PARM ENTRIES */
    struct {                      /* TEXT ENTRY OF LENGTH+PARM  */
      short unsigned __S99TULNG;  /* LENGTH OF 1ST (ONLY) PARM  */
      unsigned int   __S99TUPAR :     /*           PARAMETER    */
                                  (bytes) * CHAR_BIT;
     } __S99TUENT;
    }
/* initialize by: __S99TUNUM = 1;                                */
/*               __S99TUENT.__S99TULNG = <bytes>;                */
/*               __S99TUENT.__S99TUPAR = <value>;                */

#define __DALPRIME 0x000A           /*PRIMARY SPACE QUANTITY     */

static const __S99TUNIT_INT(3) primary = {__DALPRIME, 1, 3, 20};

int main(void)
{
    int rc;
    struct __S99struc parmlist;
    memset(&parmlist, 0, sizeof(parmlist));
    void *s[10] = {            /* array of text pointers */
    /* text units follow */
                     .    ,                     /* DSN=EXAMPLE  */
                     .    ,                     /* DISP=(,CATLG)*/
                     .    ,                     /* SPACE=(TRK,..*/
                  &primary,                     /* primary=20   */
                     .    ,                     /* secondary=1  */
                     .    ,                     /* UNIT=SYSDA   */
                     .    ,                     /* BLKSIZE=80   */
                     .    ,                     /* DSORG=PS     */
                     .    ,                     /* LRECL=80     */
                     .    };                    /* RECFM=F      */

    parmlist.__S99RBLN = 20;
    parmlist.__S99VERB = 01;      /* verb for dsname allocation       */
    parmlist.__S99FLAG1 = 0x4000; /* do not use existing allocation   */
    parmlist.__S99TXTPP = s;      /* pointer to pointer to text units */
    s[9] = (char *)((long unsigned) (s[9]) │ MASK);

    rc = svc99(&parmlist);
    if (rc != 0)
       printf(" Error code = %d   Information code = %d\n",
           parmlist.__S99ERROR, parmlist.__S99INFO);
}

Related information