simple frontend program problem

This is a discussion on simple frontend program problem within the Linux Programming forums, part of the Platform Specific Boards category; I am making single frontend program that will convert mp3 to ogg files and vice versa. First this is my ...

  1. #1
    Registered User gandalf_bar's Avatar
    Join Date
    Oct 2003
    Posts
    92

    Wink simple frontend program problem

    I am making single frontend program that will convert mp3 to ogg files and vice versa. First this is my important function:

    Code:
    int spawn( char* program, char** arg_list ) {
    	pid_t child_pid;
    
    	child_pid = fork();
    	if( child_pid != 0 ) 
    		return child_pid;
    	else {
    		execvp( program, arg_list );
    	}
    }
    Basically because this is front end, I use system call function in my program. Here's how my Linux box convert mp3 files to ogg files if done in bash shell.

    mpg321 inputfiles.mp3 -w inputfiles.wav ( takes about 10+ seconds )
    oggenc inputfiles.wav ( takes about 30+ seconds )
    rm inputfiles.wav ( takes about 1- seconds )


    Here's my program :
    Code:
    .....
    switch(type) {
    		case mp3: arg_list[0] = "mpg321";
    			  song.copy( arg_list[1], songlength, 0 );
    			  arg_list[1][songlength] = '\0';
    			  arg_list[2] = "-w";
    			  outputsong.copy( arg_list[3], outputsonglength, 0 );
    			  arg_list[3][outputsonglength] = '\0';
    			  arg_list[4] = NULL;
    			  spawn("mpg321", arg_list);
    			  wait(&childstatus);
    			  arg_list[0] = "oggenc";
    			  outputsong.copy( arg_list[1], outputsonglength, 0 );
    			  arg_list[1][outputsonglength] = '\0';
    			  arg_list[2] = NULL;
    			  spawn("oggenc", arg_list);
    			  wait(&childstatus);
    			  arg_list[0] = "rm";
    			  outputsong.copy( arg_list[1], outputsonglength, 0 );
    			  spawn("rm", arg_list);
    			  wait(&childstatus);
    			  break;
    ..........
    The problem with this approach, in converting process ( if I push convert button ), I cann't manipulate my application's window. I cann't push any button. I cann't do anything with my window. After the process is done, the window become normally again. I can remove wait(&children) statement but it will execute rm inputfiles.wav before it finish convert mp3 files to wav files ( remember mpg321 inputfiles.mp3 -w inputfiles.wav takes about 10+ seconds ). Without wait(&children) statement, my program will execute all the statements above in less than 1 second.

    To make it short, I have 3 commands to execute and I want it done in order. So command number 2 will wait command number 1 finish its processing. But in their processing, I want to manipulate my application's window.

    Any idea, guyz?????
    A man asked, "Who are you?"
    Buddha answered, "I am awaked."

  2. #2
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,558
    So use another process

    Code:
    switch(type) {
    	case mp3: do_mp3(); break;
    Where
    Code:
    void do_mp3 ( void ) {
      if ( fork() == 0 ) {
        // child process to do the conversions, and idle around waiting for things to finish
        arg_list[0] = "mpg321";
        // etc etc
        _exit( 0 );  // it's done all it needs to, just exit
      }
    }
    Of course, you can jazz this up by returning the pid of the conversion process, so that you can wait() for it, and get its exit status, and you can replace the value passed to _exit() with something more meaningful if any of the previous commands actually failed (for example).
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  3. #3
    Registered User gandalf_bar's Avatar
    Join Date
    Oct 2003
    Posts
    92
    After couples day, I have successfully make an alpha converter. Well, I have to admit that hunting bug is more difficult than coding it self. OK, now the technical question:

    Code:
    #include <iostream>
    #include <string>
    using namespace std;
    
    int main() {
     
        string c = "af.mpp";
        char *b = new char[100];
        b = NULL;
        b = "mp3";
        cout << b;
    
    
    }
    Look the code above. It works properly. Now here's my program code:
    Code:
    void do_ogg() {
    	if( fork() == 0 ) {
    		int child;
    		arg_list[0] = "oggdec";
    		song.copy( arg_list[1], songlength, 0 );
    		arg_list[1][songlength] = '\0';
    		arg_list[2] = NULL;
    		spawn( "oggdec", arg_list );
    		wait(&child);
    		arg_list[0] = "lame";
    		outputsong += ".wav";
    		outputsong.copy( arg_list[1], outputsonglength+4, 0 );
    		arg_list[1][outputsonglength+4] = '\0';
    		outputsong = outputsong.substr( 0, outputsonglength );
    		arg_list[2] = NULL;
    		spawn( "lame", arg_list );
    		wait(&child);
    		arg_list[0] = "rm";
    		spawn( "rm", arg_list );
    		wait(&child);
    
                         //Look over here: 
    		delete arg_list[2];
    		arg_list[2] = new char[100];
                         //Without two lines above, the third operations
                         //, that is mv blablabla.wav.mp3 blablabla.mp3 
                         // won't work...............                   
    
    		arg_list[0] = "mv";
    		string temp = outputsong + ".wav" + ".mp3";
    		temp.copy( arg_list[1], outputsonglength+8, 0 );
    		arg_list[1][outputsonglength+8] = '\0';
    		outputsong += ".mp3";
    		outputsong.copy( arg_list[2], outputsonglength+4, 0 );
    		arg_list[2][outputsonglength+4] = '\0';
    		arg_list[3] = NULL;
    		spawn( "mv", arg_list );
    		wait(&child);
    		_exit( 0 );
    	}
    }
    Why???????

    Second question: What is the simplest way to debug child process? I have to hack my code.
    I use combination set follow-fork-mode child, but that does not always work. I have to comment some code to make it work. I would big thank you if you give me a simple explanation how to debug child process ( fork() stuff ) in gdb session ?
    A man asked, "Who are you?"
    Buddha answered, "I am awaked."

  4. #4
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,558
    You're sure making a mess of memory allocation

    > Look the code above. It works properly.
    Maybe so, but for none of the reasons I suspect you know about.

    Lets dissect.

    char *b = new char[100];
    Ok so far, b now points to 100 chars

    b = NULL;
    Ohh, bad news, you just lost the memory and you now have a memory leak.

    b = "mp3";
    This points to a string constant (which is not the same as making a copy)

    Consider this
    Code:
        char *b = new char[100];  // allocate an array
        strcpy( b, "mp3" );    // b = "mp3" is a memory leak, 
        // you can still output b, but you'll get problems at the delete
        cout << b;
        delete [] b;    // delete an array
    > Second question: What is the simplest way to debug child process?
    By not making it a process at all.
    Make sure it works properly as inline code (and ignore the fact that your app stops for a minute). When you're sure it all works, THEN add the single line of code which calls fork() to create a child process.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  5. #5
    Registered User gandalf_bar's Avatar
    Join Date
    Oct 2003
    Posts
    92
    OK, my program works great but only can convert one file per operation. so I want to expanded so that my program be able to convert all files in one directory ( if my user choose to input directory not file. ) . Now, assume he choose to convert all ogg files to mp3 files in directory blablabla. So my program will read all files with this code:

    Code:
    DIR           *d;
    struct dirent *dir;
    d = opendir(".");
    
    int amount_ogg_files = 0;
    
    if (d)
    {
      while ((dir = readdir(d)))
      {
        //count it
        if( dir->d_name == oggfiles() ) amount_ogg_files++;
      }
      closedir(d);
    
       //Ok now I know how many ogg files in this directory
       string *the_names_of_ogg_files;
       the_names_of_ogg_files = new string[amount_og];
    
       //Read the files again, 
       d = opendir(".");
    if (d)
    {
      while ((dir = readdir(d)))
      {
        //Here's I will pass d->d_name to the_names_of_ogg_files
      }
      closedir(d);
    
    
    }
    The questions are: In that code I read the files twice. First, to know how many ogg files in this directory so I can allocate enogh string to hold the names of ogg files. Second, to catch the names of ogg files into my string. Is there anyway I can avoid read the files twice?

    Second: You see:
    Code:
    string* b;
    b = new string[amount_of_ogg_files];
    Code:
    char **s;
    s = new char*[amount_of_ogg_files];
    Which is better?

    The last one: My user is a crazy guy. He make a directory named like this: blabla.ogg in music directory. He want to convert all ogg files in music directory to mp3 files but there is a directory named blabla.ogg!!!!! How can I test if this is a directory or file?
    A man asked, "Who are you?"
    Buddha answered, "I am awaked."

  6. #6
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,558
    > Is there anyway I can avoid read the files twice?
    Yeah, use a vector, then you don't have to allocate memory yourself. Vectors can expand themselves

    Code:
    vector <string> ogg_files;
    > How can I test if this is a directory or file?
    Use the stat() function. One of the bits in the mode field indicates directory
    Code:
    struct stat sbuf;
    stat( d->d_name, &sbuf );
    if ( S_ISREG(sbuf.st_mode) ) {
      // regular file, process it
    }
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  7. #7
    Registered User gandalf_bar's Avatar
    Join Date
    Oct 2003
    Posts
    92
    Right now, I am so stuck. I don't know what to do now.....

    Ok I give you the code first. I made some variables to be global because simplify purpose. So don't say global variables are not safe. First, make it work. Then improve it. Bruce Eckel said that. After my program works, I will remove the global variables.

    My implementation file is window1.cc. And the global variables are:

    Code:
    string song, outputsong, s1;
    int songlength, outputsonglength;
    char* arg_list[10];
    const int file = 1;
    const int directory = 2;
    And the here's the function that "deal" with system call in LInux box:
    Code:
    int spawn( char* program, char** arg_list ) {
    	pid_t child_pid;
    
    	child_pid = fork();
    	if( child_pid != 0 ) 
    		return child_pid;
    	else {
    		execvp( program, arg_list );
    	}
    }
    Code:
    void do_ogg() {
    	if( fork() == 0 ) {
    		int child;
    		arg_list[0] = "oggdec";
    		song.copy( arg_list[1], songlength, 0 );
    		arg_list[1][songlength] = '\0';
    		arg_list[2] = NULL;
    		spawn( "oggdec", arg_list );
    		wait(&child);
    		arg_list[0] = "lame";
    		outputsong += ".wav";
    		outputsong.copy( arg_list[1], outputsonglength+4, 0 );
    		arg_list[1][outputsonglength+4] = '\0';
    		outputsong = outputsong.substr( 0, outputsonglength );
    		arg_list[2] = NULL;
    		spawn( "lame", arg_list );
    		wait(&child);
    		arg_list[0] = "rm";
    		spawn( "rm", arg_list );
    		wait(&child);
    		delete arg_list[2];
    		arg_list[2] = new char[100];
    		arg_list[0] = "mv";
    		string temp = outputsong + ".wav" + ".mp3";
    		temp.copy( arg_list[1], outputsonglength+8, 0 );
    		arg_list[1][outputsonglength+8] = '\0';
    		outputsong += ".mp3";
    		outputsong.copy( arg_list[2], outputsonglength+4, 0 );
    		arg_list[2][outputsonglength+4] = '\0';
    		arg_list[3] = NULL;
    		spawn( "mv", arg_list );
    		wait(&child);
    		_exit( 0 );
    	}
    }
    
    void do_mp3() {
    	if( fork() == 0 ) {
                 int child;
    	     arg_list[0] = "mpg321";
    	     song.copy( arg_list[1], songlength, 0 );
    	     arg_list[1][songlength] = '\0';
    	     arg_list[2] = "-w";
    	     outputsong.copy( arg_list[3], outputsonglength, 0 );
    	     arg_list[3][outputsonglength] = '\0';
    	     arg_list[4] = NULL;
    	     spawn("mpg321", arg_list);
    	     wait(&child);
    	     arg_list[0] = "oggenc";
    	     outputsong.copy( arg_list[1], outputsonglength, 0 );
    	     arg_list[1][outputsonglength] = '\0';
    	     arg_list[2] = NULL;
    	     spawn("oggenc", arg_list);
    	     wait(&child);
    	     arg_list[0] = "rm";
    	     outputsong.copy( arg_list[1], outputsonglength, 0 );
    	     spawn("rm", arg_list);
    	     wait(&child);
    	     _exit( 0 );
    	}
    }
    Code:
    void window1::on_processing() {
    	const int mp3 = 1, ogg = 2, no = 0;
    	for(int ii=0; ii<10; ii++) 
    		arg_list[ii] = new char[100];
    
    	int type;
    	songlength = song.length();
            string temp( song, 0, songlength-4 );
            outputsong = temp;
    	outputsonglength = outputsong.length();
            s1 = song.substr(outputsonglength+1,3) ;
                         
    	if(s1=="mp3") type = mp3;	
    	
    	else if(s1=="ogg") type = ogg;
    
    	else type = no;
    
            switch(type) {
    		case mp3: do_mp3();
    		 	  break;
    	        case ogg: do_ogg();
    			  break;
    		default: 
    			  break;
    	}
    
            for(int i=0; i<10; i++) 
                   	delete arg_list[i] ;
    }
    Now here's come the fun part:
    Code:
    void window1::on_convert_clicked()
    {  
    	if(status==1) {
    	song = input->get_text();
            on_processing();
    	}
    	else if(status==2) {
    		Gtk::Dialog *dialog;
    		dialog = new class Gtk::Dialog("bla bla", *this ) ;
                    dialog->add_button("ogg",1);
    		dialog->add_button("mp3",2);
    		int bla = 1;
    		bla = dialog->run();
    		DIR *d;
    	        struct dirent *dir;
    		delete dialog;
    		Glib::ustring Direct = input->get_text();
    	        d = opendir(Direct.c_str());
                    vector<string> files;
    	        string temp;
    		switch(bla) {
    			case 1: 
    		                if(d) {
    			                while((dir = readdir(d))) {
    						temp = dir->d_name;
    						if(temp.length()>=4)
    					               if(temp.substr(temp.length()-4,4)==".ogg")	
    						                files.push_back(temp);
    					}
    				}
    				break;
    			case 2: 
    				if(d) {
    					while((dir = readdir(d))) {
    						temp = dir->d_name;
    						if(temp.length()>=4)
    						       if(temp.substr(temp.length()-4,4)==".mp3")
    						        	files.push_back(temp);
    					}
    				}
    				break;
    			default:
    				break;
    		}
    		int child;
    
    
    
                         //Look over here, guyZ!!! Here's the part that make trouble
    		if(fork()==0) 
    		     for( int i=0; i<files.size(); i++ ) {
    		        	song = Direct + "/" + files[i] ;
    		        	on_processing();
    				wait(&child);
    		     }
                         //The end of comment 
    
    
    
    	}
    
    }
    Ok, I give you explanation. If user want to convert directory, after push the convert button, the dialog pop and ask: "Hey, dude, what do you want to do? Ogg to mp3 or mp3 to ogg?" There are two button: ogg and mp3 as you can see in on_convert_clicked function. But in testing sessing, I got this error after push the convert button:

    The program 'converter' received an X Window System error.
    This probably reflects a bug in the program.
    The error was 'BadWindow (invalid Window parameter)'.
    (Details: serial 4528 error_code 3 request_code 10 minor_code 0)
    (Note to programmers: normally, X errors are reported asynchronously;
    that is, you will receive the error a while after causing it.
    To debug your program, run it with the --sync command line
    option to change this behavior. You can then get a meaningful
    backtrace from your debugger if you break on the gdk_x_error() function.)


    I have debug it and it crash misteriously after fork() session in on_convert_clicked() function. After fork() session, it step, step, step, step, then crash. If I post my gdb sessions, it would make my post longer than needed. Again, I got no clue in my gdb session. Maybe this is not correct forum to ask like gtkmm library spesific question but a guy in gtkmm mailing list told me that:

    I've not looked at your code in any great depth, but I suspect thaton_processing() is trying to talk to the GUI. If this is the case, thenwhen you fork() and it tries to talk to the GUI from one of the childprocesses, you're asking for trouble, as you end up with X windowsshared across processes which X doesn't think they should be accessedfrom, and it starts complaining about it. Try doing everything in asingle process; if it works, then you need to consider more carefullyhow you're going to do things in the background, if you're going to doit - if you do fork(), make sure only the parent talks directly to theGUI. If you need to pass data from the children for the GUI to display,it will have to pass through the parent process in some way - pipes,FIFOs, shared memory, whatever.Hopefully that will help and I'm not barking up entirely the wrong tree.


    As you can see, guyz, none my child processes talk to GUI....... I reply his email and he said he cann't help further. So I come back into this forum because this error relate with child processes. I found this clue because if in on_convert_clicked() function, I comment these statements:
    Code:
    .......................
    		default:
    				break;
    		}
    		int child;
    
                         /*
    		if(fork()==0) 
    		     for( int i=0; i<files.size(); i++ ) {
    		        	song = Direct + "/" + files[i] ;
    		        	on_processing();
    				wait(&child);
    		     }
                        */
    	}
    ..........................
    The error dissapear. But if I comment some statements in on_processing() function:
    Code:
    ..................
    else type = no;
    
            switch(type) {
    		case mp3: // do_mp3();
    		 	  break;
    	        case ogg: // do_ogg();
    			  break;
    		default: 
    			  break;
    	}
    
            for(int i=0; i<10; i++) 
    ............
    and I use the original on_convert_clicked() function, the error still exist. So the problem is located in this function:
    Code:
    ....................
    int child;
    		if(fork()==0) 
    		     for( int i=0; i<files.size(); i++ ) {
    		        	song = Direct + "/" + files[i] ;
    		        	on_processing();
    				wait(&child);
    		     }
    .....................
    Ok, my problem relate with system call and fork() function so I guess this is the correct forum to ask. Can you help me? Is there something in my code wrong in using system call?


    Note to Salem:
    Thanx for the previous post. I really almost cann't believe that you reply my previous post in less than 5 minutes!!!! What a wonderful forum and Guru!!!!

    Note to administrator:
    I found bug. Try to use blablabla[-i] in [-code] [/-code] block and below it outside [-code] [/-code] you make this block: [-i] [/-i]. It will make italic from [-i] inside [-code] [/-code] block until found [/-i] outside [-code][/-code] block. You will see what I mean. To solve it manually I have to make it blablabla[-i] [-i] [/-i] statement. Use [-i] in [-code] [/-code] block suppose not to make it italic, right?!!! I mean [-i] in [-code] [/-code] block should has no effect, rigth!!!!!
    A man asked, "Who are you?"
    Buddha answered, "I am awaked."

  8. #8
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,558
    Consider using spaces instead of tabs for indenting your code. Code gets indented rather too much when you have half a dozen tabs.

    > for(int ii=0; ii<10; ii++) arg_list[ii] = new char[100];
    Ok so far

    > arg_list[0] = "mpg321";
    Nooooooo
    You've just lost your allocated memory, and something is going to be badly upset when you try and delete this pointer
    Use a string copy function
    strcpy( arg_list[0], "mpg321" );

    > for(int i=0; i<10; i++) delete arg_list [i] ;
    Should be delete [] arg_list [i];
    If you new an array, you must delete an array

    > Note to administrator:
    PM this to webmaster, or post it on the "Bugs" message at the top of the General Discussion forum
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  9. #9
    Registered User gandalf_bar's Avatar
    Join Date
    Oct 2003
    Posts
    92
    >Consider using spaces instead of tabs for indenting your code. Code gets indented >rather too much when you have half a dozen tabs.
    I don't use TAB because Vim already does it for me.....

    >strcpy( arg_list[0], "mpg321" );
    Ok I will use this from now. I think arg_list[0] = "mpg321" is ok as long as this pointer does not deal with NULL.

    >Should be delete [] arg_list [i] ;
    Uppss, I forgot it......


    Salem or anyone, you got to explain this to me because I finally find bug in my program. Consider this code:
    Code:
     ....................
    int child;
    if(fork()==0) 
         for( int i=0; i<files.size(); i++ ) {
            song = Direct + "/" + files [i]  ;
            on_processing();
            wait(&child);
            char *blar[] = {
                   "ls",
                   NULL
             }
             execvp("ls",blar);
         }
    .....................
    With this modification, my program run smoothly. Do you notice the difference? I add this:
    Code:
            char *blar[] = {
                   "ls",
                   NULL
             }
             execvp("ls",blar);
    I found this fact. My program would crash if the child process did not encounter this function execvp( ). Can you explain this??? Without this modification, my program would crash if it did not find any file to convert. If it find any file to convert, it will convert file(s) and error. If there was no file to convert, that means the child process did not encounter this statement: execvp() right????!!! So with this modification, my child process with or without files to convert will encounter this statement: execvp(). But this solution is stupid. Can you suggest a better one???

    I am so happy. My days are brighter now.... HO HO HO....

    Thank you.....
    A man asked, "Who are you?"
    Buddha answered, "I am awaked."

  10. #10
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,558
    > I don't use TAB because Vim already does it for me.....
    Then set it to use 4 spaces, not one TAB character.
    Whether you physically press the tab key is irrelevant, there are tab chars in your code, and it looks a mess posted here.

    > I think arg_list[0] = "mpg321" is ok as long as this pointer does not deal with NULL.
    Wrong - you can only delete what you got with new
    Since "mpg321" isn't from new, then delete will likely barf all over you.

    I suggest you use opendir() readdir() closedir() for getting directory listings.

    Hard to say what is wrong with your two examples, since neither compiles, and its too short to guess the context in which they're being used.
    In any event, you should really specify the full path to the name of the program being run "/bin/ls" instead of just "ls"
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  11. #11
    Registered User gandalf_bar's Avatar
    Join Date
    Oct 2003
    Posts
    92
    >In any event, you should really specify the full path to the name of the program being >run "/bin/ls" instead of just "ls"

    I learn about system call from http://www.advancedlinuxprogramming.com . Here's why I choose not to specify the full path of the program.


    .....................
    The exec functions replace the program running in a process with another program.
    When a program calls an exec function, that process immediately ceases executing that
    program and begins executing a new program from the beginning, assuming that the
    exec call doesn't encounter an error.
    Within the exec family, there are functions that vary slightly in their capabilities
    and how they are called.


    1 Functions that contain the letter p in their names (execvp and execlp) accept a
    program name and search for a program by that name in the current execution
    path; functions that don't contain the p must be given the full path of the pro-
    gram to be executed.


    2 Functions that contain the letter v in their names (execv, execvp, and execve)
    accept the argument list for the new program as a NULL-terminated array of
    pointers to strings. Functions that contain the letter l (execl, execlp, and
    execle) accept the argument list using the C language's varargs mechanism.
    3 Functions that contain the letter e in their names (execve and execle) accept an
    additional argument, an array of environment variables.The argument should be
    a NULL-terminated array of pointers to character strings. Each character string
    should be of the form "VARIABLE=value".
    Because exec replaces the calling program with another one, it never returns unless an
    error occurs.
    The argument list passed to the program is analogous to the command-line argu-
    ments that you specify to a program when you run it from the shell.They are available
    hrough the argc and argv parameters to main. Remember, when a program is
    nvoked from the shell, the shell sets the first element of the argument list argv[0]) to
    he name of the program, the second element of the argument list (argv[1]) to the
    irst command-line argument, and so on.When you use an exec function in your pro-
    grams, you, too, should pass the name of the function as the first element of the argu-
    ment list.
    ......................


    What do you think about that? It said if I use execvp that use 'p' character, I don't need to specify the full path of the program I use.

    Beside that I accept your suggestion fully.
    A man asked, "Who are you?"
    Buddha answered, "I am awaked."

  12. #12
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,558
    Probably doesn't matter for your program.
    But if your program was a system level program, running as root (say through setuid), it would be trivial for an attacker to change the PATH to something which would invoke an ls which you didn't expect.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  13. #13
    Registered User gandalf_bar's Avatar
    Join Date
    Oct 2003
    Posts
    92
    Quote Originally Posted by Salem
    Probably doesn't matter for your program.
    But if your program was a system level program, running as root (say through setuid), it would be trivial for an attacker to change the PATH to something which would invoke an ls which you didn't expect.
    Ok, Salem, your suggestion is good to specify the full path. But there is a problem. I know that program like cd, cp, ls, tar, ps are in /bin directory by standard but how can I know where are the non-standard programs like mpg321, oggdec, and bla bla bla?
    A man asked, "Who are you?"
    Buddha answered, "I am awaked."

  14. #14
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,558
    You either
    - search the path yourself to verify the program you find is the one you expected to find
    - don't run such programs with extra privileges (you wouldn't normally anyway)

    If the program calling exec() is already at a high privilege, then it should work extra hard to ensure the program it expects to run is the program it actually runs.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  15. #15
    Registered User gandalf_bar's Avatar
    Join Date
    Oct 2003
    Posts
    92
    Hey, Salem, I guess I know why bug happens in my program.
    Look at this code in the member function of the GUI:
    Code:
     
    void on_convert_clicked() {
        Convert lime;
        
    	if(status==1) {
                if(fork()==0) {
    	     
                    lime.setSong(input->get_text());
                    lime.on_processing();
                    
                    char *arg[] = {
                        "/bin/ls",
                        ".....",
                        NULL
                    };
                    execvp("/bin/ls",arg);
    
                }
    	}
              else {
              }
    
              //Without execvp("/bin/ls",arg); the child process will execute this as long with 
              // parent process
              int stupid = 1;
       
    ..................................
    }
    Look at the code above and you see that I have to put the stupid function ( execvp("/bin/ls", arg); ) so that my program does not crash. I did this without know why. So I guess I know why now. Without this:
    Code:
    execvp("/bin/ls",arg);
    my child will go execute
    Code:
    int stupid = 1;
    That will my GUI confuse. "Hey, there are two process that manipulate me," said GUI. "I guess it is better for me to crash."

    Is that right, Salem???? Just want to ask your confirmation.

    So I have to put execvp("/bin/ls",arg); so that child process will end after execute this function. Of course I can change execvp to return 0;

    What do you think, Salem or anyone????

    Thank you......
    A man asked, "Who are you?"
    Buddha answered, "I am awaked."

Page 1 of 2 12 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Running Program Problem
    By warfang in forum C++ Programming
    Replies: 10
    Last Post: 03-28-2007, 02:02 PM
  2. simple login program problem
    By suckss in forum C Programming
    Replies: 11
    Last Post: 11-11-2006, 04:02 PM
  3. Problem with a simple program
    By Salgat in forum C Programming
    Replies: 10
    Last Post: 06-15-2006, 05:57 PM
  4. Replies: 3
    Last Post: 03-04-2005, 01:46 PM
  5. fopen();
    By GanglyLamb in forum C Programming
    Replies: 8
    Last Post: 11-03-2002, 11:39 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21