home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / gened10.zip / SAMPLE1.C < prev    next >
Text File  |  1996-04-03  |  29KB  |  809 lines

  1. /*
  2.  *      Created 1993  IBM Corp.                                            *
  3.  *                                                                         *
  4.  *      DISCLAIMER OF WARRANTIES.  The following [enclosed] code is        *
  5.  *      sample code created by IBM Corporation. This sample code is not    *
  6.  *      part of any standard or IBM product and is provided to you solely  *
  7.  *      for  the purpose of assisting you in the development of your       *
  8.  *      applications.  The code is provided "AS IS", without               *
  9.  *      warranty of any kind.  IBM shall not be liable for any damages     *
  10.  *      arising out of your use of the sample code, even if they have been *
  11.  *      advised of the possibility of such damages.                        *
  12.  */
  13. /*****************************************************************************
  14.  * encode/decode sample program for P22 protocol (test1.asn).
  15.  * It uses:
  16.  * 1.contents-array
  17.  * 2.decoding user-exit
  18.  * 3.content user-exit
  19.  * 4.definite length form
  20.  *
  21.  * The data stream is passed in pieces to the GDSdecber routine.
  22.  * Arguments:
  23.  *            .DAT file,
  24.  *            input buffer length,
  25.  *            output buffer length,
  26.  *            only decoding (ENC or NOENC)
  27.  *****************************************************************************
  28.  */
  29.  
  30. /*
  31.  * The following are needed to compile this program.  Note that the
  32.  * order of the header files is important.
  33.  */
  34.  
  35. #include <stdlib.h>
  36. #include <stdio.h>
  37. #include <ctype.h>
  38. #include <string.h>
  39. #include "gdstypes.h"
  40. #include "gdsrcods.h"
  41. #include "gdsproto.h"
  42. #include "test1ndx.h"
  43. #include "sample.h"
  44.  
  45.  
  46. main(int argc, char **argv)
  47. {
  48.    int                   rc, onlydec;
  49.    long                  l;
  50.    static char          *dummy = "dummy";
  51.    char                  savmodname[50], *ModName, modname[50];
  52.    void                 *Mod, *env;
  53.    unsigned short        Typ;
  54.    unsigned long         EncBytes, inbuflen, outbuflen, DecBytes;
  55.    enum TypOfEnc         enctype;
  56.    struct gds           *p1;
  57.    FILE                 *trace_enc;
  58.    FILE                 *trace_dec;
  59.    FILE                 *EncStream;    /* input-output file */
  60.    FILE                 *usrdecfile;   /* file written by decoding user-exit */
  61.  
  62.    if (argc < 5) {
  63.       exit(0);
  64.    }   /* endif */
  65.  
  66.   /*
  67.    * only decoding?
  68.    */
  69.    if (!strcmp(argv[4],"ENC")) {
  70.     onlydec = 0;
  71.    } else {
  72.      if (!strcmp(argv[4],"NOENC")) {
  73.        onlydec = 1;
  74.      } else {
  75.        printf("invalid encoding YES/NO parameter\n");
  76.        return -1;
  77.      } /* endif */
  78.    } /* endif */
  79.  
  80. /*
  81.  * set the type of encoding indicator
  82.  */
  83.    enctype = ber;
  84.  
  85.    inbuflen = atol(argv[2]);           /* set the length of the input buffer */
  86.    outbuflen = atol(argv[3]);          /* set the length of output buffer */
  87.  
  88.  
  89. /*
  90.  * open the trace file for encoding gds tree
  91.  */
  92.    trace_enc = fopen("enctrace1.out","w");
  93.    if (trace_enc == NULL) {            /* open file failed */
  94.      printf("open enc trace file failed\n");
  95.      exit(-1);
  96.    } /* endif */
  97.  
  98. /*
  99.  * open the trace file for decoding gds tree
  100.  */
  101.    trace_dec = fopen("dectrace1.out","w");
  102.    if (trace_dec == NULL) {            /* open file failed */
  103.      printf("open dec trace file failed\n");
  104.      exit(-1);
  105.    } /* endif */
  106.  
  107.  
  108. /*
  109.  * open the decoding user-exit output file
  110.  */
  111.    usrdecfile = fopen("usrdec1.out","w");
  112.    if (usrdecfile == NULL) {           /* open file failed */
  113.      printf("open decoding user-exit output file failed\n");
  114.      exit(-1);
  115.    } /* endif */
  116.  
  117. /***************************
  118.  * INITIALIZATION
  119.  ***************************
  120.  */
  121.  
  122. /*
  123.  * Call the library routine, GDSinitEnvironment, to initialize the environment.
  124.  * Each User Application Program should do this before calling any routine to
  125.  * read .dat files, encode or decode GDSs.
  126.  */
  127.    GDSinitEnvironment(&env);           /* initialize environment for modules */
  128.  
  129. /*
  130.  * Call the library routine, GDSreaddatfile, to read a .dat file containing
  131.  * the metatables and symbol tables for one or more ASN.1 module.  Note that
  132.  * references between ASN.1 modules (imported and exported symbols) are *not*
  133.  * resolved by GDSreaddatfile.
  134.  */
  135.    rc = GDSreaddatfile(argv[1], env);  /* first parm should be a readable data
  136.                                         * file */
  137.    if (rc != READ_DAT_OK) {
  138.      printf("GDSreaddatfile return code: %i\n", rc);
  139.      return rc;
  140.    }
  141.  
  142. /*
  143.  * Call the library routine, GDSresolveallimports, to resolve imports and
  144.  * exports in the .dat file.  Note that if more than one .dat file had
  145.  * been read in with multiple calls to GDSreaddatfile, this call should be
  146.  * deferred as late as possible to maximize performance.  Multiple calls
  147.  * to GDSresolveallimports are allowed, however.
  148.  */
  149.    rc = GDSresolveallimports(env);
  150.    if (rc != RESOLVE_IMPORTS_OK) {
  151.       printf("GDSresolveallimports return code: %i\n", rc);
  152.  
  153.       /* Call the library routine, GDSPrintUnresolvedImports, to print the
  154.        * unresolved imports */
  155.       GDSPrintUnresolvedImports(stdout, env);
  156.       return rc;
  157.    }
  158.  
  159. /*
  160.  * Call the library routine, GDSsetUsrWrite, to set the user exit routine for
  161.  * writing buffer.
  162.  */
  163.    GDSsetUsrWrite(mywrite, env);
  164.  
  165. /*
  166.  * Call the library routine, GDSsetUsrRead, to set the user exit routine for
  167.  * writing buffer.
  168.  */
  169.    GDSsetUsrRead(myread, env);
  170.  
  171. /*
  172.  * Call the library routine, GDSsetUsrDec, to set the user exit routine
  173.  * for decoding. In this program, it is set to mydec once.  However,
  174.  * it may be called any time the User Application Program wants to change the
  175.  * encoding routine.
  176.  */
  177.    GDSsetUsrDec(mydec, env);
  178.  
  179. /***************************
  180.  * ENCODING
  181.  ***************************
  182.  */
  183. /*
  184.  * Call the library routine, GDSfirstmodule, to get pointers to the first
  185.  * moddef structure and the module name string in the current chain of modules.
  186.  */
  187.    GDSfirstmodule(&Mod,               /* return ptr to a moddef structure */
  188.                   &ModName,           /* return ptr to the module name string */
  189.                   env                 /* environment */
  190.                  );                   /* init module vars */
  191.  
  192.    strcpy(savmodname, ModName);
  193.  
  194. /*
  195.  * This loop repeatedly asks the user to enter a module and type name.
  196.  * It terminates upon user request or when an error is detected.
  197.  */
  198.    for (;;) {
  199.  
  200.       char                  *readmod, readbuf[100];
  201.       unsigned char         *cont, *out_buff, *in_buff, alldata;
  202.       long                   lencont, loc;
  203.       struct contents_str   *ContArrayPtr;
  204.       struct content_str    *cont_list;
  205.       struct gds           **gds_tree_ptr = NULL;
  206.       struct errdata         errinfo;
  207.  
  208.       if (!onlydec) {
  209.         printf("\n[%s.]Module (or stop): ", savmodname);
  210.         fflush(NULL);
  211.  
  212.      /*
  213.       * ask user for module name
  214.       */
  215.         strcpy(modname, savmodname);
  216.         readmodtype(readbuf, sizeof(readbuf), &readmod);
  217.         if (readmod != NULL) {         /* if user typed in a module name */
  218.           if (!strcmp(readmod, "stop")) {
  219.             break;
  220.           } /* endif */
  221.           strcpy(modname, readmod);    /* use the module name the user typed
  222.                                         * in */
  223.         } /* endif */
  224.  
  225. /*
  226.  * Call the library routine, GDSfindmodule, to find the moddef structure
  227.  * corresponding to the name in the modname string.
  228.  */
  229.         Mod = GDSfindmodule(modname, env);
  230.         if (Mod == NULL) {             /* if module not found */
  231.           printf("\nModule not found\n");
  232.           continue;                    /* allow more attempts */
  233.         }
  234.  
  235. /*
  236.  * Call the library routine, GDSfindtype, to find the metatable index in
  237.  * the Mod module corresponding to the type name in readtype.  Note that
  238.  * the .H files created by the ASN.1 compiler contain symbol names for
  239.  * the type and value metatable indices.  When the type or value name
  240.  * is known at application compile-time, these symbolic names can be
  241.  * used directly instead of searching through the metatables at
  242.  * runtime. In this case we call GDSfindtype as example.
  243.  */
  244.         rc = GDSfindtype(Mod,          /* module where type is to be found */
  245.                          "IPM",        /* type name string */
  246.                          &Typ          /* returned metatable index */
  247.                          );
  248.         if (rc != FIND_TYPE_OK) {            /* if type not found */
  249.            printf("\nType not found; rc = %i\n", rc);
  250.            continue;                   /* allow more attempts */
  251.         }
  252.  
  253. /*
  254.  * Call the library routine GDSallocateContentsArray to allocate
  255.  * the array of contents pointers for the specified module.
  256.  * This function returns a pointer to the first location of the array
  257.  */
  258.         rc = GDSallocateContentsArray(Mod, &ContArrayPtr);
  259.         if (rc == ALLOCATECONT_NO_ENOUGH_STORAGE) {
  260.           printf("no enough storage for contents pointers array\n");
  261.           return(-1);
  262.         } /* endif */
  263.  
  264. /*
  265.  * Load the Contents Array
  266.  */
  267. /* IPM */
  268. (ContArrayPtr[IPMSInformationObjects_IPM_SEQUENCE]).content = dummy;
  269.  
  270. /* HEADING */
  271. (ContArrayPtr[IPMSInformationObjects_HEADING_SET]).content = dummy;
  272.  
  273. /* BODY */
  274. (ContArrayPtr[IPMSInformationObjects_BODY_SEQUENCE_OF]).content = dummy;
  275. (ContArrayPtr[IPMSInformationObjects_BODY_SEQUENCE_OF]).len = 1;
  276.  
  277. /* IPMIdentifier */
  278. (ContArrayPtr[IPMSInformationObjects_IPMIdentifier_SET]).content = dummy;
  279. (ContArrayPtr[IPMSInformationObjects_LocalIPMIdentifier_PrintableString_CharacterString]).content = "mio_messaggio";
  280. (ContArrayPtr[IPMSInformationObjects_LocalIPMIdentifier_PrintableString_CharacterString]).len = 13;
  281. (ContArrayPtr[IPMSInformationObjects_LocalIPMIdentifier_PrintableString_CharacterString]).contstg = allocd;
  282.  
  283. /* Originator */
  284. (ContArrayPtr[IPMSInformationObjects_ORDescriptor_SET]).content = dummy;
  285. (ContArrayPtr[IPMSInformationObjects_ORName_SEQUENCE]).content = dummy;
  286. (ContArrayPtr[IPMSInformationObjects_StandardAttributes_SEQUENCE]).content = dummy;
  287. (ContArrayPtr[IPMSInformationObjects_CountryName_EXPLICIT]).content = dummy;
  288. (ContArrayPtr[IPMSInformationObjects_CountryName_CHOICE_iso_3166_alpha2_code_CharacterString]).content = "IT";
  289. (ContArrayPtr[IPMSInformationObjects_CountryName_CHOICE_iso_3166_alpha2_code_CharacterString]).len = 2;
  290. (ContArrayPtr[IPMSInformationObjects_CountryName_CHOICE_iso_3166_alpha2_code_CharacterString]).contstg = allocd;
  291.  
  292. (ContArrayPtr[IPMSInformationObjects_PersonalName_SET]).content = dummy;
  293. (ContArrayPtr[IPMSInformationObjects_PersonalName_SET_surname_CharacterString]).content = "Starinieri";
  294. (ContArrayPtr[IPMSInformationObjects_PersonalName_SET_surname_CharacterString]).len = 10;
  295. (ContArrayPtr[IPMSInformationObjects_PersonalName_SET_surname_CharacterString]).contstg = allocd;
  296.  
  297.  
  298. (ContArrayPtr[IPMSInformationObjects_PersonalName_SET_given_name_CharacterString]).content = "Mauro";
  299. (ContArrayPtr[IPMSInformationObjects_PersonalName_SET_given_name_CharacterString]).len = 5;
  300. (ContArrayPtr[IPMSInformationObjects_PersonalName_SET_given_name_CharacterString]).contstg = allocd;
  301.  
  302. /* Subject */
  303. (ContArrayPtr[IPMSInformationObjects_HEADING_SET_subject_EXPLICIT]).content = dummy;
  304. (ContArrayPtr[IPMSInformationObjects_SubjectField_TeletexString_CharacterString]).content =
  305.              "prova-prova";
  306. (ContArrayPtr[IPMSInformationObjects_SubjectField_TeletexString_CharacterString]).len = 11;
  307. (ContArrayPtr[IPMSInformationObjects_SubjectField_TeletexString_CharacterString]).contstg = allocd;
  308.  
  309. /* IA5 body */
  310. (ContArrayPtr[IPMSInformationObjects_IA5TextBodyPart_SEQUENCE]).content = dummy;
  311. (ContArrayPtr[IPMSInformationObjects_IA5TextParameters_SET]).content = dummy;
  312. (ContArrayPtr[IPMSInformationObjects_IA5TextData_IA5String_CharacterString]).usrcontent = mycontent;
  313. (ContArrayPtr[IPMSInformationObjects_IA5TextData_IA5String_CharacterString]).len = 330;
  314. (ContArrayPtr[IPMSInformationObjects_IA5TextData_IA5String_CharacterString]).contstg = allocd;
  315.  
  316. /*
  317.  * Call the library routine, GDSencode, to create one or more GDS structures
  318.  * that represent a value for Mod.Typ.
  319.  * Note that the GDSencode function does *not* create the BER encoded
  320.  * data.  The GDS structures contain the information needed to
  321.  * encode the data, but the actual encoding is a secondary step.  This
  322.  * allows other encoding techniques besides BER to be used.  The
  323.  * log component of the GDS structure is computed by encode assuming
  324.  * BER rules (this is a slight optimization that prevents traversing
  325.  * the GDS structure tree another time); if encber is not used to encode
  326.  * the data, the log component should not be used.
  327.  */
  328.         /* encode ThisIPMField */
  329.         Typ = IPMSInformationObjects_IPM;
  330.         rc = GDSencode(Mod,            /* moddef module where type occurs */
  331.                        &Typ,           /* metatable index where type occurs */
  332.                        ContArrayPtr,   /* pointer to Contents Array */
  333.                        &p1,            /* returned GDS structure */
  334.                        enctype,        /* type of encoding */
  335.                        env,            /* environment */
  336.                        NULL            /* parms to pass to the user encode
  337.                                         * routine, not used in this case */
  338.                       );
  339.  
  340.  
  341.         if (rc != ENCODE_MATCH) {      /* if the encoding failed */
  342.            printf("\nGDSencode return code: %i\n", rc);
  343.            printf("\nmetatable type index where error occurred: %i\n", Typ);
  344.         }    /* endif */
  345.  
  346.         l = p1->loc;                   /* get the length of encoded data */
  347.         printf("\nlength of encoded data: %ld\n", l);
  348.  
  349. /*
  350.  * open the input-output file that will contain the encoded data stream
  351.  */
  352.         EncStream = fopen("stream1.out","wb");
  353.         if (EncStream == NULL) {            /* open file failed */
  354.           printf("open input/output file failed\n");
  355.           exit(-1);
  356.         } /* endif */
  357.  
  358. /*
  359.  * Call the library routine, GDSencber, to encode the GDS using BER rules.
  360.  */
  361.         rc = GDSencber(&p1,            /* the GDS structure to be encoded */
  362.                        outbuflen,      /* the length of the output buffer */
  363.                        &out_buff,      /* output buffer pointer */
  364.                        &EncBytes,      /* the number of encoded bytes */
  365.                        0,              /* use definite length form */
  366.                        env,            /* environment */
  367.                        (void *) EncStream); /* output file pointer */
  368.  
  369.         if (rc != ENCBER_OK) {         /* if encoding was unsuccessful */
  370.            printf("\nGDSencber return code: %i\n", rc);
  371.            printf("module name: %s\n", p1->modname);
  372.            printf("type name: %s\n", p1->name);
  373.         }  /* endif */
  374.  
  375.         printf("\nnumber of encoded bytes: %lu\n", EncBytes);
  376.  
  377. /*
  378.  * Call the library routine, GDSprintgds, to print the structure and
  379.  * content of the encoded GDS.
  380.  */
  381.         rc = GDSprintgds(p1,           /* ptr to root GDS structure */
  382.                          0,            /* number of spaces to indent */
  383.                          400,          /* max content length */
  384.                          79,           /* number of characters for row */
  385.                          trace_enc,    /* gds tree trace file */
  386.                          enctype       /* type of encoding */
  387.                         );
  388.  
  389.         if (rc != PRINT_GDS_OK) {      /* if the printing failed */
  390.            printf("\nGDSprintgds return code: %i\n", rc);
  391.            GDSfreegds(p1, env);        /* reclaim space for encoded GDS tree */
  392.            continue;
  393.         }    /* endif */
  394.  
  395.         fclose(trace_enc);
  396.  
  397.         fclose(EncStream);
  398.  
  399. /*
  400.  * Call the library routine, GDSfreegds, to reclaim the storage occupied by
  401.  * the GDS structures headed by p1 which are marked as allocated.  Note
  402.  * that some GDSs may be marked as static, which prevents them from
  403.  * being freed.
  404.  */
  405.         GDSfreegds(p1, env);           /* reclaim space for encoded GDS tree */
  406.  
  407.         printf("GDSfreegds OK\n");
  408.  
  409. /*
  410.  * Call the library routine, GDSfreeContentsArray, to reclaim the storage
  411.  * allocated for the contents-array.
  412.  */
  413.         GDSfreeContentsArray(Mod, ContArrayPtr);
  414.  
  415.       } /* endif */
  416.  
  417. /***************************
  418.  * DECODING
  419.  ***************************
  420.  */
  421. /*
  422.  * ask to the user the name of the decoding module
  423.  */
  424.  
  425.       printf("\n[%s.]Module for decoding (or stop): ", savmodname);
  426.       fflush(NULL);
  427.  
  428.  
  429.    /*
  430.     * ask user for module name
  431.     */
  432.       strcpy(modname, savmodname);
  433.       readmodtype(readbuf, sizeof(readbuf), &readmod);
  434.       if (readmod != NULL) {           /* if user typed in a module name */
  435.         if (!strcmp(readmod, "stop")) {
  436.            break;
  437.         } /* endif */
  438.          strcpy(modname, readmod);     /* use the module name the user
  439.                                         * typed in */
  440.       } /* endif */
  441.  
  442. /*
  443.  * Call the library routine, GDSfindmodule, to find the moddef structure
  444.  * corresponding to the name in the modname string.
  445.  */
  446.       Mod = GDSfindmodule(modname, env);
  447.       if (Mod == NULL) {               /* if module not found */
  448.          printf("\nModule not found\n");
  449.          continue;                     /* allow more attempts */
  450.       }
  451.  
  452. /*
  453.  * Call the library routine, GDSfindtype, to find the metatable index in
  454.  * the Mod module corresponding to the type name in readtype.  Note that
  455.  * the .H files created by the ASN.1 compiler contain symbol names for
  456.  * the type and value metatable indices.  When the type or value name
  457.  * is known at application compile-time, these symbolic names can be
  458.  * used directly instead of searching through the metatables at
  459.  * runtime.
  460.  */
  461.       rc = GDSfindtype(Mod,            /* module where type is to be found */
  462.                        "IPM",          /* type name string */
  463.                        &Typ            /* returned metatable index */
  464.                       );
  465.       if (rc != FIND_TYPE_OK) {            /* if type not found */
  466.          printf("\nType not found; rc = %i\n", rc);
  467.          continue;                     /* allow more attempts */
  468.       }
  469.  
  470. /*
  471.  * open the input file that will contain the encoded data stream
  472.  */
  473.       EncStream = fopen("stream1.out","rb");
  474.       if (EncStream == NULL) {            /* open file failed */
  475.         printf("open input/output file failed\n");
  476.         exit(-1);
  477.       } /* endif */
  478.  
  479. /*
  480.  * Call the library routine, GDSdecber, to decode encoded data in the
  481.  * buffer we just built.  The result should be a tree of GDS structures
  482.  * topped by p1 which matches the original structure created by the
  483.  * encode library routine.
  484.  */
  485.       alldata = 0;
  486.       in_buff = &alldata;
  487.       rc = GDSdecber(&p1,              /* GDS structure which will be the root
  488.                                         * of the GDS tree */
  489.                      inbuflen,         /* the length of the input buffer */
  490.                      &DecBytes,        /* number of decoded bytes */
  491.                      &in_buff,         /* data buffered indicator */
  492.                      env,              /* environment */
  493.                      (void *) EncStream); /* input file pointer */
  494.  
  495.       if (rc != DECBER_OK) {           /* if decoding failed */
  496.          printf("\nGDSdecber return code: %i\n", rc);
  497.          printf("\nnumber of decoded bytes: %u\n", DecBytes);
  498.       }    /* endif */
  499.  
  500.       printf("\nnumber of decoded bytes: %u\n", DecBytes);
  501.  
  502. /*
  503.  * Call the library routine, GDSprintgds, to print the structure and
  504.  * content of the decoded GDS.
  505.  */
  506.       rc = GDSprintgds(p1,             /* ptr to root GDS structure */
  507.                        0,              /* number of spaces to indent */
  508.                        400,            /* max content length */
  509.                        79,             /* number of characters for row */
  510.                        trace_dec,      /* gds tree trace file */
  511.                        enctype         /* type of encoding */
  512.                       );
  513.  
  514.       if (rc != PRINT_GDS_OK) { /* if the printing failed */
  515.          printf("\nGDSprintgds return code: %i\n", rc);
  516.          GDSfreegds(p1, env);
  517.          continue;
  518.       }    /* endif */
  519.  
  520. /*
  521.  * Call the library routine, GDSdecode, to match the GDS structure tree
  522.  * created by GDSdecber with an ASN.1 type referenced by Mod and Typ.
  523.  * If successful, the GDS structures will have name information set.
  524.  */
  525.  
  526.       rc = GDSdecode(Mod,              /* moddef module where type occurs */
  527.                      &Typ,             /* metatable index where type occurs */
  528.                      &p1,              /* root of GDS structure tree */
  529.                      gds_tree_ptr,     /* gds-tree-array ptr */
  530.                      env,              /* environment */
  531.                      (void *) usrdecfile); /* file used by dec user-exit */
  532.  
  533.       if (rc != DECODE_MATCH) {        /* if decoding didn't go ok */
  534.         printf("\nGDSdecode return code: %i\n", rc);
  535.         printf("metatable type index where error occurred: %i\n", Typ);
  536.         printf("module name: %s\n", p1->modname);
  537.         printf("type name: %s\n", p1->name);
  538.       }   /* endif */
  539.  
  540.       printf("\nGDSdecode OK\n");
  541.  
  542. /*
  543.  * Call the library routine, GDSprintgds, to print the structure and
  544.  * content of the decoded GDS.
  545.  */
  546.       rc = GDSprintgds(p1,             /* ptr to root GDS structure */
  547.                        0,              /* number of spaces to indent */
  548.                        400,            /* max content length */
  549.                        79,             /* number of characters for row */
  550.                        trace_dec,      /* gds tree trace file */
  551.                        enctype         /* type of encoding */
  552.                       );
  553.  
  554.       if (rc != PRINT_GDS_OK) { /* if the printing failed */
  555.          printf("\nGDSprintgds return code: %i\n", rc);
  556.          GDSfreegds(p1, env);
  557.          continue;
  558.       }    /* endif */
  559.  
  560.       fclose(trace_dec);
  561.  
  562.       fclose(EncStream);
  563.  
  564. /*
  565.  * Call the library routine to free the GDS structures in the tree rooted
  566.  * by *p1.
  567.  */
  568.       GDSfreegds(p1, env);
  569.  
  570.    }        /* endfor */
  571.  
  572.    printf("\nout of loop\n");
  573.  
  574. /***************************
  575.  * TERMINATION
  576.  ***************************
  577.  */
  578.  
  579. /*
  580.  * Clean up the environment by unloading all modules by calling
  581.  * GDSunloadmodule for each module in the environment.  NOTE:
  582.  * the GDSunloadmodule function should only be called for modules which
  583.  * were loaded by the GDSreaddatfile function or which have allocated
  584.  * storage in the heap like the GDSreaddatfile function.
  585.  */
  586.  
  587.    for (GDSfirstmodule(&Mod, &ModName, env); Mod != NULL;
  588.         GDSfirstmodule(&Mod, &ModName, env)) {
  589.       GDSunloadmodule(Mod, env);
  590.    } /* endfor */
  591.    printf("\nGDSunloadmodule loop OK\n");
  592.  
  593.  /*
  594.   * Call the library routine GDSfreeEnvironment to free the
  595.   * environment storage
  596.   */
  597.    GDSfreeEnvironment(env);
  598.  
  599.    return 0;
  600. }  /* end main */
  601.  
  602. static
  603. char *readline(char *buf)
  604. {
  605.    char *r;
  606.  
  607.    *buf = '\0';                 /* init */
  608.    r = gets(buf);
  609.    if (r == NULL) {
  610.       return(0);
  611.    } /* endif */
  612.    return r;
  613. }
  614.  
  615. static
  616. void readmodtype(char *readbuf, int buflen, char **readmod)
  617. {
  618.  
  619.    /*  Read from standard input to get a modulename.typename or
  620.     *  just typename.  Skip over white space before name strings and
  621.     *  consider newline the end of the string.
  622.     */
  623.  
  624.    char *cp, *cp2;
  625.    int len;
  626.    char foo[200];
  627.  
  628.    readline(foo);
  629.    cp2 = strtok(foo, " ");
  630.  
  631.    if (cp2 == NULL) {
  632.       *readmod = NULL;
  633.       return;
  634.    } /* endif */
  635.    /* Now read characters up to a newline or the end of the buffer */
  636.    for (cp = readbuf, len = 0; len < buflen-1; cp++, cp2++, len++) {
  637.       *cp = *cp2;
  638.       if (*cp == '\0') {
  639.          break;
  640.       } /* endif */
  641.    } /* endfor */
  642.    *cp = '\0';               /* terminate the string with a null */
  643.    *readmod = readbuf;       /* the module name starts at 1st char in str */
  644. }
  645.  
  646. /*
  647.  * Writing user-exit
  648.  */
  649. unsigned long mywrite(char *buf, unsigned long buflen, void *usrparms)
  650. {
  651.   FILE *EncStream;
  652.  
  653.   EncStream = (FILE *) usrparms;
  654.   return (unsigned long) (fwrite(buf,sizeof(unsigned char),buflen,EncStream));
  655. }
  656.  
  657. /*
  658.  * Reading user-exit
  659.  */
  660. unsigned long myread(char *buf, unsigned long buflen, void *usrparms)
  661. {
  662.   FILE *EncStream;
  663.  
  664.   EncStream = (FILE *) usrparms;
  665.   return (unsigned long) (fread(buf,sizeof(unsigned char),buflen,EncStream));
  666. }
  667.  
  668. /*
  669.  * Content user-exit
  670.  */
  671. int mycontent (char **buff, unsigned long *buflen, enum lastflag *lastf)
  672. {
  673.   char *data0 = "caro amico";                     /* 10 */
  674.   char *data1 = " ti scrivo,";                    /* 11 */
  675.   char *data2 = " cosi' mi distraggo un po',";    /* 27 */
  676.   char *data3 = " e siccome sei molto lontano,";  /* 29 */
  677.   char *data4 = " piu' forte ti scrivero',";   /* 25 */
  678.   char *data5 = " da quando sei partito c'e' una grossa novita',"; /* 47 */
  679.   char *data6 = " l'anno vecchio e' finito ormai ma qualcosa ancora qui non va,";  /* 62 */
  680.   char *data7 = " si esce poco la sera, compreso quando e' festa,"; /* 48 */
  681.   char *data8 = " e c'e' qualcuno cha ha messo dei sacchi di sabbia";  /* 50 */
  682.   char *data9 = " vicino alla finestra";   /* 21 */
  683.   static int pass = 0;
  684.   int rc = 0;
  685.  
  686.   switch (pass) {
  687.   case 0:
  688.     *buff = data0;
  689.     *buflen = strlen(data0);
  690.     *lastf = NO;
  691.     break;
  692.   case 1:
  693.     *buff = data1;
  694.     *buflen = strlen(data1);
  695.     *lastf = NO;
  696.     break;
  697.   case 2:
  698.     *buff = data2;
  699.     *buflen = strlen(data2);
  700.     *lastf = NO;
  701.     break;
  702.   case 3:
  703.     *buff = data3;
  704.     *buflen = strlen(data3);
  705.     *lastf = NO;
  706.     break;
  707.   case 4:
  708.     *buff = data4;
  709.     *buflen = strlen(data4);
  710.     *lastf = NO;
  711.     break;
  712.   case 5:
  713.     *buff = data5;
  714.     *buflen = strlen(data5);
  715.     *lastf = NO;
  716.     break;
  717.   case 6:
  718.     *buff = data6;
  719.     *buflen = strlen(data6);
  720.     *lastf = NO;
  721.     break;
  722.   case 7:
  723.     *buff = data7;
  724.     *buflen = strlen(data7);
  725.     *lastf = NO;
  726.     break;
  727.   case 8:
  728.     *buff = data8;
  729.     *buflen = strlen(data8);
  730.     *lastf = NO;
  731.     break;
  732.   case 9:
  733.     *buff = data9;
  734.     *buflen = strlen(data9);
  735.     *lastf = YES;
  736.     break;
  737.   } /* endswitch */
  738.   pass++;
  739.   return rc;
  740. }
  741.  
  742. /*
  743.  * Decoding user-exit
  744.  */
  745. int mydec(unsigned short ndx, struct gds *p, char *content,
  746.           unsigned long contlen, void *usrparms)
  747. {
  748.   long   foolong;
  749.   char   foo[500];
  750.   FILE  *usrdecfile;
  751.  
  752.   usrdecfile = (FILE *) usrparms;
  753.   if (content != NULL) {
  754.     switch (ndx) {
  755.     case IPMSInformationObjects_LocalIPMIdentifier_PrintableString_CharacterString:
  756.       fprintf(usrdecfile,"IPMSInformationObjects_LocalIPMIdentifier_PrintableString_CharacterString\n");
  757.       strncpy(foo, content, contlen);
  758.       foo[contlen] = '\0';
  759.       fprintf(usrdecfile,"\"%s\" ", foo);
  760.       GDShex2str(foo, 300, content, contlen);
  761.       fprintf(usrdecfile,"(\'%s\'H)\n", foo);
  762.       break;
  763.     case IPMSInformationObjects_CountryName_CHOICE_iso_3166_alpha2_code_CharacterString:
  764.       fprintf(usrdecfile,"IPMSInformationObjects_CountryName_CHOICE_iso_3166_alpha2_code_CharacterString\n");
  765.       strncpy(foo, content, contlen);
  766.       foo[contlen] = '\0';
  767.       fprintf(usrdecfile,"\"%s\" ", foo);
  768.       GDShex2str(foo, 300, content, contlen);
  769.       fprintf(usrdecfile,"(\'%s\'H)\n", foo);
  770.       break;
  771.     case IPMSInformationObjects_PersonalName_SET_surname_CharacterString:
  772.       fprintf(usrdecfile,"IPMSInformationObjects_PersonalName_SET_surname_CharacterString\n");
  773.       strncpy(foo, content, contlen);
  774.       foo[contlen] = '\0';
  775.       fprintf(usrdecfile,"\"%s\" ", foo);
  776.       GDShex2str(foo, 300, content, contlen);
  777.       fprintf(usrdecfile,"(\'%s\'H)\n", foo);
  778.       break;
  779.     case IPMSInformationObjects_PersonalName_SET_given_name_CharacterString:
  780.       fprintf(usrdecfile,"IPMSInformationObjects_PersonalName_SET_given_name_CharacterString\n");
  781.       strncpy(foo, content, contlen);
  782.       foo[contlen] = '\0';
  783.       fprintf(usrdecfile,"\"%s\" ", foo);
  784.       GDShex2str(foo, 300, content, contlen);
  785.       fprintf(usrdecfile,"(\'%s\'H)\n", foo);
  786.       break;
  787.     case IPMSInformationObjects_SubjectField_TeletexString_CharacterString:
  788.       fprintf(usrdecfile,"IPMSInformationObjects_SubjectField_TeletexString_CharacterString\n");
  789.       strncpy(foo, content, contlen);
  790.       foo[contlen] = '\0';
  791.       fprintf(usrdecfile,"\"%s\" ", foo);
  792.       GDShex2str(foo, 300, content, contlen);
  793.       fprintf(usrdecfile,"(\'%s\'H)\n", foo);
  794.       break;
  795.     case IPMSInformationObjects_IA5TextData_IA5String_CharacterString:
  796.       fprintf(usrdecfile,"IPMSInformationObjects_IA5TextData_IA5String_CharacterString\n");
  797.       strncpy(foo, content, contlen);
  798.       foo[contlen] = '\0';
  799.       fprintf(usrdecfile,"\"%s\" ", foo);
  800.       GDShex2str(foo, 300, content, contlen);
  801.       fprintf(usrdecfile,"(\'%s\'H)\n", foo);
  802.       break;
  803.     default:
  804.      break;
  805.     } /* endswitch */
  806.   } /* endif */
  807.   return 0;
  808. }
  809.