There are numerous reports which automatically print throughout the day. Often there may be a message waiting on the printer and because no one was expecting any reports, no one discovers the problem until hours later. (By this time there may be quite a few reports waiting to print) I was trying to use the command rcvmsg (msgq qsysopr). Based on the rtntype, I wanted to send a break message to certain users if there was a message waiting for that particular printer. I ran into some problems. First of all, QSYSOPR is always allocated. I put in the monitor message for error CPF2451. The program now does not blow up but it does not work either. I have never used this command before. Can someone give me a specific example on how to use this command for what I am trying to use it for or is there a better way to do it? (Purchasing software is not an option)
Thanks
Software/Hardware used:
AS400 - V5R4
ASKED:
December 17, 2009 2:23 PM
UPDATED:
May 25, 2010 2:50 PM
Create a batch job and run that batch job after every 5 or 10 mins which checks the status of any job thru WRKACTJOB and if its in msg wait condition simply fire SNDBRKMSG command .
I think this can full fill your needs
You can change the message queue attached to the device / writer – there’s no law that it has to be the QSYSOPR message queue. Thing is, there may be important messages that are missed because they’re not in QSYSOPR.
We had an ongoing problem with printers kicking up error messages in the wee hours; whoever had on-call duty could count on being woken up at least once or twice every night. I used the system reply list to cancel writers when error messages popped up, and created a self-submitting program that tries to restart the print writers every thirty minutes. Then, proving no good deed goes unpunished, I got complaints from the on-call group because I’d cut into their off-hours remuneration. If you want, I’ll be happy to post the code for creating the system reply list entries & that for restarting the print writers.
Two possible solutions:
1. Add system reply list entries for specific printers and specific forms. This works well for all conditions that can be anticipated and always are answered the same way.
Below is a program I wrote based on an IBM example to monitor message queue when the inactivity timer was triggered. System Value QINACTITV. It is not exactly the same as your issue, but the program does work and can be modified to monitor for any message and take any action you want. Just job try the following from IBM:
/******************************************************************************/ /* PROGRAM NAME . . . . . . . . . . . . . . : INACTITV */ /* AUTHOR . . . . . . . . . . . . . . . . . : RAYMOND G. JOHNSON */ /* DATE CREATED . . . . . . . . . . . . . . : 04/20/2005 */ /* */ /* PROGRAM INFORMATION: Monitor for inactivey and vary off devices. */ /* */ /* */ /******************************************************************************/ /* CHANGE LOG: */ /******************************************************************************/ /* DATE INITIALS CHANGE DESCRIPTION */ /******************************************************************************/ /* XX/XX/200X XXX */ /* 02/03/2010 RGJ Shorten messages to INACTLOG message queue. */ /******************************************************************************/ PGM DCL VAR(&MSGDTA) TYPE(*CHAR) LEN(80) DCL VAR(&MSGID) TYPE(*CHAR) LEN(7) DCL &THEQUEUE *CHAR 20 + /* QINACTMSGQ SYSTEM VALUE */ DCL &INACTLIB *CHAR 10 /* QUEUE'S LIBRARY */ DCL &INACTQUEUE *CHAR 10 /* QUEUE NAME */ DCL &INACTDATA *CHAR 100 /* RAW MESSAGE DATA */ DCL &JOBNAME *CHAR 10 /* INACTIVE JOB NAME */ DCL &USER *CHAR 10 /* INACTIVE JOB USER */ DCL &NUMBER *CHAR 6 /* INACTIVE JOB NUMBER */ DCL &TIME *CHAR 6 /* TIME OF DAY */ DCL &MSGDTALEN *DEC (5 0) DCL &MSGID *CHAR 7 /* MESSAGE TAKEN FROM THE QUEUE*/ /******************************************************************************/ /* GLOBAL MONITOR MESSAGE - STANDARD ERROR EXIT */ /******************************************************************************/ MONMSG MSGID(CPF0000 MCH0000) EXEC(GOTO CMDLBL(ERROR)) /******************************************************************************/ /* START OF PROGRAM. */ /* JOB TO MONITOR THE SYSTEM INACTIVITY */ /* GET THE NAME OF THE QUEUE TO MONITOR FROM THE SYSTEM VALUE */ /****************************************************************************/ CHGJOB LOG(4 0 *SECLVL) LOGCLPGM(*YES) RTVSYSVAL SYSVAL(QINACTMSGQ) RTNVAR(&THEQUEUE) CHGVAR &INACTQUEUE %SUBSTRING(&THEQUEUE 1 10) CHGVAR &INACTLIB %SUBSTRING(&THEQUEUE 11 10) /****************************************************************************/ /* MAIN LOOP. */ /****************************************************************************/ LOOP: /* */ /* WAIT FOR MESSAGE ON THE MESSAGE QUEUE */ /* */ RCVMSG MSGQ(&INACTLIB/&INACTQUEUE) WAIT(*MAX) + MSGDTA(&INACTDATA) MSGDTALEN(&MSGDTALEN) + MSGID(&MSGID) /* */ /* CHECK TO SEE IF IT IS THE RIGHT MESSAGE, IF NOT, SKIP IT. */ /* */ IF (&MSGID *NE 'CPI1126') THEN(GOTO SKIP) /* */ /* RETRIEVE JOB INFORMATION. */ /* */ CHGVAR &JOBNAME %SUBSTRING(&INACTDATA 1 10) /* GET JOB NAME */ CHGVAR &USER %SUBSTRING(&INACTDATA 11 10) /* GET USER NAME*/ CHGVAR &NUMBER %SUBSTRING(&INACTDATA 21 6) /* GET JOB NUM */ /****************************************************************************/ /* SPECIAL USERS. */ /****************************************************************************/ IF COND(&USER *EQ 'GOODUSER') THEN(GOTO CMDLBL(SKIP)) /****************************************************************************/ /* SPECIAL DEVICES. */ /****************************************************************************/ IF COND(&JOBNAME *EQ 'SYSCONSOLE') THEN(GOTO CMDLBL(SKIP)) IF COND(&JOBNAME *EQ 'SYSCONSOL2') THEN(GOTO CMDLBL(SKIP)) /****************************************************************************/ /* Disconnect job or End job depending if error occurs. */ /****************************************************************************/ DSCJOB: DSCJOB JOB(&NUMBER/&USER/&JOBNAME) MONMSG MSGID(CPF1321) EXEC(GOTO CMDLBL(NEXT)) MONMSG MSGID(CPF1333 CPF1353 CPF1354 CPF1355 + CPF1358 CPF1385 CPF1386 CPF1387 CPF1388 + CPF1389 CPF1391 CPF1656) EXEC(GOTO + CMDLBL(ENDJOB)) ENDJOB: ENDJOB JOB(&NUMBER/&USER/&JOBNAME) OPTION(*CNTRLD) + DELAY(30) MONMSG MSGID(CPF1321 CPF1361 CPF1362 CPF1363) + EXEC(GOTO CMDLBL(NEXT)) /****************************************************************************/ /* Log the user even if the job went away since the device timed out. */ /****************************************************************************/ NEXT: SNDMSG MSG('USER' *BCAT &USER *BCAT 'job ended + from' *BCAT &JOBNAME *BCAT 'at' + *BCAT &TIME) TOMSGQ(ADMIN400/INACTLOG) /* LOG ALL LOGOFF ACTIONS FOR AUDITOR*/ /****************************************************************************/ /* END OF LOOP. */ /****************************************************************************/ SKIP: GOTO CMDLBL(LOOP) /* GO GET MORE MESSAGES ABOUT + OTHER TERMINALS */ RETURN: RETURN /******************************************************************************/ /* END OF PROGRAM / ERROR EXIT */ /******************************************************************************/ ERROR: RCVMSG MSGTYPE(*EXCP) MSGDTA(&MSGDTA) MSGID(&MSGID) MONMSG MSGID(CPF0000) SNDPGMMSG MSGID(&MSGID) MSGF(QCPFMSG) MSGDTA(&MSGDTA) + MSGTYPE(*ESCAPE) MONMSG MSGID(CPF0000) END: ENDPGMIn the global error handler:
ERROR: RCVMSG MSGTYPE(*EXCP) MSGDTA(&MSGDTA) MSGID(&MSGID) MONMSG MSGID(CPF0000) SNDPGMMSG MSGID(&MSGID) MSGF(QCPFMSG) MSGDTA(&MSGDTA) + MSGTYPE(*ESCAPE)You receive MSGID() but not MSGF() nor MSGFLIB(). Then you send explicitly with MSGF(QCPFMSG).
What info will you get if the *EXCP message isn’t from QSYS/QCPFMSG? I would suggest extending the RCVMSG to handle whatever messages might appear. In this specific program, it’s unlikely to make any difference, but it’s much better to handle messages “generically” in a routine that might be copied into other programs.
Tom
Please pardon the length of this entry. I removed some /copy statements to simplify the code, including our standard *PSSR. I hope it’s of some use.
I use this program to build/rebuild the system reply list entries for printer messages:
H datedit(*mdy) datfmt(*iso) debug timfmt(*hms) H dftactgrp(*no) actgrp(*caller) H expropts(*resdecpos) H option(*srcstmt: *nodebugio) H* ============================================================================================ * Add reply list entries * ============================================================================================ D Msg_1 S 7 dim(2) ctdata perrcd(1) Options D Cmp_1 S 3 0 dim(2) ctdata perrcd(1) D Rpy_1 S 1 dim(2) ctdata perrcd(1) Options D Msg_2 S 7 dim(10) ctdata perrcd(1) Options D Rpy_2 S 1 dim(10) ctdata perrcd(1) Options * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * List objects (QUSLOBJ - OBJL0200) * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - D Lstobj Pr extpgm('QUSLOBJ') D 20a const Qualified user space D 8a const Format name D 20a const Object and library n D 10a const Object type D 512a options(*varsize) const Error code * -------------------------------------------------------------------------------------------- * API error code parameter * -------------------------------------------------------------------------------------------- D Api_error Ds D ae_bprv 9b 0 inz(%size(api_error)) D ae_bava 9b 0 inz D ae_msgid 7 D 1 D ae_msgd 256 * -------------------------------------------------------------------------------------------- * Process commands (QCAPCMD) * -------------------------------------------------------------------------------------------- D ProcCmd Pr extpgm('QCAPCMD') D 1024a options(*varsize) const D 9b 0 const D 20a options(*varsize) const D 9b 0 const D 8a const D 1024a options(*varsize) const D 9b 0 const D 9b 0 const D 512a options(*varsize) const D Usrspc Ds D us 10 D usl 10 inz('QTEMP') D Object Ds D on 10 inz('*ALL') D onl 10 inz('*ALL') D Rtv_us_gh Ds D rug_ua 64 User area D rug_sgh 9b 0 Size generic header D rug_srl 4 Structure release le D rug_fn 8 Format name D rug_au 10 API used D rug_dc 7 Date created D rug_tc 6 Time created D rug_is 1 Information status D rug_sus 9b 0 Size user space D rug_oip 9b 0 Offset input paramet D rug_sip 9b 0 Size input parameter D rug_ohs 9b 0 Offset header sectio D rug_shs 9b 0 Size header section D rug_old 9b 0 Offset list data D rug_sld 9b 0 Size list data D rug_#le 9b 0 Number list entries D rug_see 9b 0 D rug_cle 9b 0 CCSID list entry D rug_cid 2 Country identifier D rug_lid 3 Language identifier D rug_sli 1 Subset list indicato D 42 Reserved 1 D rug_epn 256 Entry point name D 128 Reserved 2 D Offset S 9b 0 D Receiver S 2048 D Objl0200 Ds D onu 10 Object name used D olnu 10 Object library name D otu 10 Object type used D is 1 Information status D eoa 10 Extended object attr D td 50 Text description D uda 10 User defined attribu D 7 Reserved D A S 10 0 D B S 10 0 D Sequence S 10 0 D Start S 10 0 D Length S 10 0 D Quote S 1 inz(x'7D') * ============================================================================================ * Normal detail cycle * ============================================================================================ /Free Us = s00proc; Usl = 'QTEMP'; // ==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==- // ==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==- Crtusrspc(usrspc: 'QUSLOBJ': 16773120: x'00': '*USE': 'Test': '*YES': api_error: '*DEFAULT': 32: '1'); Exsr Check_01; // ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------ Lstobj(usrspc: 'OBJL0200': object: '*DEVD': api_error); Exsr Check_01; // ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------ Sequence = 1000; Rtvusrspc(usrspc: 1: %len(rtv_us_gh): rtv_us_gh: api_error); Exsr Check_01; Offset = rug_old + 1; For a = 1 to rug_#le; Rtvusrspc(usrspc: offset: %len(receiver): receiver: api_error); Exsr Check_01; Objl0200 = %subst(receiver: 1: %len(objl0200)); Select; When eoa = 'PRTLAN' or eoa = 'PRTVRT'; For b = 1 to %elem(msg_1); If onu = 'PRT01' and (msg_1(b) = 'CPA3394' or msg_1(b) = 'CPA3395'); Iter; EndIf; Sequence += 1; Cmdstr = 'RMVRPYLE SEQNBR(' + %char(sequence) + ')'; Proccmd(%trim(cmdstr): %len(%trim(cmdstr)): cpop0100: %len(cpop0100): cc_ocbf: cmdstr: %len(cmdstr): cc_loccsatr: api_error); EndFor; EndSl; Offset += rug_see; EndFor; // ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------ Dltusrspc(usrspc: api_error); Exsr Check_01; // ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------ For a = 1 to %elem(msg_2); Sequence += 1; Cmdstr = 'RMVRPYLE SEQNBR(' + %char(sequence) + ')'; Proccmd(%trim(cmdstr): %len(%trim(cmdstr)): cpop0100: %len(cpop0100): cc_ocbf: cmdstr: %len(cmdstr): cc_loccsatr: api_error); EndFor; // ==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==- // ==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==- Crtusrspc(usrspc: 'QUSLOBJ': 16773120: x'00': '*USE': 'Test': '*YES': api_error: '*DEFAULT': 32: '1'); Exsr Check_01; // ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------ Lstobj(usrspc: 'OBJL0200': object: '*DEVD': api_error); Exsr Check_01; // ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------ Sequence = 1000; Rtvusrspc(usrspc: 1: %len(rtv_us_gh): rtv_us_gh: api_error); Exsr Check_01; Offset = rug_old + 1; For a = 1 to rug_#le; Rtvusrspc(usrspc: offset: %len(receiver): receiver: api_error); Exsr Check_01; Objl0200 = %subst(receiver: 1: %len(objl0200)); Select; When eoa = 'PRTLAN' or eoa = 'PRTVRT'; For b = 1 to %elem(msg_1); If onu = 'PRT01' and (msg_1(b) = 'CPA3394' or msg_1(b) = 'CPA3395'); Iter; EndIf; Sequence += 1; Cmdstr = 'ADDRPYLE SEQNBR(' + %char(sequence) + ') MSGID(' + msg_1(b) + ') CMPDTA(' + quote + onu + quote + ' ' + %char(cmp_1(b)) + ') RPY(' + %trim(rpy_1(b)) + ')'; Proccmd(%trim(cmdstr): %len(%trim(cmdstr)): cpop0100: %len(cpop0100): cc_ocbf: cmdstr: %len(cmdstr): cc_loccsatr: api_error); EndFor; EndSl; Offset += rug_see; EndFor; // ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------ Dltusrspc(usrspc: api_error); Exsr Check_01; // ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------ For a = 1 to %elem(msg_2); Sequence += 1; Cmdstr = 'ADDRPYLE SEQNBR(' + %char(sequence) + ') MSGID(' + msg_2(a) + ') RPY(' + %trim(rpy_2(a)) + ')'; Proccmd(%trim(cmdstr): %len(%trim(cmdstr)): cpop0100: %len(cpop0100): cc_ocbf: cmdstr: %len(cmdstr): cc_loccsatr: api_error); EndFor; // ==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==- // ==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==- *inlr = *on; /End-free * ============================================================================================ * All subroutines * Check_01 - Check for error * ============================================================================================ * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * Check_01 - Check for error * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- /Free BegSr Check_01; If ae_bava <> *zero; Exsr *pssr; *inlr = *on; Return; EndIf; EndSr; /End-free **CTDATA Msg_1 CPA3394 CPA3395 **CTDATA Cmp_1 001 001 **CTDATA Rpy_1 G G **CTDATA Msg_2 CPA3387 CPA4002 CPA403D CPA404D CPA404F CPA405B CPA405C CPA405D CPA405E CPA405F **CTDATA Rpy_2 C I C C C C C C C CThis program is used to restart the print writers:
H datedit(*mdy) datfmt(*iso) debug timfmt(*hms) H dftactgrp(*no) actgrp(*caller) H expropts(*resdecpos) H option(*srcstmt: *nodebugio) H* ============================================================================================ * Start print writers * ============================================================================================ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * List objects (QUSLOBJ - OBJL0200) * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - D Lstobj Pr extpgm('QUSLOBJ') D 20a const Qualified user space D 8a const Format name D 20a const Object and library n D 10a const Object type D 512a options(*varsize) const Error code * -------------------------------------------------------------------------------------------- * API error code parameter * -------------------------------------------------------------------------------------------- D Api_error Ds D ae_bprv 9b 0 inz(%size(api_error)) D ae_bava 9b 0 inz D ae_msgid 7 D 1 D ae_msgd 256 * -------------------------------------------------------------------------------------------- * Process commands (QCAPCMD) * -------------------------------------------------------------------------------------------- D ProcCmd Pr extpgm('QCAPCMD') D 1024a options(*varsize) const D 9b 0 const D 20a options(*varsize) const D 9b 0 const D 8a const D 1024a options(*varsize) const D 9b 0 const D 9b 0 const D 512a options(*varsize) const D Usrspc Ds D us 10 D usl 10 inz('QTEMP') D Object Ds D on 10 inz('*ALL') D onl 10 inz('*ALL') D Rtv_us_gh Ds D rug_ua 64 User area D rug_sgh 9b 0 Size generic header D rug_srl 4 Structure release le D rug_fn 8 Format name D rug_au 10 API used D rug_dc 7 Date created D rug_tc 6 Time created D rug_is 1 Information status D rug_sus 9b 0 Size user space D rug_oip 9b 0 Offset input paramet D rug_sip 9b 0 Size input parameter D rug_ohs 9b 0 Offset header sectio D rug_shs 9b 0 Size header section D rug_old 9b 0 Offset list data D rug_sld 9b 0 Size list data D rug_#le 9b 0 Number list entries D rug_see 9b 0 D rug_cle 9b 0 CCSID list entry D rug_cid 2 Country identifier D rug_lid 3 Language identifier D rug_sli 1 Subset list indicato D 42 Reserved 1 D rug_epn 256 Entry point name D 128 Reserved 2 D Offset S 9b 0 D Receiver S 2048 D Objl0200 Ds D onu 10 Object name used D olnu 10 Object library name D otu 10 Object type used D is 1 Information status D eoa 10 Extended object attr D td 50 Text description D uda 10 User defined attribu D 7 Reserved D Timestamp S z inz(*sys) D Timefld S t D Datefld S d datfmt(*usa) D A S 10 0 D Start S 10 0 D Length S 10 0 D Quote S 1 inz(x'7D') * ============================================================================================ * Normal detail cycle * ============================================================================================ /Free Us = s00proc; Usl = 'QTEMP'; // ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------ Crtusrspc(usrspc: 'QUSLOBJ': 16773120: x'00': '*USE': 'Test': '*YES': api_error: '*DEFAULT': 32: '1'); Exsr Check_01; // ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------ Lstobj(usrspc: 'OBJL0200': object: '*DEVD': api_error); Exsr Check_01; // ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------ Rtvusrspc(usrspc: 1: %len(rtv_us_gh): rtv_us_gh: api_error); Exsr Check_01; Offset = rug_old + 1; For a = 1 to rug_#le; Rtvusrspc(usrspc: offset: %len(receiver): receiver: api_error); Exsr Check_01; Objl0200 = %subst(receiver: 1: %len(objl0200)); Select; When eoa = 'PRTLAN' or eoa = 'PRTVRT'; Cmdstr = 'STRPRTWTR DEV(' + %trim(onu) + ')'; Proccmd(%trim(cmdstr): %len(%trim(cmdstr)): cpop0100: %len(cpop0100): cc_ocbf: cmdstr: %len(cmdstr): cc_loccsatr: api_error); EndSl; Offset += rug_see; EndFor; // ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------ Dltusrspc(usrspc: api_error); Exsr Check_01; // ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------ Cmdstr = 'STRRMTWTR OUTQ(*ALL)'; Proccmd(%trim(cmdstr): %len(%trim(cmdstr)): cpop0100: %len(cpop0100): cc_ocbf: cmdstr: %len(cmdstr): cc_loccsatr: api_error); // ========================================================================================== // ========================================================================================== *inlr = *on; /End-free C AddDur 30:*minutes timestamp C Move timestamp datefld C Move timestamp timefld /Free Cmdstr = 'SBMJOB CMD(CALL PGM(*LIBL/SSSPW000)) JOB(STARTWTR) + USER(QSYSOPR) SCDDATE(' + quote + %char(datefld) + quote + ') SCDTIME(' + quote + %char(timefld) + quote + ')'; Proccmd(%trim(cmdstr): %len(%trim(cmdstr)): cpop0100: %len(cpop0100): cc_ocbf: cmdstr: %len(cmdstr): cc_loccsatr: api_error); /End-free * ============================================================================================ * All subroutines * Check_01 - Check for error * ============================================================================================ * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * Check_01 - Check for error * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- /Free BegSr Check_01; If ae_bava <> *zero; Exsr *pssr; *inlr = *on; Return; EndIf; EndSr; /End-free