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 }