oskit/oskit-20020317/netdisk/misc.c

232 lines
5.4 KiB
C
Executable File

/*
* Copyright (c) 1997, 2000, 2001 University of Utah and the Flux Group.
* All rights reserved.
*
* This file is part of the Flux OSKit. The OSKit is free software, also known
* as "open source;" you can redistribute it and/or modify it under the terms
* of the GNU General Public License (GPL), version 2, as published by the Free
* Software Foundation (FSF). To explore alternate licensing terms, contact
* the University of Utah at csl-dist@cs.utah.edu or +1-801-585-3271.
*
* The OSKit is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GPL for more details. You should have
* received a copy of the GPL along with the OSKit; see the file COPYING. If
* not, write to the FSF, 59 Temple Place #330, Boston, MA 02111-1307, USA.
*/
/* Modified from FreeBSD 2.1 sys/i386/boot/netboot */
/**************************************************************************
NETBOOT - BOOTP/TFTP Bootstrap Program
Author: Martin Renters
Date: Dec/93
**************************************************************************/
#include <string.h> /* memcpy */
#include <strings.h> /* strsep */
#include <stdarg.h> /* va_list */
#include <stdio.h> /* putchar */
#include <sys/types.h>
#include <netinet/in.h> /* INADDR_NONE */
#include <arpa/inet.h> /* htonl */
#include <netdb.h>
#include "misc.h"
/**************************************************************************
PRINTF and friends
Formats:
%X - 4 byte ASCII (8 hex digits)
%x - 2 byte ASCII (4 hex digits)
%b - 1 byte ASCII (2 hex digits)
%d - decimal
%c - ASCII char
%s - ASCII string
%I - Internet address in x.x.x.x notation
%L - Binary long
%S - String (multiple of 4 bytes) preceded with 4 byte
binary length
%M - Copy memory. Takes two args, len and ptr
**************************************************************************/
static char *
do_netprintf(char *buf, char *fmt, va_list args)
{
static char hex[]="0123456789ABCDEF";
register char *p;
char tmp[16];
while (*fmt) {
if (*fmt == '%') { /* switch() uses more space */
fmt++;
if (*fmt == 'L') {
register int h = va_arg(args, int);
*(buf++) = h>>24;
*(buf++) = h>>16;
*(buf++) = h>>8;
*(buf++) = h;
}
if (*fmt == 'S') {
register int len = 0;
char *lenptr = buf;
p = va_arg(args, char *);
buf += 4;
while (*p) {
*(buf++) = *p++;
len ++;
}
*(lenptr++) = len>>24;
*(lenptr++) = len>>16;
*(lenptr++) = len>>8;
*lenptr = len;
while (len & 3) {
*(buf++) = 0;
len ++;
}
}
if (*fmt == 'M') {
register int len = va_arg(args, int);
memcpy(buf, va_arg(args, void *), len);
buf += len;
}
if (*fmt == 'X') {
register int h = va_arg(args, int);
*(buf++) = hex[(h>>28)& 0x0F];
*(buf++) = hex[(h>>24)& 0x0F];
*(buf++) = hex[(h>>20)& 0x0F];
*(buf++) = hex[(h>>16)& 0x0F];
*(buf++) = hex[(h>>12)& 0x0F];
*(buf++) = hex[(h>>8)& 0x0F];
*(buf++) = hex[(h>>4)& 0x0F];
*(buf++) = hex[h& 0x0F];
}
if (*fmt == 'x') {
register int h = va_arg(args, int);
*(buf++) = hex[(h>>12)& 0x0F];
*(buf++) = hex[(h>>8)& 0x0F];
*(buf++) = hex[(h>>4)& 0x0F];
*(buf++) = hex[h& 0x0F];
}
if (*fmt == 'b') {
register int h = va_arg(args, int);
*(buf++) = hex[(h>>4)& 0x0F];
*(buf++) = hex[h& 0x0F];
}
if (*fmt == 'd') {
register int dec = va_arg(args, int);
p = tmp;
if (dec < 0) {
*(buf++) = '-';
dec = -dec;
}
do {
*(p++) = '0' + (dec%10);
dec = dec/10;
} while(dec);
while ((--p) >= tmp) *(buf++) = *p;
}
if (*fmt == 'I') {
register int i = va_arg(args, int);
buf = netsprintf(buf,"%d.%d.%d.%d",
(i>>24) & 0x00FF,
(i>>16) & 0x00FF,
(i>>8) & 0x00FF,
i & 0x00FF);
}
if (*fmt == 'c')
*(buf++) = va_arg(args, int);
if (*fmt == 's') {
p = va_arg(args, char *);
while (*p) *(buf++) = *p++;
}
} else *(buf++) = *fmt;
fmt++;
}
va_end(args);
*buf = 0;
return(buf);
}
char *
netsprintf(char *buf, char *fmt, ...)
{
va_list args;
char *r;
va_start(args, fmt);
r = do_netprintf(buf, fmt, args);
va_end(args);
return r;
}
void
netprintf(char *fmt, ...)
{
va_list args;
char buf[512], *p;
va_start(args, fmt);
p = buf;
do_netprintf(buf, fmt, args);
while (*p) putchar(*p++);
va_end(args);
}
/*
* Host lookup kludge since it is hard to use the oskit's gethostbyname
* since we don't use the BSD socket stuff.
* If you fix this, fix the helpstring in main.c too.
*/
unsigned long
hostlookup(const char *host_or_ip)
{
struct hostent *he;
he = gethostbyname(host_or_ip);
if (he) {
struct in_addr in;
memcpy ((char *)&in, he->h_addr, he->h_length);
return ntohl(in.s_addr);
}
return INADDR_NONE;
}
/*
* Take a string and set the IP, dir, and name components.
*/
int
parse_filespec(char *cmdline, unsigned int *ip, char **dir, char **name)
{
char *p = cmdline;
char *host_or_ip;
host_or_ip = strsep(&p, ":");
if (! p)
return 0;
*ip = hostlookup(host_or_ip);
if (*ip == INADDR_NONE)
return 0;
if (p[0] != '/')
return 0;
*dir = p;
p = strrchr(*dir, '/');
if (! p)
return 0;
*p++ = '\0';
if (! *p)
return 0;
*name = p;
/* Allow the case ip:/foo; we might have just NULified that slash. */
if ((*dir)[0] == '\0')
*dir = "/";
return 1;
}