diff options
Diffstat (limited to 'common/bsd.c')
-rw-r--r-- | common/bsd.c | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/common/bsd.c b/common/bsd.c new file mode 100644 index 0000000..69b66e7 --- /dev/null +++ b/common/bsd.c @@ -0,0 +1,192 @@ +/************************************************************************ + * IRC - Internet Relay Chat, common/bsd.c + * Copyright (C) 1990 Jarkko Oikarinen and + * University of Oulu, Computing Center + * + * 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 1, 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 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef lint +static char rcsid[] = "@(#)$Id: bsd.c,v 1.3 1998/12/13 00:02:33 kalt Exp $"; +#endif + +#include "os.h" +#ifndef CLIENT_COMPILE +# include "s_defines.h" +#else +# include "c_defines.h" +#endif +#define BSD_C +#ifndef CLIENT_COMPILE +# include "s_externs.h" +#else +# include "c_externs.h" +#endif +#undef BSD_C + +#ifdef DEBUGMODE +int writecalls = 0, writeb[10] = {0,0,0,0,0,0,0,0,0,0}; +#endif +RETSIGTYPE dummy(s) +int s; +{ +#ifndef HAVE_RELIABLE_SIGNALS + (void)signal(SIGALRM, dummy); + (void)signal(SIGPIPE, dummy); +# ifndef HPUX /* Only 9k/800 series require this, but don't know how to.. */ +# ifdef SIGWINCH + (void)signal(SIGWINCH, dummy); +# endif +# endif +#else +# if POSIX_SIGNALS + struct sigaction act; + + act.sa_handler = dummy; + act.sa_flags = 0; + (void)sigemptyset(&act.sa_mask); + (void)sigaddset(&act.sa_mask, SIGALRM); + (void)sigaddset(&act.sa_mask, SIGPIPE); +# ifdef SIGWINCH + (void)sigaddset(&act.sa_mask, SIGWINCH); +# endif + (void)sigaction(SIGALRM, &act, (struct sigaction *)NULL); + (void)sigaction(SIGPIPE, &act, (struct sigaction *)NULL); +# ifdef SIGWINCH + (void)sigaction(SIGWINCH, &act, (struct sigaction *)NULL); +# endif +# endif +#endif +} + + +/* +** deliver_it +** Attempt to send a sequence of bytes to the connection. +** Returns +** +** < 0 Some fatal error occurred, (but not EWOULDBLOCK). +** This return is a request to close the socket and +** clean up the link. +** +** >= 0 No real error occurred, returns the number of +** bytes actually transferred. EWOULDBLOCK and other +** possibly similar conditions should be mapped to +** zero return. Upper level routine will have to +** decide what to do with those unwritten bytes... +** +** *NOTE* alarm calls have been preserved, so this should +** work equally well whether blocking or non-blocking +** mode is used... +*/ +int deliver_it(cptr, str, len) +aClient *cptr; +int len; +char *str; + { + int retval; + aClient *acpt = cptr->acpt; + +#ifdef DEBUGMODE + writecalls++; +#endif +#ifndef NOWRITEALARM + (void)alarm(WRITEWAITDELAY); +#endif +#ifdef INET6 + retval = sendto(cptr->fd, str, len, 0, 0, 0); +#else + retval = send(cptr->fd, str, len, 0); +#endif + /* + ** Convert WOULDBLOCK to a return of "0 bytes moved". This + ** should occur only if socket was non-blocking. Note, that + ** all is Ok, if the 'write' just returns '0' instead of an + ** error and errno=EWOULDBLOCK. + ** + ** ...now, would this work on VMS too? --msa + */ + if (retval < 0 && (errno == EWOULDBLOCK || errno == EAGAIN || +#ifdef EMSGSIZE + errno == EMSGSIZE || +#endif + errno == ENOBUFS)) + { + retval = 0; + cptr->flags |= FLAGS_BLOCKED; + } + else if (retval > 0) + cptr->flags &= ~FLAGS_BLOCKED; + +#ifndef NOWRITEALARM + (void )alarm(0); +#endif +#ifdef DEBUGMODE + if (retval < 0) { + writeb[0]++; + Debug((DEBUG_ERROR,"write error (%s) to %s", + sys_errlist[errno], cptr->name)); +#ifndef CLIENT_COMPILE + hold_server(cptr); +#endif + } else if (retval == 0) + writeb[1]++; + else if (retval < 16) + writeb[2]++; + else if (retval < 32) + writeb[3]++; + else if (retval < 64) + writeb[4]++; + else if (retval < 128) + writeb[5]++; + else if (retval < 256) + writeb[6]++; + else if (retval < 512) + writeb[7]++; + else if (retval < 1024) + writeb[8]++; + else + writeb[9]++; +#endif + if (retval > 0) + { +#if defined(DEBUGMODE) && defined(DEBUG_WRITE) + Debug((DEBUG_WRITE, "send = %d bytes to %d[%s]:[%*.*s]\n", + retval, cptr->fd, cptr->name, retval, retval, str)); +#endif + cptr->sendB += retval; + me.sendB += retval; + if (cptr->sendB > 1023) + { + cptr->sendK += (cptr->sendB >> 10); + cptr->sendB &= 0x03ff; /* 2^10 = 1024, 3ff = 1023 */ + } + if (acpt != &me) + { + acpt->sendB += retval; + if (acpt->sendB > 1023) + { + acpt->sendK += (acpt->sendB >> 10); + acpt->sendB &= 0x03ff; + } + } + else if (me.sendB > 1023) + { + me.sendK += (me.sendB >> 10); + me.sendB &= 0x03ff; + } + } + return(retval); +} |