Implementation of ether_line, ether_hostton and ether_ntohost

Carmelo Amoroso carmelo73 at gmail.com
Tue Feb 12 19:10:41 UTC 2008


Matthew Wilcox wrote:
> I want to be able to etherwake by hostname.  Since I've gone to the
> trouble of putting that information in /etc/ethers, I think my computer
> should jolly well not force me to type in meaningless strings of hex.
> 
> So here's an implementation (ethers.c) and two test programs
> (ethers-line-test.c and ethers-test.c) which exercise it a little.
> I'm not sure how to integrate all this into your build framework; seems
> to me you guys would be the experts at that ;-)
> 
> I hope you find my contribution useful.
> 
Let me see.... indeed I'm interested into etherwake too

Cheers,
Carmelo
> (Oh, and in case anyone's wondering, I have an agreement with my
> employer that this work I did in my own time belongs to me.)
> 
> 
> 
> ------------------------------------------------------------------------
> 
> /*
>  * libc/inet/ethers.c
>  *
>  * Programmatic interface for the /etc/ethers file
>  *
>  * Copyright 2007 by Matthew Wilcox <matthew at wil.cx>
>  *
>  * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
>  */
> 
> #include <ctype.h>
> #include <stdio.h>
> #include <string.h>
> #include <netinet/ether.h>
> 
> #ifndef ETHER_FILE_NAME
> #define ETHER_FILE_NAME	"/etc/ethers"
> #endif
> #define ETHER_LINE_LEN	256
> 
> /*
>  * Internal function which returns a pointer to the part of the line
>  * with the start of the hostname, or NULL if we couldn't parse the line.
>  * Note that this line may have a comment symbol on it somewhere; if so
>  * it will return NULL if the # is before or within the ether_addr, and
>  * succeed if the # is before or within the host.  It's up to the callers
>  * to be aware of this.
>  *
>  * I would have preferred to write a NUL to the location of the comment
>  * character, but ether_line takes a const argument.  See __ether_line_w.
>  */
> static const char *__ether_line(const char *line, struct ether_addr *addr)
> {
> 	struct ether_addr *res = ether_aton_r(line, addr);
> 	if (!res)
> 		return NULL;
> 
> 	while (*line && (*line != ' ') && (*line != '\t'))
> 		line++;
> 	while (*line && ((*line == ' ')	|| (*line == '\t')))
> 		line++;
> 	return (*line) ? line : NULL;
> }
> 
> /*
>  * Strips out the comment before calling __ether_line.  We can do this,
>  * since we know the buffer is writable.
>  */
> static const char *__ether_line_w(char *line, struct ether_addr *addr)
> {
> 	char *end = strchr(line, '#');
> 	if (!end)
> 		end = strchr(line, '\n');
> 	if (end)
> 		*end = '\0';
> 	return __ether_line(line, addr);
> }
> 
> int ether_line(const char *line, struct ether_addr *addr, char *hostname)
> {
> 	const char *name = __ether_line(line, addr);
> 	if (!name)
> 		return -1;
> 
> 	while (*name) {
> 		if ((*name == '#') || isspace(*name))
> 			break;
> 		*hostname++ = *name++;
> 	}
> 	*hostname = '\0';
> 
> 	return 0;
> }
> 
> int ether_ntohost(char *hostname, const struct ether_addr *addr)
> {
> 	int res = -1;
> 	FILE *fp;
> 	char buf[ETHER_LINE_LEN];
> 
> 	fp = fopen(ETHER_FILE_NAME, "r");
> 	if (!fp)
> 		return -1;
> 
> 	while (fgets(buf, sizeof(buf), fp)) {
> 		struct ether_addr tmp_addr;
> 		const char *cp = __ether_line_w(buf, &tmp_addr);
> 		if (!cp)
> 			continue;
> 		if (memcmp(addr, &tmp_addr, sizeof(tmp_addr)))
> 			continue;
> 
> 		strcpy(hostname, cp);
> 		res = 0;
> 		break;
> 	}
> 
> 	fclose(fp);
> 	return res;
> }
> 
> int ether_hostton(const char *hostname, struct ether_addr *addr)
> {
> 	int res = -1;
> 	FILE *fp;
> 	char buf[ETHER_LINE_LEN];
> 
> 	fp = fopen(ETHER_FILE_NAME, "r");
> 	if (!fp)
> 		return -1;
> 
> 	while (fgets(buf, sizeof(buf), fp)) {
> 		const char *cp = __ether_line_w(buf, addr);
> 		if (!cp)
> 			continue;
> 		if (strcasecmp(hostname, cp))
> 			continue;
> 
> 		res = 0;
> 		break;
> 	}
> 
> 	fclose(fp);
> 	return res;
> }
> 
> 
> ------------------------------------------------------------------------
> 
> #include <netinet/ether.h>
> #include <stdio.h>
> #include <sys/mman.h>
> #include <sys/types.h>
> #include <sys/stat.h>
> #include <fcntl.h>
> 
> #include "ethers.c"
> 
> int main(void)
> {
> 	struct ether_addr addr;
> 	char hostname[1024];
> 	int fd = open("ethers", O_RDONLY);
> 	const char *ethers = mmap(NULL, 100000, PROT_READ, MAP_SHARED, fd, 0);
> 
> 	ether_line(ethers, &addr, hostname);
> 
> 	printf("%s\n", hostname);
> 
> 	return 0;
> }
> 
> 
> ------------------------------------------------------------------------
> 
> #define ETHER_FILE_NAME "ethers"
> #include "ethers.c"
> 
> int main(void)
> {
> 	struct ether_addr addr;
> 	char host[256];
> 	int i, res = ether_hostton("teeth", &addr);
> 	if (res)
> 		return 1;
> 
> 	for (i = 0; i < 6; i++) {
> 		printf("%02x", addr.ether_addr_octet[i]);
> 		if (i == 5)
> 			printf(" ");
> 		else
> 			printf(":");
> 	}
> 
> 	res = ether_ntohost(host, &addr);
> 	if (res)
> 		return 1;
> 	printf("%s\n", host);
> 
> 	return 0;
> }
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> uClibc mailing list
> uClibc at uclibc.org
> http://busybox.net/cgi-bin/mailman/listinfo/uclibc




More information about the uClibc mailing list