execv - linux



  • Moin zusammen,

    ich sollte heute auf der Arbeit ein C Prog schreiben welches automatisiert ein anderes File aufruft. Je nach Argumenten...
    Allerdings krieg ich immer Warnings um die Ohren gehauen. Vorallem das der 2 Parameter von execv nicht kompatibel ist.
    Ich poste hier einfach mal rasch den Code wie er gerade im mom ist. Wäre cool wenn mir jemand einen Hinweis geben könnte wo der Fehler liegt....

    DANKE!

    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    
    int main(int argc, char *argv[])
    {
    	char start[]		="-start";
    	char stop[]			="-stop";
    
    	char startProg[]	="start";
    	char stopProg[]		="stop";
    	char *ptrn			= NULL;
    
    	char appPath[]="root/opt/coldfusion/bin/";
    	char *prog[3];
    
    	/*
    	*prog[0] = startProg;
    	*prog[1] = stopProg;
    	*prog[2] = ptrn;
    	*/
    
    	if (argc == 2)
    	{
    		if (!strcmp(argv[1],start))
    		{
    			execv(appPath, startProg);
    			printf("+++++ ColdFusion started +++++\n");
    		}
    		else if(!strcmp(argv[1],stop))
    		{
    			execv(appPath, prog[1]);
    			printf("+++++ ColdFusion stoped +++++\n");
    		}
    		else
    			printf("Error:\nAgruments -> \"-start\" or \"-stop\"\n");
    	}
    	else
    		printf("Error: Agruments");
    
    	return 0;
    }
    


  • execv erwartet einen mit 0 abgeschlossenes Array auf char-Pointer, welches die Argumente enthält. Ich denke Du suchst execl, der erwartet alle Parameter hintereinander (aber auch mit 0 abgeschlossen).

    Achja: Bei beiden muss der erste Parameter (!) der Programmname sein, mit oder ohne Pfad ist egal.

    execl(appPath, appPath, startProg, 0);
    

    EDIT:
    Wenn appPath übrigens ein vollständiger absoluter Pfad ist kannst Du auch execlp nehmen, denn execl durchsucht den $PATH wenn der Programmname kein Slash enthält.



  • Moin!

    Danke vielmals Du hast mich auf den richtigen Weg geschubst.
    Allerdings habe ich ne andere Frage.
    Ich wollte das nun mit spawn() umsetzen, da die exec die Programme "festhalten"
    ich wollte aber direkt nach Start wieder zurück in mein Prog.

    Allerdings habe ich gerade festgestellt, dass mir bei dem Linux gcc dings die <process.h> fehlt. Ist das normal? (Debian-Linux) Muss man unter Linux etwas anderes benuten?

    Danke!



  • Um genau zu sein halten die execs die Prozesse nicht fest, sie ersetzen sie vollständig. Nach dem exec gibt es Dein Programm im Speicher nicht mehr.

    Spawn habe ich noch nie benutzt (genauergesagt, noch nie was davon gehört). Dafür gibt es eigentlich fork (und das benutzt intern clone), welches einen Prozess in zwei teilt. Einen von den beiden (üblicherweise den Kindprozess) ersetzt Du dann mit exec(), der andere läuft weiter.

    pid_t pid = fork();
    if (pid == 0) {
      // Kindprozess
      execl(....);
      _exit(127); // Für den Fall dass execl schiefgeht!
    }
    
    // Weiter im Text
    


  • Okay, ich danke dir nochmals und habe eine (wahrscheinlich letzte) Frage:

    Ich kriege folgende Ausgabe von Linux angezeigt:

    myHome:/# ./cfloader -start

    +++ ColdFusion loader +++

    Error: Failed to start...

    myHome:/# CF-Start

    myHome:/#

    Ich kriege eine Fehlermeldung obowhl das Ding ausgeführt wird... liegt wahrscheinlich am "aufgabeln" der Prozesse...
    Ich hab mal den ganzen Code angehängt, vielleicht kannst Du mir erklären wie ich das machen müsste das in einem Fehlerfall und auch nur dann eine MSG rausgeht...

    DANKE!

    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include  <sys/types.h>
    
    void error(char *msg)
    {
    	printf("\nError:\t");
    	printf("%s\n",msg);
    }
    int main(int argc, char *argv[])
    {
    	char start[]		="-start";
    	char stop[]			="-stop";
    
    	printf("\n +++ ColdFusion loader +++\n");
    
    	if (argc == 2)
    	{
    		if (!strcmp(argv[1],start))
    		{
    			pid_t pid = fork();
    			if (pid == 0)
    			{
    				printf("CF-Start\n");
    				execl("/opt/coldfusion/bin/start", "start", NULL);
    				_exit(127); // Für den Fall dass execl schiefgeht!
    			}
    			else
    			{
    				error("Failed to start...\n");
    			}
    		}
    		else if(!strcmp(argv[1],stop))
    		{
    			pid_t pid = fork();
    			if (pid == 0)
    			{
    				printf("CF-Stop\n");
    				execl("/opt/coldfusion/bin/stop", "stop", NULL);
    				_exit(127); // Für den Fall dass execl schiefgeht! 
    			}
    			else
    			{
    				error("Failed to stop...\n");
    			}
    		}
    		else
    		{
    			error("Agruments -> \"-start\" or \"-stop\"\n");
    		}
    	}
    	else
    		error("Check Agruments.\n");
    	return 0;
    }
    


  • pid_t pid = fork();
                if (pid == 0)
                {
                    printf("CF-Start\n");
                    execl("/opt/coldfusion/bin/start", "start", NULL);
                    _exit(127); // Für den Fall dass execl schiefgeht!
                }
                else
                {
                    error("Failed to start...\n");
                }
    

    Hier passiert es. Fork kehrt 2 mal zurück. Er erzeugt eine Kopie des Prozesses und kehrt im Child mit dem Rückgabewert 0 zurück. Der startet dann Dein Programm. Im Parent kehrt er mit der pid des Childs zurück. Der gibt dann diese Fehlermeldung aus.

    Tntnet



  • Du hast fork falsch verstanden 😉

    Es ist kein Fehler wenn pid ungleich 0 ist, sondern Du bist dann im Elternprozess. Wie schon gesagt, fork TEILT den Prozess. Alle Befehle nach fork laufen ZWEIMAL - PARALLEL!

    Nur anhand der Pid kannst Du unterscheiden ob Du dich in dem Elternprozess befindest (fork gibt 0 zurück) oder im Kindprozess (fork gibt > 0 zurück) - aber wie gesagt, fork kehrt ZWEIMAL zurück, in unterschiedlichen Prozessen! Nur wenn pid < 0 ist, ist ein Fehler aufgetreten, dann gibt es auch keinen Kindprozess.



  • Oha... das ist allerdings etwas Neues für mich.
    Hmmm, mal kucken wie ich das nun umsetzte 🙂 Aber ich denke jetzt habe ich alle Infos um das sauber zum laufen zu kriegen.

    Ich möchte mich nochmals herzlichst bei Euch bedanken...

    Danke!



  • Ich hab mal in meiner Codesammlung etwas gesucht und tatsaechlich noch ein kleines Programm gefunden, das mit execv arbeitet:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <sys/uio.h>
    #include <unistd.h>
    
    #define BUFFER_SIZE			1024
    #define NUM_ARGS			 100
    #define CHILD_FORK_PID		   0
    #define SHELL_PROMPT    "\r\n$ "
    
    void get_user_command( char *command );
    void parse_command( char *command, char **args );
    void exec_command( char **command );
    
    int main( int argc, char** argv )
    {
    	char	buffer[BUFFER_SIZE];
    	char	*args[NUM_ARGS];
    
    	while( 1 ) 
    	{
    		get_user_command( buffer );
    		parse_command( buffer, args );
    		exec_command( args );
    	}
    
    	return 0;
    }
    
    void get_user_command( char *command ) 
    {
    	fprintf( stdout, SHELL_PROMPT ); /* Print shell promt */
    	fflush( stdin );
    	fflush( stdout );
    	fgets( command, BUFFER_SIZE, stdin ); /* Get user command */
    }
    
    void parse_command( char *command, char **args )
    {
    	int i;
    
    	i = 0;
    	args[i] = strtok( command, " \t\n" ); /* split ' ', '\n', '\t' */
    
    	while ( ( args[i] != NULL ) ) 
    	{
    		i++;
    		args[i] = strtok( NULL, " \t\n" );
    	}
    	args[i] = NULL;
    
    	i = 0;
    	while ( args[i] != NULL ) 
    	{
    		printf( "%s\n", args[i] );
    		i++;
    	}
    }
    
    void exec_command( char **command )
    {
    	int		status;
    	pid_t	pid;
    
    	if ( command[0] != NULL ) /* If there is a command */
    	{
    		pid = fork();
    
    		if ( pid == CHILD_FORK_PID ) 
    		{ /* Child */
    			execvp( command[0], command ); 
    			perror( "" );
    			exit( EXIT_FAILURE );
    		}
    		else if ( pid > CHILD_FORK_PID ) 
    		{ /* Parent waits for it's child */
    			wait(&status);
    		}
    		else if ( pid < CHILD_FORK_PID ) 
    		{
    			fprintf( stderr, "Error: fork()\n" );
    		}
    	}
    }
    

    Ist ne simple shell mit der man aber nur einzelne Kommandos ausfuehren kann, pipes und so sind nicht moeglich.
    Dich duerfte am meisten die void exec_command( char **command )-Funktion interessieren!

    mfg


Anmelden zum Antworten