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.
(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.)
--
Intel are signing my paycheques ... these opinions are still mine
"Bill, look, we understand that you're interested in selling us this
operating system, but compare it to ours. We can't possibly take such
a retrograde step."
/*
* libc/inet/ethers.c
*
* Programmatic interface for the /etc/ethers file
*
* Copyright 2007 by Matthew Wilcox <[EMAIL PROTECTED]>
*
* 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
[email protected]
http://busybox.net/cgi-bin/mailman/listinfo/uclibc