C/400

99. API: QUSRJOBI による正しいジョブ情報の検索

ジョブ情報を検索するのであれば API を使わなくてもコマンド RTVJOBA
使えば十分ではないかと諸兄は考えるかも知れないが、実は RTVJOBA
うかつに信用してしまうと、とんでもないことになる場合がある。
実は、

RTVJOBA : ジョブ情報の検索は自分のジョブしか検索することができない

のである。
例えばバッチ・ジョブや他のジョブの情報を RTVJOBA コマンドを使って

RTVJOBA コマンド

のように検索したいとする。
指定したジョブの情報が得られるかと思いきや、実は戻り値として戻ってくるのは
指定したジョブではなくて、この RTVJOBA コマンドを実行した自分自身のジョブの
情報が戻ってくるだけである。
これには長い間気づかなかった。
指定したジョブ情報を正しく取得するには API: QUSRJOBI を使って検索しなければならない。
次は API: QUSRJOBI を使って RTVJOBA と同じ情報を戻す C/400 のサンプルである。

【サンプル・ソース: RTVJOBA】
0001.00 #include <stdio.h>
0002.00 #include <stdlib.h>
0003.00 #include <string.h>
0004.00 #include <qusrjobi.h>
0005.00 #include <decimal.h>
0006.00 #include <QMHRTVM.h>
0007.00
0008.00 #define TRUE         0
0009.00 #define FALSE       -1
0010.00 #define ID_LEN       16
0011.00 typedef struct {
0012.00    char job[10];
0013.00    char user[10];
0014.00    char jobnbr[6];
0015.00 } JOBINFO;
0016.00 JOBINFO  jobinfo;
0017.00 typedef struct {
0018.00    int  BYTESPRO;
0019.00    int  BYTESAVL;
0020.00    char MSGID[7];
0021.00    char RESRVD;
0022.00    char EXCPDATA[100];
0023.00 } ERRSTRUCTURE;     /* Define the error return structure            */
0024.00 ERRSTRUCTURE  errcode;/* Error Code Structure for RCVMSG      */
0025.00
0026.00 /*************************************************************/
0027.00 /*       内 部 使 用  関  数                          */
0028.00 /*************************************************************/
0029.00 void  GetParam(int argc, char *argv[]);
0030.00 void  INZSR(void);
0031.00 void  ApiError(char* place, int stmno, ERRSTRUCTURE* errcode, char* pgm);
0032.00 /*************************************************************/
0033.00 /*        グ ロ ー バ ル 変 数                         */
0034.00 /*************************************************************/
0035.00    char job[11], user[11], jobnbr[7], outq[11], outqlib[11], date[8];
0036.00    char type[2], prtdev[11], langid[4], cntryid[3], ccsid[6];
0037.00    char dftccsid[6], cymddate[9], sbmmsgq[11], sbmmsgqlib[11];
0038.00    char jobid[ID_LEN], ascnbr[7], m_ccsid[6];
0039.00    decimal(5, 0) dftCCSID, CCSID;
0040.00
0041.00 int  main(int argc, char *argv[]){
0042.00    Qwc_JOBI0300_t  jobi0300;
0043.00    Qwc_JOBI0400_t  jobi0400;
0044.00    char jobid[16];
0045.00
0046.00    GetParam(argc, argv);  /*[ パラメータの取得 ]*/
0047.00    INZSR();               /*[ 初期設定 ]*/
0048.00
0049.00    memset(jobid, ' ', sizeof(jobid));
0050.00    QUSRJOBI(&jobi0300, sizeof(Qwc_JOBI0300_t), "JOBI0300", &jobinfo,
0051.00                  jobid, &errcode);
0052.00    if(errcode.BYTESAVL != 0){/* APIERR */
0053.00       ApiError("QUSRJOBI", __LINE__, &errcode, "VT5250"); exit(-1);
0054.00    }/* APIERR */
0055.00    memcpy(jobid, jobi0300.Int_Job_ID, 16);
0056.00    memcpy(outq, jobi0300.Outq_Name, 10);
0057.00    outq[10] = 0x00;
0058.00    memcpy(outqlib, jobi0300.Outq_Lib, 10);
0059.00    outqlib[10] = 0x00;
0060.00    memcpy(date, jobi0300.Job_Date, 7);
0061.00    date[7] = 0x00;
0062.00    memcpy(prtdev, jobi0300.Prt_Dev_Name, 10);
0063.00    prtdev[10] = 0x00;
0064.00    memcpy(sbmmsgq, jobi0300.Subm_Msgq_Name, 10);
0065.00    sbmmsgq[10] = 0x00;
0066.00    memcpy(sbmmsgqlib, jobi0300.Subm_Msgq_Lib, 10);
0067.00    sbmmsgqlib[10] = 0x00;
0068.00    memcpy(cymddate, jobi0300.Date_Put_On_Jobq, 8);
0069.00    cymddate[8] = 0x00;
0070.00    memset(&jobinfo, ' ', sizeof(jobinfo));
0071.00    memcpy(jobinfo.job, "*INT      ", 10);
0072.00    QUSRJOBI(&jobi0400, sizeof(Qwc_JOBI0400_t), "JOBI0400", &jobinfo,
0073.00                  jobid, &errcode);
0074.00    if(errcode.BYTESAVL != 0){/* APIERR */
0075.00       ApiError("QUSRJOBI", __LINE__, &errcode, "VT5250"); exit(-1);
0076.00    }/* APIERR */
0077.00    memcpy(langid, jobi0400.Language_ID, 3);
0078.00    langid[3] = 0x00;
0079.00    memcpy(cntryid, jobi0400.Country_ID, 2);
0080.00    cntryid[2] = 0x00;
0081.00    if(jobi0400.Job_Type[0] == 'B') strcpy(type, "0");
0082.00    else strcpy(type, "1");
0083.00    sprintf(ccsid, "%05d", jobi0400.Coded_Char_Set_ID);
0084.00    CCSID = (decimal(5, 0))jobi0400.Coded_Char_Set_ID;
0085.00    sprintf(dftccsid, "%05d", jobi0400.Default_Coded_Char_Set_Id);
0086.00    dftCCSID = (decimal(5, 0))jobi0400.Default_Coded_Char_Set_Id;
0087.00
0088.00    strcpy(argv[1], job);
0089.00    strcpy(argv[2], user);
0090.00    strcpy(argv[3], jobnbr);
0091.00    strcpy(argv[4], outq);
0092.00    strcpy(argv[5], outqlib);
0093.00    strcpy(argv[6], date);
0094.00    strcpy(argv[7], type);
0095.00    strcpy(argv[8], prtdev);
0096.00    strcpy(argv[9], langid);
0097.00    strcpy(argv[10], cntryid);
0098.00    memcpy(argv[11], &CCSID, 3);
0099.00    memcpy(argv[12], &dftCCSID, 3);
0100.00    strcpy(argv[13], cymddate);
0101.00    strcpy(argv[14], sbmmsgq);
0102.00    strcpy(argv[15], sbmmsgqlib);
0103.00    return;
0104.00 }
0105.00 /*************************************/
0106.00 void  GetParam(int argc, char *argv[])
0107.00 /*************************************/
0108.00 {
0109.00    memcpy(job, argv[1], 10);
0110.00    job[10] = 0x00;
0111.00    memcpy(user, argv[2], 10);
0112.00    user[10] = 0x00;
0113.00    memcpy(jobnbr, argv[3], 6);
0114.00    jobnbr[6] = 0x00;
0115.00 }
0116.00 /****************/
0117.00 void  INZSR(void)
0118.00 /****************/
0119.00 {
0120.00    errcode.BYTESPRO = sizeof(errcode);
0121.00    errcode.BYTESAVL = 0;
0122.00 }
0123.00 /*********************************************************************/
0124.00 void  ApiError(char* place, int stmno, ERRSTRUCTURE* errcode, char* pgm)
0125.00 /*********************************************************************/
0126.00 {
0127.00    char msgid[8], msgf[11], msgflib[11], msgdta[101], Message[512];
0128.00    int  msglen, msgdtalen, pos, strpos = FALSE;
0129.00    char* ptr;
0130.00    typedef struct {
0131.00      Qmh_Rtvm_RTVM0100_t  rtvm0100;
0132.00      char msg[512];
0133.00    } ERRMSG;
0134.00    ERRMSG errmsg;
0135.00
0136.00    memcpy(msgid, errcode->MSGID, 7);
0137.00    msgid[7] = 0x00;
0138.00    if(msgid[0] == 0x00 || msgid[0] == ' '){/*msgid なし */
0139.00      perror("APIERROR");
0140.00      printf("    at %s, STMNO=%d\n", place, stmno);
0141.00      getchar();
0142.00      return;
0143.00    }/*msgid なし */
0144.00    memcpy(msgdta, errcode->EXCPDATA, 100);
0145.00    msgdta[100] = 0x00;
0146.00    msglen = sizeof(ERRMSG);
0147.00    msgdtalen = strlen(msgdta);
0148.00    memset(&errmsg, 0, sizeof(ERRMSG));
0149.00    QMHRTVM(&errmsg,  msglen, "RTVM0100", msgid, "QCPFMSG   *LIBL     ",
0150.00           msgdta, msgdtalen, "*YES      ", "*YES      ", errcode);
0151.00    memset(Message, 0, sizeof(Message));
0152.00    memcpy(Message, errmsg.msg, 512);
0153.00    ptr = strstr(Message, "&N");
0154.00    while(ptr != NULL){/*while*/
0155.00      pos = (int)(ptr - Message);
0156.00      if(strpos == FALSE) strpos = pos;
0157.00      Message[pos] = 0x15; pos ++;
0158.00      Message[pos] = ' ';
0159.00      ptr = strstr(&Message[pos], "&N");
0160.00    }/*while*/
0161.00    if(strpos != FALSE) Message[strpos] = 0x00;
0162.00    printf("PGM-%s:APIERR %s-%s\n", pgm, msgid, Message);
0163.00    printf("    AT %s, STMNO=%d\n", place, stmno);
0164.00    printf("    MSGDTA      =%s\n", msgdta);
0165.00 }
【解説】

API: QUSRJOBIJOBI0300 JOBI0400 の2つの機能による呼び出しによって
コマンド : RTVJOBA と同じ機能を再現しようととているのであるが

0081.00    if(jobi0400.Job_Type[0] == 'B') strcpy(type, "0");
0082.00    else strcpy(type, "1"); 

にも注意して頂きたい。API: QUSRJOBI による実行ジョブのタイプを取得すると
バッチ・ジョブの場合は「B」が入り、対話式ジョブの場合は「I」が入る。
これに対して RTVJOBA コマンドの場合は、バッチ・ジョブの場合は「0」が入り、
対話式ジョブの場合は「1」が入る。
従って QUSRJOBI の戻り値をうっかりそのまま信用してしまうと、ここでも
落とし穴」にはまってしまうようである。
使用頻度が最も高いと思われる RTVJOBA コマンドには、このように
いくつもの盲点が潜んでいる。自分自身のジョブしか検索することはできない、とは
IBM マニュアルのどこにも書かれていないので、これはバグと言えるものでは
ないだろうか。