close_s() is calling free even though a buffer has not been allocated. I
have attached a fixed sockserv.c
Tnx es 73
de K0NY Winona, MN USA
--
Mr. Clare Jarvis
Jarvis Computer Software
PO Box 1264
Winona MN 55987-7264
(507) 454 2575
Reply to: [EMAIL PROTECTED]
/*
* Tlf - contest logging program for amateur radio operators
* Copyright (C) 2001-2002-2003 Rein Couperus <[EMAIL PROTECTED]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* Socket server (and client!) utilities, */
/* intended to simplify the porting of JNOS servers and clients to Unix */
/* Written by N2RJT - Dave Brown */
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <memory.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <errno.h>
#include "sockserv.h"
#include "main.h"
/* This structure holds the buffers for each open socket. It was an */
/* afterthought, so it is not used for anything else. The array is only */
/* allocated when the socket is opened, and freed when the socket is closed. */
struct sockbuffer {
char *buf;
int buflen;
int fragment;
int whole_lines;
int cr_translation;
} sockbuf[FD_SETSIZE];
/* This array holds the SERVED sockets, that can be connected to. */
/* It does not hold CLIENT sockets. */
static int lsock[MAX_SERVED_SOCKETS];
static int initialized = 0;
static int nlsock = 0;
static struct timeval *socktimeval = NULL;
static struct timeval *selecttimeval = NULL;
static struct sockaddr_in udp_peer;
static int udpport = 0;
static unsigned int peerlen = 0;
int udp_socket = -1;
static fd_set readfds, openfds;
static int nfds = 0;
static int ifds = -1;
#define SOBUF 512
#define NULLCHAR (char *) NULL
#define myperror perror
void setlinemode(int s, int tf)
{
sockbuf[s].whole_lines = tf;
}
int close_s(int s)
{
FD_CLR(s, &openfds);
if ( 0 != sockbuf[s].buflen )
free(sockbuf[s].buf);
sockbuf[s].buflen = 0;
sockbuf[s].fragment = 0;
shutdown(s, 2);
return close(s);
}
void fds_copy(fd_set *tofd, fd_set *fmfd)
{
memcpy(tofd, fmfd, sizeof(fd_set));
}
int usputs(int s, char *buf)
{
int len, i;
len = strlen(buf);
if (sockbuf[s].cr_translation) {
for (i = 0; i < len; i++) {
if (buf[i] == '\n')
usputb(s, "\r\n", 2);
else
usputb(s, buf + i, 1);
}
return len;
} else
return usputb(s, buf, len);
}
int usputb(int s, char *buf, int buflen)
{
extern WINDOW *sclwin;
strcpy(sockserv_error, "");
if (udp_socket == s) {
peerlen = sizeof(udp_peer);
if (sendto(s, buf, buflen, 0, (struct sockaddr *) &udp_peer,
peerlen) < 0) {
myperror("usputb:sendto");
return -1;
} else
return buflen;
} else {
if (write(s, buf, buflen) < 0) {
// myperror("usputb:write");
wprintw(sclwin, "Not connected !!");
wrefresh(sclwin);
sleep(2);
return -1;
} else
return buflen;
}
}
int usvprintf(int s, char *fmt, va_list args)
{
int len, withargs;
char *buf;
if (strchr(fmt, '%') == NULLCHAR) {
/* Common case optimization: no args */
withargs = 0;
buf = fmt;
len = strlen(fmt);
} else {
/* Use a default value that is huge */
withargs = 1;
buf = (char *) malloc(SOBUF);
if ((len = vsprintf(buf, fmt, args)) >= SOBUF) {
/* It's too late to be sorry. He's dead, Jim */
fprintf(stderr, "usprintf() exceeded %d bytes (%d bytes)\n",
SOBUF, len);
exit(1);
}
}
len = usputs(s, buf);
if (withargs)
free(buf);
return len;
}
int usprintf(int s, char *fmt,...)
{
va_list args;
int len;
va_start(args, fmt);
len = usvprintf(s, fmt, args);
va_end(args);
return len;
}
int tprintf(char *fmt,...)
{
va_list args;
int len;
va_start(args, fmt);
len = usvprintf(ifds, fmt, args);
va_end(args);
return len;
}
int tputstr(char *buf)
{
return usputs(ifds, buf);
}
int tputc(char c)
{
char ic;
ic = c;
return usputb(ifds, &ic, 1);
}
static void (*login[MAX_SERVED_SOCKETS]) (int i);
char sockserv_error[80];
static int initialize(void)
{
int i;
strcpy(sockserv_error, "");
/* First-time initialization */
if (!initialized) {
initialized = 1;
for (i = 0; i < FD_SETSIZE; i++) {
sockbuf[i].buf = NULL;
sockbuf[i].buflen = 0;
sockbuf[i].fragment = 0;
sockbuf[i].whole_lines = 0;
sockbuf[i].cr_translation = 0;
}
FD_ZERO(&openfds);
}
return 0;
}
int startup(int portnum, void (*newin) (int))
{
struct sockaddr_in sin;
initialize();
while ((lsock[nlsock] = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
if (errno != EINTR) {
myperror("startup: socket");
exit(1);
}
}
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(portnum);
setsockopt(lsock[nlsock], SOL_SOCKET, SO_REUSEADDR, (char *) 0, 0);
while (bind(lsock[nlsock], (struct sockaddr *) &sin, sizeof(sin)) == -1) {
if (errno != EINTR) {
myperror("startup: bind");
exit(1);
}
}
while (listen(lsock[nlsock], 5) == -1) {
if (errno != EINTR) {
myperror("startup: listen");
exit(1);
}
}
login[nlsock] = newin;
FD_SET(lsock[nlsock], &openfds);
sockbuf[lsock[nlsock]].buf = (char *) malloc(sizeof(char) * SOBUF);
sockbuf[lsock[nlsock]].buflen = 0;
sockbuf[lsock[nlsock]].fragment = 0;
sockbuf[lsock[nlsock]].whole_lines = 0;
sockbuf[lsock[nlsock]].cr_translation = 0;
if (nfds <= lsock[nlsock])
nfds = lsock[nlsock] + 1;
if (ifds == -1)
ifds = nfds - 1;
nlsock++;
return lsock[nlsock-1];
}
int startup_udp(int portnum)
{
struct sockaddr_in sin;
initialize();
if (udp_socket == -1) {
while ((udp_socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
if (errno != EINTR) {
myperror("startup_udp: socket");
exit(1);
}
}
}
if (portnum && !udpport) {
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(portnum);
while (bind(udp_socket, (struct sockaddr *) &sin, sizeof(sin)) == -1) {
if (errno != EINTR) {
myperror("startup_udp: bind");
exit(1);
}
}
}
udpport = portnum;
FD_SET(udp_socket, &openfds);
sockbuf[udp_socket].buf = (char *) malloc(sizeof(char) * SOBUF);
sockbuf[udp_socket].buflen = 0;
sockbuf[udp_socket].fragment = 0;
sockbuf[udp_socket].whole_lines = 0;
sockbuf[udp_socket].cr_translation = 0;
if (nfds <= udp_socket)
nfds = udp_socket + 1;
if (ifds == -1)
ifds = nfds - 1;
return udp_socket;
}
int recvline(int *fd, char *buf, int buflen)
{
unsigned int len;
int ns, i;
struct sockaddr_in client;
char *nl;
strcpy(sockserv_error, "");
if (selecttimeval != NULL && socktimeval != NULL) {
selecttimeval->tv_sec = socktimeval->tv_sec;
selecttimeval->tv_usec = socktimeval->tv_usec;
}
if (ifds == -1)
ifds = nfds - 1;
while (1) {
if (++ifds == nfds) {
fds_copy(&readfds, &openfds);
while ((ifds = select(nfds, &readfds, (fd_set *) NULL, (fd_set *) NULL,
selecttimeval)) < 0) {
if (errno != EINTR) {
myperror("recvline: select");
exit(1);
}
fds_copy(&readfds, &openfds);
}
if (!ifds)
return -2;
ifds = 0;
} else if (FD_ISSET(ifds, &readfds)) {
for (i = 0; i < nlsock; i++)
if (lsock[i] == ifds)
break;
if (i < nlsock) {
if (FD_ISSET(lsock[i], &readfds)) {
len = sizeof(client);
while ((ns = accept(lsock[i], (struct sockaddr *) &client,
&len)) == -1) {
if (errno != EINTR) {
myperror("recvline: accept");
exit(1);
}
}
if (nfds <= ns)
nfds = ns + 1;
FD_SET(ns, &openfds);
sockbuf[ns].buf = (char *) malloc(sizeof(char) * SOBUF);
sockbuf[ns].buflen = 0;
sockbuf[ns].fragment = 0;
sockbuf[ns].whole_lines = sockbuf[lsock[i]].whole_lines;
sockbuf[ns].cr_translation = 0;
(*login[i]) (ns);
}
FD_CLR(lsock[i], &readfds);
} else {
if (!sockbuf[ifds].buflen) {
if (ifds == udp_socket) {
peerlen = sizeof(udp_peer);
while ((sockbuf[ifds].buflen =
recvfrom(ifds, sockbuf[ifds].buf + sockbuf[ifds].fragment,
SOBUF - 1, 0, (struct sockaddr *) &udp_peer, &peerlen)) == -1) {
if (errno != EINTR) {
break;
}
peerlen = sizeof(udp_peer);
}
} else {
while ((sockbuf[ifds].buflen =
read(ifds, sockbuf[ifds].buf + sockbuf[ifds].fragment,
SOBUF - 1)) == -1) {
if (errno != EINTR) {
break;
}
}
}
if (sockbuf[ifds].buflen <= 0) {
if (ifds != udp_socket) {
FD_CLR(ifds, &openfds);
free(sockbuf[ifds].buf);
}
sockbuf[ifds].buflen = 0;
*fd = ifds;
buf[0] = '\0';
return -1;
} else {
sockbuf[ifds].buflen += sockbuf[ifds].fragment;
sockbuf[ifds].fragment = 0;
sockbuf[ifds].buf[sockbuf[ifds].buflen] = '\0';
}
}
nl = strchr(sockbuf[ifds].buf, '\n');
if (nl == NULL && sockbuf[ifds].whole_lines) {
nl = strchr(sockbuf[ifds].buf, '\r');
if (nl) {
sockbuf[ifds].cr_translation = 1;
printf("Enabling CR translation for socket %d\n", ifds);
}
}
if (nl == NULL && sockbuf[ifds].whole_lines) {
sockbuf[ifds].fragment = sockbuf[ifds].buflen;
sockbuf[ifds].buflen = 0;
continue;
} else {
if (sockbuf[ifds].whole_lines) {
*nl = '\0';
len = strlen(sockbuf[ifds].buf) + 1;
} else if (sockbuf[ifds].buflen > buflen)
len = buflen;
else
len = sockbuf[ifds].buflen;
memcpy(buf, sockbuf[ifds].buf, len);
if (sockbuf[ifds].buflen > len)
memcpy(sockbuf[ifds].buf, sockbuf[ifds].buf + len,
sockbuf[ifds].buflen - len);
sockbuf[ifds].buflen -= len;
*fd = ifds;
if (sockbuf[ifds].buflen)
ifds--;
}
return len;
}
}
}
}
long resolve(char *hostname)
{
unsigned long int haddr;
unsigned char a[4];
int i;
char *s, *d, *c;
int valid = 1;
if (initialize())
return -1L;
s = hostname;
for (i = 0; i < 4; i++) {
if (s) {
d = strchr(s, '.');
if (!d)
d = s + strlen(s);
for (c = s; c < d; c++)
if (*c < '0' || *c > '9')
valid = 0;
if (!valid)
break;
a[i] = atoi(s);
s = strchr(s, '.');
if (s)
s++;
} else {
valid = 0;
break;
a[i] = 0;
}
}
if (valid) {
haddr = a[3] + 256 * (a[2] + 256 * (a[1] + 256 * a[0]));
haddr = htonl(haddr);
} else {
struct hostent *hp;
if ((hp = gethostbyname(hostname)) == NULL) {
herror("resolve: gethostbyname");
return -1L;
}
memcpy(&haddr, hp->h_addr, hp->h_length);
}
strcpy(sockserv_error, "");
return (haddr);
}
int startcliaddr(int family, unsigned long int addr, unsigned short int portnum)
{
extern WINDOW *sclwin;
int s;
struct sockaddr_in sin;
initialize();
memset(&sin, 0, sizeof(sin));
sin.sin_addr.s_addr = addr;
sin.sin_family = family;
sin.sin_port = htons(portnum);
while ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
if (errno != EINTR) {
wprintw(sclwin, "socket failure");
wrefresh(sclwin);
sleep(1);
return -1;
}
}
while (connect(s, (struct sockaddr *) &sin, sizeof(sin)) == -1) {
if (errno != EINTR) {
return (-1);
}
}
if (nfds <= s)
nfds = s + 1;
if (ifds == -1)
ifds = nfds - 1;
FD_SET(s, &openfds);
wprintw(sclwin, "still here...");
wrefresh(sclwin);
sleep(2);
sockbuf[s].buf = (char *) malloc(sizeof(char) * SOBUF);
// sockbuf[s].buf = (char *)socketbuffer; // debug
sockbuf[s].buflen = 0;
sockbuf[s].fragment = 0;
sockbuf[s].whole_lines = 0;
wprintw(sclwin, "not dead...");
wrefresh(sclwin);
sleep(1);
return s;
}
int startcli(void)
{
extern char pr_hostaddress[];
extern int portnum;
unsigned long int haddr;
int addrtype;
haddr = resolve(pr_hostaddress);
addrtype = AF_INET;
return (startcliaddr(addrtype, haddr, (short) portnum));
}
void socktimeout(int msec)
{
if (!socktimeval)
socktimeval = (struct timeval *) malloc(sizeof(struct timeval));
if (!selecttimeval)
selecttimeval = (struct timeval *) malloc(sizeof(struct timeval));
socktimeval->tv_sec = msec / 1000L;
socktimeval->tv_usec = (msec % 1000L) * 1000L;
}
void nosocktimeout(void)
{
free(socktimeval);
socktimeval = NULL;
free(selecttimeval);
selecttimeval = NULL;
}
void set_udp_peer(long address, int portnum)
{
memset(&udp_peer, 0, sizeof(udp_peer));
udp_peer.sin_addr.s_addr = address;
udp_peer.sin_family = AF_INET;
udp_peer.sin_port = htons(portnum);
peerlen = sizeof(udp_peer);
}
void get_udp_peer(long *address, int *portnum)
{
*address = udp_peer.sin_addr.s_addr;
*portnum = 0;
*portnum = ntohs(udp_peer.sin_port);
}
_______________________________________________
Tlf-devel mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/tlf-devel