diff --git a/src/libraries/libisc-new/demo/tcp.c b/src/libraries/libisc-new/demo/tcp.c new file mode 100644 index 0000000000000000000000000000000000000000..cf39316c90e0343f65635515a1be74af9b1af588 --- /dev/null +++ b/src/libraries/libisc-new/demo/tcp.c @@ -0,0 +1,225 @@ +/* +** tcp.c A small ISC TCP/IP subsystem demo program +** +** Copyright (c) 1992 Peter Eriksson and Per Cederqvist of the +** Lysator Academic Computer Association. +** +** history: +** 910306 pen initial coding +** 920211 pen cleaned up +*/ + +#include <stdio.h> +#include <errno.h> + +/* +** Could do a "#define ISC_UDGTYPE foobar" to change the type of +** the (IscSession) 'udg' member pointer type from "void *" to "foobar *". +*/ +#include <isc.h> + + +extern void abort(void); + +static IscConfig cfg = +{ + 1005, + { + 1001, + { -1, -1, -1, -1, -1 } + }, + { + 1001, + { NULL, NULL, NULL }, + NULL + } +}; + +#define TIMEOUT 30000 /* 30 seconds */ + +Perror(char *msg) +{ + perror(msg); + exit(1); +} + +void +main(void) +{ + IscMaster * mcb; /* ISC master control block */ + IscSession * scb; /* ISC session control block */ + IscEvent * ecb; /* ISC event control block */ + + + + puts("Beginning operation..."); + + /* + ** Initialize the ISC subsystem, create a Master Control Block + */ + if ((mcb = isc_initialize(&cfg)) == NULL) + Perror("isc_initialize"); + + puts("ISC initialized, connecting to remote service..."); + + /* + ** Establish a TCP session to a remote service (IRC) + */ + if ((scb = isc_opentcp(mcb, "obel5.ida.liu.se", "2000")) == NULL) + Perror("isc_opentcp"); + + puts("Connection initiated, enabling listening ports..."); + + /* + ** Enable remote connection attempts at port #20000 and #20001 + */ + if (isc_listentcp(mcb, "localhost", "20000") == NULL) + Perror("isc_listentcp-20000"); + + if (isc_listentcp(mcb, NULL, "20001") == NULL) + Perror("isc_listentcp-20001"); + + puts("Listening ports installed, entering main event loop..."); + + /* + ** Handle all events + */ + while (ecb = isc_getnextevent(mcb, TIMEOUT)) + { + switch (ecb->event) + { + case ISC_EVENT_CONNECTED: + puts("Server connection established."); + break; + + case ISC_EVENT_REJECTED: + puts("Server connection rejected."); + isc_destroy(mcb, scb); + scb = NULL; + break; + + case ISC_EVENT_ERROR: /* ISC subsystem error */ + fprintf(stderr, "ISC-ERROR: errno = %d", errno); + if (ecb->msg) + fprintf(stderr, " (%s)", ecb->msg->buffer); + putc('\n', stderr); + + /* + ** Should probably do something more sensible than + ** just finishing off the session + */ + if (ecb->session) + isc_destroy(mcb, ecb->session); + break; + + case ISC_EVENT_TIMEOUT: /* Timeout limit reached */ + puts("*** Timeout ***"); + break; + + case ISC_EVENT_LOGIN: /* New client requesting connection */ + { + char laddr[256]; + char lserv[256]; + char raddr[256]; + char rserv[256]; + + strcpy(raddr, "<unknown>"); + strcpy(rserv, "<unknown>"); + strcpy(laddr, "<unknown>"); + strcpy(lserv, "<unknown>"); + + fetch_address(ecb->session->info.tcp.raddr, + raddr, + sizeof(raddr)-1, + rserv, + sizeof(rserv)-1); + + fetch_address(ecb->session->info.tcp.laddr, + laddr, + sizeof(laddr)-1, + lserv, + sizeof(lserv)-1); + + + printf("New session #%d on %s/%s connecting from: %s/%s\n", + ecb->session, + laddr, lserv, + raddr, rserv); + + /* + ** Here we could assign the 'ecb->session->udg' member some + ** arbitrary value to be used later by our own routines + */ + } + break; + + case ISC_EVENT_LOGOUT: /* Client closed connection */ + if (ecb->session == scb) + printf("Server disconnecting\n"); + else + printf("Client #%d disconnecting\n", ecb->session); + + /* + ** Deallocate the storage reserved for the session + */ + isc_destroy(mcb, ecb->session); + break; + + case ISC_EVENT_MESSAGE: /* Message from client or server */ + if (ecb->session == scb) + printf("Message from server: '%s'\n", ecb->msg->buffer); + else + { + printf("Message from client #%d: '%s'\n", + ecb->session, + ecb->msg->buffer); + + /* + ** Reply with some text to the client + */ + isc_write(ecb->session, "OK, got it\n\r", 12); + isc_flush(ecb->session); + } + break; + + default: /* NOTREACHED - OR SHOULDN'T BE ATLEAST :-) */ + Perror("NOTREACHED"); + } + + /* + ** Finished with the event, lets get rid of it + */ + isc_dispose(ecb); + } + + /* NOTREACHED - I THINK ... */ + Perror("SHUTDOWN"); +} + + +const char *strerror(int num) +{ + static char foo[256]; + + sprintf(foo, "Error #%d", num); + return foo; +} + + +fetch_address(IscAddress *ia, + char *host, + int hlen, + char *port, + int plen) +{ + char *cp; + + + cp = isc_gethostname(ia, host, hlen); + if (!cp) + isc_getipnum(ia, host, hlen); + + cp = isc_getservice(ia, port, plen, ISC_TYPE_TCP); + if (!cp) + sprintf(port, "%d", isc_getportnum(ia)); +} diff --git a/src/libraries/libisc-new/src/intern.h b/src/libraries/libisc-new/src/intern.h new file mode 100644 index 0000000000000000000000000000000000000000..e811a6fc13b9587cd401182fe1627d4532d55d18 --- /dev/null +++ b/src/libraries/libisc-new/src/intern.h @@ -0,0 +1,112 @@ +/* +** intern.h Definitions and prototypes used internally +** +** Copyright (c) 1991 Peter Eriksson and Per Cederqvist of the +** Lysator Academic Computer Association. +** +** history: +** 910305 pen initial coding +*/ + +#ifndef __ISC_INTERNALS_H__ +#define __ISC_INTERNALS_H__ + + +/* isc_log.c */ +extern void +isc_log(const char *format, ...); + + +/* isc_abort.c */ +extern void +isc_abort(const char *message); + + +/* isc_alloc.c */ +extern void * +isc_malloc(size_t length); + +extern void * +isc_realloc(void *buf, size_t length); + +extern void +isc_free(void *buf); + +extern char * +isc_strdup(const char *str); + + +/* isc_queue.c */ +extern IscMsgQueue * +isc_newqueue(void); + +extern int +isc_pollqueue(IscMsgQueue *queue); + +extern void +isc_killqueue(IscMsgQueue *queue); + +extern void +isc_pushqueue(IscMsgQueue *queue, IscMessage *msg); + +extern IscMessage * +isc_topqueue(IscMsgQueue *queue); + +extern int +isc_sizequeue(IscMsgQueue *queue); + +extern IscMessage * +isc_popqueue(IscMsgQueue *queue); + + +extern IscMessage * +isc_default_read_fn(IscHandlerList *hl, IscSession *scb); + +extern int +isc_default_write_fn(IscHandlerList *hl, IscSession *scb, IscMessage *msg); + +extern int +isc_default_close_fn(IscHandlerList *hl, IscSession *scb); + + +extern IscAddress * +isc_mkipaddress(struct sockaddr *addr); + + +extern void +isc_oflush(IscSession * scb); + + +/* +** Setup a set of functions to handle memory allocation +*/ +extern void +isc_setallocfn(void * (*mallocfn)(size_t size), + void * (*reallocfn)(void * buf, size_t size), + void (*freefn)(void * buf)); + + + +/* +** Setup a function to handle fatal abort requests +*/ +extern void +isc_setabortfn(void (*abortfn)(const char * msg)); + + + + +#define ISC_XNEW(var) (var = isc_malloc(sizeof(*var))) + + +#define ISC_SCALLFUN1(SCB, NAME, ARG) \ + (*SCB->fun.NAME->hcb->NAME)(SCB->fun.NAME, ARG) + +#define ISC_SCALLFUN2(SCB, NAME, A1, A2) \ + (*SCB->fun.NAME->hcb->NAME)(SCB->fun.NAME, A1, A2) + +#define ISC_SCALLFUN3(SCB, NAME, A1, A2, A3) \ + (*SCB->fun.NAME->hcb->NAME)(SCB->fun.NAME, A1, A2, A3) + + +#endif diff --git a/src/libraries/libisc-new/src/isc.h b/src/libraries/libisc-new/src/isc.h new file mode 100644 index 0000000000000000000000000000000000000000..0ec7d43ddff0b86b01a73ffc4e390c33282aa4b8 --- /dev/null +++ b/src/libraries/libisc-new/src/isc.h @@ -0,0 +1,689 @@ +/* +** isc.h structures and defines used in a ISC server +** +** Copyright (c) 1991 Peter Eriksson and Per Cederqvist of the +** Lysator Academic Computer Association. +** +** history: +** 910306 pen major overhaul +** 910307 pen type name changes, changes in structs.. +** 920207 pen updated +*/ + +#ifndef __ISC_H__ +#define __ISC_H__ + +#include <time.h> +#include <stdarg.h> +#include <sys/types.h> +#include <sys/socket.h> + + + +/* +** Give the poor user a chance to change it +*/ +#ifndef ISC_UDGTYPE +# define ISC_UDGTYPE void +#endif + + + +/* +** Some type names (typedef? What is that? :-) +*/ +#define IscSessionConfig struct isc_session_cfg +#define IscMasterConfig struct isc_master_config +#define IscConfig struct isc_config +#define IscAddress union isc_address +#define IscMessage struct isc_msg +#define IscMsgQE struct isc_msg_q_entry +#define IscMsgQueue struct isc_msgqueue +#define IscSessionInfo union isc_session_info +#define IscSessionStats struct isc_session_stats +#define IscHandler struct isc_handler +#define IscHandlerList struct isc_handler_list +#define IscHandlerCache struct isc_handler_cache +#define IscSession struct isc_scb +#define IscSessionList struct isc_scb_entry +#define IscMaster struct isc_mcb +#define IscEvent struct isc_ecb + + + +/* +** Some nice defaults +*/ +#define ISC_DEFAULT_MAX_MSG_SIZE 2048 +#define ISC_DEFAULT_MAX_QUEUED_SIZE 300 +#define ISC_DEFAULT_MAX_DEQUEUE_LEN 10 +#define ISC_DEFAULT_MAX_OPEN_RETRIES 10 +#define ISC_DEFAULT_MAX_BACKLOG 5 + + + +/* +** Configuration structure for sessions +*/ +IscSessionConfig +{ + int version; /* This is version 1001 */ + struct + { + int msgsize; + int queuedsize; + int dequeuelen; + int openretries; + int backlog; + } max; +}; + + + +/* +** Master configuration structure +*/ +IscMasterConfig +{ + int version; /* This is version 1001 */ + struct + { + void * (*alloc) (size_t size); + void * (*realloc) (void *bufp, size_t size); + void (*free) (void *bufp); + } memfn; + void (*abortfn)(const char *msg); +}; + + + +/* +** Configuration structure +*/ +IscConfig +{ + int version; /* This is version 1005 */ + IscSessionConfig session; + IscMasterConfig master; +}; + + + +/* +** Various types of events that may happen +*/ +typedef enum +{ + ISC_EVENT_ERROR, + ISC_EVENT_TIMEOUT, + ISC_EVENT_LOGIN, + ISC_EVENT_LOGOUT, + ISC_EVENT_MESSAGE, + ISC_EVENT_CONNECTED, + ISC_EVENT_REJECTED +} IscEventType; + + + +/* +** Various types of sessions +*/ +typedef enum +{ + ISC_TYPE_UNKNOWN, + ISC_TYPE_TCP, + ISC_TYPE_PIPE, + ISC_TYPE_FILE, + ISC_TYPE_UDP +} IscSessionType; + + + +/* +** The different session states +*/ +typedef enum +{ + ISC_STATE_UNKNOWN, + ISC_STATE_CONNECTING, + ISC_STATE_RUNNING, + ISC_STATE_DISABLED, + ISC_STATE_CLOSING, + ISC_STATE_LISTENING +} IscSessionState; + + + +/* +** Message information structure +*/ +IscAddress +{ + struct + { + struct sockaddr saddr; + } ip; +}; + + + +/* +** Generic message type +*/ +IscMessage +{ + int size; /* Maximum buffer size */ + int length; /* Length of used buffer */ + char * buffer; /* Pointer to buffer */ + IscAddress * address; /* Pointer to address */ +}; + + + +/* +** Entry in a message queue +*/ +IscMsgQE +{ + IscMsgQE * prev; + IscMsgQE * next; + IscMessage * msg; +}; + + + +/* +** The generic message queue +*/ +IscMsgQueue +{ + IscMsgQE * head; + IscMsgQE * tail; + int entries; +}; + + + +/* +** Session information structures +*/ +IscSessionInfo +{ + struct + { + IscAddress *raddr; + IscAddress *laddr; + } tcp; + struct + { + IscAddress *raddr; + IscAddress *laddr; + } udp; + struct + { + char * pathname; + } file; + struct + { + char * pathname; + } pipe; +}; + + + +/* +** Statistical data about a session +*/ +IscSessionStats +{ + struct + { + long bytes; + long packets; + } rx, tx; +}; + + +IscHandlerCache +{ + IscHandlerList * read; + IscHandlerList * write; + IscHandlerList * close; + IscHandlerList * poll; + IscHandlerList * accept; + IscHandlerList * destroy; + IscHandlerList * parse; +}; + + + +/* +** Session control structure +*/ +IscSession +{ + int nlinks; + + IscSessionType type; + IscSessionState state; + int fd; + int mode; + int errno; + + IscMsgQueue * rd_msg_q; + IscMsgQueue * wr_msg_q; + + IscSessionConfig * cfg; + IscSessionInfo info; + + /* Cheap transmit buffer */ + /* Should be dynamically allocated - into an IscMessage */ + char sendbuf[2048]; + int sendindex; + + time_t logintime; + time_t idlesince; + + IscSessionStats stats; + + IscHandlerList * handlers; + IscHandlerCache fun; + + ISC_UDGTYPE * udg; /* User defined garbage :-) */ +}; + + + + +IscHandler +{ + IscMessage * (*read) (IscHandlerList *, + IscSession *scb); + + int (*write) (IscHandlerList *hl, + IscSession *scb, + IscMessage *msg); + + int (*close) (IscHandlerList *hl, + IscSession *scb); + + int (*poll) (IscHandlerList *hl, + IscSession *scb); + + IscSession * (*accept) (IscHandlerList *hl, + IscSession *scb, + IscMessage *msg); + + void (*destroy) (IscHandlerList *hl, + IscSession *scb); + + IscEvent * (*parse) (IscHandlerList *hl, + IscSession *scb, + IscMessage *msg); +}; + + + +IscHandlerList +{ + IscHandlerList * next; + IscHandler * hcb; + IscHandlerCache old; +}; + + + +/* +** Session list entry +*/ +IscSessionList +{ + IscSessionList * prev; + IscSessionList * next; + + IscSession * scb; +}; + + + +/* +** The Master Control Block +*/ +IscMaster +{ + IscSessionConfig scfg; + IscSessionList * sessions; +}; + + + +/* +** Event control structure +*/ +IscEvent +{ + IscEventType event; + IscSession * session; + IscMessage * msg; +}; + + + +/* +** This routine will setup the ISC subsystem +*/ +extern IscMaster * +isc_initialize(IscConfig * cfg); + + + +/* +** Shut down all sessions associated with an ISC Master Control Block +** and deallocate all storage used by the MCB. +*/ +extern void +isc_shutdown(IscMaster * mcb); + + + +/* +** Establish a TCP port to listen for connections at +*/ +extern IscSession * +isc_listentcp(IscMaster * mcb, + const char * address, + const char * service); + + + +/* +** Initiate a new session with a previously opened file +*/ +extern IscSession * +isc_openfd(IscMaster * mcb, + int fd); + + + +/* +** Initiate a new session with a specified file +*/ +extern IscSession * +isc_openfile(IscMaster * mcb, + const char * pathname, + int openmode); + + + +/* +** Initiate a new session with a remote TCP service +*/ +extern IscSession * +isc_opentcp(IscMaster * mcb, + const char * address, + const char * service); + + + +/* +** Initiate a new session with a remote UDP service +*/ +extern IscSession * +isc_openudp(IscMaster * mcb, + const char * address, + const char * service); + + + +extern void +isc_close(IscSession * scb); + + + +extern int +isc_destroy(IscMaster * mcb, IscSession * scb); + + + +/* +** This function returns the number of sessions +*/ +extern int +isc_sessions(IscMaster * mcb); + + + +/* +** Wait for an event on a specific server. Timeout is specified +** in milliseconds +*/ +extern IscEvent * +isc_getnextevent(IscMaster * mcb, + long timeout); + + + +/* +** This should be used to discard an event when it has been processed. +*/ +extern void +isc_dispose(IscEvent * ecb); + + + +/* +** Flush the transmit queue for a specific session +*/ +extern void +isc_flush(IscSession * scb); + + + +/* +** Add a new message to the transmit queue +*/ +extern int +isc_send(IscSession * scb, IscMessage * mcb); + + + +/* +** Put a buffer on the transmit queue for a session +*/ +extern int +isc_write(IscSession * scb, + const void * buffer, + size_t length); + + + +/* +** Put a single character on the transmit queue +*/ +extern int +isc_putc(int chr, + IscSession * scb); + + + +/* +** Put a formatted string on the transmit queue +*/ +extern int +isc_printf(IscSession * scb, + const char * format, + ...); + +extern int +isc_vprintf(IscSession * scb, + const char * format, + va_list AP); + + + +/* +** Allocate a new IscMessage of specified size +*/ +extern IscMessage * +isc_allocmsg(size_t size); + + + +/* +** Reallocate an old IscMessage +*/ +extern IscMessage * +isc_reallocmsg(IscMessage * msg, + size_t size); + + + +/* +** Make a copy of an old IscMessage +*/ +extern IscMessage * +isc_copymsg(IscMessage *msg); + + + +/* +** Free an allocated IscMessage +*/ +extern void +isc_freemsg(IscMessage * msg); + + + +/* +** Make an IscMessage out of a string +*/ +extern IscMessage * +isc_mkstrmsg(const char * str); + + + +/* +** Enable a previously disabled session +*/ +extern int +isc_enable(IscSession *scb); + + + +/* +** Disable a session. The session will not generate events. +*/ +extern int +isc_disable(IscSession *scb); + + +extern int +isc_insert(IscMaster *mcb, IscSession *scb); + +extern int +isc_remove(IscMaster *mcb, IscSession *scb); + + +extern IscSession * +isc_create(IscSessionConfig *cfg, IscHandler *fun); + + +extern IscSession * +isc_createtcp(IscSessionConfig *cfg, int fd); + + +extern IscSession * +isc_createudp(IscSessionConfig *cfg); + + +extern int +isc_bindtcp(IscSession *scb, const char *address, const char *port); + +extern int +isc_bindudp(IscSession *scb, const char *address, const char *port); + +extern int +isc_connecttcp(IscSession *scb, const char *address, const char *port); + +extern int +isc_connectudp(IscSession *scb, const char *address, const char *port); + + +/* +** Establish an UDP port to listen for incoming messages at +*/ +extern IscSession * +isc_listenudp(IscMaster * mcb, + const char * address, + const char * service); + + + +extern IscAddress * +isc_getladdress(IscSession *scb); + + +extern IscAddress * +isc_getraddress(IscSession *scb); + + +extern void +isc_freeaddress(IscAddress *addr); + + +extern IscAddress * +isc_copyaddress(IscAddress *addr); + +extern char * +isc_getipnum(IscAddress *ia, + char *address, + int len); + +extern char * +isc_gethostname(IscAddress *ia, + char *address, + int len); + +extern int +isc_getportnum(IscAddress *ia); + + +extern char * +isc_getservice(IscAddress *sa, + char *buf, + int len, + IscSessionType type); + + +extern IscHandler * +isc_newhandler(void); + +extern void +isc_freehandler(IscHandler *hcb); + +extern IscHandler * +isc_copyhandler(IscHandler *hcb); + +extern void +isc_pushhandler(IscSession *scb, IscHandler *hcb); + +extern IscHandler * +isc_pophandler(IscSession *scb); + + + +/* +** Handler call function macros +*/ +#define ISC_HCALLFUN1(HLIST,NAME,ARG) \ + (*HLIST->old.NAME->hcb->NAME)(HLIST->old.NAME, ARG) + +#define ISC_HCALLFUN2(HLIST,NAME,A1,A2) \ + (*HLIST->old.NAME->hcb->NAME)(HLIST->old.NAME, A1, A2) + +#define ISC_HCALLFUN3(HLIST,NAME,A1,A2,A3) \ + (*HLIST->old.NAME->hcb->NAME)(HLIST->old.NAME, A1, A2, A3) + + + +#endif /* __ISC_H__ */ diff --git a/src/libraries/libisc-new/src/isc_abort.c b/src/libraries/libisc-new/src/isc_abort.c new file mode 100644 index 0000000000000000000000000000000000000000..8e1ac120cf5cd9e746fd202fa6e3202ce153175f --- /dev/null +++ b/src/libraries/libisc-new/src/isc_abort.c @@ -0,0 +1,46 @@ +/* +** isc_abort.c Route to handle fatal errors +** +** Copyright (c) 1991 Peter Eriksson and Per Cederqvist of the +** Lysator Academic Computer Association. +** +** history: +** 910305 pen moved into separate file +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include "isc.h" +#include "intern.h" + +/* +** External function declarations +*/ +extern int fprintf(FILE *, char *, ...); +#if defined(__sun__) && !defined(__stdlib_h) +extern void abort(void); +#endif + +static void (*isc_abortfn)(const char *msg) = (void (*)(const char *))NULL; + + +void +isc_setabortfn(void (*abortfn)(const char *msg)) +{ + isc_abortfn = abortfn; +} + + +void +isc_abort(const char *message) +{ + if (isc_abortfn) + (*isc_abortfn)(message); + else + { + fprintf(stderr, "\n\r*** ISC SUBSYSTEM FATAL ERROR: %s\n\r", message); + abort(); + } +} + diff --git a/src/libraries/libisc-new/src/isc_alloc.c b/src/libraries/libisc-new/src/isc_alloc.c new file mode 100644 index 0000000000000000000000000000000000000000..6e999fa746b4e80d61ab43ec15a0172e2b01f011 --- /dev/null +++ b/src/libraries/libisc-new/src/isc_alloc.c @@ -0,0 +1,171 @@ +/* +** isc_alloc.c ISC storage allocation routines +** +** Copyright (c) 1991 Peter Eriksson and Per Cederqvist of the +** Lysator Academic Computer Association. +** +** history: +** 910305 pen moved into separate file +*/ + +#include <stdlib.h> +#include <stddef.h> +#include <string.h> +#include "isc.h" +#include "intern.h" + +/* +** Some magic numbers +*/ +#define ISC_MAGIC_ALLOC 0x12F54ACE +#define ISC_MAGIC_FREE 0xEE47A37F + + +/* +** External declarations +*/ +#if defined(__sun__) && !defined(__stdlib_h) +extern void *malloc(size_t); +extern void *calloc(int, size_t); +extern void *realloc(void *, size_t); +extern void free(void *); +#endif + +/* +** Pointers to functions to handle storage allocation +*/ +static void * (*isc_mallocfn)(size_t size) = + (void * (*)(size_t)) NULL; + +static void * (*isc_reallocfn)(void *bufp, size_t size) = + (void * (*)(void *, size_t)) NULL; + +static void (*isc_freefn)(void *bufp) = + (void (*)(void *)) NULL; + + +/* +** Define functions to handle storage allocation +*/ +void +isc_setallocfn(void * (*mallocfn)(size_t size), + void * (*reallocfn)(void *buf, size_t size), + void (*freefn)(void *buf)) +{ + isc_mallocfn = mallocfn; + isc_reallocfn = reallocfn; + isc_freefn = freefn; +} + + + +void * +isc_malloc(size_t size) +{ + unsigned int * buf; + + + if (isc_mallocfn) + buf = (unsigned int *) (*isc_mallocfn)(size + sizeof(unsigned int)); + else + { + buf = (unsigned int *) malloc(size + sizeof(unsigned int)); + if (!buf) + isc_abort("isc_malloc"); + } + + *buf++ = ISC_MAGIC_ALLOC; + + return (void *) buf; +} + + +void * +isc_realloc(void *oldbuf, size_t size) +{ + unsigned int *buf; + + + if (!oldbuf) + return isc_malloc(size); + + buf = (unsigned int *) oldbuf; + switch (*--buf) + { + case ISC_MAGIC_ALLOC: + break; + + case ISC_MAGIC_FREE: + isc_abort("isc_realloc"); + + default: + isc_abort("isc_realloc"); + } + + *buf = ISC_MAGIC_FREE; + + if (isc_reallocfn) + buf = (unsigned int *) (*isc_reallocfn)((void *) buf, + size + sizeof(unsigned int)); + else + { + buf = (void *) realloc((void *) buf, size + sizeof(unsigned int)); + if (!buf) + isc_abort("isc_realloc"); + } + + *buf++ = ISC_MAGIC_ALLOC; + return (void *) buf; +} + + + +void +isc_free(void *buf) +{ + unsigned int *ibuf; + + + if (!buf) + isc_abort("isc_free"); + + ibuf = (unsigned int *) buf; + switch (*--ibuf) + { + case ISC_MAGIC_ALLOC: + break; + + case ISC_MAGIC_FREE: + isc_abort("isc_free"); + + default: + isc_abort("isc_free"); + } + + *ibuf = ISC_MAGIC_FREE; + + if (isc_freefn) + { + (*isc_freefn)((void *) ibuf); + return; + } + else + free((void *) ibuf); +} + + + +/* +** Safe (hopefully) string duplicator +*/ +char * +isc_strdup(const char *str) +{ + char *newstr; + + + newstr = isc_malloc(strlen(str)+1); + strcpy(newstr, str); + return newstr; +} +