538 lines
23 KiB
C
538 lines
23 KiB
C
|
|
/*
|
|
* Copyright (c) 1991-1994 by the University of Southern California
|
|
*
|
|
* For copying and distribution information, please see the file
|
|
* <usc-license.h>.
|
|
*/
|
|
|
|
#include <usc-license.h>
|
|
|
|
#include <stdio.h> /* for FILE */
|
|
#ifdef ARCHIE_TIMING
|
|
#include <time.h>
|
|
#include <sys/param.h>
|
|
#include <sys/time.h>
|
|
#include <sys/resource.h>
|
|
#endif
|
|
|
|
/*
|
|
* Written by bcn 1989-92 as pfs.h in the Prospero distribution
|
|
* Modified by bcn 1/93 separate include file and extended preq structure
|
|
* Modified by swa 11/93 error reporting; less dependent on Prospero
|
|
*/
|
|
|
|
#ifndef ARDP_H_INCLUDED
|
|
|
|
#define ARDP_H_INCLUDED
|
|
#include <pfs_threads.h> /* PFS threads package. */
|
|
|
|
#include <sys/time.h>
|
|
#include <sys/types.h>
|
|
|
|
/* Unfortunately, some buggy compilers (in this case, gcc 2.1 under
|
|
VAX BSD 4.3) get upset if <netinet/in.h> is included twice. */
|
|
/* Note that the IEEE C standard specifies that multiple inclusions of an
|
|
include file should not matter. */
|
|
#if !defined(IP_OPTIONS)
|
|
#include <netinet/in.h>
|
|
#endif
|
|
|
|
#include <list_macros.h>
|
|
|
|
/* Note: In doubly linked lists of the structures used for prospero, the */
|
|
/* ->previous element of the head of the list is the tail of the list and */
|
|
/* the ->next element of the tail of the list is NULL. This allows fast */
|
|
/* addition at the tail of the list. */
|
|
|
|
/* #defining this turns on extra consistency checking code in the various
|
|
memory allocators that checks for double freeing. Turn on this compilation
|
|
option if you are experimenting with the PFS library and want to make sure
|
|
you are not making this common mistake. We have left it turned on for this
|
|
ALPHA release. */
|
|
/* This consistency checking mechanism is used by the ARDP library and general
|
|
Prospero data structures. The only exception is the RREQ structure, which
|
|
does consistency checking differently. */
|
|
#define P_ALLOCATOR_CONSISTENCY_CHECK
|
|
#define ALLOCATOR_CONSISTENCY_CHECK /* deprecated but still necessary */
|
|
#ifdef P_ALLOCATOR_CONSISTENCY_CHECK /* patterns to set the 'consistency' member
|
|
to. */
|
|
#define FREE_PATTERN P__FREE_PATTERN /* old interface deprecated */
|
|
#define INUSE_PATTERN P__INUSE_PATTERN /* old interface deprecated */
|
|
#define P__FREE_PATTERN 0Xca01babe /* pattern to use if memory is now free. */
|
|
#define P__INUSE_PATTERN 0X53ad00d /* Pattern to set consistency member to
|
|
if memory is in use. */
|
|
#endif
|
|
|
|
#define PROSPERO
|
|
|
|
#ifdef PROSPERO
|
|
#define ARDP_DEFAULT_PEER "dirsrv"/* Default destination port name */
|
|
#define ARDP_DEFAULT_PORT 1525 /* Default destination port number */
|
|
#endif /* PROSPERO */
|
|
|
|
#define ARDP_BACKOFF(x) (2 * x) /* Backoff algorithm */
|
|
#define ARDP_DEFAULT_TIMEOUT 4 /* Default time before retry (sec) */
|
|
#define ARDP_DEFAULT_RETRY 3 /* Default number of times to try */
|
|
#define ARDP_DEFAULT_WINDOW_SZ 16 /* Default maximum packets to send at
|
|
once, unless special request
|
|
received from client. */
|
|
#define ARDP_MAX_WINDOW_SZ 256 /* Maximum # of packets we'll send
|
|
out, no matter what a client
|
|
requests. Might be redefined
|
|
locally if you're at the far end of
|
|
a slow link. */
|
|
#define ARDP_FIRST_PRIVP 901 /* First prived local port to try */
|
|
#define ARDP_NUM_PRIVP 20 /* Number of prived ports to try */
|
|
#define ARDP_PTXT_HDR 64 /* Max offset for start */
|
|
#define ARDP_PTXT_LEN 1250 /* Max length for data to send */
|
|
#define ARDP_PTXT_LEN_R 1405 /* Max length for received data */
|
|
|
|
/* Rationale for MAX_PTXT_LEN_R: According to IEEE std. 802.5, 1492 is the */
|
|
/* max data length for an ethernet packet. IP implementers tend to use */
|
|
/* this information in deciding how large a packet could be sent without IP */
|
|
/* fragmentation occurring. Subtract 16 octets for the IP header. */
|
|
/* Subtract 8 octets for UDP header. The maximum ARDP header size is 6 bits */
|
|
/* or 64, so subtract 64 more for the ARDP header. This leaves 1404 bytes. */
|
|
/* Note we only generate 1250 bytes because there are preV5 implementations */
|
|
/* out there with smaller limits. We also add one to MAX_PTXT_LEN_R to make */
|
|
/* sure there is always room to insert a null if needed. */
|
|
|
|
/* Must leave room to insert header when sending and to strip it on receipt */
|
|
#define ARDP_PTXT_DSZ ARDP_PTXT_LEN_R+2*ARDP_PTXT_HDR
|
|
|
|
/* Definition of text structure used to pass around each packet */
|
|
struct ptext {
|
|
#ifdef ALLOCATOR_CONSISTENCY_CHECK
|
|
int consistency;
|
|
#endif
|
|
unsigned int seq; /* Packet sequence number */
|
|
int length; /* Length of text (from start) */
|
|
char *start; /* Start of packet */
|
|
char *text; /* Start of text */
|
|
char *ioptr; /* Current position for i/o */
|
|
char dat[ARDP_PTXT_DSZ];/* The data itself incl headers */
|
|
unsigned long mbz; /* ZERO to catch runaway strings */
|
|
struct ptext *previous; /* Previous element in list */
|
|
struct ptext *next; /* Next element in linked list */
|
|
};
|
|
|
|
typedef struct ptext *PTEXT;
|
|
typedef struct ptext PTEXT_ST;
|
|
#define NOPKT ((PTEXT) 0) /* NULL pointer to ptext */
|
|
|
|
|
|
/* Request structure: maintains information about pending requests */
|
|
struct rreq {
|
|
int status; /* Status of request *rr1 */
|
|
int flags; /* Options for ARDP library *rr2 */
|
|
unsigned short cid; /* Connection ID - net byte order */
|
|
short priority; /* Priority - host byte order */
|
|
int pf_priority; /* Priority assigned by pri_func */
|
|
short peer_ardp_version;/* Peer ARD protocol version *rr3 */
|
|
struct ptext *inpkt; /* Packet in process by applic */
|
|
unsigned short rcvd_tot; /* Total # of packets to receive */
|
|
struct ptext *rcvd; /* Received packets */
|
|
unsigned short rcvd_thru; /* Received all packets through # */
|
|
struct ptext *comp_thru; /* Pointer to RCVD_THRUth packet */
|
|
struct ptext *outpkt; /* Packets not yet sent */
|
|
unsigned short trns_tot; /* Total # of packets for trns */
|
|
struct ptext *trns; /* Transmitted packets */
|
|
unsigned short prcvd_thru; /* Peer's rcvd_thru (host byte ord)*/
|
|
unsigned short window_sz; /* My window size (default: 0 (sender
|
|
does whatever they choose)
|
|
(hostorder) */
|
|
unsigned short pwindow_sz; /* Peer window (dflt ARDP_WINDOW_SZ).
|
|
0 means no limit on # to send.
|
|
(hostorder)*/
|
|
struct sockaddr_in peer; /* Sender/Destination */
|
|
#define peer_addr peer.sin_addr /* Address in network byte order */
|
|
#define peer_port peer.sin_port /* Port in network byte order */
|
|
struct timeval rcvd_time; /* Time request was received */
|
|
struct timeval svc_start_time; /* Time service began on request */
|
|
struct timeval svc_comp_time; /* Time service was completed */
|
|
struct timeval timeout; /* Initial time to wait for resp */
|
|
struct timeval timeout_adj; /* Adjusted time to wait for resp */
|
|
struct timeval wait_till; /* Time at which timeout expires */
|
|
unsigned short retries; /* Number of times to retry */
|
|
unsigned short retries_rem; /* Number of retries remaining */
|
|
unsigned short svc_rwait; /* Svc suggested tm2wait b4 retry */
|
|
unsigned short svc_rwait_seq; /* Seq # when scv_rwait changed */
|
|
unsigned short inf_queue_pos; /* Service queue pos if available */
|
|
int inf_sys_time; /* Expected time til svc complete */
|
|
#ifdef PROSPERO
|
|
struct pfs_auth_info *auth_info; /* Client authentication info */
|
|
#endif /* PROSPERO */
|
|
char *client_name; /* Client name string for logging */
|
|
char *peer_sw_id; /* Peer's software specific ident */
|
|
int (*cfunction)(); /* Function to call when done */
|
|
char *cfunction_args; /* Additional args to cfunction */
|
|
struct rreq *previous; /* Previous element in list */
|
|
struct rreq *next; /* Next element in linked list */
|
|
#ifdef ARCHIE_TIMING
|
|
int no_matches; /* Number of matches returned */
|
|
char query_state; /* State of query S,F */
|
|
char match_type; /* Type of match E,S,R */
|
|
char cached;
|
|
char case_type; /* Case S,X */
|
|
char domain_match; /* Domain match D,X */
|
|
char path_match; /* Path match P,X */
|
|
char search_str[MAXPATHLEN]; /* search string */
|
|
char launch[30]; /* Time started the processing */
|
|
char start[30]; /* Time got request */
|
|
char end[30]; /* Time returned request */
|
|
struct rusage qtime_start; /* To figure out the timings */
|
|
struct rusage qtime_end;
|
|
struct rusage stime_start;
|
|
struct rusage stime_end;
|
|
struct rusage htime_start;
|
|
struct rusage htime_end;
|
|
int hosts; /* Hosts that contain */
|
|
int hosts_searched; /* Hosts searched */
|
|
#endif
|
|
};
|
|
/* *rr1: this is also used for consistency checking. */
|
|
/* Values for this field: */
|
|
#define ARDP_STATUS_NOSTART 0 /* not started or inactive */
|
|
#define ARDP_STATUS_INACTIVE 0
|
|
#define ARDP_STATUS_COMPLETE -1 /* done */
|
|
#define ARDP_STATUS_ACTIVE -2 /* running */
|
|
#define ARDP_STATUS_ACKPEND -3
|
|
#define ARDP_STATUS_GAPS -4
|
|
#define ARDP_STATUS_ABORTED -5
|
|
#define ARDP_STATUS_FREE -6 /* used for consistency checking; free */
|
|
#define ARDP_STATUS_FAILED 255
|
|
|
|
/* *rr2: There is only one flag currently defined. */
|
|
/* Send the client's preferred window size along with the next packet you
|
|
transmit. At the moment, this flag is never cleared once it is set, so all
|
|
packets are tagged with the preferred window size. There are other
|
|
strategies that will be tried later. */
|
|
/* At the moment, this flag is only set in ardp_rqalloc(). */
|
|
#define ARDP_FLAG_SEND_MY_WINDOW_SIZE 0x1
|
|
#ifdef PROSPERO
|
|
/* This is used only on the clients. It means they're when speaking to a
|
|
Version 0 Prospero server, but one which used the Prospero 5.0, 5.1, or 5.2
|
|
releases. */
|
|
#define ARDP_FLAG_PEER_HAS_EXCESSIVE_ACK_BUG 0x2
|
|
#endif
|
|
|
|
/* *rr3: There are several odd numbers you might find. */
|
|
/* 0 is the current version of the ARDP library. */
|
|
/* -1 is an older version. This is used only on the servers when speaking to
|
|
V1 archie clients. */
|
|
/* -2 is a newer version than -1, but still old enough that bugs appeared.
|
|
This is used only on the servers when speaking to V1 archie clients. */
|
|
/* Version 1 of the ARDP library has been designed. Not yet implemented. */
|
|
|
|
#define S_AD_SZ sizeof(struct sockaddr_in)
|
|
|
|
#define PEER_PORT(req) (ntohs((req)->peer_port)) /* host byte order */
|
|
|
|
typedef struct rreq *RREQ;
|
|
typedef struct rreq RREQ_ST;
|
|
#define NOREQ ((RREQ) 0) /* NULL pointer to rreq */
|
|
|
|
/* ARDP library error status codes. */
|
|
/* These must remain in the range 0-20 for compatibility with the Prospero
|
|
File System. */
|
|
/* Note that ARDP_SUCCESS must remain 0, due to code implementation. */
|
|
#define ARDP_SUCCESS 0 /* Successful completion of call */
|
|
#define ARDP_PORT_UNKN 1 /* DIRSRV UDP port unknown */
|
|
#define ARDP_UDP_CANT 2 /* Can't open local UDP port */
|
|
#define ARDP_BAD_HOSTNAME 3 /* Can't resolve hostname */
|
|
#define ARDP_NOT_SENT 4 /* Attempt to send message failed */
|
|
#define ARDP_SELECT_FAILED 5 /* Select failed */
|
|
#define ARDP_BAD_RECV 6 /* Recvfrom failed */
|
|
#define ARDP_BAD_VERSION 7 /* bad version # in rdgram protocol */
|
|
#define ARDP_BAD_REQ 8 /* Inconsistent request structure */
|
|
#define ARDP_TIMEOUT 9 /* Timed out - retry count exceeded */
|
|
#define ARDP_REFUSED 10 /* Connection refused by server */
|
|
#define ARDP_FAILURE 11 /* Unspecified ARDP failure */
|
|
#define ARDP_TOOLONG 12 /* Buffer too long for packet */
|
|
/* These are the interface used to the ARDP library's error reporting.
|
|
These are the same as definitions used in the Prospero PFS library. */
|
|
/* extern int perrno; \* Place where error codes are set. */
|
|
extern void p_clear_errors(void); /* Clear perrno in ARDP library; clear pwarn
|
|
and p_err_string and p_warn_string as well
|
|
in PFS library. */
|
|
|
|
#define ARDP_PENDING -1 /* The request is still pending */
|
|
#define ARDP_WAIT_TILL_TO -1 /* Wait until timeout occurs */
|
|
|
|
#define ARDP_A2R_SPLIT 0x00 /* OK to split across packets */
|
|
#define ARDP_A2R_NOSPLITB 0x01 /* Don't split across packets */
|
|
#define ARDP_A2R_NOSPLITL 0x02 /* Don't split lines across packets */
|
|
#define ARDP_A2R_NOSPLITBL 0x03 /* NOSPLITB|NOSPLITL */
|
|
#define ARDP_A2R_TAGLENGTH 0x04 /* Include length tag for buffer */
|
|
#define ARDP_A2R_COMPLETE 0x08 /* This is the final packet to add */
|
|
|
|
#define ARDP_R_INCOMPLETE 0x00 /* More messages will follow */
|
|
#define ARDP_R_NOSEND 0x02 /* Add to req->trns but don't send */
|
|
#define ARDP_R_COMPLETE 0x08 /* This is the final packet to send */
|
|
|
|
/* Queuing priorities for requests */
|
|
#define ARDP_MAX_PRI 32765 /* Maximum user proiority */
|
|
#define ARDP_MAX_SPRI 32767 /* Maximum priority for system use */
|
|
#define ARDP_MIN_PRI -32765 /* Maximum user proiority */
|
|
#define ARDP_MIN_SPRI -32768 /* Maximum priority for system use */
|
|
|
|
/* LONG_TO_SHORT_NAME is needed for linkers that can't handle long names */
|
|
#ifdef LONG_TO_SHORT_NAME
|
|
#define ardp_abort RDABOR
|
|
#define ardp_abort_on_int RDABOI
|
|
#define ardp_accept RDACPT
|
|
#define ardp_activeQ RDACTV
|
|
#define ardp_add2req RDA2RQ
|
|
#define ardp_acknowledge RDACKN
|
|
#define ardp_bind_port RDBPRT
|
|
#define ardp_breply RDBREP
|
|
#define ardp_completeQ RDCMPQ
|
|
#define ardp_def_port_no RDDPNO
|
|
#define ardp_default_retry RDDFRT
|
|
#define ardp_default_timeout RDDFTO
|
|
#define ardp_doneQ RDDONQ
|
|
#define ardp_get_nxt RDGNXT
|
|
#define ardp_get_nxt_nonblocking RDGNNB
|
|
#define ardp_headers RDHDRS
|
|
#define ardp_init RDINIT
|
|
#define ardp_next_cid RDNCID
|
|
#define ardp_partialQ RDPRTQ
|
|
#define ardp_pendingQ RDPNDQ
|
|
#define ardp_port RDPORT
|
|
#define ardp_pri_func RDPRIF
|
|
#define ardp_pri_override RDOVRD
|
|
#define ardp_priority RDPRIO
|
|
#define ardp_process_active RDPACT
|
|
#define ardp_prvport RDPPRT
|
|
#define ardp_ptalloc RDPTAL
|
|
#define ardp_ptfree RDPTFR
|
|
#define ardp_ptlfree RDPTLF
|
|
#define ardp_redirect RDREDR
|
|
#define ardp_refuse RDRFSE
|
|
#define ardp_reply RDREPL
|
|
#define ardp_respond RDRESP
|
|
#define ardp_retrieve RDRETR
|
|
#define ardp_rqalloc RDRQAL
|
|
#define ardp_rqfree RDRQFR
|
|
#define ardp_rq_partialfree RDRQPF
|
|
#define ardp_rqlfree RDRQLF
|
|
#define ardp_runQ RDRUNQ
|
|
#define ardp_rwait RDRWAI
|
|
#define ardp_send RDSEND
|
|
#define ardp_set_prvport RDSPPT
|
|
#define ardp_set_queuing_policy RDSQPL
|
|
#define ardp_set_retry RDSETR
|
|
#define ardp_showbuf RDSHBF
|
|
#define ardp_snd_pkt RDSPKT
|
|
#define ardp_srvport RDSPRT
|
|
#define ardp_trap_int RDTINT
|
|
#define ardp_update_cfields RDUPCF
|
|
#define ardp_xmit RDXMIT
|
|
#define ptext_count PTXCNT
|
|
#define ptext_max PTXMAX
|
|
#define rreq_count RRQCNT
|
|
#define rreq_max RRQMAX
|
|
#endif /* LONG_TO_SHORT_NAME */
|
|
|
|
/* Please keep this list alpphabetically sorted. */
|
|
|
|
int ardp_abort(RREQ);
|
|
int ardp_abort_on_int(void);
|
|
int ardp_accept(void);
|
|
int ardp_add2req(RREQ,int,char*,int);
|
|
int ardp_acknowledge(RREQ req);
|
|
int ardp_bind_port(char*);
|
|
int ardp_breply(RREQ,int,char*,int);
|
|
RREQ ardp_get_nxt(void);
|
|
RREQ ardp_get_nxt_nonblocking(void);
|
|
int ardp_headers(RREQ);
|
|
/* Variable name "hostname" Commented out to shut up GCC -Wshadow */
|
|
int ardp_hostname2addr(const char * /* hostname */, struct sockaddr_in *hostaddr);
|
|
void ardp_hostname2addr_initcache(void);
|
|
extern int ardp_priority;
|
|
int ardp_process_active(void);
|
|
PTEXT ardp_ptalloc(void);
|
|
void ardp_ptfree(PTEXT);
|
|
void ardp_ptlfree(PTEXT);
|
|
int ardp_reply(RREQ,int,char*);
|
|
int ardp_respond(RREQ,int);
|
|
int ardp_retrieve(RREQ,int);
|
|
RREQ ardp_rqalloc(void);
|
|
void ardp_rqfree(RREQ);
|
|
#ifndef NDEBUG
|
|
void ardp_rq_partialfree(RREQ);
|
|
#endif
|
|
void ardp_rqlfree(RREQ);
|
|
int ardp_rwait(RREQ,int,short,int);
|
|
int ardp_send(RREQ,char*,struct sockaddr_in*,int);
|
|
int ardp_set_prvport(int);
|
|
int ardp_set_queuing_policy(int(*pf)(),int);
|
|
int ardp_set_retry(int,int);
|
|
void ardp_showbuf(const char *st, int length, FILE *out);
|
|
int ardp_snd_pkt(PTEXT,RREQ);
|
|
int ardp_xmit(RREQ,int);
|
|
/* these are used to look for memory leaks. Currently used by dirsrv.c to
|
|
return STATUS information. Internal to ARDP library. */
|
|
extern int dnscache_count;
|
|
extern int dnscache_max;
|
|
/* Used to see how many cached items are in */
|
|
extern int alldnscache_count;
|
|
|
|
/* Checked for memory leaks. */
|
|
extern int filelock_count;
|
|
extern int filelock_max;
|
|
extern int pfs_debug; /* used in ARDP library for error messages. */
|
|
/* Should be renamed. */
|
|
/* these are used to look for memory leaks. Currently used by dirsrv.c to
|
|
return STATUS information. */
|
|
extern int ptext_count;
|
|
extern int ptext_max;
|
|
extern int rreq_count;
|
|
extern int rreq_max;
|
|
/* Check for case-blind string equality, where s1 or s2 may be null
|
|
pointer. */
|
|
int stcaseequal(const char *s1, const char*s2);
|
|
extern const char*unixerrstr(void);
|
|
|
|
|
|
/* File locking prototypes. */
|
|
/* Could these be made ARDP internal? hope so. */
|
|
#include <../lib/ardp/flocks.h>
|
|
FILELOCK filelock_alloc(void);
|
|
void filelock_free(FILELOCK fl);
|
|
void filelock_lfree(FILELOCK fl);
|
|
void filelock_freespares(void);
|
|
void filelock_release(const char *filename, int readonly);
|
|
void filelock_obtain(const char *filename, int readonly);
|
|
|
|
/* File locking functions. Also in pfs_threads.h */
|
|
extern int locked_fclose_A(FILE *afle, const char *filename, int readonly);
|
|
extern FILE *locked_fopen(const char *filename, const char *mode);
|
|
int locked_fclose_and_rename(FILE *afile, const char *tmpfilename, const char *filename, int retval);
|
|
extern void locked_clear(FILE *a); /* also in pfs_threads.h */
|
|
|
|
|
|
/* Mutex stuff for pfs_threads on server side only still.. */
|
|
extern void ardp_init_mutexes(void); /* need not be called. */
|
|
#ifndef NDEBUG
|
|
extern void ardp_diagnose_mutexes(void); /* need not be called. */
|
|
#endif /*NDEBUG*/
|
|
EXTERN_MUTEXED_DECL(RREQ, ardp_runQ);
|
|
EXTERN_MUTEXED_DECL(RREQ, ardp_doneQ);
|
|
EXTERN_MUTEXED_DECL(RREQ, ardp_pendingQ);
|
|
#ifdef PFS_THREADS
|
|
extern p_th_mutex p_th_mutexARDP_ACCEPT; /* declared in ardp_mutexes.c */
|
|
extern p_th_mutex p_th_mutexPTEXT; /* declared in ardp_mutexes.c */
|
|
extern p_th_mutex p_th_mutexARDP_RQALLOC; /* declared in ardp_mutexes.c */
|
|
extern p_th_mutex p_th_mutexGETHOSTBYNAME; /* declared in ardp_mutexes.c */
|
|
extern p_th_mutex p_th_mutexARDP_SELFNUM; /* declared in ardp_mutexes.c */
|
|
#endif
|
|
|
|
#include <implicit_fixes.h> /* Fixes for implicit definitions */
|
|
/* Internal error handling code (formerly in pfs.h). */
|
|
|
|
/* Internal error handling routines used by the pfs code; formerly in *
|
|
* internal_error.h. These include a replacement for the assert() *
|
|
* macro, and an interface for internal error handling, better *
|
|
* documented in internal_error.c */
|
|
/* XXX These are duplicated in include/pfs_utils.h; need to do code
|
|
cleanup here. */
|
|
|
|
#ifndef NDEBUG
|
|
#ifndef assert
|
|
#define assert(expr) \
|
|
do { \
|
|
if (!(expr)) \
|
|
internal_error("assertion violated: " #expr); \
|
|
} while(0)
|
|
#endif /* assert */
|
|
#else /* NDEBUG */
|
|
#ifndef assert
|
|
#define assert(expr) do {;} while(0)
|
|
#endif /* assert() */
|
|
#endif /* NDEBUG */
|
|
|
|
|
|
|
|
#if 0 /* OLD version -- keep until new one works */
|
|
#define internal_error(msg) \
|
|
do { \
|
|
write(2, "Internal error in file " __FILE__ ": ", \
|
|
sizeof "Internal error in file " __FILE__ ": " -1); \
|
|
write(2, msg, strlen(msg)); \
|
|
write(2, "\n", 1); \
|
|
if (internal_error_handler) \
|
|
(*internal_error_handler)(__FILE__, __LINE__, msg); \
|
|
else { \
|
|
fprintf(stderr, "line of error: %d\n", __LINE__); \
|
|
abort(); \
|
|
} \
|
|
} while(0)
|
|
#else
|
|
#ifndef internal_error
|
|
#define internal_error(msg) \
|
|
internal_error_helper(msg, __LINE__)
|
|
#define internal_error_helper(msg,line) \
|
|
do { \
|
|
write(2, "Internal error in file " __FILE__ " (line " #line "): ",\
|
|
sizeof "Internal error in file " __FILE__ " (line " #line "): " -1);\
|
|
write(2, msg, strlen(msg)); \
|
|
write(2, "\n", 1); \
|
|
if (internal_error_handler) \
|
|
(*internal_error_handler)(__FILE__, line, msg); \
|
|
/* If the internal_error_handler() ever returns, we should not continue.
|
|
*/ \
|
|
abort(); \
|
|
} while(0)
|
|
#endif /* internal_error() */
|
|
#endif
|
|
|
|
/* This function may be set to handle internal errors. Dirsrv handles them in
|
|
this way, by logging to plog. We make it int instead of void, because
|
|
older versions of the PCC (Portable C Compiler) cannot handle pointers to
|
|
void functions. */
|
|
/* variable name "line" commented out to shut up GCC -Wshadow. */
|
|
extern int (*internal_error_handler)(const char file[], int /* line */, const char mesg[]);
|
|
|
|
|
|
/* Some short macros that really hike the efficiency of this code. */
|
|
/* Like bcopy(a, b, 1), but much faster. */
|
|
#define bcopy1(a, b) do { \
|
|
((char *) (b))[0] = ((char *) (a))[0]; \
|
|
} while(0)
|
|
|
|
#define bcopy2(a, b) do { \
|
|
bcopy1(a, b); \
|
|
/* Next line depends on unary cast having higher precedence than \
|
|
addition. (Guaranteed to be true.) */ \
|
|
bcopy1((char *) (a) + 1, (char *) (b) + 1); \
|
|
} while(0)
|
|
|
|
#define bcopy4(a, b) do { \
|
|
bcopy2((a), (b)); \
|
|
bcopy2((char *) (a) + 2, (char *) (b) + 2);\
|
|
} while(0)
|
|
|
|
#define bzero1(a) do { \
|
|
((char *) (a))[0] = '\0'; \
|
|
} while(0)
|
|
|
|
#define bzero2(a) do { \
|
|
bzero1(a); \
|
|
bzero1((char *) (a) + 1); \
|
|
} while (0)
|
|
|
|
#define bzero3(a) do { \
|
|
bzero2(a); \
|
|
bzero1((char *) (a) + 2); \
|
|
} while(0)
|
|
|
|
#define bzero4(a) do { \
|
|
bzero2(a); \
|
|
bzero2((char *) (a) + 2); \
|
|
} while(0)
|
|
|
|
|
|
#endif /* not ARDP_H_INCLUDED */
|