def dscb1data_from_dsname_and_volser(dsname, volser, debug=False, svc_args=None, encoding=None): if svc_args is None: svc_args = bytearray(5 * 8) if encoding is None: dsname = codecs.encode("{:44s}".format(dsname), encoding=cp1047_oe) volser = codecs.encode("{:6s}".format(volser), encoding=cp1047_oe) obtain_search = bytearray_set_address_size( bytearray(4 + 4 + 4 + 4 + 44 + 6 + 140), 31) struct.pack_into( '=IIII' + '44s6s', obtain_search, 0, 0xC1000000 + 0x801, # CAMLST_SEARCH + CAMLST_EADSCB_OK bytearray_buffer_address(obtain_search) + 4 * 4, bytearray_buffer_address(obtain_search) + 4 * 4 + 44, bytearray_buffer_address(obtain_search) + 4 * 4 + 44 + 6, dsname, volser) struct.pack_into('QQQQQ', svc_args, 0, 0, 0, bytearray_buffer_address(obtain_search), 27, SYSTEM_CALL__SVC) # CAMLST OBTAIN zos_system_call(svc_args) rc = struct.unpack_from('=4xI', svc_args, 0)[0] if rc != 0: raise OSError("CAMLIST SEARCH returned rc=0x%X" % (rc, )) if debug: print( dump_region( bytearray_buffer_address(obtain_search) + 4 * 4 + 44 + 6, 140)) return (obtain_search, 4 * 4 + 44 + 6)
def build_a24(self, ddname): self.a24 = bytearray_set_address_size(bytearray(a24_size), 24) a24 = self.a24 struct.paueck_into('HHHHHHHHHHHHHHHHH', a24, abend_exit_offset, 0x5870, 0x1004, # L R7,4(,R1) # R7 is the DCB 0x9104, 0x1003, # TM 3(R1),X'04' # is it ignorable? 0x4770, 0xF012, # BNZ *+10 0x9200, 0x1003, # MVI 3(R1),X'00' # if we can't ignore, allow it to abend 0x07FE, # BR R14 # return 0x9204, 0x1003, # MVI 3(R1),X'04' # ignore it 0xA77A, 0xFFFF & -dcb_offset, # AHI R7,xxxx 0xD203, 0x7000, 0x1000, # MVC 0(R7),0(R1) 0x07FE) # BR R14 # return struct.pack_into('I', a24, exit_list_offset, ((0x80 + 0x11)<<24) + (bytearray_buffer_address(a24) + abend_exit_offset)) # DCB DSORG=PO,MACRF=R for i in (0x17, 0x1F, 0x23, 0x37, 0x3B, 0x47, 0x4B, 0x4F, 0x57): a24[dcb_offset + i] = 0x01 a24[dcb_offset + 0x1A] = 0x02 a24[dcb_offset + 0x30] = 0x02 a24[dcb_offset + 0x32] = 0x24 struct.pack_into("8s", a24, dcb_offset + 0x28, codecs.encode("{:8s}".format(ddname), encoding=cp1047_oe)) exit_list_address = bytearray(4) struct.pack_into('I', exit_list_address, 0, bytearray_buffer_address(a24) + exit_list_offset) struct.pack_into("3s", a24, dcb_offset + 0x35, exit_list_address[1:])
def call(self, request_type, criteria={}, requested_fields=None): self.requested_fields = requested_fields ssob_and_stat = self.ssob_and_stat arglist = self.arglist save_area = self.save_area ssreq = self.ssreq request_types = ('job_terse', 'job_verbose', 'close', 'sysout_terse', 'sysout_verbose', 'data_set_list') struct.pack_into('B', ssob_and_stat, 0x2C, request_types.index(request_type) + 1) for name, value in criteria.items(): if not value: continue struct_fmt, position_list, bit_position, bit = criteria_fields[ name] if isinstance(value, str): value = codecs.encode( ("{:%ds}" % int(struct_fmt[:-1])).format(value), encoding=cp1047_oe) if isinstance(position_list, tuple): for position in position_list: struct.pack_into(struct_fmt, ssob_and_stat, position, value) else: position = position_list struct.pack_into(struct_fmt, ssob_and_stat, position, value) ssob_and_stat[bit_position] |= bit struct.pack_into('QQQQQ', ssreq, 0, ssreq_fn, 0, bytearray_buffer_address(arglist), bytearray_buffer_address(save_area), SYSTEM_CALL__CALL31) zos_system_call(ssreq) self.ssi_return_code = struct.unpack_from('=4xI', self.ssreq, 0)[0] if self.ssi_return_code != 0: error_index = self.ssi_return_code / 4 - 1 error_messages = ( "The subsystem does not support this function.", "The subsystem exists, but is not active.", "The subsystem is not defined to MVS.", "Invalid SSOB, SSIB or function code", "The SSOB or SSIB have invalid lengths or formats", "The SSI has not been initialized.") raise Exception(error_messages[errior_index]) self.subsystem_return_code = struct.unpack_from( '=I', ssob_and_stat, 0x0C)[0] # SSOBRETN self.version, self.reason, self.reason2 = struct.unpack_from( '=BxBB', self.ssob_and_stat, 0x28) # STATVER, STATREAS, STATREA2 if self.ssi_return_code == 4: raise Exception("Invalid search arguments") elif self.ssi_return_code == 8: raise Exception("Logic error, reason=0x%X" % self.reason) elif self.ssi_return_code == 12: raise Exception("Unsupported call type") #print(dump_region(bytearray_buffer_address(ssob_and_stat), len(self.ssob_and_stat))) return None
def __init__(self, outputs, pid=0, thid=0, asid=0, loginname=None): self.pid = pid self.thid = thid self.pgtha = self.make_pgtha(outputs, pid=pid, thid=thid, asid=asid, loginname=loginname) pgtha = self.pgtha self.pgthb = self.make_pgthb() pgthb = self.pgthb self.BPX1GTH_args = bytearray(7 * 8 + 2 * 8 + 5 * 4) BPX1GTH_args = self.BPX1GTH_args struct.pack_into( 'QQQQQQQ' 'QQ' 'IIIII', BPX1GTH_args, 0, bytearray_buffer_address(BPX1GTH_args) + 9 * 8 + 0 * 4, bytearray_buffer_address(BPX1GTH_args) + 7 * 8, bytearray_buffer_address(BPX1GTH_args) + 9 * 8 + 1 * 4, bytearray_buffer_address(BPX1GTH_args) + 8 * 8, bytearray_buffer_address(BPX1GTH_args) + 9 * 8 + 2 * 4, bytearray_buffer_address(BPX1GTH_args) + 9 * 8 + 3 * 4, bytearray_buffer_address(BPX1GTH_args) + 9 * 8 + 4 * 4, bytearray_buffer_address(pgtha), bytearray_buffer_address(pgthb), len(pgtha), len(pgthb), 0, 0, 0) self.call_args = bytearray(5 * 8)
def close(self): # CLOSE (MYDCB),MODE=31 a24 = self.a24 bldl_list = self.bldl_list close_args = bytearray_set_address_size(bytearray(8), 31) struct.pack_into('=B3xI', close_args, 0, 0x80, bytearray_buffer_address(a24) + dcb_offset) struct.pack_into('QQQQQ', self.svc_args, 0, 0, bytearray_buffer_address(close_args), 0, 20, SYSTEM_CALL__SVC) zos_system_call(self.svc_args) rc = struct.unpack_from('Q', self.svc_args, 0)
def load(self): # LOAD DE=bldl_list,DCB=dcb,ERRRET=NEXT a24 = self.a24 bldl_list = self.bldl_list struct.pack_into('QQQQQ', self.svc_args, 0, 0, bytearray_buffer_address(bldl_list)+4, 0x80000000 + (bytearray_buffer_address(a24) + dcb_offset), 8, SYSTEM_CALL__SVC) zos_system_call(self.svc_args) #unsigned int r15; /* good:0 bad:returnCode */ #unsigned int r0; /* good:ep_including_amode bad:n/a */ #unsigned int r1; /* good:apf+length_in_doublewords bad:reasonCode */ codes = struct.unpack_from("4xI8x4xI", self.svc_args, 0) # ignore the high order 32 bits if codes[0] == 0: self.ep = struct.unpack_from("4xI", self.svc_args, 1*8)[0] else: raise OSError("LOAD return_code=%X, reason_code=%X" % codes)
def show_text_units(text_unit_array): text_unit_array_address = bytearray_buffer_address(text_unit_array) end = False tu_count = 0 while not end: tu_address = struct.unpack_from("I", text_unit_array, tu_count * 4)[0] offset = tu_address - text_unit_array_address tu_count += 1 end = 0 != (offset & 0x80000000) offset = offset & 0x7FFFFFFF code = struct.unpack_from("H", text_unit_array, offset)[0] offset += 2 count = struct.unpack_from("H", text_unit_array, offset)[0] offset += 2 print("%04X %04X " % (code, count), end=('\n' if count == 0 else '')) for index in range(count): if index > 0: print(" ", end='') length = struct.unpack_from("H", text_unit_array, offset)[0] offset += 2 print("%04X " % length, end='') data = struct.unpack_from("%ds" % length, text_unit_array, offset)[0] offset += length for i in range(len(data)): print("%02X" % data[i], end=' ') print('')
def bldl(self, name): a24 = self.a24 # BLDL bldl_list,dcb self.bldl_list = bytearray_set_address_size(bytearray(72), 31) bldl_list = self.bldl_list struct.pack_into('=HH8s', self.bldl_list, 0, 1, 68, codecs.encode("{:8s}".format(name), encoding=cp1047_oe) ) if self.verbose: print(["%08X" % v for v in struct.unpack_from('III', self.bldl_list, 0)]) struct.pack_into('QQQQQ', self.svc_args, 0, 0, bytearray_buffer_address(bldl_list), bytearray_buffer_address(a24) + dcb_offset, 18, SYSTEM_CALL__SVC) zos_system_call(self.svc_args) rc, reason = struct.unpack_from('7xB7xB', self.svc_args, 0) if rc > 0: raise OSError("BLDL failed for %s, rc=%X, reason=%X" % (self.name, rc, reason))
def parse_information(self, address, remaining_length, result=None): if not result: result = {} type_and_modifier = ctypes.c_ushort.from_address(address + 0x2).value data_format = structure_info.get(type_and_modifier, ()) if data_format: address += 4 for name, ctype, offset, convert, size in data_format: if name and (not self.requested_fields or name in self.requested_fields): if self.verbose: print("%X %s %s" % (offset, name, dump_region(address + offset, size, show_header=False, show_address=False)), flush=True) if ctype: value = convert( ctype.from_address(address + offset).value) else: value = bytearray(size) ctypes.memmove(bytearray_buffer_address(value), address + offset, size) if value: result[name] = value return result
def open(self): # OPEN (dcb,(INPUT)),MODE=31 a24 = self.a24 open_args = bytearray_set_address_size(bytearray(8), 31) struct.pack_into('=B3xI', open_args, 0, 0x80, bytearray_buffer_address(a24) + dcb_offset) struct.pack_into('QQQQQ', self.svc_args, 0, 0, bytearray_buffer_address(open_args), 0, 19, SYSTEM_CALL__SVC) zos_system_call(self.svc_args) rc = struct.unpack_from('7xB', self.svc_args, 0)[0] if rc > 4: abend_code = struct.unpack_from('I', a24, 0)[0] if abend_code: raise OSError("OPEN abend %X" % abend_code) else: raise OSError("OPEN failed, rc=%X" % rc)
def volser_from_dsname(dsname, svc_args=None, encoding=None): if svc_args is None: svc_args = bytearray(5 * 8) if encoding is None: dsname = codecs.encode("{:44s}".format(dsname), encoding=cp1047_oe) locate = bytearray_set_address_size( bytearray(4 + 4 + 4 + 4 + 44 + 4 + 265), 31) struct.pack_into('=IIII' + '44s', locate, 0, 0x44000000, bytearray_buffer_address(locate) + 4 * 4, 0, bytearray_buffer_address(locate) + 4 * 4 + 44 + 4, dsname) struct.pack_into('QQQQQ', svc_args, 0, 0, 0, bytearray_buffer_address(locate), 26, SYSTEM_CALL__SVC) # LOCATE zos_system_call(svc_args) rc = struct.unpack_from('=4xI', svc_args, 0)[0] if rc != 0: raise OSError("LOCATE NAME returned rc=0x%X" % (rc, )) volser = struct.unpack_from('6s', locate, 4 * 4 + 44 + 4 + 2 + 4)[0] if encoding is None: volser = codecs.decode(volser_ebcdic, cp1047_oe) locate = None return volser
def load(name): name_buffer = bytearray_set_address_size(bytearray(8), 31) struct.pack_into("8s", name_buffer, 0, codecs.encode("{:8s}".format(name), encoding=cp1047_oe)) load_params = bytearray_set_address_size(bytearray(3*4), 31) struct.pack_into('IIBBBB', load_params, 0, bytearray_buffer_address(name_buffer), 0, 0, 0, 0x20, 0) svc_args = bytearray(5*8) struct.pack_into('QQQQQ', svc_args, 0, 9, 0, bytearray_buffer_address(load_params), 122, SYSTEM_CALL__SVC) zos_system_call(svc_args) #unsigned int r15; /* good:0 bad:returnCode */ #unsigned int r0; /* good:ep_including_amode bad:n/a */ #unsigned int r1; /* good:apf+length_in_doublewords bad:reasonCode */ codes = struct.unpack_from("4xI8x4xI", svc_args, 0) # ignore the high order 32 bits if codes[0] == 0: return struct.unpack_from("4xI", svc_args, 1*8)[0] else: raise OSError("LOAD return_code=%X, reason_code=%X" % codes)
def __next__(self): BPX1GTH_args = self.BPX1GTH_args rc = struct.unpack_from('i', BPX1GTH_args, 9 * 8 + 2 * 4)[0] if rc == -1: raise StopIteration() struct.pack_into('QQQQQ', self.call_args, 0, BPX1GTH_addr, 0, bytearray_buffer_address(BPX1GTH_args), 0, SYSTEM_CALL__CALL) zos_system_call(self.call_args) rc = struct.unpack_from('I', BPX1GTH_args, 9 * 8 + 2 * 4)[0] if rc == -1: raise StopIteration() self.move_next_from_pgthb_to_pgtha() if self.pid and self.pid != self.pgtha_pid: raise StopIteration() if self.thid and self.thid != self.pgtha_thid: raise StopIteration() return self.extract_data_from_pgthb()
def allocate_spool_dataset(data_set_name=None, client_token=None, subsystem=None): bytearray_set_address_size(client_token, 31) rc, results = dynalloc({ "DSNAME": data_set_name, "STATUS": "SHR", "UNAUTHORIZED_SUBSYSTER_REQUEST": subsystem, "BROWSE_TOKEN": (codecs.encode("BTKN", encoding=cp1047_oe), bytes( (3, 3)), bytearray_buffer_address(client_token).to_bytes( 4, sys.byteorder) if client_token else 0, 0, 0, 0, 0), "CLOSE": None, "DDNAME_RETURN": None }) if rc != 0: raise OSError("dynalloc returned %X" % rc) return results["DDNAME_RETURN"]
def dynallocInternal(verb, text_unit_mapping, flags1=0, flags2=0, verbose=False, message_level=0, message_function=print_message): keyword_definitions = text_keyword_definitions[verb] text_unit_array_size = process_text_units(text_unit_mapping, keyword_definitions, None, verbose=verbose) if verbose: print("test_unit_array_size = %r" % text_unit_array_size) text_unit_array = bytearray_set_address_size( bytearray(text_unit_array_size), 31) process_text_units(text_unit_mapping, keyword_definitions, text_unit_array, verbose=verbose) if verbose: show_text_units(text_unit_array) message_severity_level = 0 # informational, that is, include all the messages message_block_subpool = 4 message_options = 0x48 # return message to caller + specified subpool svc99rbx = bytearray_set_address_size(bytearray(36), 31) struct.pack_into( 'BBBBBBBBBBB', svc99rbx, 0, 0xE2, 0xF9, 0xF9, 0xD9, 0xC2, 0xE7, 1, #'S99RBX', version message_options, message_block_subpool, 8, message_severity_level) svc99rb = bytearray_set_address_size(bytearray(20), 31) struct.pack_into('BBHHHIII', svc99rb, 0, 20, verb_codes[verb], flags1, 0, 0, bytearray_buffer_address(text_unit_array), bytearray_buffer_address(svc99rbx), flags2) svc99plist = bytearray_set_address_size(bytearray(4), 31) struct.pack_into('I', svc99plist, 0, 0x80000000 | bytearray_buffer_address(svc99rb)) svc_args = bytearray(5 * 8) struct.pack_into('QQQQQ', svc_args, 0, 0, 0, bytearray_buffer_address(svc99plist), 99, SYSTEM_CALL__SVC) zos_system_call(svc_args) svc99_rc = struct.unpack_from('L', svc_args, 0)[0] if verbose: s99error_and_info = struct.unpack_from('HH', svc99rb, 4) print("s99rc=%X, error=%04X, info=%04X" % (svc99_rc, s99error_and_info[0], s99error_and_info[1])) show_text_units(text_unit_array) retrieve_dynalloc_messages(message_function, verb, keyword_definitions, svc99rbx, svc99rb, svc_args, verbose=verbose) output_mapping = process_text_units(text_unit_mapping, keyword_definitions, text_unit_array, tu_input=False, verbose=verbose) return (svc99_rc, output_mapping)
def retrieve_dynalloc_messages(message_function, verbName, keyword_definitions, svc99rbx, svc99rb, svc_args, verbose=False): svc99_rc = struct.unpack_from('L', svc_args, 0)[0] s99error = struct.unpack_from('H', svc99rb, 4)[0] s99info = struct.unpack_from('H', svc99rb, 6)[0] if svc99_rc != 0: message_function("%s failed, return code=%d, error=%04X, info=%04X" % (verbName, svc99_rc, s99error, s99info)) block_count = svc99rbx[11] if verbose: print("s99rbx message_count = %d" % block_count) if block_count == 0: return if block_count > MAX_EM_MESSAGES: block_count = MAX_EM_MESSAGES emMessages = bytearray_set_address_size(bytearray(256 * block_count), 31) emCall = bytearray_set_address_size(bytearray(28), 31) struct.pack_into('BBBxII4xI', emCall, 0, 0x20, 50, block_count, bytearray_buffer_address(svc99rb), svc99_rc, bytearray_buffer_address(emMessages)) if verbose: print(["%08X" % v for v in struct.unpack_from('IIIII', emCall, 0)]) emCallPlist = bytearray_set_address_size(bytearray(4), 31) struct.pack_into('I', emCallPlist, 0, 0x80000000 | bytearray_buffer_address(emCall)) save_area = bytearray_set_address_size(bytearray(18 * 4), 31) call_args = bytearray(5 * 8) struct.pack_into('QQQQQ', call_args, 0, get_IEFDB476(), 0, bytearray_buffer_address(emCallPlist), bytearray_buffer_address(save_area), SYSTEM_CALL__CALL31) zos_system_call(call_args) IEFDB476_rc = struct.unpack_from('Q', call_args, 0)[0] if verbose: print("IEFDB476_rc=%X" % IEFDB476_rc) if verbose: print( ["%X" % v for v in struct.unpack_from('xxBBIIHHI', svc99rbx, 16)]) print(["%X" % v for v in struct.unpack_from('BBBxII4xI', emCall, 0)]) print("block_count=%X" % block_count) for i in range(block_count): message_length = struct.unpack_from('H', emMessages, 256 * i)[0] if verbose: print('message_length=%d' % message_length) message_text = emMessages[256 * i + 4:256 * i + 4 + message_length] message = str.rstrip(codecs.decode(message_text, cp1047_oe)) message_function(message) if s99error == 0x035C: # Invalid PARM specified in text unit, with corresponding message IKJ56231I info = keyword_definitions[s99info] if info: message_function("text unit %04X is %s %s" % (s99info, info[0][0], info[0][2]))
def process_text_units(text_unit_mapping, keyword_definitions, text_unit_array, tu_input=True, verbose=False): if text_unit_array: text_unit_array_address = bytearray_buffer_address(text_unit_array) return_mapping = {} if not tu_input else None tu_count = len(text_unit_mapping.items()) ptr_offset = 0 size = tu_count * 4 count = 0 for key, value in text_unit_mapping.items(): count += 1 definition = keyword_definitions[key] if verbose: print(definition) tu_type = definition[KEYWORD_DEFINITION_TYPE] max_len = definition[KEYWORD_DEFINITION_MAX_LEN] max_value_count = definition[KEYWORD_DEFINITION_MAX_COUNT] code = definition[KEYWORD_DEFINITION_KEY] return_value = definition[KEYWORD_DEFINITION_RETURN] if len( definition) >= (KEYWORD_DEFINITION_RETURN + 1) else None if not tu_input and not return_value: continue if text_unit_array: tu_offset = (count - 1) * 4 if tu_input: struct.pack_into( "I", text_unit_array, tu_offset, text_unit_array_address + size + (0 if count < tu_count else 1 << 31)) struct.pack_into("H", text_unit_array, size, code) else: size = (struct.unpack_from("I", text_unit_array, tu_offset)[0] & 0x7FFFFFFF) - text_unit_array_address size += 2 if (code == DALSYSOU and value == '*') or ( code == DALSSNM and value is None) or max_value_count == 0: value = () min_value_count = 0 else: min_value_count = 1 if tu_input: if return_value: value_count = max_value_count else: if isinstance( value, str) or not isinstance(value, collections.Iterable): value = (value, ) value_count = len(value) if value_count > max_value_count or value_count < min_value_count: raise ValueError if text_unit_array: struct.pack_into("H", text_unit_array, size, value_count) else: value = [] value_count = struct.unpack_from("H", text_unit_array, size)[0] size += 2 for element in value if not return_value else range(value_count): if return_value: if tu_input: if text_unit_array: struct.pack_into("H", text_unit_array, size, max_len) size += 2 + max_len else: len_element = struct.unpack_from("H", text_unit_array, size)[0] size += 2 if tu_type == KD_TYPE_VARCHAR: element = str.rstrip( codecs.decode( struct.unpack_from("%ds" % len_element, text_unit_array, size)[0], cp1047_oe)) else: offset = 0 if len_element == 1: fmt = 'B' elif len_element == 2: fmt = 'H' elif len_element == 3: fmt = 'I' else: fmt = 'I' element = struct.unpack_from(fmt, text_unit_array, size + offset)[0] if len_element == 3: element = element & 0xFFFFFF if isinstance(tu_type, collections.Mapping): pass # FIXME. invert the mapping and use it to decode the value value.append(element) continue if isinstance(element, str): if isinstance(tu_type, collections.Mapping): element = tu_type[element] else: element = codecs.encode(element, encoding=cp1047_oe) if isinstance(element, int): if text_unit_array and tu_input: struct.pack_into("H", text_unit_array, size, max_len) size += 2 nb = max_len while nb > 0: if text_unit_array and tu_input: text_unit_array[size + nb - 1] = element & 0xFF element = element >> 8 nb -= 1 size += max_len continue len_element = len(element) if text_unit_array and tu_input: struct.pack_into("H", text_unit_array, size, len_element) size += 2 if text_unit_array and tu_input: struct.pack_into("%ds" % len_element, text_unit_array, size, element) size += len_element if not tu_input: if max_value_count == 1: value = value[0] return_mapping[definition[KEYWORD_DEFINITION_NAMES][0]] = value return size if tu_input else return_mapping
class extended_status: verbose = False ssreq_fn = MEM4(MEM4(MEM4(0, 0x10), 0x128), 0x14) ssob_and_stat_len = 0x23C # version 10 ssob_and_stat = bytearray_set_address_size(bytearray(ssob_and_stat_len), 31) arglist = bytearray_set_address_size(bytearray(4), 31) struct.pack_into('=I', arglist, 0, bytearray_buffer_address(ssob_and_stat)) struct.pack_into( '=4sHHI4xI', ssob_and_stat, 0, codecs.encode("{:4s}".format("SSOB"), encoding=cp1047_oe), # E2E2D6C2 0x1C, 80, 0, bytearray_buffer_address(ssob_and_stat) + 0x20) # 0x1C is the SSOB length; 80 is extended status struct.pack_into( 'H4sBB5x', ssob_and_stat, 0x20, 0x21C, # version 10 length codecs.encode("{:4s}".format("STAT"), encoding=cp1047_oe), # E2E3C1E3 10, 0) # version 10, modifier 0 struct.pack_into( 'B', ssob_and_stat, 0xDA, # STATOPT1 0x04) # Returned areas may be obtained in 64-bit storage save_area = bytearray_set_address_size(bytearray(18 * 4), 31) ssreq = bytearray(5 * 8) def call(self, request_type, criteria={}, requested_fields=None): self.requested_fields = requested_fields ssob_and_stat = self.ssob_and_stat arglist = self.arglist save_area = self.save_area ssreq = self.ssreq request_types = ('job_terse', 'job_verbose', 'close', 'sysout_terse', 'sysout_verbose', 'data_set_list') struct.pack_into('B', ssob_and_stat, 0x2C, request_types.index(request_type) + 1) for name, value in criteria.items(): if not value: continue struct_fmt, position_list, bit_position, bit = criteria_fields[ name] if isinstance(value, str): value = codecs.encode( ("{:%ds}" % int(struct_fmt[:-1])).format(value), encoding=cp1047_oe) if isinstance(position_list, tuple): for position in position_list: struct.pack_into(struct_fmt, ssob_and_stat, position, value) else: position = position_list struct.pack_into(struct_fmt, ssob_and_stat, position, value) ssob_and_stat[bit_position] |= bit struct.pack_into('QQQQQ', ssreq, 0, ssreq_fn, 0, bytearray_buffer_address(arglist), bytearray_buffer_address(save_area), SYSTEM_CALL__CALL31) zos_system_call(ssreq) self.ssi_return_code = struct.unpack_from('=4xI', self.ssreq, 0)[0] if self.ssi_return_code != 0: error_index = self.ssi_return_code / 4 - 1 error_messages = ( "The subsystem does not support this function.", "The subsystem exists, but is not active.", "The subsystem is not defined to MVS.", "Invalid SSOB, SSIB or function code", "The SSOB or SSIB have invalid lengths or formats", "The SSI has not been initialized.") raise Exception(error_messages[errior_index]) self.subsystem_return_code = struct.unpack_from( '=I', ssob_and_stat, 0x0C)[0] # SSOBRETN self.version, self.reason, self.reason2 = struct.unpack_from( '=BxBB', self.ssob_and_stat, 0x28) # STATVER, STATREAS, STATREA2 if self.ssi_return_code == 4: raise Exception("Invalid search arguments") elif self.ssi_return_code == 8: raise Exception("Logic error, reason=0x%X" % self.reason) elif self.ssi_return_code == 12: raise Exception("Unsupported call type") #print(dump_region(bytearray_buffer_address(ssob_and_stat), len(self.ssob_and_stat))) return None def job_elements(self): have_64bit_results = struct.unpack_from('B', self.ssob_and_stat, 0x108)[0] & 0x40 for self.jq64 in (True, False) if have_64bit_results else (False, ): self.jqe_address = struct.unpack_from( 'Q' if self.jq64 else 'I', self.ssob_and_stat, 0x118 if self.jq64 else 0x0F4)[0] if self.verbose: print("jq64=%r, jqe=%X" % (self.jq64, self.jqe_address)) while self.jqe_address: self.subsystem_name = codecs.decode((ctypes.c_char*4)\ .from_address(self.jqe_address + 0x10).value, cp1047_oe) job = {"subsystem": self.subsystem_name} job = self.parse_element_information(self.jqe_address, 'job_terse', job) self.job_verbose_address = (ctypes.c_ulong if self.jq64 else ctypes.c_uint)\ .from_address(self.jqe_address + (0x30 if self.jq64 else 0x14)).value if self.job_verbose_address: if self.verbose: print("job_verbose=%X" % (self.job_verbose_address, )) job = self.parse_element_information( self.job_verbose_address, 'job_verbose', job) yield job self.jqe_address = (ctypes.c_ulong if self.jq64 else ctypes.c_uint)\ .from_address(self.jqe_address + (0x20 if self.jq64 else 0x08)).value if self.verbose: print("jqe=%X" % (self.jqe_address, )) def job_dependency_elements(self): if ctypes.c_short.from_address(self.jqe_address + 0x4).value >= 0x48: self.dependency_address = ctypes.c_ulong.from_address( self.jqe_address + 0x40).value while self.dependency_address: yield self.parse_element_information(self.dependency_address, 'job_dependency') self.dependency_address = ctypes.c_ulong.from_address( self.dependency_address + 0x8).value def sysout_terse_elements(self): self.sysout_terse_address = (ctypes.c_ulong if self.jq64 else ctypes.c_uint)\ .from_address(self.jqe_address + (0x28 if self.jq64 else 0x0C)).value while self.sysout_terse_address: yield self.parse_element_information(self.sysout_terse_address, 'sysout_terse') self.sysout_terse_address = (ctypes.c_ulong if self.jq64 else ctypes.c_uint)\ .from_address(self.sysout_terse_address + (0x18 if self.jq64 else 0x08)).value def sysout_verbose_elements(self): self.sysout_verbose_address = (ctypes.c_ulong if self.jq64 else ctypes.c_uint)\ .from_address(self.sysout_terse_address + (0x28 if self.jq64 else 0x10)).value while self.sysout_verbose_address: yield self.parse_element_information(self.sysout_verbose_address, 'sysout_verbose') self.sysout_verbose_address = (ctypes.c_ulong if self.jq64 else ctypes.c_uint)\ .from_address(self.sysout_verbose_address + (0x30 if self.jq64 else 0x14)).value def parse_element_information(self, header_address, header_type, result=None): if not result: result = {} offset = ctypes.c_ushort.from_address(header_address + 0x4).value total_length = ctypes.c_ushort.from_address(header_address + offset + 0x0).value address = header_address + offset offset = 4 while offset < total_length: section_length = ctypes.c_ushort.from_address(address + offset + 0x0).value result = self.parse_information(address + offset, total_length - offset, result) offset += section_length return result def parse_information(self, address, remaining_length, result=None): if not result: result = {} type_and_modifier = ctypes.c_ushort.from_address(address + 0x2).value data_format = structure_info.get(type_and_modifier, ()) if data_format: address += 4 for name, ctype, offset, convert, size in data_format: if name and (not self.requested_fields or name in self.requested_fields): if self.verbose: print("%X %s %s" % (offset, name, dump_region(address + offset, size, show_header=False, show_address=False)), flush=True) if ctype: value = convert( ctype.from_address(address + offset).value) else: value = bytearray(size) ctypes.memmove(bytearray_buffer_address(value), address + offset, size) if value: result[name] = value return result