If you have used some of the password database functions like getpwent(3) before, the functions about to be described here will seem similar. The synopsis of the getservent(3) function is as
follows:
#include <netdb.h>
struct servent *getservent(void);
For each call to getservent(3), you are returned a pointer to a structure that represents one entry from the /etc/services file. When the end-of-file is reached, a NULL pointer is returned
(but see the caution that follows). If an error occurs, a NULL pointer is also returned, with the reason for the error posted to variable errno.
CAUTION
Even when the value of errno is zeroed prior to calling getservent(3), when end-of-file is reached and indicated by a NULL return pointer, the errno value for Red Hat Linux 6.0 is code ENOENT. Under other UNIX operating systems, such as HP-UX 10.2 and Sun Solaris 5.5.1, the errno value is left at zero when end-of-file is returned. This leads the author to speculate that this behavior is a bug, which might be corrected in a later release of Linux. When the pointer returned is not NULL, it points to the structure servent, as illustrated in Listing below
Example
The struct servent Structure
struct servent {
char *s_name; // official service name
char **s_aliases; // alias list
int s_port; // port number
char *s_proto; // protocol to use
}
CAUTION
Be careful to note that the value in s_port is already in network byte order. To print this value in printf(3), for example, make sure you convert this value back to host order by using ntohs(sp->s_port), for example. When setting the port number in a socket address, you merely assign this value as-is, since the port number is expected to be in network byte order. Listing later in this post shows an example of this use.
The structure member s_aliases is actually an array of character pointers. If sp points to the structure, and x is an int subscript, then you can iterate through each alias sp->s_alias[x], until you reach a NULL pointer. A NULL pointer marks the end of this alias list. Listing 7.2 shows a simple program that lists all /etc/services entries and their aliases, if any.
/*
* getservent.c:
* Example getservent(3) program:
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char **argv) {
int x;
struct servent *sp;
for (;;) {
errno = 0;
if ( !(sp = getservent()) ) {
break;
}
printf("%s:\n"
"\tPort: %d\n"
"\tProtocol: %s\n"
"\tAliases: ",
sp->s_name,
ntohs(sp->s_port),
sp->s_proto);
for ( x=0; sp->s_aliases[x] != NULL; ++x ) {
printf("%s ",sp->s_aliases[x]);
}
putchar('\n');
}
if ( errno != 0 && errno != ENOENT ) { /* For RH-6.0 */
fprintf(stderr,
"%s: getservent(3) %d\n",
strerror(errno),errno);
}
return 0;
}
/*
* OUTPUT
*
[sgupta@rhel55x86 chap7]$ gcc -o getservent getservent.c
[sgupta@rhel55x86 chap7]$ ./getservent
tcpmux:
Port: 1
Protocol: tcp
Aliases:
tcpmux:
Port: 1
Protocol: udp
Aliases:
rje:
Port: 5
Protocol: tcp
Aliases:
rje:
Port: 5
Protocol: udp
Aliases:
echo:
Port: 7
Protocol: tcp
Aliases:
echo:
Port: 7
Protocol: udp
Aliases:
discard:
Port: 9
Protocol: tcp
Aliases: sink null
iqobject:
Port: 48619
Protocol: udp
Aliases:
[sgupta@rhel55x86 chap7]$
*/
The error message ''Broken pipe" in Listing 7.3 is simply due to the head command being used (it closed the pipe early). There are some companions to the getservent(3) function, and these will be covered next.
No comments:
Post a Comment