ジョブ情報を検索するのであれば API を使わなくてもコマンド 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: QUSRJOBI の JOBI0300 と 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 マニュアルのどこにも書かれていないので、これはバグと言えるものでは
ないだろうか。