/// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// Przekazywanie listy argumentow do execl() /// /// /// /// /// /// /// /// /// /// /// /// by gminick /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// Calkiem niedawno na comp.unix.programmer jakis gosc zapytal sie, jak ma przkekazac zmienna ilosc parametrow do execl()'a... Byla niedziela, przeczytalem juz ponad 4000 postow od samego rana, wiec stwierdzilem, ze czemu czegos nie napisac, pomyslalem i ponizej troche efektow: Pierwsza rzecz: Nie mam pojecia, czemu nie uzyl execvp()'a albo innych... Druga (i ostatnia) rzecz - zalozenie: napisac program, ktory w liscie argumentow bedzie pobieral, jako pierwszy argument nazwe programu do wykonania, a potem jego parametry, przy czym wywolywanie programu bedzie sie odbywac przez execl(). Definicja funkcji wyglada tak: int execl( const char *path, const char *arg, ...); i teraz problem, bo jak powiedziec execl()'owi, ze ma np. wykonac /bin/ps'a z parametrami a,u,x,w ? Otoz, tak: ----------------------------- #include #include #include #include #include #include #include int main(int argc, char **argv) { int i, k, stat; char **argv_tmp; pid_t pid, wpid; argv_tmp = malloc(1); for(i=2, k=0; i<=argc; i++) { *(argv_tmp+k) = argv[i]; k+=1; } if((pid = fork()) == -1) { fprintf(stderr,"%s\n",strerror(errno)); exit(errno); } if(pid==0) { execl(argv[1], argv[1], *(argv_tmp+0)!=NULL?*(argv_tmp+0):NULL, *(argv_tmp+1)!=NULL?*(argv_tmp+1):NULL, *(argv_tmp+2)!=NULL?*(argv_tmp+2):NULL, *(argv_tmp+3)!=NULL?*(argv_tmp+3):NULL, *(argv_tmp+4)!=NULL?*(argv_tmp+4):NULL, *(argv_tmp+5)!=NULL?*(argv_tmp+5):NULL, *(argv_tmp+6)!=NULL?*(argv_tmp+6):NULL, *(argv_tmp+7)!=NULL?*(argv_tmp+7):NULL, NULL); } if(pid > 0) { wpid=wait(&stat); } return 0; } ----------------------------------- No, dobra, jakby ktos nie wiedzial o co chodzi to teraz kawalek po kawalku: 1. Najpierw deklarujemy sobie tablice wskaznikow do char, czyli takie tymczasowe argv: * char **argv_tmp; Teraz alokujemy pamiec, wystarczy bajt (?), bo tak i juz :) * argv_tmp = malloc(1); Teraz kopiujemy odpowiednie wskazniki z argv do naszej tymczasowej tablicy parametrow (pomijamy nazwe programu i pierwszy parametr, czyli nazwe programu do wykonania): * for(i=2, k=0; i<=argc; i++) { * *(argv_tmp+k) = argv[i]; * k+=1; * } Potem po prostu tworzymy nowy proces i w nim odpalamy execl()'a, ktoremu przekazujemy parametry z naszego argv_tmp, kazdy argument jest sprawdzany, jesli nie jest rowny NULL, to zostanie wykorzystany jako parametr, w przeciwnym razie bedzie ostatnim argumentem dla execl()'a, na koncu jest samo NULL, na wypadek, jakby wywolywany program mial 7 parametrow... * if(pid==0) { * execl(argv[1], argv[1], *(argv_tmp+0)!=NULL?*(argv_tmp+0):NULL, * *(argv_tmp+1)!=NULL?*(argv_tmp+1):NULL, * *(argv_tmp+2)!=NULL?*(argv_tmp+2):NULL, * *(argv_tmp+3)!=NULL?*(argv_tmp+3):NULL, * *(argv_tmp+4)!=NULL?*(argv_tmp+4):NULL, * *(argv_tmp+5)!=NULL?*(argv_tmp+5):NULL, * *(argv_tmp+6)!=NULL?*(argv_tmp+6):NULL, * *(argv_tmp+7)!=NULL?*(argv_tmp+7):NULL, * NULL); * } No i czas na test, powiedzmy, ze zrodelko nazywa sie bubu.c, kompilujemy: $ gcc -Wall -o bubu bubu.c i czas na testy: $ ./bubu /bin/cat /etc/passwd root:x:0:0:root:/root:/bin/zsh bin:x:1:1:bin:/bin: daemon:x:2:2:daemon:/sbin: .... $ ./bubu /bin/ps a u x w USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.3 1064 468 ? S 15:04 0:07 init [3] root 2 0.0 0.0 0 0 ? SW 15:04 0:00 [kflushd] root 3 0.0 0.0 0 0 ? SW 15:04 0:00 [kupdate] root 4 0.0 0.0 0 0 ? SW 15:04 0:01 [kswapd] root 5 0.0 0.0 0 0 ? SW< 15:04 0:00 [mdrecoveryd] root 285 0.0 0.4 1168 568 ? S 15:04 0:00 syslogd -m 0 .... Dziala :)) _______ gminick