2012-03-20 8 views
6

descubrí el próximo número de este simple código:OCaml: excepción inesperada con Unix.getlogin cuando StdIn redirigido

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

Correr en el caso normal, con ./a.out da:

Hello 
ricardo 

Pero corriendo como ./a.out </dev/null hace Unix.getlogin falte;

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

cualquier ID ¿por qué sucede esto?

+0

Acabo de probar esto en mi sistema: Mac OS X 10.6.8/OCaml 3.12.0 y no veo el problema. El resultado es el mismo en ambos casos. ¿Cuál es tu sistema? –

+0

Linux, he leído de nuevo man 3 getlogin y vi el "error" en glibc sobre redirigir el código fuente: -/ – Ricardo

+0

Sí, bkconrad lo ha descifrado. –

Respuesta

5

Redirigir la entrada de un programa anula su terminal de control. Sin un terminal de control, no hay una entrada que se encuentran:

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

Puede, sin embargo, todavía encontrar el nombre de un usuario (tal vez) al obtener el ID del usuario (getuid) y mirando hacia arriba su passwd entry (related docs) (getpwuid), luego encontrando su nombre de usuario en él.

+0

La respuesta debe venir del usuario del proceso, no del terminal de control. Pero aún así este podría ser el problema. –

+0

Suponiendo que llama al 'getlogin' real (http://linux.die.net/man/3/getlogin), de hecho, proviene del terminal de control. – bkconrad

+0

Wow. En BSD (y Mac OS X), se establece un valor por separado cuando se inicia sesión. No se basa en getuid() o geteuid() como esperaba, pero tampoco en el terminal de control. Me parece un poco mejor. –

3

Dependiendo de su aplicación:

  • si realmente no se preocupan por el valor devuelto por "getlogin", se puede hacer algo como:

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

    es probable que obtener algo mejor que getuid, ya que también funcionará para programas con banderas Set-User-ID (sudo/su).

  • si realmente te importa el valor devuelto por "getlogin", es decir, si realmente quieres saber quién está conectado, solo debes fallar cuando getlogin falle. Cualquier otra solución le dará solo una aproximación del resultado correcto.

Cuestiones relacionadas