From 89880e96b9c54af5dc5b6322c22a75acd1267df8 Mon Sep 17 00:00:00 2001 From: "Kelvin M. Klann" Date: Tue, 18 Oct 2022 04:10:32 -0300 Subject: sort.py: enumerate lines from 1 Instead of manually adding 1 to lineno. --- contrib/sort.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contrib/sort.py b/contrib/sort.py index 6f21370ec..0758d5fec 100755 --- a/contrib/sort.py +++ b/contrib/sort.py @@ -53,7 +53,7 @@ def fix_profile(filename): lines = profile.read().split("\n") was_fixed = False fixed_profile = [] - for lineno, line in enumerate(lines): + for lineno, line in enumerate(lines, 1): if line[:12] in ("private-bin ", "private-etc ", "private-lib "): fixed_line = f"{line[:12]}{sort_alphabetical(line[12:])}" elif line[:13] in ("seccomp.drop ", "seccomp.keep "): @@ -69,8 +69,8 @@ def fix_profile(filename): if fixed_line != line: was_fixed = True print( - f"{filename}:{lineno + 1}:-{line}\n" - f"{filename}:{lineno + 1}:+{fixed_line}" + f"{filename}:{lineno}:-{line}\n" + f"{filename}:{lineno}:+{fixed_line}" ) fixed_profile.append(fixed_line) if was_fixed: -- cgit v1.2.3-70-g09d2 From 801a9951fefd004b6b6b549a3c4bd41e64a8f500 Mon Sep 17 00:00:00 2001 From: "Kelvin M. Klann" Date: Tue, 18 Oct 2022 04:46:21 -0300 Subject: sort.py: pass the str.casefold function directly To the sort function, instead of wrapping it in a lambda function. --- contrib/sort.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/sort.py b/contrib/sort.py index 0758d5fec..9ce57802e 100755 --- a/contrib/sort.py +++ b/contrib/sort.py @@ -29,7 +29,7 @@ from sys import argv, exit as sys_exit def sort_alphabetical(raw_items): items = raw_items.split(",") - items.sort(key=lambda s: s.casefold()) + items.sort(key=str.casefold) return ",".join(items) -- cgit v1.2.3-70-g09d2 From b9c2843111cd208ef40b2683e64edd2d6059c28f Mon Sep 17 00:00:00 2001 From: "Kelvin M. Klann" Date: Tue, 18 Oct 2022 00:00:03 -0300 Subject: sort.py: simplify "checking" message code Which also makes it fit in under 80 characters. Always print "profile(s)" instead of changing the message based on the argument count. --- contrib/sort.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/sort.py b/contrib/sort.py index 9ce57802e..ca43e5bd5 100755 --- a/contrib/sort.py +++ b/contrib/sort.py @@ -85,7 +85,7 @@ def fix_profile(filename): def main(args): exit_code = 0 - print(f"sort.py: checking {len(args)} {'profiles' if len(args) != 1 else 'profile'}...") + print(f"sort.py: checking {len(args)} profile(s)...") for filename in args: try: if exit_code not in (1, 101): -- cgit v1.2.3-70-g09d2 From 2a7cc2e7ad1aaff6ccb4d8b6ac5de0bc0121d6ee Mon Sep 17 00:00:00 2001 From: "Kelvin M. Klann" Date: Mon, 17 Oct 2022 23:15:10 -0300 Subject: sort.py: rename raw_items to original_items To make it clearer. Both the input and output of the sort_alphabetical function are strings of comma-separated items, so there is no format conversion of any kind being done (from "raw" to "not raw"), only sorting. --- contrib/sort.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/sort.py b/contrib/sort.py index ca43e5bd5..8f42e9e5c 100755 --- a/contrib/sort.py +++ b/contrib/sort.py @@ -27,8 +27,8 @@ Exit-Codes: from sys import argv, exit as sys_exit -def sort_alphabetical(raw_items): - items = raw_items.split(",") +def sort_alphabetical(original_items): + items = original_items.split(",") items.sort(key=str.casefold) return ",".join(items) -- cgit v1.2.3-70-g09d2 From aa17ca5fc9b251cac33e8e48ac539e534c8c3c74 Mon Sep 17 00:00:00 2001 From: "Kelvin M. Klann" Date: Mon, 17 Oct 2022 23:20:49 -0300 Subject: sort.py: rename protocols to original_protocols To make it clearer. There are 3 different instances of protocol-related objects being used in the fix_protocol function: * The input * The array of common sorted lines * The (sorted) output --- contrib/sort.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contrib/sort.py b/contrib/sort.py index 8f42e9e5c..69af99d6e 100755 --- a/contrib/sort.py +++ b/contrib/sort.py @@ -33,17 +33,17 @@ def sort_alphabetical(original_items): return ",".join(items) -def sort_protocol(protocols): +def sort_protocol(original_protocols): """sort the given protocols into this scheme: unix,inet,inet6,netlink,packet,bluetooth""" # shortcut for common protocol lines - if protocols in ("unix", "unix,inet,inet6"): - return protocols + if original_protocols in ("unix", "unix,inet,inet6"): + return original_protocols fixed_protocols = "" for protocol in ("unix", "inet", "inet6", "netlink", "packet", "bluetooth"): for prefix in ("", "-", "+", "="): - if f",{prefix}{protocol}," in f",{protocols},": + if f",{prefix}{protocol}," in f",{original_protocols},": fixed_protocols += f"{prefix}{protocol}," return fixed_protocols[:-1] -- cgit v1.2.3-70-g09d2 From adff09c6dbec927374f9eabe999a43f17e730f8b Mon Sep 17 00:00:00 2001 From: "Kelvin M. Klann" Date: Tue, 18 Oct 2022 03:15:40 -0300 Subject: sort.py: line-wrap and improve comments Changes: * Line-wrap comments at 79 characters * Make comments clearer * Make main docstring more similar to a command "usage" output See the result with the following command, which generates a man-page-like output and opens it in the man pager (such as in `less`): $ pydoc ./contrib/sort.py See also PEP-257, "Docstring Conventions"[1]. [1] https://peps.python.org/pep-0257/ --- contrib/sort.py | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/contrib/sort.py b/contrib/sort.py index 69af99d6e..b4e06d345 100755 --- a/contrib/sort.py +++ b/contrib/sort.py @@ -3,11 +3,17 @@ # Copyright (C) 2014-2022 Firejail Authors # License GPL v2 """ -Sort the items of multi-item options in profiles, the following options are supported: - private-bin, private-etc, private-lib, caps.drop, caps.keep, seccomp.drop, seccomp.drop, protocol +Sort the arguments of commands in profiles. + +Usage: ./sort.py [/path/to/profile ...] + +The following commands are supported: + + private-bin, private-etc, private-lib, caps.drop, caps.keep, seccomp.drop, + seccomp.drop, protocol + +Note that this is only applicable to commands that support multiple arguments. -Usage: - $ ./sort.py /path/to/profile [ /path/to/profile2 /path/to/profile3 ... ] Keep in mind that this will overwrite your profile(s). Examples: @@ -16,10 +22,10 @@ Examples: $ ./sort.py ~/.config/firejail/*.{profile,inc,local} $ sudo ./sort.py /etc/firejail/*.{profile,inc,local} -Exit-Codes: - 0: No Error; No Profile Fixed. - 1: Error, one or more profiles were not processed correctly. - 101: No Error; One or more profile were fixed. +Exit Codes: + 0: Success: No profiles needed fixing. + 1: Error: One or more profiles could not be processed correctly. + 101: Info: One or more profiles were fixed. """ # Requirements: @@ -34,7 +40,11 @@ def sort_alphabetical(original_items): def sort_protocol(original_protocols): - """sort the given protocols into this scheme: unix,inet,inet6,netlink,packet,bluetooth""" + """ + Sort the given protocols into the following order: + + unix,inet,inet6,netlink,packet,bluetooth + """ # shortcut for common protocol lines if original_protocols in ("unix", "unix,inet,inet6"): -- cgit v1.2.3-70-g09d2 From 863585842993f8a64c782254e011bb268a452d4e Mon Sep 17 00:00:00 2001 From: "Kelvin M. Klann" Date: Tue, 18 Oct 2022 03:53:28 -0300 Subject: sort.py: print errors to stderr Misc: The trailing comma is due to using the opinionated `black` Python formatter (which seems to be a relatively common one). This was the only change made, so the code seems to already be following the format used by this tool. --- contrib/sort.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/contrib/sort.py b/contrib/sort.py index b4e06d345..595ad0536 100755 --- a/contrib/sort.py +++ b/contrib/sort.py @@ -30,7 +30,7 @@ Exit Codes: # Requirements: # python >= 3.6 -from sys import argv, exit as sys_exit +from sys import argv, exit as sys_exit, stderr def sort_alphabetical(original_items): @@ -103,13 +103,16 @@ def main(args): else: fix_profile(filename) except FileNotFoundError: - print(f"[ Error ] Can't find `{filename}'") + print(f"[ Error ] Can't find `{filename}'", file=stderr) exit_code = 1 except PermissionError: - print(f"[ Error ] Can't read/write `{filename}'") + print(f"[ Error ] Can't read/write `{filename}'", file=stderr) exit_code = 1 except Exception as err: - print(f"[ Error ] An error occurred while processing `{filename}': {err}") + print( + f"[ Error ] An error occurred while processing `{filename}': {err}", + file=stderr, + ) exit_code = 1 return exit_code -- cgit v1.2.3-70-g09d2 From 9bf491212a8887e940ce9f272e107830e47dfc9d Mon Sep 17 00:00:00 2001 From: "Kelvin M. Klann" Date: Tue, 18 Oct 2022 03:54:17 -0300 Subject: sort.py: print more standard error messages Where applicable, instead of creating custom ones. Example error messages: rm -f 123 && ./contrib/sort.py 123 [ Error ] [Errno 2] No such file or directory: '123' touch 123 && chmod -rwx 123 && ./contrib/sort.py 123 [ Error ] [Errno 13] Permission denied: '123' --- contrib/sort.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/contrib/sort.py b/contrib/sort.py index 595ad0536..5cd4045f0 100755 --- a/contrib/sort.py +++ b/contrib/sort.py @@ -102,15 +102,15 @@ def main(args): exit_code = fix_profile(filename) else: fix_profile(filename) - except FileNotFoundError: - print(f"[ Error ] Can't find `{filename}'", file=stderr) + except FileNotFoundError as err: + print(f"[ Error ] {err}", file=stderr) exit_code = 1 - except PermissionError: - print(f"[ Error ] Can't read/write `{filename}'", file=stderr) + except PermissionError as err: + print(f"[ Error ] {err}", file=stderr) exit_code = 1 except Exception as err: print( - f"[ Error ] An error occurred while processing `{filename}': {err}", + f"[ Error ] An error occurred while processing '{filename}': {err}", file=stderr, ) exit_code = 1 -- cgit v1.2.3-70-g09d2 From b1bf9a81033d7fbe413ee817c6da61ad567fbe3e Mon Sep 17 00:00:00 2001 From: "Kelvin M. Klann" Date: Tue, 18 Oct 2022 17:02:35 -0300 Subject: sort.py: print usage if there are no arguments And return a specific exit code, as suggested by @rusty-snake[1]. Escape the first line in the docstring to avoid printing a blank line as the first line of the output. [1] https://github.com/netblue30/firejail/pull/5429#discussion_r999637842 --- contrib/sort.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/contrib/sort.py b/contrib/sort.py index 5cd4045f0..388a29710 100755 --- a/contrib/sort.py +++ b/contrib/sort.py @@ -2,7 +2,7 @@ # This file is part of Firejail project # Copyright (C) 2014-2022 Firejail Authors # License GPL v2 -""" +"""\ Sort the arguments of commands in profiles. Usage: ./sort.py [/path/to/profile ...] @@ -25,6 +25,7 @@ Examples: Exit Codes: 0: Success: No profiles needed fixing. 1: Error: One or more profiles could not be processed correctly. + 2: Error: Missing arguments. 101: Info: One or more profiles were fixed. """ @@ -94,8 +95,13 @@ def fix_profile(filename): def main(args): - exit_code = 0 + if len(args) < 1: + print(__doc__, file=stderr) + return 2 + print(f"sort.py: checking {len(args)} profile(s)...") + + exit_code = 0 for filename in args: try: if exit_code not in (1, 101): -- cgit v1.2.3-70-g09d2 From c648adc9a6e2f50e3b742d2f71a148e9f9e41c89 Mon Sep 17 00:00:00 2001 From: "Kelvin M. Klann" Date: Tue, 18 Oct 2022 17:10:10 -0300 Subject: sort.py: use script name in usage/main docstring With this, the help section remains consistent regardless of how the script is called and even if the filename is changed. For example, if someone renames "sort.py" to "firejail-sort" and puts it somewhere in `$PATH`. Example outputs of the script name (using `print(argv[0]); return`): $ ./contrib/sort.py ./contrib/sort.py $ python contrib/sort.sh contrib/sort.py $ (cd contrib && ./sort.py) ./sort.py Note: This depends on `os.path` and `sys.argv`, so the imports have to appear before the docstring. In which case, the docstring has to be explicitly assigned to `__doc__` (as it ceases to be the first statement in the file). Note2: When running `pydoc ./contrib/sort.py`, `argv[0]` becomes "/usr/bin/pydoc" (using python 3.10.8-1 on Artix Linux). --- contrib/sort.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/contrib/sort.py b/contrib/sort.py index 388a29710..638f14516 100755 --- a/contrib/sort.py +++ b/contrib/sort.py @@ -2,10 +2,16 @@ # This file is part of Firejail project # Copyright (C) 2014-2022 Firejail Authors # License GPL v2 -"""\ + +# Requirements: +# python >= 3.6 +from os import path +from sys import argv, exit as sys_exit, stderr + +__doc__ = f"""\ Sort the arguments of commands in profiles. -Usage: ./sort.py [/path/to/profile ...] +Usage: {path.basename(argv[0])} [/path/to/profile ...] The following commands are supported: @@ -17,10 +23,10 @@ Note that this is only applicable to commands that support multiple arguments. Keep in mind that this will overwrite your profile(s). Examples: - $ ./sort.py MyAwesomeProfile.profile - $ ./sort.py new_profile.profile second_new_profile.profile - $ ./sort.py ~/.config/firejail/*.{profile,inc,local} - $ sudo ./sort.py /etc/firejail/*.{profile,inc,local} + $ {argv[0]} MyAwesomeProfile.profile + $ {argv[0]} new_profile.profile second_new_profile.profile + $ {argv[0]} ~/.config/firejail/*.{{profile,inc,local}} + $ sudo {argv[0]} /etc/firejail/*.{{profile,inc,local}} Exit Codes: 0: Success: No profiles needed fixing. @@ -29,10 +35,6 @@ Exit Codes: 101: Info: One or more profiles were fixed. """ -# Requirements: -# python >= 3.6 -from sys import argv, exit as sys_exit, stderr - def sort_alphabetical(original_items): items = original_items.split(",") -- cgit v1.2.3-70-g09d2