captureLoginPath function

Future<String?> captureLoginPath({
  1. required String shell,
  2. Duration timeout = const Duration(seconds: 10),
})

Runs shell as a login+interactive shell and returns the PATH it exports, or null on Windows, when script/the shell fails, on timeout, or when the markers are missing.

Implementation

Future<String?> captureLoginPath({
  required String shell,
  Duration timeout = const Duration(seconds: 10),
}) async {
  if (Platform.isWindows) return null;

  Process process;
  try {
    process = await Process.start(shell, [
      '-l',
      '-i',
      '-c',
      'printf "$_startMarker%s$_endMarker" "\$PATH"',
    ], runInShell: false);
  } on Object {
    return null;
  }

  final stdoutFuture = process.stdout.transform(utf8.decoder).join();
  // Drain stderr so the child does not block on a full pipe.
  unawaited(process.stderr.drain<void>());

  Timer? killer;
  killer = Timer(timeout, () => process.kill(ProcessSignal.sigkill));
  try {
    final exitCode = await process.exitCode;
    final out = await stdoutFuture;
    killer.cancel();
    if (exitCode != 0 && !out.contains(_startMarker)) return null;
    return _extract(out);
  } on Object {
    killer.cancel();
    return null;
  }
}