@@ -211,6 +211,8 @@ fn run_wizard() -> anyhow::Result<()> {
211211 }
212212 } ;
213213
214+ print_pam_extension_hint ( ) ;
215+
214216 // -- Summary --
215217 println ! ( "\n --- Setup Complete ---\n " ) ;
216218 let encryption_label = match config. encryption . method {
@@ -1387,6 +1389,17 @@ fn download_model(entry: &ModelEntry, dest: &Path) -> anyhow::Result<()> {
13871389// --- PAM installation ---
13881390
13891391const PAM_LINE : & str = "auth sufficient pam_facelock.so" ;
1392+
1393+ /// Print a copy-pasteable hint so users can extend PAM integration to any service.
1394+ fn print_pam_extension_hint ( ) {
1395+ println ! ( ) ;
1396+ println ! ( "==> facelock PAM line for manual extension to other services:" ) ;
1397+ println ! ( "==> {PAM_LINE}" ) ;
1398+ println ! (
1399+ "==> Add the above line above the first 'auth' line in any /etc/pam.d/<service> file."
1400+ ) ;
1401+ }
1402+
13901403const PAM_MODULE_PATH : & str = "/lib/security/pam_facelock.so" ;
13911404const SENSITIVE_SERVICES : & [ & str ] = & [ "system-auth" , "login" , "sshd" ] ;
13921405
@@ -1405,7 +1418,9 @@ pub fn run_pam(service: &str, remove: bool, yes: bool) -> anyhow::Result<()> {
14051418 if remove {
14061419 pam_remove ( service)
14071420 } else {
1408- pam_install ( service, yes)
1421+ pam_install ( service, yes) ?;
1422+ print_pam_extension_hint ( ) ;
1423+ Ok ( ( ) )
14091424 }
14101425}
14111426
@@ -1444,8 +1459,39 @@ fn pam_install(service: &str, yes: bool) -> anyhow::Result<()> {
14441459 return Ok ( ( ) ) ;
14451460 }
14461461
1447- // 4. Create backup (always, before any modification)
1462+ // 4. Preview change and confirm before any modification
14481463 let backup_path = format ! ( "{pam_path}.facelock-backup" ) ;
1464+
1465+ // Decide where the line will go BEFORE prompting, so the preview is accurate.
1466+ let insertion_hint = if content. lines ( ) . any ( |l| l. trim_start ( ) . starts_with ( "auth" ) ) {
1467+ "inserted before the first 'auth' line"
1468+ } else {
1469+ "no 'auth' line found — inserted at the top of the file"
1470+ } ;
1471+
1472+ println ! ( ) ;
1473+ println ! ( "About to modify {pam_path}:" ) ;
1474+ println ! ( " + {PAM_LINE} ({insertion_hint})" ) ;
1475+ println ! ( " Backup will be saved to: {backup_path}" ) ;
1476+ println ! ( ) ;
1477+ println ! ( "(To configure manually instead, add the line above to each service yourself.)" ) ;
1478+
1479+ let proceed = if yes || !std:: io:: stdin ( ) . is_terminal ( ) {
1480+ true
1481+ } else {
1482+ Confirm :: new ( )
1483+ . with_prompt ( "Proceed?" )
1484+ . default ( true )
1485+ . interact ( )
1486+ . context ( "failed to read confirmation" ) ?
1487+ } ;
1488+
1489+ if !proceed {
1490+ println ! ( "Skipped {pam_path}." ) ;
1491+ return Ok ( ( ) ) ;
1492+ }
1493+
1494+ // 4b. Create backup (always, before any modification)
14491495 fs:: copy ( pam_file, & backup_path)
14501496 . with_context ( || format ! ( "failed to back up {pam_path} to {backup_path}" ) ) ?;
14511497 println ! ( "Backed up {pam_path} -> {backup_path}" ) ;
0 commit comments