diff options
| author | Dylan Araps <dylan.araps@gmail.com> | 2026-03-14 09:31:51 +0200 |
|---|---|---|
| committer | Dylan Araps <dylan.araps@gmail.com> | 2026-03-14 09:31:51 +0200 |
| commit | 79eb4385bd34e8ee06b35637f092ee45dc3e3706 (patch) | |
| tree | 4c3de5583733e9c9cfdc7b5f31a56f8d2ba205ba | |
| parent | f3416de0e2fd920dda7379c3b7dc2b3087cc30c6 (diff) | |
dfm: Add privilege escalation.
Pressing 'Z' (default) will spawn a nested dfm by escalating privileges
using the value of DFM_SU (default 'sudo'). Pressing 'Z' again inside
of this escalated mode returns to the original dfm.
| -rw-r--r-- | README.md | 16 | ||||
| -rw-r--r-- | config.h.in | 7 | ||||
| -rw-r--r-- | config_key.h.in | 1 | ||||
| -rwxr-xr-x | configure | 2 | ||||
| -rw-r--r-- | dfm.c | 29 | ||||
| -rw-r--r-- | lib/util.h | 9 |
6 files changed, 63 insertions, 1 deletions
@@ -50,6 +50,7 @@ Initial Announcement: https://dylan.gr/1772192922 * [Searching](#searching) * [Marking](#marking) * [Commands](#commands) + * [Privilege Escalation](#privilege-escalation) * [Bound Commands](#bound-commands) * [Design Considerations](#design-considerations) * [Conclusion](#conclusion) @@ -190,6 +191,8 @@ environment, default values are derived from the `config.h.in` file. - DFM_TRASH_DIR (Path to trash directory) - DFM_IMG_MODE (Image mode to use: 'chafa' (default), 'kitty') + +- DFM_SU (Privilege escalation tool to use: 'sudo' (default)) ``` ### CD On Exit @@ -386,6 +389,19 @@ and sends it all to the shell. ``` +### Privilege Escalation + +Commands can be run as root by prepending `sudo` or a similar tool on the +command-line. For more complex situations, pressing `Z` by default will use +`DFM_SU` (default `sudo`) to spawn another `dfm` as `root`. The statusline will +be a different color, show the nest level and display an `R` indicator to make +the escalation obvious. Pressing `Z` again inside of this escalated mode quits +and returns to the original `dfm`. + +This can be configured at runtime using the environment variable `DFM_SU` and +at compile time via the `config.h.in` file. + + ### Bound Commands Commands can be bound to keys. When a command is bound it can either run diff --git a/config.h.in b/config.h.in index f6fb6d4..23f4258 100644 --- a/config.h.in +++ b/config.h.in @@ -34,6 +34,13 @@ #define DFM_BOOKMARK_9 "" // +// Default privilege escalation utiliy. +// This is used to become root in dfm (default 'Z'). +// Values: "sudo", "doas", "ssu", "su", "run0", etc +// +#define DFM_SU "sudo" + +// // Default image viewer. // The command is executed as follows: // 'arg0' 'arg1' '{col}x{row}' 'img' diff --git a/config_key.h.in b/config_key.h.in index 0026853..4c087bf 100644 --- a/config_key.h.in +++ b/config_key.h.in @@ -91,6 +91,7 @@ static inline void (*fm_key(u32 cp))(struct fm *) case 'x': return act_stat; case 'i': return act_view_image; case 'z': return act_alt_buffer; + case 'Z': return act_toggle_root; case 'p': return cmd_chmod; case 'P': return cmd_chown; case 'B': return cmd_bulk_rename; @@ -19,7 +19,7 @@ # Program configuration. # export CFG_NAME=dfm -export CFG_VERSION=1.0.0 +export CFG_VERSION=1.0.1 export c_version=c99 # @@ -196,6 +196,7 @@ struct fm { s64 tz; u8 nl; u8 im; + const char *a0; }; // Entry Virtual {{{ @@ -2853,6 +2854,33 @@ act_quit_print_pwd(struct fm *p) } static inline void +act_toggle_root(struct fm *p) +{ + cut pe = get_env("DFM_SU", DFM_SU); + if (p->f & FM_ROOT) + term_set_dead(&p->t, 1); + else if (!pe.l) + fm_draw_err(p, S("DFM_SU not set"), 0); + else { + usize o = p->ppwd.l; + STR_PUSH(&p->ppwd, "env DFM_LEVEL="); + str_push_c(&p->ppwd, p->nl ? p->nl : '0'); + str_push_c(&p->ppwd, ' '); + str_push_s(&p->ppwd, p->a0); + str_terminate(&p->ppwd); + p->ppwd.l = o; + if (!strcmp(basename_l(pe.d, pe.l), "su")) { + const char *const a[] = { pe.d, "-c", p->ppwd.m + o, NULL }; + fm_exec(p, -1, NULL, a, 0, 1); + } else { + p->ppwd.m[o + 15] = 0; + const char *const a[] = { pe.d, "env", p->ppwd.m + 5, p->a0, NULL }; + fm_exec(p, -1, NULL, a, 0, 1); + } + } +} + +static inline void act_cd_home(struct fm *p) { cut h = get_env("HOME", ""); @@ -3700,6 +3728,7 @@ int main(int argc, char *argv[]) { static struct fm p; + p.a0 = argv[0]; str *s = &p.pwd; if (fm_init(&p) < 0) { @@ -336,5 +336,14 @@ path_resolve(char *s, usize l) return w; } +static inline const char * +basename_l(const char *s, usize l) +{ + for (usize i = l; i; i--) + if (s[i - 1] == '/') + return s + i; + return s; +} + #endif // DYLAN_UTIL_H |