2012-03-20 9 views
6

dowiedziałem się kolejny problem w ten prosty kodu:OCaml: nieoczekiwany wyjątek z Unix.getlogin gdy stdin przekierowany

let() = 
    print_endline "Hello"; 
    print_endline (Unix.getlogin()) 

pracuje w normalnym przypadku, przy ./a.out daje:

Hello 
ricardo 

Ale działa jak ./a.out </dev/null sprawia Unix.getlogin fail:

Hello 
Fatal error: exception Unix.Unix_error(20, "getlogin", "") 

Wszelkie id dlaczego tak się dzieje?

+0

Po prostu wypróbowałem to na moim systemie: Mac OS X 10.6.8/OCaml 3.12.0 i nie widzę problemu. Wynik jest taki sam w obu przypadkach. Jaki jest twój system? –

+0

Linux, ponownie przeczytałem man 3 getlogin i widziałem "błąd" w glibc o przekierowaniu stdin: -/ – Ricardo

+0

Tak, bkconrad przybił to! –

Odpowiedz

5

Przekierowanie wejścia programu zastępuje jego terminal sterujący. Bez terminala sterującego, nie ma logowania można znaleźć:

$ tty 
/dev/pts/2 
$ tty < /dev/null 
not a tty 

Można jednak jeszcze znaleźć nazwę użytkownika (być może) poprzez uzyskanie identyfikatora użytkownika (getuid) i patrząc w górę jego passwd entry (related docs) (getpwuid) następnie znajdując w nim swoją nazwę użytkownika.

+0

Odpowiedź powinna pochodzić od nazwy procesu, a nie od terminala sterującego. Ale wciąż może to być problem. –

+0

Zakładając, że nazywa się prawdziwy 'getlogin' (http://linux.die.net/man/3/getlogin), to faktycznie pochodzi z terminalu kontrolującego. – bkconrad

+0

Wow. W BSD (i Mac OS X) jest to oddzielna wartość ustawiona podczas logowania. Nie jest oparta na getuid() lub geteuid(), jak się spodziewałem, ale nie na sterującym terminalu. Wydaje mi się, że jest trochę lepiej. –

3

W zależności od zastosowania:

  • jeśli nie troszczą się o wartości zwracanej przez „getlogin”, można zrobić coś takiego:

    try 
        Unix.getlogin() 
    with _ -> Sys.getenv "USER" 
    

    prawdopodobnie będzie coś lepiej niż getuid, ponieważ będzie również działać dla programów z flagami Set-User-ID (sudo/su).

  • jeśli naprawdę zależy Ci na wartości zwróconej przez "getlogin", tzn. Naprawdę chcesz wiedzieć, kto jest zalogowany, powinieneś po prostu zawieść, gdy getlogin się nie powiedzie. Każde inne rozwiązanie daje tylko przybliżenie prawidłowego wyniku.

Powiązane problemy