def remquote(*nums): """ Remove one or more quotes from the quotes list. Args: *nums: the id of the quote to be deleted. If 'preserve-deled-qs' is set to true in the quotes config, quotes will be set to non-displayable, instead of deleted. """ pres = config.configs["quotes"]["preserve-deled-qs"] nums = [int(num) for num in nums] for num in nums: # If the specified number isn't in the quotes list, *or* (it is but set # to nondisplay *and* config is set to preserve deleted). In this way, # preserved quotes will only be permanently deleted if preserve has # since been set to false. quote_cant_display = (num not in quotes or (pres and not quotes[num].get("display", True))) if quote_cant_display: raise CommandException( f"There isn't any quote #{num} on the list.", ) for num in nums: if pres: quotes[num]["display"] = False else: del quotes[num] write_quotes() quote_numbers = ", ".join(f"#{num}" for num in nums) return f"Quote{'s' if len(nums) > 1 else ''} deleted: {quote_numbers}"
def screen_return_codes(msg_on_hit, return_code_target, o, e, rc, command): """Provides a central mechanism to screen return codes from executing smart commands. This is required as some non zero return codes would otherwise trigger a generic exception clause in our general purpose run_command. If the target return code is seen then email root with the message provided, otherwise raise a generic exception with the command information. N.B. May be done better by acting as a SMART run_command wrapper (Future). :param msg_on_hit: message used to email root :param return_code_target: return code to screen for :param o: the output from the command when it was run :param e: the error from the command when it was run :param rc: the return code from running the command :param command: the command that produced the previous o, e, and rc params. """ # if our return code is our target then log with our message and email root # with the same. if rc == return_code_target: logger.error(msg_on_hit) email_root('S.M.A.R.T error', msg_on_hit) # In all other non zero (error) instances we raise an exception as normal. elif rc != 0: e_msg = ('non-zero code(%d) returned by command: %s output: ' '%s error: %s' % (rc, command, o, e)) logger.error(e_msg) raise CommandException(('%s' % command), o, e, rc)
def usermod(username, passwd): cmd = [PASSWD, '--stdin', username] p = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) out, err = p.communicate(input=passwd) rc = p.returncode if (rc != 0): raise CommandException(out, err, rc) return (out, err, rc)
def smbpasswd(username, passwd): cmd = [SMBPASSWD, '-s', '-a', username] p = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) pstr = ('%s\n%s\n' % (passwd, passwd)) out, err = p.communicate(input=pstr) rc = p.returncode if (rc != 0): raise CommandException(out, err, rc) return (out, err, rc)
def run_command(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, throw=True): p = subprocess.Popen(cmd, shell=shell, stdout=stdout, stderr=stderr) out, err = p.communicate() out = out.split('\n') err = err.split('\n') rc = p.returncode if (throw and rc != 0): raise CommandException(out, err, rc) return (out, err, rc)
def join_winbind_domain(username, passwd): up = '%s%%%s' % (username, passwd) cmd = [NET, 'ads', 'join', '-U', up, '--request-timeout', '30'] out, err, rc = run_command( cmd, throw=False, ) if (rc != 0): error = ('Below error can occur due to DNS issue. Ensure ' 'that /etc/resolv.conf on Rockstor is pointing to ' 'the right nameserver -- stdout: %s stderr: %s' % (' '.join(out), ' '.join(err))) raise CommandException(out, error, rc) return (out, err, rc)
def getCodeFileNameIfExists(self): global CPP_EXTENSION fileName = None for t in self.parameters: for ext in CPP_EXTENSION: if t.endswith(ext): fileName = t if not fileName: message = 'Could not find source file in command' logMessage(message) raise CommandException(message) return fileName
def smbpasswd(username, passwd): cmd = [SMBPASSWD, "-s", "-a", username] p = subprocess.Popen( cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, ) pstr = "%s\n%s\n" % (passwd, passwd) out, err = p.communicate(input=pstr.encode("utf8")) rc = p.returncode if rc != 0: raise CommandException(cmd, out, err, rc) return (out, err, rc)
def regex(msg, *args): """ Force-trigger a regex for the provided message. """ msg = copy(msg) msg.text_content = " ".join(args) msg.sender_group = "default" resp = regex_msg_handler(msg) if not resp: raise CommandException("No regex found.") return resp
def validate_command_args(cmd, args, alias=None): """ Validate the syntax of a set of arguments for the given command callable. Args: cmd: the callable command to validate arguments for. args: the arguments to validate. alias: the alias that the command was called with. Optional. """ cmd_name = alias or cmd.meta["name"] if not cmd.meta["args_val"](*args): prefix = config.configs["commands"]["command-prefix"] usage = cmd.meta["args_usage"] raise CommandException( f"Invalid args. Usage: {prefix}{cmd_name} {usage}", )
def run_command(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, throw=True, log=False): p = subprocess.Popen(cmd, shell=shell, stdout=stdout, stderr=stderr) out, err = p.communicate() out = out.split('\n') err = err.split('\n') rc = p.returncode if (rc != 0): if (log): e_msg = ( 'non-zero code(%d) returned by command: %s. output: %s error:' ' %s' % (rc, cmd, out, err)) logger.error(e_msg) if (throw): raise CommandException(cmd, out, err, rc) return (out, err, rc)
def usermod(username, passwd): # TODO: 'salt = crypt.mksalt()' # Python 3.3 onwards provides system best. # Salt starting "$6$" & of 19 chars signifies SHA-512 current system best. # Salt must contain only [./a-zA-Z0-9] chars (bar first 3 if len > 2) salt_header = '$6$' # SHA-512 rnd = random.SystemRandom() salt = ''.join([ rnd.choice(string.ascii_letters + string.digits + './') for _ in range(16) ]) crypted_passwd = crypt.crypt(passwd.encode('utf8'), salt_header + salt) cmd = [USERMOD, '-p', crypted_passwd, username] p = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) out, err = p.communicate(input=None) rc = p.returncode if rc != 0: raise CommandException(cmd, out, err, rc) return out, err, rc
def resquote(*nums): """ Restore one or more deleted quotes. Restoration of a quote is only possible if said quote was deleted while preservation was enabled in the quotes config. Args: *nums: a list of ids of quotes to be restored. """ nums = [int(num) for num in nums] for num in nums: if num not in quotes or quotes[num].get("display", True): raise CommandException(f"Quote #{num} is not restorable.") for num in nums: quotes[num]["display"] = True write_quotes() quote_numbers = ", ".join(f"#{num}" for num in nums) return f"Quote{'s' if len(nums) > 1 else ''} restored: {quote_numbers}"
def error_logs(device): o, e, rc = run_command( [SMART, '-l', 'error', '/dev/%s' % device], throw=False) # As we mute exceptions when calling the above command we should at least # examine what we have as return code (rc); 64 has been seen when the error # log contains errors but otherwise executes successfully so we catch this. if rc == 64: e_msg = 'Drive /dev/%s has logged S.M.A.R.T errors. Please view ' \ 'the Error logs tab for this device.' % device logger.error(e_msg) email_root('S.M.A.R.T error', e_msg) # In all other instances that are an error (non zero) we raise exception # as normal. elif rc != 0: e_msg = ('non-zero code(%d) returned by command: %s -l error output: ' '%s error: %s' % (rc, SMART, o, e)) logger.error(e_msg) raise CommandException(('%s -l error /dev/%s' % (SMART, device)), o, e, rc) ecode_map = { 'ABRT': 'Command ABoRTed', 'AMNF': 'Address Mark Not Found', 'CCTO': 'Command Completion Timed Out', 'EOM': 'End Of Media', 'ICRC': 'Interface Cyclic Redundancy Code (CRC) error', 'IDNF': 'IDentity Not Found', 'ILI': '(packet command-set specific)', 'MC': 'Media Changed', 'MCR': 'Media Change Request', 'NM': 'No Media', 'obs': 'obsolete', 'TK0NF': 'TracK 0 Not Found', 'UNC': 'UNCorrectable Error in Data', 'WP': 'Media is Write Protected', } summary = {} log_l = [] for i in range(len(o)): if (re.match('=== START OF READ SMART DATA SECTION ===', o[i]) is not None): err_num = None lifetime_hours = None state = None etype = None details = None for j in range(i + 1, len(o)): log_l.append(o[j]) if (re.match('Error ', o[j]) is not None): fields = o[j].split() err_num = fields[1] if ('lifetime:' in fields): lifetime_hours = int(fields[fields.index('lifetime:') + 1]) if (re.match( 'When the command that caused the error occurred, the device was', o[j].strip()) is not None): state = o[j].strip().split('the device was ')[1] if (re.search('Error: ', o[j]) is not None): e_substr = o[j].split('Error: ')[1] e_fields = e_substr.split() etype = e_fields[0] if (etype in ecode_map): etype = ecode_map[etype] details = ' '.join( e_fields[1:]) if (len(e_fields) > 1) else None summary[err_num] = list( [lifetime_hours, state, etype, details]) err_num = lifetime_hours = state = etype = details = None print('summary_d %s' % summary) return (summary, log_l)
def cmd_msg_handler(msg): """ Message event handler for commands. """ com_conf = config.configs["commands"] command_prefix = com_conf["command-prefix"] message_starts_with_prefix = msg.text_content.startswith(command_prefix) message_is_prefix = msg.text_content == command_prefix if message_starts_with_prefix and not message_is_prefix: try: # Commands can throw errors, so those should be handled. # Discard the command prefix and split the message into arguments # along spaces. components = ( msg.text_content[len(com_conf["command-prefix"]):] .split() ) cmd_name, args = components[0], components[1:] # Truncate arguments at 20 characters to avoid stupid values # e.g. !roll 9999999999... args = [arg[:20] for arg in args] # Find and run the proper command function. command = delegate_command(cmd_name) name = "cmd." + command.meta["name"] # If commands are disabled or this particular command hasn't cooled # down, stop resolution. Either way, never disable the 'enable' # command. disableable = ( name == "cmd.enable" or ( cooldown.has_cooled_down("cmds") and cooldown.has_cooled_down(name) ) ) if not disableable: return if command.meta["static"]: perm = "cmd.statics" else: perm = name # Check that the user has perms. if not group_has_perm(msg.sender_group, perm): if command.meta["no_perms_msg"]: raise CommandException(command.meta["no_perms_msg"]) raise CommandException("Insufficient permissions.") validate_command_args(command, args, cmd_name) if command.meta["pass_msg"]: args = [msg] + args resp = command(*args) cooldown.set_cooldown(name, command.meta["cooldown"]) if resp: # XOR prepend_name = ( com_conf["prepend-name"] != (command.meta["name"] in com_conf["prepend-exceptions"]) ) if prepend_name: resp = f"{msg.sender_name}: {resp}" return resp except CommandException as ex: # Avoid sending an error if the exception is due to an unknown # command, and those are configured to be silent. silence_error = ( isinstance(ex, UnknownCommandException) and not config.configs["commands"]["err-unknown-cmd"] ) if not silence_error: return f"{msg.sender_name}: Error - {ex.args[0]}"
def handleMessage(message, uID): _, command, *args = message.content.split() try: with open(str(uID) + filename, 'rb') as f: currNotepad = pickle.load(f) except: currNotepad = [] if command == 'remindme': if len(args) < 1: raise CommandException('Missing duration argument.') delta = parseDuration(args[0]) addReminder(delta, message.message) message.room.send_message( 'I will remind you of this message in {0}.'.format(delta)) if command == 'snooze': if len(args) < 1: delta = timedelta(minutes=5) else: delta = parseDuration(args[0]) myMessage = message.message.parent errStr = 'Snooze requires a reply to my reminder "Reminder for this message is due." message.' if not myMessage: raise CommandException(errStr) # .parent creates a new message struct. Avoid initialization twice reminderMessage = myMessage.parent if not reminderMessage: raise CommandException(errStr) if reminderMessage.owner.id != message.message.owner.id: raise CommandException( 'You cannot snooze a message that doesn\'t belong to you.') addReminder(delta, reminderMessage) message.room.send_message( 'Your message has been snoozed for {0}.'.format(delta)) if command == 'add': currNotepad.append(' '.join(args)) message.room.send_message('Added message to your notepad.') if command == 'rm': try: which = int(args[0]) if which > len(currNotepad): raise CommandException('Item does not exist.') del currNotepad[which - 1] message.room.send_message('Message deleted.') except: return if command == 'rma': currNotepad = [] message.room.send_message('All messages deleted.') if command == 'show': if not currNotepad: raise CommandException('You have no saved messages.') report = buildReport(currNotepad) r = requests.post(apiUrl, json=report) r.raise_for_status() js = r.json() message.room.send_message('Opened your notepad [here]({}).'.format( js['reportURL'])) return with open(str(uID) + filename, 'wb') as f: pickle.dump(currNotepad, f)
out, err = p.communicate() out = out.split('\n') err = err.split('\n') rc = p.returncode except Exception, e: msg = ('Exception while running command(%s): %s' % (cmd, e.__str__())) raise Exception(msg) if (rc != 0): if (log): e_msg = ( 'non-zero code(%d) returned by command: %s. output: %s error:' ' %s' % (rc, cmd, out, err)) logger.error(e_msg) if (throw): raise CommandException(cmd, out, err, rc) return (out, err, rc) def uptime(): with open('/proc/uptime') as ufo: return int(float(ufo.readline().split()[0])) def def_kernel(): kernel = None o, e, rc = run_command([GRUBBY, '--default-kernel'], throw=False) if (len(o) > 0): k_fields = o[0].split('/boot/vmlinuz-') if (len(k_fields) == 2): kernel = k_fields[1]