Mail/News 環境用の私的改造
対象
mnews を使用していて困った事は、News 記事の保存において 階層構造を作らず、フラットに行う点でした。
つまり、fj.sys.sun の記事を保存すると、‾/News/fj.sys.sun.cdrom のようなファイルができます。
これは、‾/News/fj/sys/sun/cdrom となって欲しいと思って mnews の設定を探してみたのですが、できないようでしたので ソースの改造に踏み切りました。
`#ifndef ORIG' で囲まれた部分が私の入れた改造です。
19 #endif /* DONT_HAVE_FTIME */
20
21 #define READER_NAME "mnews"
22 #ifndef ORIG
23 #define MNEWS_VERSION "1.21pp"
24 #else
25 #define MNEWS_VERSION "1.21"
26 #endif /* ORIG */
27 #define MNEWS_DATE "1997-12/23(Tue)"
28 #define ERROR_FILE "mnewserr"
29
単に表示されるバージョンをオリジナルと区別したかった だけです。`pp' は `private patch' の意味で入れています。
2353 }
2354 #else /* !MSDOS */
2355 sprintf(file_name, "%s%c%s", save_dir, SLASH_CHAR, select_name);
2356 #ifndef ORIG
2357 {
2358 char *p;
2359
2360 p = file_name + strlen(save_dir) + 1;
2361
2362 /* 私の好み */
2363 while(p = strchr(p, '.')){
2364 *p = '/';
2365 p++;
2366 }
2367
2368 strcat(file_name, "/");
2369 }
2370 #endif /* ORIG */
2371 #endif /* !MSDOS */
2372 input_line(INPUT_EXPAND_MASK | INPUT_COMP_MASK,
2373 "ファイル名を入力して下さい:", "Input file name:", file_name);
保存するファイル名が格納されている領域の `.' を `/' に 変えています。
2453 } else {
2454 strcpy(tmp_file1, (char*)extract); /* 汚い処理です */
2455 }
2456 #ifndef ORIG
2457 if(file_name[(int)strlen(file_name) - 1] == '/'){
2458 return(status);
2459 }
2460
2461 {
2462 char *p;
2463 char dir[MAXPATHLEN];
2464
2465 /* ディレクトリの作成 */
2466 p = file_name;
2467 while(p = strchr(p, '/')){
2468 memset(dir, 0x00, MAXPATHLEN);
2469 memcpy(dir, file_name, p - file_name + 1);
2470 p++;
2471 if(access(dir, R_OK) == -1){
2472 status = mkdir(dir, 0755);
2473 if(status == -1){
2474 switch(errno){
2475 case EEXIST:
2476 status = 0;
2477 continue;
2478 default:
2479 break;
2480 }
2481 status = 1;
2482 return(status);
2483 }
2484 }
2485 }
2486 status = 1;
2487 }
2488 #endif /* ORIG */
2489 create_temp_name(tmp_file2, "SD");
2490 if (save_code == ASCII_CODE) {
2491 convert_code(tmp_file1, tmp_file2, save_code, 0);
途中のディレクトリが存在しない場合は作成します。
以上の改造で、News グループの階層に準じて、ディレクトリが 作成されるようになります。
nmh の msgchk や inc は Mail を POP で取得する場合、pop server の pop3 ポートつまり 110 番ポートにアクセスします。
ところが、某所で、あやしいツールを 使用して Mail を取得しているのですが、このツールは一般ユーザ 権限で動作させていますので、接続ポートを 110 番にできません。
つまり、msgchk や inc があやしいツール を動かしているマシンの予約ポート以外にアクセスする必要が あります。
ところが、msgchk や inc は pop3 をキーにポート番号を取得 します (getservbyname) ので /etc/services を書き換えねば なりません。ですが、一般ユーザは /etc/services は編集 できません。
そこで、msgchk や inc の引数 `-host' に `server:port' を 認識させる改造を行いました。
`#ifndef ORIG' で囲まれた部分が私の入れた改造です。
96 #ifndef BIND
97 register struct netent *np;
98 #endif
99 #ifndef ORIG
100 struct servent se;
101 #endif /* ORIG */
102
103 #ifdef KPOP
104 char *cp;
service entry 構造体を用意します。
112 #endif /* KPOP */
113
114
115 #ifndef ORIG
116 if(strchr(args, ':')){
117 char *wp;
118 wp = strchr(args, ':');
119 *wp = '¥0';
120 wp++;
121
122 se.s_name = (char *)malloc(strlen(service) + 1);
123 if(!se.s_name){
124 return NOTOK;
125 }
126 strcpy(se.s_name, service);
127
128 se.s_aliases = 0x00;
129
130 se.s_port = htons((int)atoi(wp));
131
132 se.s_proto = (char *)malloc(strlen(protocol) + 1);
133 if(!se.s_proto){
134 free(se.s_name);
135 return NOTOK;
136 }
137 strcpy(se.s_proto, protocol);
138
139 sp = &se;
140 }else{
141 #endif /* ORIG */
142
143 if ((sp = getservbyname (service, protocol)) == NULL) {
144 #ifdef HESIOD
getservbyname の変わりに、service entry 構造体に値を 格納します。
s_port は `server:port' の `port' の値です。ネットワーク バイトオーダにするのを忘れないでください。
151 return NOTOK;
152 #endif
153 }
154 #ifndef ORIG
155 }
156 #endif /* ORIG */
157
158 ap = arguments;
159 if (args != NULL && *args != 0)
`:' が無ければ、今まで通りの処理を行います。
これで、/etc/services を編集せずに、ホームディレクトリの .mh_profile にマシン名とポート番号を書けば大丈夫です。