2008-11-07 16 views
15

En el entorno C/Unix en el que trabajo, veo algunos desarrolladores que usan __progname en lugar de argv [0] para los mensajes de usage(). ¿Hay alguna ventaja en esto? ¿Cuál es la diferencia entre __progname y argv [0]? ¿Es portátil?Usando '__progname' en lugar de argv [0]

Respuesta

18

__progname no es estándar y, por lo tanto, no es portátil, prefiera argv[0]. Supongo que __progname podría buscar un recurso de cadena para obtener el nombre que no depende del nombre de archivo con el que lo ejecutó. Pero argv[0] le dará el nombre que en realidad lo ejecutó como el que me resultaría más útil.

+3

Considere: execl ("/ bin/sh "," hot potatoes "," -c "," echo $ 0 - Hi ", (char *) 0); Funciona bien; argv [0] es" hot potatoes "; se hace eco de" hot potatoes - Hi ". Eso no es nada para hacer con el nombre del ejecutable que se ejecutó. –

+2

A pesar del comentario anterior, estoy de acuerdo en que argv [0] es más portable. Y solo unos pocos programas se mezclan con argv [0] así, pero cualquier atacante puede hacerlo. Tenga cuidado con b Tomando decisiones críticas sobre argv [0]. –

6

El uso de __progname le permite modificar el contenido de la matriz argv[] mientras aún mantiene el nombre del programa. Algunas de las herramientas comunes como getopt() modifican argv[] mientras procesan los argumentos.

Para portabilidad, puede strcopy argv[0] en su propio buffer progname cuando se inicia el programa.

+0

GNU getopt() se entromete con argv; las versiones que no son GNU generalmente no lo hacen. –

+3

@Jonathan: Sí, gracias por la aclaración. I GNU Me había quedado con una plataforma por mucho tiempo. (Lo siento) –

4

Es un BSDismo, y definitivamente no portátil.

0

Si su programa se ejecutó utilizando, por ejemplo, un enlace simbólico, argv [0] contendrá el nombre de ese enlace.

Supongo que __progname contendrá el nombre del archivo de programa real.

En cualquier caso, argv [0] está definido por el estándar C. __progname no es.

4

Veo al menos dos posibles problemas con argv [0].

Primero, argv [0] o argv en sí mismo pueden ser NULL si execve() llamador fue malvado o descuidado. Llamar a execve ("foobar", NULL, NULL) suele ser una forma fácil y divertida de demostrar que un programador confiado en su código no es a prueba de sig11.

También se debe tener en cuenta que argv no se definirá fuera de main() mientras que __progname generalmente se define como una variable global que puede usar desde dentro de su función use() o incluso antes de llamar a main() (como non constructores estándar de GCC).

+1

Pero "una aplicación POSIX estrictamente conforme para pasar al menos un argumento a la función exec, garantizando así que argc sea uno o más cuando se invoque por una aplicación de este tipo". ¡Seguramente nadie violaría POSIX! (http://www.opengroup.org/onlinepubs/000095399/functions/exec.html) –

6

También hay una extensión GNU para esto, de modo que se puede acceder al nombre de invocación del programa desde fuera de main() sin guardarlo manualmente. Sin embargo, podría ser mejor hacerlo manualmente; por lo tanto, es portátil en lugar de depender de la extensión de GNU. Sin embargo, aquí proporciono un extracto de la documentación disponible.

De the on-line GNU C Library manual (visitada en la actualidad):.

"Muchos programas que no leen la entrada de la terminal están diseñados para salir si falla cualquier llamada al sistema Por convención, el mensaje de error de un programa de este tipo debe comenzar con . el nombre del programa, sans directorios puede encontrar ese nombre en la variable program_invocation_short_name, el nombre completo del archivo se almacena la variable program_invocation_name

  • variable: char * program_invocation_name . El valor de esta variable es el nombre que se utilizó para invocar el programa que se ejecuta en el proceso actual. Es lo mismo que argv[0]. Tenga en cuenta que esto no es necesariamente un nombre de archivo útil; a menudo no contiene nombres de directorio.

  • variable: char * program_invocation_short_name valor de esta variable es el nombre que se utiliza para invocar el programa que se ejecuta en el proceso actual, con los nombres de directorio eliminado. (Es decir, es el mismo que program_invocation_name menos todo hasta la última barra, si los hubiera.) Código de inicialización

La biblioteca pone en marcha estas dos variables antes de llamar principal.

Portabilidad Nota: Estas dos variables son extensiones de GNU. Si desea que su programa trabaje con bibliotecas que no sean de GNU, debe guardar el valor de argv[0] en main, y luego quitar los nombres de directorio usted mismo. Agregamos estas extensiones para que sea posible escribir subrutinas de informe de errores independientes que no requieren una cooperación explícita del principal. "

1

__progname es solo argv [0], y los ejemplos en otras respuestas aquí muestran las debilidades de su uso . Aunque tampoco es portátil, estoy usando readlink en/proc/self/exe (Linux, Android) y leyendo el contenido de/proc/self/exefile (QNX).

Cuestiones relacionadas