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
414 lines
9.1 KiB
4 years ago
|
/*
|
||
|
* $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: */
|