Home | History | Annotate | Download | only in os400
      1 /**
      2 ***     XMLCATALOG command response program.
      3 ***
      4 ***     See Copyright for the status of this software.
      5 ***
      6 ***     Author: Patrick Monnerat <pm (at) datasphere.ch>, DATASPHERE S.A.
      7 **/
      8 
      9 #include <stdio.h>
     10 #include <stdlib.h>
     11 #include <string.h>
     12 #include <qshell.h>
     13 
     14 
     15 /* Variable-length string, with 16-bit length. */
     16 typedef struct {
     17         short           len;
     18         char            string[5000];
     19 }               vary2;
     20 
     21 
     22 /* Variable-length string, with 32-bit length. */
     23 typedef struct {
     24         int             len;
     25         char            string[5000];
     26 }               vary4;
     27 
     28 
     29 /* Multiple occurrence parameter list. */
     30 #define paramlist(itemsize, itemtype)                                   \
     31         _Packed struct {                                                \
     32                 short           len;                                    \
     33                 _Packed union {                                         \
     34                          char           _pad[itemsize];                 \
     35                         itemtype        param;                          \
     36                 }               item[1];                                \
     37         }
     38 
     39 /* Add element list structure. */
     40 typedef struct {
     41         short           elcount;        /* Element count (=3). */
     42         paramlist(16, char) type;       /* vary2(16). */
     43         paramlist(256, char) origin;    /* vary2(256). */
     44         paramlist(256, char) replace;   /* vary2(256). */
     45 }               addelement;
     46 
     47 /* SGML add element list structure. */
     48 typedef struct {
     49         short           elcount;        /* Element count (=3). */
     50         paramlist(256, char) catalog;   /* vary2(256). */
     51         paramlist(256, char) ident;     /* vary2(256). */
     52 }               sgmladdelement;
     53 
     54 
     55 /* Arguments from CL command. */
     56 typedef struct {
     57         char *          pgm;            /* Program name. */
     58         vary2 *         instmf;         /* Input catalog file name. */
     59         vary2 *         kind;           /* Catalog kind. */
     60         vary2 *         outstmf;        /* Output catalog file name. */
     61         vary2 *         convert;        /* Convert SGML to XML. */
     62         vary2 *         superupd;       /* --no-super-update. */
     63         vary2 *         verbose;        /* Verbose output. */
     64         paramlist(256 + 2, vary2) * delete; /* Identifiers to delete. */
     65         paramlist(2, unsigned short) * add; /* Items to add. */
     66         paramlist(2, unsigned short) * sgmladd; /* SGML items to add. */
     67         paramlist(256 + 2, vary2) * resolve; /* Identifiers to resolve. */
     68         paramlist(5000 + 2, vary2) * catalog; /* Additional catalog files. */
     69 }               arguments;
     70 
     71 
     72 /* Definition of QSHELL program. */
     73 extern void     qshell(vary4 * cmd);
     74 #pragma linkage(qshell, OS)
     75 #pragma map(qshell, "QSHELL/QZSHQSHC")
     76 
     77 /* Macro to handle displacements. */
     78 #define OFFSETBY(t, p, n)       ((t *) (((char *) (p)) + (n)))
     79 
     80 
     81 static void
     82 vary4nappend(vary4 * dst, const char * src, size_t len)
     83 
     84 {
     85         if (len > sizeof(dst->string) - dst->len)
     86                 len = sizeof(dst->string) - dst->len;
     87 
     88         if (len) {
     89                 memcpy(dst->string + dst->len, src, len);
     90                 dst->len += len;
     91                 }
     92 }
     93 
     94 
     95 static void
     96 vary4append(vary4 * dst, const char * src)
     97 
     98 {
     99         vary4nappend(dst, src, strlen(src));
    100 }
    101 
    102 
    103 static void
    104 vary4arg(vary4 * dst, const char * arg)
    105 
    106 {
    107         vary4nappend(dst, " ", 1);
    108         vary4append(dst, arg);
    109 }
    110 
    111 
    112 static void
    113 vary4varg(vary4 * dst, vary2 * arg)
    114 
    115 {
    116         vary4nappend(dst, " ", 1);
    117         vary4nappend(dst, arg->string, arg->len);
    118 }
    119 
    120 
    121 static void
    122 vary4vescape(vary4 * dst, vary2 * arg)
    123 
    124 {
    125         int i;
    126 
    127         for (i = 0; i < arg->len; i++)
    128                 if (arg->string[i] == '\'')
    129                         vary4nappend(dst, "'\"'\"'", 5);
    130                 else
    131                         vary4nappend(dst, arg->string + i, 1);
    132 }
    133 
    134 
    135 static void
    136 vary4vargquote(vary4 * dst, vary2 * arg)
    137 
    138 {
    139         vary4nappend(dst, " '", 2);
    140         vary4vescape(dst, arg);
    141         vary4nappend(dst, "'", 1);
    142 }
    143 
    144 
    145 int
    146 main(int argsc, arguments * args)
    147 
    148 {
    149         vary4 cmd;
    150         int i;
    151         char c;
    152         addelement * aelp;
    153         sgmladdelement * saelp;
    154 
    155         /* Specify additional catalogs. */
    156         cmd.len = 0;
    157         if (args->catalog->len) {
    158                 for (i = 0; i < args->catalog->len &&
    159                             !args->catalog->item[i].param.len; i++)
    160                         ;
    161 
    162                 vary4append(&cmd, "XML_CATALOG_FILES=");
    163                 if (i < args->catalog->len) {
    164                         c = '\'';
    165                         for (i = 0; i < args->catalog->len; i++) {
    166                                 if (!args->catalog->item[i].param.len)
    167                                         continue;
    168                                 vary4nappend(&cmd, &c, 1);
    169                                 c = ' ';
    170                                 vary4vescape(&cmd,
    171                                             &args->catalog->item[i].param);
    172                                 }
    173                         vary4nappend(&cmd, "'", 1);
    174                         }
    175                 vary4nappend(&cmd, " ", 1);
    176                 }
    177 
    178         /* find length of library name. */
    179         for (i = 0; i < 10 && args->pgm[i] && args->pgm[i] != '/'; i++)
    180                 ;
    181 
    182         /* Store program name in command buffer. */
    183         vary4append(&cmd, "/QSYS.LIB/");
    184         vary4nappend(&cmd, args->pgm, i);
    185         vary4append(&cmd, ".LIB/XMLCATALOG.PGM");
    186 
    187         /* Map command arguments to standard xmlcatalog argument vector. */
    188         if (args->kind && args->kind->len)
    189                 vary4varg(&cmd, args->kind);
    190 
    191         if (args->verbose && args->verbose->len)
    192                 vary4varg(&cmd, args->verbose);
    193 
    194         if (args->delete)
    195                 for (i = 0; i < args->delete->len; i++) {
    196                         vary4arg(&cmd, "--del");
    197                         vary4vargquote(&cmd, &args->delete->item[i].param);
    198                         }
    199 
    200         if (args->kind && args->kind->len) {
    201                 /* Process SGML-specific parameters. */
    202                 if (args->superupd && args->superupd->len)
    203                         vary4varg(&cmd, args->superupd);
    204 
    205                 if (args->sgmladd)
    206                         for (i = 0; i < args->sgmladd->len; i++) {
    207                                 saelp = OFFSETBY(sgmladdelement, args->sgmladd,
    208                                                 args->sgmladd->item[i].param);
    209                                 if (!((vary2 *) &saelp->catalog)->len)
    210                                         continue;
    211                                 vary4arg(&cmd, "--add");
    212                                 vary4vargquote(&cmd, (vary2 *) &saelp->catalog);
    213                                 vary4vargquote(&cmd, (vary2 *) &saelp->ident);
    214                                 }
    215                 }
    216         else {
    217                 /* Process XML-specific parameters. */
    218                 if (args->convert && args->convert->len)
    219                         vary4varg(&cmd, args->convert);
    220 
    221                 if (args->add)
    222                         for (i = 0; i < args->add->len; i++) {
    223                                 aelp = OFFSETBY(addelement, args->add,
    224                                                 args->add->item[i].param);
    225                                 if (!((vary2 *) &aelp->origin)->len)
    226                                         continue;
    227                                 vary4arg(&cmd, "--add");
    228                                 vary4varg(&cmd, (vary2 *) &aelp->type);
    229                                 vary4vargquote(&cmd, (vary2 *) &aelp->origin);
    230                                 vary4vargquote(&cmd, (vary2 *) &aelp->replace);
    231                                 }
    232                 }
    233 
    234         /* Avoid INSTMF(*NEW) and OUTSMTF(*INSTMF). */
    235         if (args->outstmf && args->outstmf->len && !args->outstmf->string[0])
    236                 if (args->instmf && args->instmf->len)
    237                         args->outstmf = args->instmf;
    238                 else
    239                         args->outstmf = NULL;
    240 
    241         /* If INSTMF(*NEW) and OUTSTMF(somepath), Use --create --noout and
    242            somepath as (unexisting) input file. */
    243         if (args->outstmf && args->outstmf->len)
    244                 if (!args->instmf || !args->instmf->len) {
    245                         vary4arg(&cmd, "--create");
    246                         vary4arg(&cmd, "--noout");
    247                         args->instmf = args->outstmf;
    248                         args->outstmf = NULL;
    249                         }
    250 
    251         /* If output to input file, use --noout option. */
    252         if (args->instmf && args->outstmf && args->instmf->len &&
    253             args->instmf->len == args->outstmf->len &&
    254             !strncmp(args->instmf->string, args->outstmf->string,
    255                      args->instmf->len)) {
    256                 vary4arg(&cmd, "--noout");
    257                 args->outstmf = NULL;
    258                 }
    259 
    260         /* If no input file create catalog, else specify the input file name. */
    261         /* Specify the input file name: my be a dummy one. */
    262         if (!args->instmf || !args->instmf->len) {
    263                 vary4arg(&cmd, "--create -");
    264                 vary4arg(&cmd, ".dmyxmlcatalog");
    265                 }
    266         else {
    267                 vary4arg(&cmd, "-");
    268                 vary4vargquote(&cmd, args->instmf);
    269                 }
    270 
    271         /* Query entities. */
    272 
    273         if (args->resolve)
    274                 for (i = 0; i < args->resolve->len; i++)
    275                         vary4vargquote(&cmd, &args->resolve->item[i].param);
    276 
    277         /* Redirect output if requested. */
    278         if (args->outstmf && args->outstmf->len) {
    279                 vary4arg(&cmd, ">");
    280                 vary4vargquote(&cmd, args->outstmf);
    281                 }
    282 
    283         /* Execute the shell command. */
    284         qshell(&cmd);
    285 
    286         /* Terminate. */
    287         exit(0);
    288 }
    289