brag을 쓰면서 파일명 처리에 문제가 생기는 경우가 있어서 확인차 코드를 보았는데 Tcl을 전혀 모르는 채로 문법을 찾아보면서 따라가는 게 쉽지 않다. convmv를 따로 호출하기기본적으로 생성되는 파일명은 서버측 환경대로 EUC-KR이라서 전송이 끝나고 나면 하지만 convmv 자체도 cron으로 돌리고 있기 때문에 아무 필요없을 때도 매번 시행되는 게 좀 그랬는데, incron이라고 inotify를 통해 이벤트가 잡히면 명령을 실행하는 걸 발견했다. 하지만 이런저런 조건을 생각하면 어떻게 써야 딱 맞을지 좀 그렇다. 그러다 2010년 1월 경 어느 때부터 mv 역할을 하는 rename 단계에서 에러가 나면서 제대로 처리가 안 되었다. 나중에 짐작하기로는 아마 cron 내부의 로케일 기본값이 바뀌면서 Tcl이 인식하는 로케일이 바뀌어 파일명에 접근을 못하게 된 게 아닐까 싶다. 그래서 convmv를 쓰지 않고 바로 처리할 수 있지 않을까 해서 살펴보게 되었다. 내부 동작 분석구조를 보니, unfinished 디렉토리 안에 ID로 디렉토리를 만들어 파트는 part.111 식의 일괄적인 형식으로 받고 그 제목도 subject 파일로 따로 저장을 하고, 파트가 완료되면 그 목록을 uudeview에 넘겨서 디코딩을 마친 뒤 결과 파일을 finished 디렉토리로 옮기는 식이다. 결국 디코딩된 파일이 중요한 것으로, 기본적으로 서버측 설정대로 EUC-KR로 되어 있는 걸 UTF-8로 적절하게 바꿔주면 되는 것이다.이때 brag에서 디코딩 결과에 대해 정확한 파일명을 보유하는 것이 아니라 후처리 과정에서 스스로 생성한 파일들은 삭제하고 그 나머지가 결과물일 것으로 간주하는 식이다. uudeview의 출력을 활용하는 것도 생각해 보았지만 깔끔하게 결과 파일명만 나오는 게 아니라서 그 결과를 파싱하는 건 지나치게 복잡한 방법인 것으로 보인다. rename 단계에서 처리하기Tcl에서는 가령 set subjectConv [encoding convertfrom cp949 $subject]fconfigure stdout -encoding utf-8이때 후처리 과정에서 glob으로 추출한 디코딩된 파일은 uudeview에서 원본 인코딩인 EUC-KR로 파일명을 만들었으므로 rename 과정에서 대상 파일을 UTF-8 인코딩으로 만들어 전달하면 바로 처리될 것이라 생각했다. 하지만 실제로 해본 결과 Tcl이 인코딩 중립적이지 않은 것인지, rename에서 원본 파일의 EUC-KR 파일명과 대상 파일의 UTF-8 파일명을 동시에 인식하지 못해 파일명을 인식하지 못하고 실패한다. 아예 두 번으로 나누어 원본-tmp-대상 식으로 중간 단계를 두고 각 경우의 직전에 (LANG 환경변수를 설정하는 것과 같은 효과를 내는) encoding system cp949, encoding system utf-8를 호출해 파일명에 맞게 시스템 인코딩으로 인식하는 값을 설정해보았지만 의외로 이것도 실패.convmv를 내부에서 호출하기EUC-KR 파일명만 전달하면 외부에서 처리가 되도록 convmv 호출해보았다. uudeview를 호출하는 부분을 참조하여 eval exec convmv -f cp949 -t utf-8 ... 식으로 호출하고 바깥을 catch {...} results 처럼 감싸 출력이 있을 경우 잡아내도록 했다.이 경우 문제는 exec에 파일명을 어떻게 잘 전달하는가가 되는데 파일명에 온갖 문자가 들어가 있을 수 있어서 Tcl 문법과의 충돌을 피하기 위해 escape 처리가 필요하다. Tcl에서 escape를 어떻게 처리하는가 찾아봤지만 딱 이거다 싶은 게 없었다. { }로 대상을 감싸라는 얘기가 있긴 했지만 (awk를 언급하는 부분이어서 그쪽에 특화된 건가 싶기도 하고) 기대했던 결과가 나오지 않았던 것 같다. (정확한 기억이 아니다.) 그러나 이 방식 또한 Tcl이 인식하는 시스템 인코딩과 밀접하게 연관되어 있어, 파일명을 인자로 전달하는 방식을 택하는 이상 문제가 있을 수 밖에 없었다. 그렇다면 관건은 파일명을 직접 호출하지 않는 것. 이를 위해 convmv에 -r 옵션을 주고 대상을 현재 디렉토리인 .으로 하였다. catch {eval exec convmv -f cp949 -t utf-8 --notest -r -- .}출력 처리출력되는 내용 중 아티클의 제목 부분은 깨져서 나오는데 이는 전송 소켓이 fconfigure $sock -encoding binary의 적용을 받는데다 기본적으로 EUC-KR 인코딩이기 때문이다. 사용에는 지장이 없으나, 로그를 깔끔하게 하려면 print에서 해당 부분을 [encoding convertfrom cp949 $var] 식으로 감싸주면 $var를 cp949에서 내부 유니코드로 변환하고 이는 출력 때 UTF-8로 변환 처리된다.제대로 하자면 소켓에서 꺼내와 내부에서 유통하는 모든 내용을 제대로 인코딩 변환해서 처리하면 좋겠지만 어차피 다들 임시로 소진되는 파일이기 때문에 굳이 안쪽으로 더 파고 들어갈 생각은 안 든다. |