def display(self, msg, modifier=None): if not type(msg) is unicode: # force output unicode string to output # Python will hopefully handle output printing msg = obj2utf8(msg) if msg: if modifier == "error": self.stdout.write(PupyCmd.format_error(msg)) elif modifier == "success": self.stdout.write(PupyCmd.format_success(msg)) elif modifier == "info": self.stdout.write(PupyCmd.format_info(msg)) elif modifier == "srvinfo": buf_bkp = readline.get_line_buffer() #nG move cursor to column n #nE move cursor ro the beginning of n lines down #nK Erases part of the line. If n is zero (or missing), clear from cursor to the end of the line. If n is one, clear from cursor to beginning of the line. If n is two, clear entire line. Cursor position does not change. self.stdout.write("\x1b[0G" + PupyCmd.format_srvinfo(msg) + "\x1b[0E") self.stdout.write("\x1b[2K") #clear line self.stdout.write(self.raw_prompt + buf_bkp) #"\x1b[2K") try: readline.redisplay() except Exception: pass elif modifier == "warning": self.stdout.write(PupyCmd.format_warning(msg)) else: self.stdout.write(PupyCmd.format_log(msg))
def redisplay ( self ): if util.isPlatformWindows (): import pyreadline Readline ().redisplay () else: import readline readline.redisplay ()
def newEmitFn(*args, **kwargs): oldEmitFn(*args, **kwargs) global _previousReadlineBufferContents b = readline.get_line_buffer() if b != _previousReadlineBufferContents: readline.redisplay() _previousReadlineBufferContents = b
def pre_input_hook(): readline.insert_text(display.display( thing, shortid=False, colored=False)) readline.redisplay() # Unset the hook again readline.set_pre_input_hook(None)
def _input_hook(self): """Input hook for adding a string to the new line.""" if self.line: readline.insert_text(self.line) if not IS_WINDOWS: readline.redisplay() self.line = ''
def _run_printer(self): """A thread to print messages to the command line.""" while(True): # See if we have anything to print loop = True printed = False self.output_lock.acquire() while(loop): try: msg = self.print_queue.get_nowait() print msg printed = True except Queue.Empty: loop = False if printed: readline.redisplay() self.output_lock.release() # Reprint the prompt and the user's current input if necessary if printed: self.readline_lock.acquire() readline.redisplay() self.readline_lock.release() # See if we need to terminate if self.print_terminate.isSet(): return # Wait until we have something to print again self.print_event.wait() self.print_event.clear()
def tab_complete(self, text, state): try: is_double_tab = False current_text = readline.get_line_buffer() if self.last_tab and self.last_tab == current_text: is_double_tab = True self.last_tab = current_text # if no input do nothing if not current_text: return # get last input split_input = current_text.split()[-1] search_path = os.path.split(split_input)[0] search_text = os.path.split(split_input)[1] data = self.send_command({"cmd":"tab_complete","args":search_path if search_path else "."}) results = json.loads(data) matched_keys = [] if results: keys = results.keys() keys.sort() # append / if it is a directory for k in keys: # continue if no match if k.startswith(search_text): matched_keys.append(k) # edge cases if not matched_keys: # don't do anything if we have no matches return elif len(matched_keys) == 1: # if there is only 1 match and that match is a directory, append a '/' readline.insert_text(matched_keys[0][len(search_text):]) if matched_keys[0] in results: if results[matched_keys[0]] == 4 or results[matched_keys[0]] == 10: readline.insert_text("/") readline.redisplay() return elif not is_double_tab: # lcp of multiple matched find = h.find_longest_common_prefix(matched_keys) readline.insert_text(find[len(search_text):]) readline.redisplay() return print("") for k in matched_keys: if results[k] == 4: print(h.COLOR_INFO + k + h.ENDC) elif results[k] == 10: print(h.COLOR_INFO + k + h.ENDC) else: print(k) # back to where we are sys.stdout.write(self.get_handle() + current_text) except Exception as e: print("\n error - " + str(e))
def display_hook(prompt, session, context, matches, longest_match_len): # type: (str, ShellSession, BundleContext, List[str], int) -> None """ Displays the available services matches and the service details :param prompt: Shell prompt string :param session: Current shell session (for display) :param context: BundleContext of the shell :param matches: List of words matching the substitution :param longest_match_len: Length of the largest match """ # Prepare a line pattern for each match (-1 for the trailing space) match_pattern = "{{0: <{}}} from {{1}}".format(longest_match_len - 1) # Sort matching names matches = sorted(match for match in matches) # Print the match and the associated name session.write_line() with use_ipopo(context) as ipopo: for factory_name in matches: # Remove the spaces added for the completion factory_name = factory_name.strip() bnd = ipopo.get_factory_bundle(factory_name) session.write_line( match_pattern, factory_name, bnd.get_symbolic_name() ) # Print the prompt, then current line session.write(prompt) session.write_line_no_feed(readline.get_line_buffer()) readline.redisplay()
def display_hook(prompt, session, context, matches, longest_match_len): # type: (str, ShellSession, BundleContext, List[str], int) -> None """ Displays the available services matches and the service details :param prompt: Shell prompt string :param session: Current shell session (for display) :param context: BundleContext of the shell :param matches: List of words matching the substitution :param longest_match_len: Length of the largest match """ # Prepare a line pattern for each match (-1 for the trailing space) match_pattern = "{{0: <{}}} from {{1}}".format(longest_match_len - 1) # Sort matching names matches = sorted(match for match in matches) # Print the match and the associated name session.write_line() with use_ipopo(context) as ipopo: for factory_name in matches: # Remove the spaces added for the completion factory_name = factory_name.strip() bnd = ipopo.get_factory_bundle(factory_name) session.write_line(match_pattern, factory_name, bnd.get_symbolic_name()) # Print the prompt, then current line session.write(prompt) session.write_line_no_feed(readline.get_line_buffer()) readline.redisplay()
def log(*args, date=False, **kwargs): with logging_lock: print('\r \r' + (str(datetime.now()) if date else ''), end='') print(*args, **kwargs) sys.stdout.flush() readline.redisplay() sys.stderr.flush()
def display_hook(prompt, session, context, matches, longest_match_len): # type: (str, ShellSession, BundleContext, List[str], int) -> None """ Displays the available bundle matches and the bundle name :param prompt: Shell prompt string :param session: Current shell session (for display) :param context: BundleContext of the shell :param matches: List of words matching the substitution :param longest_match_len: Length of the largest match """ # Prepare a line pattern for each match match_pattern = "{{0: >{}}}: {{1}}".format(longest_match_len) # Sort matching IDs matches = sorted(int(match) for match in matches) # Print the match and the associated name session.write_line() for bnd_id in matches: bnd = context.get_bundle(bnd_id) session.write_line(match_pattern, bnd_id, bnd.get_symbolic_name()) # Print the prompt, then current line session.write(prompt) session.write_line_no_feed(readline.get_line_buffer()) readline.redisplay()
def display(self, msg, modifier=None): if not type(msg) is unicode: # force output unicode string to output # Python will hopefully handle output printing msg=obj2utf8(msg) if msg: if modifier=="error": self.stdout.write(PupyCmd.format_error(msg)) elif modifier=="success": self.stdout.write(PupyCmd.format_success(msg)) elif modifier=="info": self.stdout.write(PupyCmd.format_info(msg)) elif modifier=="srvinfo": buf_bkp=readline.get_line_buffer() #nG move cursor to column n #nE move cursor ro the beginning of n lines down #nK Erases part of the line. If n is zero (or missing), clear from cursor to the end of the line. If n is one, clear from cursor to beginning of the line. If n is two, clear entire line. Cursor position does not change. self.stdout.write("\x1b[0G"+PupyCmd.format_srvinfo(msg)+"\x1b[0E") self.stdout.write("\x1b[2K")#clear line self.stdout.write(self.raw_prompt+buf_bkp)#"\x1b[2K") try: readline.redisplay() except Exception: pass elif modifier=="warning": self.stdout.write(PupyCmd.format_warning(msg)) else: self.stdout.write(PupyCmd.format_log(msg))
def display_hook(prompt, session, context, matches, longest_match_len): # type: (str, ShellSession, BundleContext, List[str], int) -> None """ Displays the available services matches and the service details :param prompt: Shell prompt string :param session: Current shell session (for display) :param context: BundleContext of the shell :param matches: List of words matching the substitution :param longest_match_len: Length of the largest match """ try: # Prepare a line pattern for each match match_pattern = "{{0: >{}}}: {{1}}".format(longest_match_len) # Sort matching IDs matches = sorted(int(match) for match in matches) # Print the match and the associated name session.write_line() for svc_id in matches: svc_ref = context.get_service_reference( None, "({}={})".format(SERVICE_ID, svc_id)) session.write_line(match_pattern, svc_id, str(svc_ref)) # Print the prompt, then current line session.write(prompt) session.write_line_no_feed(readline.get_line_buffer()) readline.redisplay() except Exception as ex: session.write_line("\n{}\n\n", ex)
def redisplay(self): if util.isPlatformWindows(): import pyreadline Readline().redisplay() else: import readline readline.redisplay()
def recv(h): while True: msg = yield h.recv() if msg.frm and msg.body: # msg.frm.partition('/')[0] print '< %s'%(msg.body.cdata,) if readline: readline.redisplay()
def printf(self, string): #readline.set_startup_hook(lambda: readline.insert_text("{0}".format(str)) or readline.redisplay()) self.stdout.write(str("\n{0}\n".format(string))+"\n") self.stdout.flush() #readline.parse_and_bind('\C-M') readline.insert_text("oi\n") #readline.parse_and_bind('\\n') readline.redisplay()
def pre_input_hook(self): """If a line buffer has been filled then inject it into the readline buffer for the user to edit.""" if self.line_buffer: readline.insert_text( self.line_buffer.decode(ex_config.FILE_ENCODING).rstrip('\n')) readline.redisplay() self.line_buffer = None
def sighandler(signum, frame): '''Clean and tidy shutdown when killed.''' if po.opts.debug: ps_lib.msg('debug', 'Signal %s received.' % signum) #print 'removing:', readline.remove_history_item(readline.get_current_history_length()-1) # how to clear the line buffer? there doesn't seem to be a function to do it. print readline.redisplay() if signum == signal.SIGINT: sigintreceived = True
def draw(): raw_line = readline.get_line_buffer() line = highlight(raw_line, lexer, formatter)[:-1] with lock: with terminal.location(x = 3): print line, readline.redisplay()
def complete(self,text,state): if text.endswith(".__doc__"): new_text = text.replace(".__doc__","") help(eval(new_text)) readline.redisplay() readline.insert_text(new_text) else: value = Completer.complete(self,text,state) return value
def match_display_hook(substitution, matches, longest_match_length): ## Unused args are ok. pylint: disable=W0613 """ Cleaner display for line completion """ print '\n--- possible matches ---' for match in matches: print match #print self.prompt.rstrip(), print '------------------------' print readline.get_line_buffer(), readline.redisplay()
def color_print(message, printed_color="\033[37m"): """Formats a message with a specific color (as Display.color)""" line_buffer = readline.get_line_buffer() preface = len(line_buffer) * "\b \b" print( "{0}{1}{2}{3}\n{4}".format(preface, printed_color, message, Display.color.end, line_buffer), end="", flush=True, ) readline.redisplay()
def main(): global server global commandLine host = None port = None if len(sys.argv[1:]) == 1: host = socket.gethostname() port = sys.argv[1] if len(sys.argv[1:]) == 2: host = sys.argv[1] port = sys.argv[2] if host and port: print 'Starting Crossfire client on ' + host + ':' + port client = CrossfireClient(host, int(port)) commandLine = CommandLine() try: client.start() commandLine.start() print "Sending version command...\n" command = Command("", "version") client.sendPacket(command) print "Listing contexts...\n" command = Command("", "listcontexts") client.sendPacket(command) while True: packet = client.getPacket() if packet: print json.dump(packet, sys.stdout, sort_keys=True, indent=2) print "\n" + COMMAND_PROMPT, readline.redisplay() if 'event' in packet and packet['event'] == "closed": client.restart() command = commandLine.getCommand() if command: print "\nSending command => " + command.command client.sendPacket(command) except (KeyboardInterrupt): pass else: print 'No host and/or port specified.' print 'Usage: $> python crossfire_test_client.py [<host>] <port>' quit()
def readline_display_matches_hook(self, substitution, matches, longest_match_length): self.logger.debug('Readline display matches hook:\n substitution=%s, matches=%s longtest_match_length=%s' % \ (substitution, matches, longest_match_length)) print for match in matches: print match print "%s%s" % (self.prompt, readline.get_line_buffer()), readline.redisplay()
def complete(self, text, state): if not text: readline.insert_text(' ') if TabCompleter.uses_editline: # It won't move the cursor for us, apparently sys.stdout.write('\x1b[4C') readline.redisplay() sys.stdout.flush() return None else: return rlcompleter.Completer.complete(self, text, state)
def redraw_line(self, msg=''): buf = readline.get_line_buffer() self.stdout.write(''.join([ '\x1b[0G', msg + '\n', '\x1b[0E\x1b[2K', '' if msg.startswith(self.raw_prompt) else self.raw_prompt, buf ])) try: readline.redisplay() except Exception: pass
def poll(self): for fd, _ in self._poller.poll(self.timeout): if fd == self.conn_fd: data = self.sock.recv(1024 * 1024) sys.stdout.write(data.decode('utf8')) sys.stdout.flush() readline.redisplay() elif fd == self.read_fd: data = os.read(self.read_fd, 1024) self.sock.sendall(data) else: raise RuntimeError("Unknown FD %s" % fd)
def complete(self, text, state): readline.redisplay() if state == 0: if text: self.matches = [s for s in self.options if s and s.lower().startswith(text.lower())] else: self.matches = self.options[:] try: return self.matches[state] except IndexError: return None
def completer(text, state): try: options = _getPyCompletions(text) except Exception as e: print("\n%s" % e) sys.stdout.write("> %s" % text) sys.stdout.flush() readline.redisplay() return None if state < len(options): return options[state] else: return None
def rl_display_hook(self, substitution, matches, longest_match_length): """ A replacement of readline's display hook. Customizes the output of completion. :param substitution: :param matches: a list of completion matches. :param longest_match_length: """ self.stdout.write('\n') self.stdout.write(' '.join(matches) + '\n'), self.stdout.write(PROMPT + readline.get_line_buffer()), readline.redisplay()
def main(): global done done = False while not done: ttyio.echo("top of loop") t = Timer(5, hello) t.start() ttyio.inputstring("gfd main: ", timeout=0, noneok=True)# , timeouthandler=timeouthandler) ttyio.echo("foo") done = True readline.redisplay() ttyio.echo("bottom of loop") t.cancel()
def poll(self): milliseconds = self.timeout * 1000 for fd, _ in self._poller.poll(milliseconds): if fd == self.conn_fd: data = self.sock.recv(1024*1024) sys.stdout.write(data.decode('utf8')) sys.stdout.flush() readline.redisplay() elif fd == self.read_fd: data = os.read(self.read_fd, 1024) self.sock.sendall(data) else: raise RuntimeError("Unknown FD %s" % fd)
def post_complete(substitution, matches, longest_match_length): curr_line = readline.get_line_buffer() maxlen = 0 for item in matches: if len(item) + 1 > maxlen: maxlen = len(item) + 1 print("") for item in matches: if item != "" and item[0] != " ": item = " " + item + (" " * (maxlen - len(item) + 1 + 10)) + "help" print(item) sys.stdout.write(display_cmd_prompt() + curr_line) sys.stdout.flush() readline.redisplay()
def complete(self, text, state): readline.redisplay() if state == 0: if text: self.matches = [ s for s in self.options if s and s.lower().startswith(text.lower()) ] else: self.matches = self.options[:] try: return self.matches[state] except IndexError: return None
def display_srvinfo(self, msg): if isinstance(msg, Text): msg = hint_to_text(msg) else: msg = colorize('[*] ', 'blue') + msg buf = readline.get_line_buffer() self.stdout.write(''.join( ['\x1b[0G', msg + '\n', '\x1b[0E\x1b[2K', self.raw_prompt, buf])) try: readline.redisplay() except Exception: pass
def __exec_line__(self, line): r"""Execute the input line. emptyline: no-op unknown command: print error message known command: invoke the corresponding method The parser method, parse_line(), can be overriden in subclasses to apply different parsing rules. Please refer to the doc string of parse_line() for complete information. Arguments: line: A string, representing a line of input from the shell. This string is preprocessed by cmdloop() to convert the EOF character to '\x04', i.e., 'D' - 64, if the EOF character is the only character from the shell. """ # Ignoe empty lines and lines starting with a pound sign. if not line or line.rstrip().startswith('#'): return cmd, args = ( '', [] ) toks = shlex.split(line) if not toks: return if line == _ShellBase.EOF: # This is a hack to allow the EOF character to behave exactly like # typing the 'exit' command. readline.insert_text('exit\n') readline.redisplay() cmd = 'exit' elif toks and toks[0] in self._cmd_map_internal.keys(): cmd = toks[0] args = toks[1:] if len(toks) > 1 else [] else: cmd, args = self.parse_line(line) if not cmd in self._cmd_map_all.keys(): self.stderr.write("{}: command not found\n".format(cmd)) return func_name = self._cmd_map_all[cmd] func = getattr(self, func_name) return func(cmd, args)
def handler(signum, frame): cli = get_cli() if cli != None: if cli.executing_command() == True: return try: bcli_exit() except NameError: # If there is no a bcli_exit function # defined, end execution # The core lib include a bcli_exit at restrictedmodes.py sys.exit() get_cli().redisplay() readline.redisplay() else: sys.exit()
def complete(self, text: str, state: int) -> Optional[str]: if not text.strip(): if state == 0: readline.insert_text("\t") readline.redisplay() return "" else: return None if state == 0: if "." in text: self._matches = self._expr_matches(text) else: self._matches = self._global_matches(text) if 0 <= state < len(self._matches): return self._matches[state] else: return None
def print(self, text): current_input = readline.get_line_buffer() delete_chars = len(self.query) + len(current_input) # remove the input: sys.stdout.flush() for i in range(delete_chars): sys.stdout.write("\b \b") # end for sys.stdout.write("\033[K") sys.stdout.flush() # actual output sys.stdout.write(str(text)) sys.stdout.write("\n") sys.stdout.flush() # load back the input sys.stdout.write(self.query) sys.stdout.flush() sys.stdout.write(current_input) sys.stdout.flush() readline.redisplay()
def complete(text, state): words = readline.get_line_buffer().split(' ') cmd, args = words[0], words[1:] if len(args) == 0: if state != 0: return None if cmd == '': print '\n' + HELP_TEXT readline.redisplay() else: for possible in CMDS: if possible.startswith(cmd): return possible else: return None else: if cmd == 'state': possibilities = [st.name for st in STATES] elif cmd == 'value': if len(args) == 1: possibilities = cur_state.devices['master'].values else: return None elif cmd == 'event': possibilities = cur_state.devices['master'].events elif cmd == 'test': possibilities = [t.name for t in TESTS] else: return None remaining = [ thing for thing in possibilities if thing.startswith(args[0]) ] if state < len(remaining): return remaining[state] else: return None
def run(): """Once entered, this function won't necessarily return within foreseeable future. It is where the main loop of `kathaireo's` shell runs. In every repetition, an input line is retrieved from the :mod:`.prompt` module, and passed over to the :func:`~.commands.execute` function of module :mod:`.commands`, whose returning status message or command response is again given to the :mod:`.prompt` module for printing. """ rdf.set_graph(None) #commands.init() TODO: read, compile and register std cmds prompt.display('*ok*.\n') # init readline module readline.set_completer_delims(' \t\n;') readline.parse_and_bind("tab: complete") readline.set_completer(complete) #TODO: naja... # go! line='' while True: line = prompt.input() readline.redisplay() output = commands.execute(line) prompt.display(output)
def run(): """Once entered, this function won't necessarily return within foreseeable future. It is where the main loop of `kathaireo's` shell runs. In every repetition, an input line is retrieved from the :mod:`.prompt` module, and passed over to the :func:`~.commands.execute` function of module :mod:`.commands`, whose returning status message or command response is again given to the :mod:`.prompt` module for printing. """ rdf.set_graph(None) #commands.init() TODO: read, compile and register std cmds prompt.display('*ok*.\n') # init readline module readline.set_completer_delims(' \t\n;') readline.parse_and_bind("tab: complete") readline.set_completer(complete) #TODO: naja... # go! line = '' while True: line = prompt.input() readline.redisplay() output = commands.execute(line) prompt.display(output)
def rawInput(promptText="", inputText=""): """Создает поле ввода promptText - текст перед полем ввода inputText - текст в поле ввода """ # Вывод в строку ввода import readline if inputText: # Записываем текст для последующего вывода в строке ввода readline.set_pre_input_hook(lambda:\ readline.insert_text(inputText) or\ readline.redisplay()) strInput = "" if promptText: # Получаем текст введенный пользователем strInput = raw_input(promptText) else: strInput = raw_input() if inputText: # Сбрасываем строку ввода readline.set_pre_input_hook(None) return strInput
def hook(): readline.insert_text(text) readline.redisplay()
def pre_input_hook(): readline.insert_text(self._dump_line(task)) readline.redisplay() # Unset the hook again readline.set_pre_input_hook(None)
def displayer(self, substitution, matches, longest_match_length): # try: max_line_width = self.shell_size()[1] # max(itertools.imap(lambda x: len(x), matches)) + 2 #two blank spaces column_width = longest_match_length + 2 num_per_line = max_line_width / column_width # need this as if partial auto-complete happens then get duplicate text # this is bcoz readline.get_line_buffer() already contains the partial # completed text user_input = readline.get_line_buffer()[:readline.get_endidx()] class_label, class_name, method_name, arg_num = current_class_method_and_arg( user_input, self.ns) if num_per_line == 0 or user_input.strip().endswith( '(') or user_input.strip().endswith(','): num_per_line = 1 # constructor if class_name is not None and method_name is None and user_input.strip( ).endswith(','): # if user_input.strip().endswith('(') or # user_input.strip().endswith(','): tmp = arg_splitter(user_input + ')', strip_args=False) new = tmp[:] # map(lambda x: x.strip(), tmp) wrong = False unrecognised = [] for i, arg in enumerate( itertools.ifilter(lambda x: x != '', itertools.imap(lambda x: x.strip(), new))): if '=' in arg: split_arg = arg.split('=') if split_arg[0].strip() not in eval( 'dict(%s._impl._schema.allItems())' % class_name, self.ns): unrecognised.append((split_arg[0].strip(), class_name)) # include = to avoid replacing letters e.g. a in the # RHS also to keep the users spaces intact new[i] = new[i].replace( split_arg[0] + '=', getColour('fg.red') + split_arg[0] + getColour('fg.normal') + '=') elif not eval('isinstance(%s, %s)' % (arg, class_name), self.ns): new[i] = new[i].replace( arg, getColour('fg.red') + arg + getColour('fg.normal')) wrong = True user_input = user_input.replace(','.join(tmp), ','.join(new)) if wrong: logger.warning( 'Only one positional arg allowed which must be an object of the same type to copy from' ) #user_input = user_input.replace(','.join(tmp), ','.join(new)) if unrecognised: for a, c in unrecognised: logger.warning( "Unrecognised keyword argument, '%s' is not a modifyable attribute of '%s'" % (a, c)) colour_green = getColour('fg.green') colour_red = getColour('fg.red') #colour_blue = getColour('fg.blue') colour_normal = getColour('fg.normal') display_str = '\n' for i, m in enumerate(itertools.ifilter(lambda x: x != '', matches)): coloured_text = self.colouriser(m, user_input) width = column_width if colour_green in coloured_text: width = column_width + len(colour_green) + len(colour_normal) elif colour_red in coloured_text: width = column_width + len(colour_red) + len(colour_normal) display_str += ('{0:<%d}' % width).format(coloured_text) if num_per_line and (i + 1) % num_per_line == 0: display_str += '\n' if num_per_line and (i + 1) % num_per_line == 0: display_str += '\n' else: display_str += '\n\n' display_str += getColour('fg.blue') display_str += 'In [%s]:' % len(self.ns['In']) display_str += getColour('fg.normal') display_str += user_input print(display_str, end='') readline.redisplay()
return RichImage(thresholded_img) def default_threshold(self): return self.set_to(10,0) #set any pixel <= 10 to black (0) if __name__ == "__main__": import sys from platform import system import os # make sure we're not dealing with windows... if system() != 'Windows': try: print "using readline tools..." import readline readline.set_pre_input_hook(readline.redisplay()) except: pass class Displayer(object): def __init__(self, img): self.direction = "h" self.exit_cmds = ["q", "exit"] self.help_cmds = ["?", "help"] self.save_cmds = ["s", "save"] self.horizontal_cmds = ["horizontal"] self.vertical_cmds = ["v", "vertical"]
libc = CDLL(find_library("c"))libpam = CDLL(find_library("pam")) calloc = libc.calloccalloc.restype = c_void_pcalloc.argtypes = [c_size_t, c_size_t] pam_end = libpam.pam_endpam_end.restype = c_intpam_end.argtypes = [PamHandle, c_int] pam_start = libpam.pam_startpam_start.restype = c_intpam_start.argtypes = [c_char_p, c_char_p, POINTER(PamConv), POINTER(PamHandle)] pam_setcred = libpam.pam_setcredpam_setcred.restype = c_intpam_setcred.argtypes = [PamHandle, c_int] pam_strerror = libpam.pam_strerrorpam_strerror.restype = c_char_ppam_strerror.argtypes = [PamHandle, c_int] pam_authenticate = libpam.pam_authenticatepam_authenticate.restype = c_intpam_authenticate.argtypes = [PamHandle, c_int] class pam(): code = 0 reason = None def __init__(self): pass def authenticate(self, username, password, service='login', encoding='utf-8', resetcreds=True): """username and password authentication for the given service. Returns True for success, or False for failure. self.code (integer) and self.reason (string) are always stored and may be referenced for the reason why authentication failed. 0/'Success' will be stored for success. Python3 expects bytes() for ctypes inputs. This function will make necessary conversions using the supplied encoding. Inputs: username: username to authenticate password: password in plain text service: PAM service to authenticate against, defaults to 'login' Returns: success: True failure: False """ @conv_func def my_conv(n_messages, messages, p_response, app_data): """Simple conversation function that responds to any prompt where the echo is off with the supplied password""" # Create an array of n_messages response objects addr = calloc(n_messages, sizeof(PamResponse)) response = cast(addr, POINTER(PamResponse)) p_response[0] = response for i in range(n_messages): if messages[i].contents.msg_style == PAM_PROMPT_ECHO_OFF: dst = calloc(len(password)+1, sizeof(c_char)) memmove(dst, cpassword, len(password)) response[i].resp = dst response[i].resp_retcode = 0 return 0 # python3 ctypes prefers bytes if sys.version_info >= (3,): if isinstance(username, str): username = username.encode(encoding) if isinstance(password, str): password = password.encode(encoding) if isinstance(service, str): service = service.encode(encoding) else: if isinstance(username, unicode): username = username.encode(encoding) if isinstance(password, unicode): password = password.encode(encoding) if isinstance(service, unicode): service = service.encode(encoding) if b'\x00' in username or b'\x00' in password or b'\x00' in service: self.code = 4 # PAM_SYSTEM_ERR in Linux-PAM self.reason = 'strings may not contain NUL' return False # do this up front so we can safely throw an exception if there's # anything wrong with it cpassword = c_char_p(password) handle = PamHandle() conv = PamConv(my_conv, 0) retval = pam_start(service, username, byref(conv), byref(handle)) if retval != 0: # This is not an authentication error, something has gone wrong starting up PAM self.code = retval self.reason = "pam_start() failed" return False retval = pam_authenticate(handle, 0) auth_success = retval == 0 if auth_success and resetcreds: retval = pam_setcred(handle, PAM_REINITIALIZE_CRED); # store information to inform the caller why we failed self.code = retval self.reason = pam_strerror(handle, retval) if sys.version_info >= (3,): self.reason = self.reason.decode(encoding) pam_end(handle, retval) return auth_success def authenticate(*vargs, **dargs): """ Compatibility function for older versions of python-pam. """ return pam().authenticate(*vargs, **dargs) if __name__ == "__main__": import readline, getpass def input_with_prefill(prompt, text): def hook(): readline.insert_text(text) readline.redisplay() readline.set_pre_input_hook(hook) if sys.version_info >= (3,): result = input(prompt) else: result = raw_input(prompt) readline.set_pre_input_hook() return result pam = pam() username = input_with_prefill('Username: '******'{} {}'.format(pam.code, pam.reason))
def pre_input_hook(): readline.insert_text(default) readline.redisplay()
def pre_input_hook(self): if self.lastcommandhelp: readline.insert_text(self.lastline) readline.redisplay() self.lastcommandhelp = False
def inserter(): readline.insert_text(s) readline.redisplay()
def pre_input_hook(): readline.insert_text(line.encode(ENCODING)) readline.redisplay() # Unset the hook again readline.set_pre_input_hook(None)
def hook(): readline.insert_text(prefill) readline.redisplay()