xref: /plan9/sys/src/ape/lib/bsd/getprotobyname.c (revision 96cbc34f1b36a29efdcfd47b10e70703a690febc)
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 
27 struct protoent *getprotobyname(const char *name) {
28 	int fd, i, m;
29 	char *p, *bp;
30 	int nn, na;
31 	unsigned long x;
32 	static char buf[1024], proto[1024];
33 	static char *nptr[Nname+1];
34 
35 	/* connect to server */
36 	fd = open("/net/cs", O_RDWR);
37 	if(fd < 0){
38 		_syserrno();
39 		h_errno = NO_RECOVERY;
40 		return 0;
41 	}
42 
43 	/* construct the query, always expect a protocol# back */
44 	snprintf(buf, sizeof buf, "!protocol=%s ipv4proto=*", name);
45 
46 	/* query the server */
47 	if(write(fd, buf, strlen(buf)) < 0){
48 		_syserrno();
49 		h_errno = TRY_AGAIN;
50 		return 0;
51 	}
52 	lseek(fd, 0, 0);
53 	for(i = 0; i < sizeof(buf)-1; i += m){
54 		m = read(fd, buf+i, sizeof(buf) - 1 - i);
55 		if(m <= 0)
56 			break;
57 		buf[i+m++] = ' ';
58 	}
59 	close(fd);
60 	buf[i] = 0;
61 
62 	/* parse the reply */
63 	nn = na = 0;
64 	for(bp = buf;;){
65 		p = strchr(bp, '=');
66 		if(p == 0)
67 			break;
68 		*p++ = 0;
69 		if(strcmp(bp, "protocol") == 0){
70 			if(!nn)
71 				r.p_name = p;
72 			if(nn < Nname)
73 				nptr[nn++] = p;
74 		} else if(strcmp(bp, "ipv4proto") == 0){
75 			r.p_proto = atoi(p);
76 			na++;
77 		}
78 		while(*p && *p != ' ')
79 			p++;
80 		if(*p)
81 			*p++ = 0;
82 		bp = p;
83 	}
84 	nptr[nn] = 0;
85 	r.p_aliases = nptr;
86 	if (nn+na == 0)
87 		return 0;
88 
89 	return &r;
90 }
91