Программа в z/OS может быть выполнена: 1. в задании // EXEC PGM=... 2. в TSO // EXEC PGM=IKJEFT01,PARM=' CALL ...' 3. в ISPF // EXEC PGM=IKJEFT01,PARM=' ISPSTART PGM(...)' 4. в shell // EXEC PGM=BPXBATCH,PARM='pgm ...' 5. в CICS region как транзакция CICS 6. в IMS region как транзакция IMS 7. в TSO под управлением CAF // EXEC PGM=IKJEFT01,PARM=' DSN ...' 8. в DB2 как внешняя хранимая процедура etc...
ограничиваясь 1-4 (так как в 5-8 не может быть выполнена любая программа), как определить, в какой именно среде выполняется программа?
Идеи: - выполнить какой-нибудь вызов сервиса данной среды, например, чтобы определить 3. выполнить какой-нибудь ISPCALL, скажем 'VDEFINE ...' и если код возврата равен 0, то считать что программа вызвана из ISPF. Поскольку вызов сервиса не должен приводить к abend в других средах, не очень понятно, какие вызовы для этого использовать. - использовать IRXSUBCM, чтобы установить наличие определенных host environment: CALL IRXSUBCM('QUERY ',SCRPTR,32,'ISPEXEC ',ENVBPTR,RETCODE); или эквивалент 'SUBCOM имя' в REXX. Этот подход выглядит многообещающе, и действительно, позволяет легко различить 1-3 (проверка среды TSO, ISPEXEC), но я не смог применить его для shell (4). Несмотря на то, что среда SH существует, вызов CALL IRXSUBCM('QUERY ',SCTPTR,32,'SH ',ENVBPTR,RETCODE); возвращает код 28, и таким способом не получается различить 1 и 4 - анализ управляющих блоков? а каких именно?
Для начала задам частный вопрос - как отличить 1 и 4, иными словами, как определить что программа выполняется в z/OS UNIX (shell)?
Сообщение отредактировал Gregory - Чт, 21.09.2017, 09:36
L R2,TCBJSCB my JSCB USING IEZJSCB,R2 ICM R3,B'1111',JSCBPSCB TSO PSCB JNZ INIT645L TSO, jump INIT645N OI NON_TSO,L'NON_TSO J INIT680 no TSO, no ISPF INIT645L ST R3,PSCB@ save PSCB address MVC UPT@,PSCBUPT-PSCB(R3) save ECT address L R3,PSAAOLD-PSA(,0) point at ASCB USING ASCB,R3 L R4,ASCBASXB my ASXB L R4,ASXBLWA-ASXB(,R4) Logon Work Area ST R4,LWA@ save LWA address USING LWA,R4 MVC ECT@,LWAPECT SAVE FOR PUTLINE ICM R14,B'1111',ASCBTSB check TSB address JNZ INIT645T TSO on-line, jump INIT645B OI TSO_BATCH,L'TSO_BATCH J INIT645X INIT645T OI TSO_ON_LINE,L'TSO_ON_LINE
А такая задача не ставилась :-) Как в batch TSO, так и в online TSO все сервисы TSO доступны и могут использоваться. То же касается и online ISPF / batch ISPF.
А как же позиция 2 Ну да ладно, Позиция 1, без команд
- из своего TCB определяем TCB шага задания (TCBJSTCB) - читаем адрес текущего RB (TCBRBP) - идем по цепочке RB (CDCHAIN), до нужного, то есть когда адрес следующего RB равен адресу TCBшага (RBLINKB) - читаем CDE (RBCDE) - на всякий случай убеждаемся что CDE - главное - из CDE читаем имя (CDNAME) - сравниваем с своим именем, при равенстве - запуск по EXEC Как-то так (возможны варианты )
С запуском в шелл, надо посмотреть решение поэлегантнее, но в принципе метод может быть тем же (наш модуль вряд ли будет в начале цепочки RB). Плюс могут быть разные варианты запуска нашего модуля (spawn или exec) или еще какой-нибудь OMVS-экзот
Это, конечно, решение. Но, согласитесь, странно сообщать программе то, что она может узнать сама...
Зато просто! И всегда абсолютно точный результат.
ЦитатаGregory ()
не могли бы Вы пояснить?
Надо поискать, где-то у меня должно быть... Точно помню, что писали код, который добирается до текста (читает JESJCL? не помню точно), и потом уже тупо делает парсинг в поисках нужного.
Точно помню, что писали код, который добирается до текста (читает JESJCL? не помню точно), и потом уже тупо делает парсинг в поисках нужного.
интересно было бы взглянуть, несмотря на то, что это способ принципиально не может гарантировать абсолютно достоверный результат: // EXEC PGM=IKJEFT01 //STEPLIB DD DSN=MY.LOADLIB это TSO? :-)
Метод поиска текста JCL не годится 1. Можем стартовать например процедурой под SUB=MSTR, если нам ничего не нужно от JES-а, а там добраться до JCL проблематично (JCT вроде бы и есть, а фактически его нет, неизвестно как его искать) 2. наша программа чаще всего под USS выполняется в дочернем адресном пространстве USS, а не в родительском (зависит от настроек), опять же JCT есть только у родительского 3. есть еще много вариантов, когда адресное пространство есть, программа там выполняется, а JCL как бы нет или оно чужое
- из своего TCB определяем TCB шага задания (TCBJSTCB) - читаем адрес текущего RB (TCBRBP) - идем по цепочке RB (CDCHAIN), до нужного, то есть когда адрес следующего RB равен адресу TCBшага (RBLINKB) - читаем CDE (RBCDE) - на всякий случай убеждаемся что CDE - главное - из CDE читаем имя (CDNAME) - сравниваем с своим именем, при равенстве - запуск по EXEC
самый быстрый, надёжный и точный способ, это передавать параметр!
Так тогда уж лучше использовать разные точки входа в программу: ABCTSO, ABCJCL, ABCUSS etc. Передача параметров требует изменений в вызывающей программе и не всегда так уж проста.
ну так разные точки входа тоже же требуют изменений в вызывающей программе! а что сложного в передаче ассемблерной программе ешё одного, опционального, параметра?
CHTRKID DS CL1 - CSCB TYPE IDENTIFIER CHTSID EQU X'01' - TIME SHARING USER IDENTIFIER CHJOBID EQU X'02' - JOB IDENTIFIER CHINITID EQU X'03' - INITIATOR IDENTIFIER CHSASID EQU X'04' - SYSTEM ADDRESS SPACE IDENTIFIER CHATXPID EQU X'05' - ATX ADDRESS SPACE IDENTIFIER
Последнее - это APPC, так что не актуально
System Automaition еще как-то различает MOUNT и Started Task Других делений по типу адресного пространства нет. Unix-процесс может быть порожден совершенно разными способами, так что для него остается один выход - сканировать CDE и по именам модулей определять кто же нас вызвал