xref: /plan9/sys/src/ape/lib/bsd/getprotobyname.c (revision 781103c4074deb8af160e8a0da2742ba6b29dc2b)
1 /* posix */
2 #include <sys/types.h>
3 #include <unistd.h>
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <fcntl.h>
7 #include <string.h>
8 #include <errno.h>
9 
10 /* bsd extensions */
11 #include <sys/uio.h>
12 #include <sys/socket.h>
13 #include <netinet/in.h>
14 #include <netdb.h>
15 
16 #include "priv.h"
17 
18 extern int h_errno;
19 
20 enum
21 {
22 	Nname= 6,
23 };
24 
25 static struct protoent r;
26 
getprotobyname(const char * name)27 struct protoent *getprotobyname(const char *name) {
28 	int fd, i, m;
29 	char *p, *bp;
30 	int nn, na;
31 	static char buf[1024], proto[1024];
32 	static char *nptr[Nname+1];
33 
34 	/* connect to server */
35 	fd = open("/net/cs", O_RDWR);
36 	if(fd < 0){
37 		_syserrno();
38 		h_errno = NO_RECOVERY;
39 		return 0;
40 	}
41 
42 	/* construct the query, always expect a protocol# back */
43 	snprintf(buf, sizeof buf, "!protocol=%s ipv4proto=*", name);
44 
45 	/* query the server */
46 	if(write(fd, buf, strlen(buf)) < 0){
47 		_syserrno();
48 		h_errno = TRY_AGAIN;
49 		return 0;
50 	}
51 	lseek(fd, 0, 0);
52 	for(i = 0; i < sizeof(buf)-1; i += m){
53 		m = read(fd, buf+i, sizeof(buf) - 1 - i);
54 		if(m <= 0)
55 			break;
56 		buf[i+m++] = ' ';
57 	}
58 	close(fd);
59 	buf[i] = 0;
60 
61 	/* parse the reply */
62 	nn = na = 0;
63 	for(bp = buf;;){
64 		p = strchr(bp, '=');
65 		if(p == 0)
66 			break;
67 		*p++ = 0;
68 		if(strcmp(bp, "protocol") == 0){
69 			if(!nn)
70 				r.p_name = p;
71 			if(nn < Nname)
72 				nptr[nn++] = p;
73 		} else if(strcmp(bp, "ipv4proto") == 0){
74 			r.p_proto = atoi(p);
75 			na++;
76 		}
77 		while(*p && *p != ' ')
78 			p++;
79 		if(*p)
80 			*p++ = 0;
81 		bp = p;
82 	}
83 	nptr[nn] = 0;
84 	r.p_aliases = nptr;
85 	if (nn+na == 0)
86 		return 0;
87 
88 	return &r;
89 }
90