cygwin getservbyname実験室

cygwin環境でサービスのポート番号がどのように決定されるか実験してみた。

% ls -l /etc/services
lrwxrwxrwx  1 haradats なし 37 Nov  2 23:33 /etc/hosts -> C:\WINDOWS\system32\drivers\etc\services
% perl -e 'print getservbyname("ftp", "tcp") . "\n";'
21
% mv /etc/services /etc/services.bak
% perl -e 'print getservbyname("ftp", "tcp") . "\n";'
21
% mv /etc/services.bak /etc/services
% mv 'c:\windows\system32\drivers\etc\services' 'c:\windows\system32\drivers\etc\services.bak'
% perl -e 'print getservbyname("ftp", "tcp") . "\n";'

% mv 'c:\windows\system32\drivers\etc\services.bak' '
c:\windows\system32\drivers\etc\services'
% perl -e 'print getservbyname("ftp", "tcp") . "\n";'
21
%
  • cygwinのgetservbynameは/etc/servicesを参照していない(削除しても動作する)。その代わりに、
  • %SystemRoot%\System32\drivers\etc\servicesを参照しているようだ
  • cygwinのgetservbynameは、サービスとポート番号の対応について、レジストリのDataBasePathの値に格納されている値が示す「フォルダ」の下にあるservicesというファイルにより参照している。

上記はperlのone linerだが、C言語で書いても同じ結果だった。

#include  
#include  
 
main(int argc, char **argv) 
{ 
    struct servent *servent; 
 
    if (argc != 2) {
	fprintf(stderr, "usage: %s \n", argv[0]);
	exit(1);
    }
    if ( (servent = getservbyname(argv[1], "tcp")) != NULL) { 
	printf("%s\n", servent->s_name);	/* official service name */
	/* char	**s_aliases;	/* alias list */
	printf("%d\n", ntohs(servent->s_port));		/* port # */
	printf("%s\n", servent->s_proto);	/* protocol to use */
    }
    else {
	perror(argv[1]);
    }
}