Created
April 25, 2017 15:27
-
-
Save timofurrer/311183a7674f70240584b4521ad33e08 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # -*- coding: utf-8 -*- | |
| """ | |
| Parse compiled terminfo DB files | |
| python terminfo.py /usr/share/terminfo adm3a | |
| """ | |
| import os | |
| import sys | |
| import struct | |
| BASEPATHS = [ | |
| os.environ.get('USER'), | |
| '/etc/terminfo', | |
| '/lib/terminfo', | |
| '/usr/share/terminfo' | |
| ] | |
| BOOLEAN_NAMES = [ | |
| 'auto_left_margin', | |
| 'auto_right_margin', | |
| 'no_esc_ctlc', | |
| 'ceol_standout_glitch', | |
| 'eat_newline_glitch', | |
| 'erase_overstrike', | |
| 'generic_type', | |
| 'hard_copy', | |
| 'has_meta_key', | |
| 'has_status_line', | |
| 'insert_null_glitch', | |
| 'memory_above', | |
| 'memory_below', | |
| 'move_insert_mode', | |
| 'move_standout_mode', | |
| 'over_strike', | |
| 'status_line_esc_ok', | |
| 'dest_tabs_magic_smso', | |
| 'tilde_glitch', | |
| 'transparent_underline', | |
| 'xon_xoff', | |
| 'needs_xon_xoff', | |
| 'prtr_silent', | |
| 'hard_cursor', | |
| 'non_rev_rmcup', | |
| 'no_pad_char', | |
| 'non_dest_scroll_region', | |
| 'can_change', | |
| 'back_color_erase', | |
| 'hue_lightness_saturation', | |
| 'col_addr_glitch', | |
| 'cr_cancels_micro_mode', | |
| 'has_print_wheel', | |
| 'row_addr_glitch', | |
| 'semi_auto_right_margin', | |
| 'cpi_changes_res', | |
| 'lpi_changes_res' | |
| ] | |
| NUMBER_NAMES = [ | |
| 'columns', | |
| 'init_tabs', | |
| 'lines', | |
| 'lines_of_memory', | |
| 'magic_cookie_glitch', | |
| 'padding_baud_rate', | |
| 'virtual_terminal', | |
| 'width_status_line', | |
| 'num_labels', | |
| 'label_height', | |
| 'label_width', | |
| 'max_attributes', | |
| 'maximum_windows', | |
| 'max_colors', | |
| 'max_pairs', | |
| 'no_color_video', | |
| 'buffer_capacity', | |
| 'dot_vert_spacing', | |
| 'dot_horz_spacing', | |
| 'max_micro_address', | |
| 'max_micro_jump', | |
| 'micro_col_size', | |
| 'micro_line_size', | |
| 'number_of_pins', | |
| 'output_res_char', | |
| 'output_res_line', | |
| 'output_res_horz_inch', | |
| 'output_res_vert_inch', | |
| 'print_rate', | |
| 'wide_char_size', | |
| 'buttons', | |
| 'bit_image_entwining', | |
| 'bit_image_type' | |
| ] | |
| STRING_NAMES = [ | |
| 'back_tab', | |
| 'bell', | |
| 'carriage_return', | |
| 'change_scroll_region', | |
| 'clear_all_tabs', | |
| 'clear_screen', | |
| 'clr_eol', | |
| 'clr_eos', | |
| 'column_address', | |
| 'command_character', | |
| 'cursor_address', | |
| 'cursor_down', | |
| 'cursor_home', | |
| 'cursor_invisible', | |
| 'cursor_left', | |
| 'cursor_mem_address', | |
| 'cursor_normal', | |
| 'cursor_right', | |
| 'cursor_to_ll', | |
| 'cursor_up', | |
| 'cursor_visible', | |
| 'delete_character', | |
| 'delete_line', | |
| 'dis_status_line', | |
| 'down_half_line', | |
| 'enter_alt_charset_mode', | |
| 'enter_blink_mode', | |
| 'enter_bold_mode', | |
| 'enter_ca_mode', | |
| 'enter_delete_mode', | |
| 'enter_dim_mode', | |
| 'enter_insert_mode', | |
| 'enter_secure_mode', | |
| 'enter_protected_mode', | |
| 'enter_reverse_mode', | |
| 'enter_standout_mode', | |
| 'enter_underline_mode', | |
| 'erase_chars', | |
| 'exit_alt_charset_mode', | |
| 'exit_attribute_mode', | |
| 'exit_ca_mode', | |
| 'exit_delete_mode', | |
| 'exit_insert_mode', | |
| 'exit_standout_mode', | |
| 'exit_underline_mode', | |
| 'flash_screen', | |
| 'form_feed', | |
| 'from_status_line', | |
| 'init_1string', | |
| 'init_2string', | |
| 'init_3string', | |
| 'init_file', | |
| 'insert_character', | |
| 'insert_line', | |
| 'insert_padding', | |
| 'key_backspace', | |
| 'key_catab', | |
| 'key_clear', | |
| 'key_ctab', | |
| 'key_dc', | |
| 'key_dl', | |
| 'key_down', | |
| 'key_eic', | |
| 'key_eol', | |
| 'key_eos', | |
| 'key_f0', | |
| 'key_f1', | |
| 'key_f10', | |
| 'key_f2', | |
| 'key_f3', | |
| 'key_f4', | |
| 'key_f5', | |
| 'key_f6', | |
| 'key_f7', | |
| 'key_f8', | |
| 'key_f9', | |
| 'key_home', | |
| 'key_ic', | |
| 'key_il', | |
| 'key_left', | |
| 'key_ll', | |
| 'key_npage', | |
| 'key_ppage', | |
| 'key_right', | |
| 'key_sf', | |
| 'key_sr', | |
| 'key_stab', | |
| 'key_up', | |
| 'keypad_local', | |
| 'keypad_xmit', | |
| 'lab_f0', | |
| 'lab_f1', | |
| 'lab_f10', | |
| 'lab_f2', | |
| 'lab_f3', | |
| 'lab_f4', | |
| 'lab_f5', | |
| 'lab_f6', | |
| 'lab_f7', | |
| 'lab_f8', | |
| 'lab_f9', | |
| 'meta_off', | |
| 'meta_on', | |
| 'newline', | |
| 'pad_char', | |
| 'parm_dch', | |
| 'parm_delete_line', | |
| 'parm_down_cursor', | |
| 'parm_ich', | |
| 'parm_index', | |
| 'parm_insert_line', | |
| 'parm_left_cursor', | |
| 'parm_right_cursor', | |
| 'parm_rindex', | |
| 'parm_up_cursor', | |
| 'pkey_key', | |
| 'pkey_local', | |
| 'pkey_xmit', | |
| 'print_screen', | |
| 'prtr_off', | |
| 'prtr_on', | |
| 'repeat_char', | |
| 'reset_1string', | |
| 'reset_2string', | |
| 'reset_3string', | |
| 'reset_file', | |
| 'restore_cursor', | |
| 'row_address', | |
| 'save_cursor', | |
| 'scroll_forward', | |
| 'scroll_reverse', | |
| 'set_attributes', | |
| 'set_tab', | |
| 'set_window', | |
| 'tab', | |
| 'to_status_line', | |
| 'underline_char', | |
| 'up_half_line', | |
| 'init_prog', | |
| 'key_a1', | |
| 'key_a3', | |
| 'key_b2', | |
| 'key_c1', | |
| 'key_c3', | |
| 'prtr_non', | |
| 'char_padding', | |
| 'acs_chars', | |
| 'plab_norm', | |
| 'key_btab', | |
| 'enter_xon_mode', | |
| 'exit_xon_mode', | |
| 'enter_am_mode', | |
| 'exit_am_mode', | |
| 'xon_character', | |
| 'xoff_character', | |
| 'ena_acs', | |
| 'label_on', | |
| 'label_off', | |
| 'key_beg', | |
| 'key_cancel', | |
| 'key_close', | |
| 'key_command', | |
| 'key_copy', | |
| 'key_create', | |
| 'key_end', | |
| 'key_enter', | |
| 'key_exit', | |
| 'key_find', | |
| 'key_help', | |
| 'key_mark', | |
| 'key_message', | |
| 'key_move', | |
| 'key_next', | |
| 'key_open', | |
| 'key_options', | |
| 'key_previous', | |
| 'key_print', | |
| 'key_redo', | |
| 'key_reference', | |
| 'key_refresh', | |
| 'key_replace', | |
| 'key_restart', | |
| 'key_resume', | |
| 'key_save', | |
| 'key_suspend', | |
| 'key_undo', | |
| 'key_sbeg', | |
| 'key_scancel', | |
| 'key_scommand', | |
| 'key_scopy', | |
| 'key_screate', | |
| 'key_sdc', | |
| 'key_sdl', | |
| 'key_select', | |
| 'key_send', | |
| 'key_seol', | |
| 'key_sexit', | |
| 'key_sfind', | |
| 'key_shelp', | |
| 'key_shome', | |
| 'key_sic', | |
| 'key_sleft', | |
| 'key_smessage', | |
| 'key_smove', | |
| 'key_snext', | |
| 'key_soptions', | |
| 'key_sprevious', | |
| 'key_sprint', | |
| 'key_sredo', | |
| 'key_sreplace', | |
| 'key_sright', | |
| 'key_srsume', | |
| 'key_ssave', | |
| 'key_ssuspend', | |
| 'key_sundo', | |
| 'req_for_input', | |
| 'key_f11', | |
| 'key_f12', | |
| 'key_f13', | |
| 'key_f14', | |
| 'key_f15', | |
| 'key_f16', | |
| 'key_f17', | |
| 'key_f18', | |
| 'key_f19', | |
| 'key_f20', | |
| 'key_f21', | |
| 'key_f22', | |
| 'key_f23', | |
| 'key_f24', | |
| 'key_f25', | |
| 'key_f26', | |
| 'key_f27', | |
| 'key_f28', | |
| 'key_f29', | |
| 'key_f30', | |
| 'key_f31', | |
| 'key_f32', | |
| 'key_f33', | |
| 'key_f34', | |
| 'key_f35', | |
| 'key_f36', | |
| 'key_f37', | |
| 'key_f38', | |
| 'key_f39', | |
| 'key_f40', | |
| 'key_f41', | |
| 'key_f42', | |
| 'key_f43', | |
| 'key_f44', | |
| 'key_f45', | |
| 'key_f46', | |
| 'key_f47', | |
| 'key_f48', | |
| 'key_f49', | |
| 'key_f50', | |
| 'key_f51', | |
| 'key_f52', | |
| 'key_f53', | |
| 'key_f54', | |
| 'key_f55', | |
| 'key_f56', | |
| 'key_f57', | |
| 'key_f58', | |
| 'key_f59', | |
| 'key_f60', | |
| 'key_f61', | |
| 'key_f62', | |
| 'key_f63', | |
| 'clr_bol', | |
| 'clear_margins', | |
| 'set_left_margin', | |
| 'set_right_margin', | |
| 'label_format', | |
| 'set_clock', | |
| 'display_clock', | |
| 'remove_clock', | |
| 'create_window', | |
| 'goto_window', | |
| 'hangup', | |
| 'dial_phone', | |
| 'quick_dial', | |
| 'tone', | |
| 'pulse', | |
| 'flash_hook', | |
| 'fixed_pause', | |
| 'wait_tone', | |
| 'user0', | |
| 'user1', | |
| 'user2', | |
| 'user3', | |
| 'user4', | |
| 'user5', | |
| 'user6', | |
| 'user7', | |
| 'user8', | |
| 'user9', | |
| 'orig_pair', | |
| 'orig_colors', | |
| 'initialize_color', | |
| 'initialize_pair', | |
| 'set_color_pair', | |
| 'set_foreground', | |
| 'set_background', | |
| 'change_char_pitch', | |
| 'change_line_pitch', | |
| 'change_res_horz', | |
| 'change_res_vert', | |
| 'define_char', | |
| 'enter_doublewide_mode', | |
| 'enter_draft_quality', | |
| 'enter_italics_mode', | |
| 'enter_leftward_mode', | |
| 'enter_micro_mode', | |
| 'enter_near_letter_quality', | |
| 'enter_normal_quality', | |
| 'enter_shadow_mode', | |
| 'enter_subscript_mode', | |
| 'enter_superscript_mode', | |
| 'enter_upward_mode', | |
| 'exit_doublewide_mode', | |
| 'exit_italics_mode', | |
| 'exit_leftward_mode', | |
| 'exit_micro_mode', | |
| 'exit_shadow_mode', | |
| 'exit_subscript_mode', | |
| 'exit_superscript_mode', | |
| 'exit_upward_mode', | |
| 'micro_column_address', | |
| 'micro_down', | |
| 'micro_left', | |
| 'micro_right', | |
| 'micro_row_address', | |
| 'micro_up', | |
| 'order_of_pins', | |
| 'parm_down_micro', | |
| 'parm_left_micro', | |
| 'parm_right_micro', | |
| 'parm_up_micro', | |
| 'select_char_set', | |
| 'set_bottom_margin', | |
| 'set_bottom_margin_parm', | |
| 'set_left_margin_parm', | |
| 'set_right_margin_parm', | |
| 'set_top_margin', | |
| 'set_top_margin_parm', | |
| 'start_bit_image', | |
| 'start_char_set_def', | |
| 'stop_bit_image', | |
| 'stop_char_set_def', | |
| 'subscript_characters', | |
| 'superscript_characters', | |
| 'these_cause_cr', | |
| 'zero_motion', | |
| 'char_set_names', | |
| 'key_mouse', | |
| 'mouse_info', | |
| 'req_mouse_pos', | |
| 'get_mouse', | |
| 'set_a_foreground', | |
| 'set_a_background', | |
| 'pkey_plab', | |
| 'device_type', | |
| 'code_set_init', | |
| 'set0_des_seq', | |
| 'set1_des_seq', | |
| 'set2_des_seq', | |
| 'set3_des_seq', | |
| 'set_lr_margin', | |
| 'set_tb_margin', | |
| 'bit_image_repeat', | |
| 'bit_image_newline', | |
| 'bit_image_carriage_return', | |
| 'color_names', | |
| 'define_bit_image_region', | |
| 'end_bit_image_region', | |
| 'set_color_band', | |
| 'set_page_length', | |
| 'display_pc_char', | |
| 'enter_pc_charset_mode', | |
| 'exit_pc_charset_mode', | |
| 'enter_scancode_mode', | |
| 'exit_scancode_mode', | |
| 'pc_term_options', | |
| 'scancode_escape', | |
| 'alt_scancode_esc', | |
| 'enter_horizontal_hl_mode', | |
| 'enter_left_hl_mode', | |
| 'enter_low_hl_mode', | |
| 'enter_right_hl_mode', | |
| 'enter_top_hl_mode', | |
| 'enter_vertical_hl_mode', | |
| 'set_a_attributes', | |
| 'set_pglen_inch' | |
| ] | |
| class Term(object): | |
| SEARCH_PATHS = [ | |
| os.environ.get('USER'), | |
| '/etc/terminfo', | |
| '/lib/terminfo', | |
| '/usr/share/terminfo' | |
| ] | |
| def __init__(self, name): | |
| self.name = name | |
| self.raw_db = None | |
| self.db = None | |
| def load(self): | |
| self.load_db() | |
| self.db = self.parse_db() | |
| def load_db(self): | |
| """ | |
| Get the path to the DB file on the | |
| system by concatinating the basepath | |
| and the terminal name appropriately. | |
| """ | |
| for basepath in (x for x in Term.SEARCH_PATHS if x is not None): | |
| path = os.path.join(basepath, self.name[0], self.name) | |
| try: | |
| with open(path, 'rb') as dbfile: | |
| self.raw_db = dbfile.read() | |
| return | |
| except FileNotFoundError: | |
| pass | |
| raise FileNotFoundError('terminfo file for "{0}" not found'.format( | |
| self.name)) | |
| def parse_db(self): | |
| """ | |
| Parse the given terminfo DB content | |
| """ | |
| offset = 0 | |
| magic_number, names_section_size, bool_sec_size, number_sec_size, string_sec_size, string_table_size = struct.unpack_from('HHHHHH', self.raw_db, offset) | |
| print('magic number:', oct(magic_number)) | |
| print('names_section_size,:', names_section_size) | |
| print('bool_sec_size:', bool_sec_size) | |
| print('number_sec_size,:', number_sec_size) | |
| print('string_sec_size,:', string_sec_size) | |
| print('string_table_size:', string_table_size) | |
| offset = struct.calcsize('H') * 6 | |
| # read termial names | |
| names = struct.unpack_from('{0}s'.format(names_section_size), self.raw_db, offset)[0] | |
| print('terminal names:', names) | |
| offset += names_section_size | |
| # read boolean flags | |
| bool_flags = struct.unpack_from('B' * bool_sec_size, self.raw_db, offset) | |
| print('boolean flags:', bool_flags) | |
| offset += bool_sec_size | |
| # add byte if offset is odd | |
| offset += (12 + names_section_size + bool_sec_size) % 2 | |
| # parse numbers | |
| numbers = struct.unpack_from('<' + 'h' * number_sec_size, self.raw_db, offset) | |
| print('numbers:', numbers) | |
| offset += struct.calcsize('<h') * number_sec_size | |
| # parse string table offsets | |
| string_offsets = struct.unpack_from('h' * string_sec_size, self.raw_db, offset) | |
| print('string offsets:', string_offsets) | |
| offset += struct.calcsize('h') * string_sec_size | |
| # parse string table | |
| # raw_strings = self.raw_db[offset:] | |
| strings = self.raw_db[offset:] | |
| # strings = raw_strings.split(b'\0') | |
| # print('string table:', strings) | |
| return { | |
| 'terminal_names': names, | |
| 'booleans': bool_flags, | |
| 'numbers': numbers, | |
| 'string_offsets': string_offsets, | |
| 'strings': strings | |
| } | |
| def __getattr__(self, name): | |
| section = None | |
| if name in BOOLEAN_NAMES: | |
| section = 'booleans' | |
| index = BOOLEAN_NAMES.index(name) | |
| elif name in NUMBER_NAMES: | |
| section = 'numbers' | |
| index = NUMBER_NAMES.index(name) | |
| elif name in STRING_NAMES: | |
| section = 'strings' | |
| index_string_offset = STRING_NAMES.index(name) | |
| index = self.db['string_offsets'][index_string_offset] | |
| cap = self.db[section][index:].partition(b'\0')[0] | |
| return cap | |
| else: | |
| raise AttributeError('No capability "{0}" in term "{1}"'.format( | |
| name, self.name)) | |
| return self.db[section][index] | |
| if __name__ == '__main__': | |
| term = Term(sys.argv[1]) | |
| term.load() | |
| print(term.max_colors) | |
| print(term.set_a_background) | |
| print(term.set_a_foreground) | |
| print(term.cursor_up) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment