• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #define _BSD_SOURCE
2 #include<netdb.h>
3 #include<errno.h>
4 #include<stdlib.h>
5 #include<stdio.h>
6 #include<string.h>
7 
8 #define SERV_FILE_PATH  "/etc/services"
9 #define BUFFER_SIZE     200
10 #define MAX_PORT        65535
11 #define MAX_ALIAS_NO    10
12 
13 struct servdata
14 {
15 	FILE *servf;
16 	int stayopen;
17 	struct servent se;
18 	char buf[BUFFER_SIZE];
19 	char *alias_list[MAX_ALIAS_NO + 1];
20 };
21 static struct servdata *sd = NULL;
22 
servent_resolv()23 static int servent_resolv()
24 {
25 	if (sd->buf[0] == '#')
26 		return -1;
27 	char *ch, *temp, *ptr = NULL;
28 	ch = strchr(sd->buf, '#');
29 	if (ch)
30 		*ch = '\0';
31 	ch = strtok_r(sd->buf, " \t\n", &ptr);
32 	temp = strtok_r(NULL, " \t\n", &ptr);
33 	if (!ch || !temp)
34 		return -1;
35 
36 	sd->se.s_name = ch;
37 	ch = strchr(temp, '/');
38 	if (ch == NULL)
39 		return -1;
40 	*ch++ = '\0';
41 	sd->se.s_port = atoi(temp);
42 	if (sd->se.s_port < 1 || sd->se.s_port > MAX_PORT)
43 		return -1;
44 	sd->se.s_port = htons(sd->se.s_port);
45 	if (strcmp(ch, "tcp") != 0 && strcmp(ch, "udp") != 0)
46 		return -1;
47 	sd->se.s_proto = ch;
48 
49 	int i = 0;
50 	while (i < MAX_ALIAS_NO) {
51 		ch = strtok_r(NULL, " \t\n", &ptr);
52 		sd->alias_list[i++] = ch;
53 	}
54 	sd->alias_list[MAX_ALIAS_NO] = NULL;
55 	sd->se.s_aliases = sd->alias_list;
56 	return 0;
57 }
58 
getservent(void)59 struct servent *getservent(void)
60 {
61 	if (sd == NULL) {
62 		if ((sd = malloc(sizeof(struct servdata))) == NULL) {
63 			errno = ENOMEM;
64 			return NULL;
65 		}
66 		sd->servf = NULL;
67 		sd->stayopen = 0;
68 	}
69 	if (!sd->servf && !(sd->servf = fopen(SERV_FILE_PATH, "r"))) {
70 		errno = ENOENT;
71 		free(sd);
72 		sd = NULL;
73 		return NULL;
74 	}
75 	do {
76 		if (!fgets(sd->buf, BUFFER_SIZE - 1, sd->servf)) {
77 			errno = EINVAL;
78 			return NULL;
79 		}
80 	} while (servent_resolv());
81 	return &(sd->se);
82 }
83 
endservent(void)84 void endservent(void)
85 {
86 	if (sd == NULL)
87 		return;
88 	if (sd->stayopen == 0) {
89 		if (sd->servf != NULL)
90 			fclose(sd->servf);
91 		free(sd);
92 		sd = NULL;
93 	}
94 }
95 
setservent(int stayopen)96 void setservent(int stayopen)
97 {
98 	if (sd == NULL) {
99 		if ((sd = malloc(sizeof(struct servdata))) == NULL) {
100 			errno = ENOMEM;
101 			return;
102 		}
103 		sd->servf = NULL;
104 	}
105 	if (!sd->servf)
106 		sd->servf = fopen(SERV_FILE_PATH, "r");
107 	else
108 		rewind(sd->servf);
109 	sd->stayopen = stayopen;
110 }