ibmi-brunch-learn

Announcement

Collapse
No announcement yet.

IBM APIs

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • IBM APIs

    I'm still fairly fresh to the IBM i and have been playing around with some of the IBM APIs, specifically, QZLSCHSI - Change Server Information. This API is specifically for the iNetServer instance on the i. We've been getting errors wherein a user is disabled for iNetServer access and we need to enable them manually. Potentially, this API will allow us to do it automatically, however, I can't seem to get it to work.

    Does anyone have any experience with this particular API?
    I am writing the program in C, which if I recall, not many on this forum have experience with.
    I've placed my code below for review. Perhaps there is something obvious that I'm missing that someone might be able to point out to me.

    The code does compile, but calling the program doesn't result in enabling the specified test account.

    Code:
    #include <stdio.h>
    #include <string.h>
    #include <qusec.h>
    #include <qzlschsi.h>
    
    typedef struct error_code_t {
        Qus_EC_t ec_fields;
        char Exception_Data[100];
    } error_code_t;
    
    main(){
        error_code_t error_code;
        char name[10] = "RSPEIGHT";
        int length = 10;
        char format[8] = "ZLSS0200";
        char* errorCode = "X'0000'";
    
        printf("\nBytes_Provided: %d\n", error_code.ec_fields.Bytes_Provided);
    
        \\memcpy(error_code.ec_fields.Exception_Id," ",7);
        \\error_code.ec_fields.Bytes_Provided = 0;
    
        printf("%s\t%d\t%s\n", name, length, format);
        printf("change 5 \n");
    
        QZLSCHSI((char*)name,
            &length,
            format,
            (char*)&error_code
        );
    
        printf("\nBytes_Provided: %d\n", error_code.ec_fields.Bytes_Provided);
    
        printf("\nException: %s\n", error_code.Exception_Data);
    
        if(error_code.ec_fields.Bytes_Provided > 0){
            printf("error\n");
        };
    
        printf("Success?\n");
    }

  • #2
    I'm not a c pgmr but I think something like this

    Code:
    QZLSCHSI(&name,
             &length,
            "ZLSS0200",
            &error_code
            );


    Comment


    • #3
      The first parameter is meant to be a structure in ZLSS0200 format -- but you are just passing a simple null-terminated string rather than a structure.

      I'm guessing from the (very strange) "errorCode" variable and all of the printf statements that you were really struggling with the error code data structure as well. This brings up two points that I think you might(?) not understand:
      1. IBM APIs generally use variable-length structures that contain length variables (typically 32-bit integers) to denote their size. This is done because IBM will often extend these structures to add more features over time. By examining the lengths, they can determine whether you are using the newer features or not -- thus allowing them to add functionality without breaking backward compatibility.
      2. IBM APIs are meant to be programming-language neutral. This can feel quirky when you're used to a particular language, but it works differently than you'd expect. For example, your "name" variable is defined as a char[10], which is correct -- but you are using the C convention of having a zero (null character) at the end -- which is not used by many/most other programming languages, which is not correct. It should always be 10 bytes long, but the remaining bytes should be filled with blanks.

      Comment


      • #4
        Here is an example that works for me to reenable profiles. Notice how the addProfile function always fills the name with blanks, and doesn't assign the trailing null/zero character. If you tried to print it or view it in the debugger, it'd be weird (because there's no null, code that's expecting a C char array will just keep going and show the subsequent profile names -- but the API won't, it'll only use 10 bytes for each.)

        Code:
        #include <stdio.h>
        #include <string.h>
        #include <qusec.h>
        #include <qzlschsi.h>
        
        typedef struct _error_code {
            Qus_EC_t ec_fields;
            char msgData[32767];
        } my_error_code_t;
        
        typedef struct _my_UserProfile {
          char name[10];
        } my_UserProfile_t;
        
        typedef struct _my_ZLSS0200 {
          int numberOfUserProfileNames;
          my_UserProfile_t userProfile[100]; /* up to 100 profiles */
        } my_ZLSS0200_t;
        
        void addProfile(my_ZLSS0200_t *list, const char *name);
        
        int main(int argc, char **argv) {
        
          my_error_code_t error_code;
          my_ZLSS0200_t list;
          int length = sizeof(list);
        
          /* Initialize structures. */
        
          memset(&error_code, 0, sizeof(error_code));
          memset(&list, ' ', sizeof(list));
          list.numberOfUserProfileNames = 0;
        
        
          /* Add one user to be re-enabled */
        
          addProfile(&list, "RSPEIGHT");
          addProfile(&list, "QPGMR");
          addProfile(&list, "QUSER");
          addProfile(&list, "SKLEMENT");
        
          QZLSCHSI((char*)&list,
            &length,
            "ZLSS0200",
            (char*)&error_code
          );
        
        }
        
        void addProfile(my_ZLSS0200_t *list, const char *name) {
        
          int count = list->numberOfUserProfileNames;
          memset(&(list->userProfile[count].name), ' ', sizeof(my_UserProfile_t));
          memcpy(&(list->userProfile[count].name), name, strlen(name));
          count++;
          list->numberOfUserProfileNames = count;
        
        }

        Comment

        Working...
        X