aboutsummaryrefslogtreecommitdiff
path: root/common/bsd.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/bsd.c')
-rw-r--r--common/bsd.c192
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);
+}