Skip to content

Commit 8f26ca4

Browse files
committed
make group_cmnd express more clearly what it does
1 parent b419ed5 commit 8f26ca4

1 file changed

Lines changed: 20 additions & 21 deletions

File tree

src/sudoers/mod.rs

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ mod entry;
1010
mod tokens;
1111

1212
use std::collections::{HashMap, HashSet};
13+
use std::io;
1314
use std::path::{Path, PathBuf};
14-
use std::{io, mem};
1515

1616
use crate::common::resolve::resolve_path;
1717
use crate::defaults;
@@ -204,14 +204,18 @@ impl Sudoers {
204204
}
205205
}
206206

207+
// a `take_while` variant that does not consume the first non-matching item
208+
fn peeking_take_while<'a, T>(
209+
iter: &'a mut std::iter::Peekable<impl Iterator<Item = T>>,
210+
pred: impl Fn(&T) -> bool + 'a,
211+
) -> impl Iterator<Item = T> + 'a {
212+
std::iter::from_fn(move || iter.next_if(&pred))
213+
}
214+
207215
fn group_cmd_specs_per_runas<'a>(
208216
cmnd_specs: impl Iterator<Item = (Option<&'a RunAs>, (Tag, &'a Spec<Command>))>,
209217
cmnd_aliases: &'a [Def<Command>],
210218
) -> impl Iterator<Item = Entry<'a>> {
211-
let mut entries = vec![];
212-
let mut last_runas = None;
213-
let mut collected_specs = vec![];
214-
215219
// `distribute_tags` will have given every spec a reference to the "runas specification"
216220
// that applies to it. The output of sudo --list splits the CmndSpec list based on that:
217221
// every line only has a single "runas" specifier. So we need to combine them for that.
@@ -221,24 +225,19 @@ fn group_cmd_specs_per_runas<'a>(
221225
// once a RunAs is parsed, it will have a unique identifier in the form of its address.
222226
let origin = |runas: Option<&RunAs>| runas.map(|r| r as *const _);
223227

224-
for (runas, (tag, spec)) in cmnd_specs {
225-
if origin(runas) != origin(last_runas) {
226-
if !collected_specs.is_empty() {
227-
entries.push(Entry::new(
228-
last_runas,
229-
mem::take(&mut collected_specs),
230-
cmnd_aliases,
231-
));
232-
}
233-
234-
last_runas = runas;
235-
}
228+
let mut cmnd_specs = cmnd_specs.peekable();
229+
let mut entries = vec![];
236230

237-
collected_specs.push((tag, spec));
238-
}
231+
while let Some(&(cur_runas, _)) = cmnd_specs.peek() {
232+
let specs = peeking_take_while(&mut cmnd_specs, |&(runas, _)| {
233+
origin(runas) == origin(cur_runas)
234+
});
239235

240-
if !collected_specs.is_empty() {
241-
entries.push(Entry::new(last_runas, collected_specs, cmnd_aliases));
236+
entries.push(Entry::new(
237+
cur_runas,
238+
specs.map(|x| x.1).collect(),
239+
cmnd_aliases,
240+
));
242241
}
243242

244243
entries.into_iter()

0 commit comments

Comments
 (0)