windows에서의 exec 함수군 아규먼트 전달
alzip 을 써서 압축파일내의 파일을 편집하는데
등록이 안된 파일을 편집할 때 외부프로그램을 지정하게 되어있더라고요.
vim을 등록시키고 파일을 클릭하면 vim 이 뜨면서
파일을 편집하려고 하는데 'C:\Documents' 라는 파일을 편집하려고 시도를 합니다.
아마 해당 파일에 대한 임시파일을 임시디렉토리에 만들면서,
임시파일의 경로에 빈칸들이 들어가서 그렇게 된 것 같습니다.
임시파일이름은 다음과 같이 만들어졌습니다.
'C:\Documents and Settings\Administrator\Local Settings\Temp\_AZTMP18_\c'
확장자 .txt 는 vim 으로 연결되어 있어서 .txt 파일을 편집할 때는
별 이상없이 제대로 잘 수행됩니다.
alzip에서 어떤 함수를 통해 외부프로그램을 부르는지 모르겠지만,
꽁수로 viwrap 이라는 프로그램을 하나 만들어서
대략 아규먼트가 짤라져 들어와도 원 파일이름은 스페이스로 나눠졌을 것 같아서
스페이스들로 다시 아규먼트를 묶어서 exec 로 vim 을 불러줄려고 했습니다.
아래 코드가 대략 그 일을 수행하는 것인데,
exec 가 잘 안되서 현재는 그냥 system() 을 부르도록 해 놨습니다.
(이것 때문에 cmd 창이 하나 떠서 번거롭습니다. -_-;;)
#include <stdio.h> #include <process.h> #define VIM_PROG "gvim.exe" main(int argc, char **argv) { char param[512]; char *new_argv[3]; char cmd[512]; int i; memset(param, 0, sizeof(param)); if (argc == 1) execlp(VIM_PROG, VIM_PROG, (char *)0); printf("param[1] is '%s'\n", argv[1]); strcat(param, argv[1]); for (i = 2; i < argc; i++) { /* Probably the delimiter(s) is a single space */ strcat(param, " "); strcat(param, argv[i]); } printf("new param is '%s'\n", param); new_argv[0] = VIM_PROG; new_argv[1] = param; new_argv[2] = NULL; sprintf(cmd, "%s \"%s\"", VIM_PROG, param); system(cmd); /* execlp(VIM_PROG, VIM_PROG, param, (char *)0); _execvp(VIM_PROG, new_argv); */ }
% viwrap a b
라고 주면 new param is 'a b' 까지 잘 나오는데,
exec 를 거치면서 다시 'a' 'b' 두개의 파라메터로 나뉘는 것입니다.
gvim.exe 대신에 아래 프로그램을 prog.exe 정도로 컴파일해서
viwrap.exe에서 이 프로그램이 불리도록 하면 보실 수 있을 것입니다.
#include <stdio.h> main(int argc, char **argv) { int i; for (i = 0; i < argc; i++) { printf("argv[%d] = '%s'\n", i, argv[i]); } }
MSDN에서 exec쪽을 보니 exec 에서는 argv 로 넘기거나 args 로 넘긴 아규먼트가
exec되는 프로그램에게 그대로 전달되는 것이 아니라 한 단계 아규먼트에 대한 조작이 이루어지는 것 같습니다.
즉, 아규먼트들을 모두 스페이스로 묶어 버린 후 다시 새 프로그램의 아규먼트 리스트를 구성하는 것 같습니다.
(아래 인용의 *** *** 부분 참조)
Parameters are passed to the new process by giving one or more pointers to character strings as parameters in the _exec call. These character strings form the parameter list for the new process. The combined length of the inherited environment settings and the strings forming the parameter list for the new process must not exceed 32K bytes. The terminating null character ('\0') for each string is not included in the count, but space characters (***inserted automatically to separate the parameters***) are counted.
그래서 exec의 아규먼트에 "a b", "c", "d e", NULL 을 넘겨도 받는 프로그램은
"a", "b", "c", "d", "e", NULL 로 받는 것으로 생각됩니다.
뭐 윈도우는 그런가보다 생각할 수 있는데,
윈도우 명령행(cmd) 에서는 잘 된다는게 이상합니다.
윈도우 명령행에서는
% prog "a b c"
를 주면 argv[1] 이 'a b c' 가 됩니다.
cmd도 다른 프로그램을 실행시키려면 exec를 호출해야 할 듯 한데,
(음.. 다른 방법이 있나요? ㅡ.ㅡ?)
어떻게 처리하길래 빈칸이 들어간 아규먼트를 제대로 넘길 수가 있을까요?
====>
질문 올리다가 혹시나 해서 테스트를 해 봤는데,
exec에 전달할 빈칸이 들어간 아규먼트를 " " 로 묶어줘 봤습니다.
즉, execlp("gvim.exe", "gvim.exe", "\"a b\"", (char *)0);
로 줬더니만 받는 프로그램에서 " " 떼고 argv[1] 을 'a b' 로 받네요.
좀 엽기스럽다는 느낌이 드는군요..
Posix의 exec 스펙을 봤더니 꼭 caller에서 전달한 argv[i] 가
callee에서 argv[i] 로 전달되어야 한다는말은 없네요. -_-;;
그래도 좀...
당연한것 같은데요..." , " 가 있으면 그것을 하나의 아규먼트로
당연한것 같은데요...
" , " 가 있으면 그것을 하나의 아규먼트로 집어 넣는 것 아닌가요?
알집때문에 문제라면 파일패스를 " , "로 묶어서 전달해주면 될것 같은데요...
-- 아쉬운 하루 되세요 --
[quote="voider"]당연한것 같은데요..." , " 가 있으
네, 하나의 아규먼트로 넣는 것이 일반적으로 기대하는 행동일텐데요,
보통 유닉스에서는 이것을 하나의 아규먼트로 해석하는 역할을 해 주는 것이 쉘 이라는 것이죠.
명령행에서
% prog "filename with space"
라고 치면 유닉스의 경우에는 쉘에서 " "를 해석해서 실제 exec 를 부를때는
execlp("prog", "prog", "filename with space", (char *)0);
라고 되는 것이죠.
그러나 Windows의 경우에는
% prog "filename with space"
를 주면 (추정하건데) cmd 쉘이 quote 를 해석하는 것이 아니라,
또는 cmd 쉘이 해석하더라도 execlp (이 녀석을 부르는지는 모르겠습니다.)
를 호출할 때
execlp("prog.exe", "prog.exe", "\"filename with space\"", (char *)0);
로 전달된다는 것이죠.
이건 마치 'hello, world' 를 찍기 위해서
printf("%s", "hello, world");
를 해주는 것이 아니라
printf("%s", "\"hello, world\"");
를 해 주는 것 같은 느낌이 들어서요.
이건 quoting이나 escaping에 대한 부담을 쉘에서 해소시키지 않고,
명령행을 파싱하고 exec 를 이용하는 어플리케이션, 또는 exec 를 수행시키는
Windows의 일부분에게 지우는 것 같아서 영 달갑지 않습니다.
alzip에서 제가 등록한 프로그램을 부르는 방식은,
alzip 5.5에서는 제가 건드릴 수 있는게 프로그램명(문자열)을 등록하는 밖에는 없는데
"%1" 등의 구문을 alzip에서는 해석하지 않고 그것도 통채로 프로그램이름으로
생각하는 것 같습니다. 전달되는 파일명을 " " 으로 묶을 수 있는 통로가
사용자에게는 없는 것 같았습니다.
cmd 에서 아규먼트에 " 와 \ 이 여러개 섞인 것들을 테스트 해보면 직관적이거나
일관적인 동작을 못 보여주는 것 같습니다. (예는 생략)
개인적인 생각으로는 Windows 쉘이나 exec 콜 쪽의 quoting이나 escaping 쪽이
좀 정립되어야 할 것 같습니다.
댓글 달기