You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

414 lines
9.1 KiB

/*
* $Id: utils.c,v 1.47 2006/10/12 14:21:23 desrod Exp $
*
* utils.c: misc. stuff for dealing with packets.
*
* Portions Copyright (c) 1996, D. Jeff Dionne.
* Portions Copyright (c) 1996, Kenneth Albanowski
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This library 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 GNU Library
* General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <string.h>
#include "pi-debug.h"
#include "pi-source.h"
void pi_timeout_to_timespec(int timeout, struct timespec *ts);
void get_pilot_rate(int *establishrate, int *establishhighrate);
int pi_timespec_to_timeout(const struct timespec *ts);
int pi_timeout_expired(const struct timespec *ts);
size_t palm_strftime(char *s, size_t max, const char *fmt,
const struct tm *tm);
/* this routine ruthlessly stolen verbatim from Brian J. Swetland */
/***********************************************************************
*
* Function: crc16
*
* Summary: Implementation of the CRC16 Cyclic Redundancy Check
*
* Parameters: None
*
* Returns: CRC + NULL
*
***********************************************************************/
int crc16(unsigned char *ptr, int count)
{
int crc,
i;
crc = 0;
while (--count >= 0) {
crc = crc ^ (int) *ptr++ << 8;
for (i = 0; i < 8; ++i)
if (crc & 0x8000)
crc = crc << 1 ^ 0x1021;
else
crc = crc << 1;
}
return (crc & 0xFFFF);
}
void get_pilot_rate(int *establishrate, int *establishhighrate)
{
/* Default PADP connection rate */
char *rate_env = getenv("PILOTRATE");
if (rate_env) {
/* Establish high rate */
if (rate_env[0] == 'H') {
*establishrate = atoi(rate_env + 1);
*establishhighrate = 1;
} else {
*establishrate = atoi(rate_env);
*establishhighrate = 0;
}
}
else {
*establishrate = -1;
}
}
#ifndef HAVE_STRDUP
char *strdup(const char *s)
{
char *result;
size_t size = strlen(s) + 1;
if (!(result = malloc(size))) {
return NULL;
}
memcpy(result, s, size);
return result;
}
#endif
/* Borrowed from GNU sh-utils, and then probably from GNU libc */
#ifndef HAVE_PUTENV
#if HAVE_GNU_LD
# define environ __environ
#else
extern char **environ;
#endif
/* Put STRING, which is of the form "NAME=VALUE", in the environment */
int putenv(const char *string)
{
const char *const name_end = strchr(string, '=');
register size_t size;
register char **ep;
if (name_end == NULL) {
/* Remove the variable from the environment. */
size = strlen(string);
for (ep = environ; *ep != NULL; ++ep)
if (!strncmp(*ep, string, size)
&& (*ep)[size] == '=') {
while (ep[1] != NULL) {
ep[0] = ep[1];
++ep;
}
*ep = NULL;
return 0;
}
}
size = 0;
for (ep = environ; *ep != NULL; ++ep)
if (!strncmp(*ep, string, name_end - string)
&& (*ep)[name_end - string] == '=')
break;
else
++size;
if (*ep == NULL) {
static char **last_environ = NULL;
char **new_environ =
(char **) malloc((size + 2) * sizeof(char *));
if (new_environ == NULL)
return -1;
(void) memcpy((void *) new_environ, (void *) environ,
size * sizeof(char *));
new_environ[size] = (char *) string;
new_environ[size + 1] = NULL;
if (last_environ != NULL)
free((void *) last_environ);
last_environ = new_environ;
environ = new_environ;
} else
*ep = (char *) string;
return 0;
}
#endif
#ifdef OS2
/* Replacement version of getenv(), because the one in the EMX 0.9c, fix03
dist appears to be busted when called from inside a DLL. (MJJ) */
char *getenv(const char *envar)
{
APIRET rc;
unsigned char *envstring;
/* just call the OS/2 function directly */
rc = DosScanEnv(envar, &envstring);
if (rc)
return NULL;
else
return envstring;
}
#endif
#ifndef HAVE_INET_ATON
/***********************************************************************
*
* Function: inet_aton
*
* Summary: Manipulate our network address information
*
* Parameters: None
*
* Returns: Nothing
*
***********************************************************************/
int inet_aton(const char *cp, struct in_addr *addr)
{
register u_long val;
register int base;
register int n;
register char c;
u_int parts[4];
register u_int *pp = parts;
for (;;) {
/* Collect number up to ``.''. Values are specified as for
C: 0x=hex, 0=octal, other=decimal. */
val = 0;
base = 10;
if (*cp == '0') {
if (*++cp == 'x' || *cp == 'X')
base = 16, cp++;
else
base = 8;
}
while ((c = *cp) != '\0') {
if (isascii(c) && isdigit(c)) {
val = (val * base) + (c - '0');
cp++;
continue;
}
if (base == 16 && isascii(c) && isxdigit(c)) {
val =
(val << 4) + (c + 10 -
(islower(c) ? 'a' :
'A'));
cp++;
continue;
}
break;
}
if (*cp == '.') {
/* Internet format:
a.b.c.d
a.b.c (with c treated as 16-bits)
a.b (with b treated as 24 bits) */
if (pp >= parts + 3 || val > 0xff)
return (0);
*pp++ = val, cp++;
} else
break;
}
/* Check for trailing characters. */
if (*cp && (!isascii(*cp) || !isspace(*cp)))
return (0);
/* Concoct the address according to the number of parts specified. */
n = pp - parts + 1;
switch (n) {
case 1: /* a -- 32 bits */
break;
case 2: /* a.b -- 8.24 bits */
if (val > 0xffffff)
return (0);
val |= parts[0] << 24;
break;
case 3: /* a.b.c -- 8.8.16 bits */
if (val > 0xffff)
return (0);
val |= (parts[0] << 24) | (parts[1] << 16);
break;
case 4: /* a.b.c.d -- 8.8.8.8 bits */
if (val > 0xff)
return (0);
val |=
(parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
break;
}
if (addr)
addr->s_addr = htonl(val);
return (1);
}
#endif
char *printlong(unsigned long val)
{
static char buf[5];
set_long(buf, val);
buf[4] = 0;
return buf;
}
unsigned long makelong(char *c)
{
int l = strlen(c);
char c2[4];
if (l >= 4)
return get_long(c);
memset(c2, ' ', 4);
memcpy(c2, c, (size_t)l);
return get_long(c2);
}
double get_float(void *buffer)
{
unsigned char *buf = buffer;
unsigned long frac = get_long(buf);
int expr = get_sshort(buf + 4),
sign = get_byte(buf + 6);
/* if (sign) f = frac; else f = -frac; return ldexp(f, exp); */
return ldexp(sign ? (double) frac : -(double) frac, expr);
}
void set_float(void *buffer, double value)
{
int expr,
sign;
unsigned char *buf = buffer;
unsigned long frac;
double r;
/* Take absolute */
if (value < 0) {
sign = 0;
value = -value;
} else
sign = 0xFF;
/* Convert mantissa to 32-bit integer, and take exponent */
r = ldexp(frexp(value, &expr), 32);
frac = (unsigned long)r;
expr -= 32;
/* Store values in buffer */
set_long(buf, frac);
set_sshort(buf + 4, expr);
set_byte(buf + 6, sign);
set_byte(buf + 7, 0);
}
int compareTm(struct tm *a, struct tm *b)
{
int date;
date = a->tm_year - b->tm_year;
if (date)
return date;
date = a->tm_mon - b->tm_mon;
if (date)
return date;
date = a->tm_mday - b->tm_mday;
if (date)
return date;
date = a->tm_hour - b->tm_hour;
if (date)
return date;
date = a->tm_min - b->tm_min;
if (date)
return date;
date = a->tm_sec - b->tm_sec;
return date;
}
void pi_timeout_to_timespec(int timeout, struct timespec *ts)
{
/* convert a timeout value (in milliseconds) to an absolute timespec */
struct timeval now;
gettimeofday(&now, NULL);
ts->tv_sec = now.tv_sec + (long)(timeout / 1000);
ts->tv_nsec = (now.tv_usec + ((long)timeout % 1000) * 1000) * 1000;
if (ts->tv_nsec >= 1000000000) {
ts->tv_nsec -= 1000000000;
ts->tv_sec++;
}
}
int pi_timespec_to_timeout(const struct timespec *ts)
{
/* convert an absolute timespec to a timeout value (in milliseconds) from now
* returns a negative if the timeout expired already
*/
struct timeval now;
gettimeofday(&now, NULL);
return (int)(((double)ts->tv_sec * 1000.0 + (double)ts->tv_nsec / 1000000.0) -
((double)now.tv_sec * 1000.0 + (double)now.tv_usec / 1000.0));
}
int pi_timeout_expired(const struct timespec *ts)
{
return pi_timespec_to_timeout(ts) <= 0;
}
/* Fix some issues with some locales reporting 2 or 4 digit years */
size_t palm_strftime(char *s, size_t max, const char *fmt,
const struct tm *tm) {
return strftime(s, max, fmt, tm);
}
/* vi: set ts=8 sw=4 sts=4 noexpandtab: cin */
/* ex: set tabstop=4 expandtab: */
/* Local Variables: */
/* indent-tabs-mode: t */
/* c-basic-offset: 8 */
/* End: */