Author: Bleep <tomh@inxpress.net>
[ircu2.10.12-pk.git] / ircd / bsd.c
1 /*
2  * IRC - Internet Relay Chat, common/bsd.c
3  * Copyright (C) 1990 Jarkko Oikarinen and
4  *                    University of Oulu, Computing Center
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 1, or (at your option)
9  * any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 #include "sys.h"
22 #include <signal.h>
23 #include <sys/socket.h>         /* Needed for send() */
24 #include "h.h"
25 #include "struct.h"
26 #include "s_bsd.h"
27 #include "ircd.h"
28 #include "bsd.h"
29
30 RCSTAG_CC("$Id$");
31
32 #ifdef DEBUGMODE
33 int writecalls = 0;
34 int writeb[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
35 #endif
36
37 RETSIGTYPE dummy(HANDLER_ARG(int UNUSED(sig)))
38 {
39 #ifndef HAVE_RELIABLE_SIGNALS
40   signal(SIGALRM, dummy);
41   signal(SIGPIPE, dummy);
42 #ifndef HPUX                    /* Only 9k/800 series require this,
43                                    but don't know how to.. */
44 #ifdef SIGWINCH
45   signal(SIGWINCH, dummy);
46 #endif
47 #endif
48 #else
49 #ifdef POSIX_SIGNALS
50   struct sigaction act;
51
52   act.sa_handler = dummy;
53   act.sa_flags = 0;
54   sigemptyset(&act.sa_mask);
55   sigaddset(&act.sa_mask, SIGALRM);
56   sigaddset(&act.sa_mask, SIGPIPE);
57 #ifdef SIGWINCH
58   sigaddset(&act.sa_mask, SIGWINCH);
59 #endif
60   sigaction(SIGALRM, &act, (struct sigaction *)NULL);
61   sigaction(SIGPIPE, &act, (struct sigaction *)NULL);
62 #ifdef SIGWINCH
63   sigaction(SIGWINCH, &act, (struct sigaction *)NULL);
64 #endif
65 #endif
66 #endif
67 }
68
69 /*
70  * deliver_it
71  *   Attempt to send a sequence of bytes to the connection.
72  *   Returns
73  *
74  *   < 0     Some fatal error occurred, (but not EWOULDBLOCK).
75  *           This return is a request to close the socket and
76  *           clean up the link.
77  *
78  *   >= 0    No real error occurred, returns the number of
79  *           bytes actually transferred. EWOULDBLOCK and other
80  *           possibly similar conditions should be mapped to
81  *           zero return. Upper level routine will have to
82  *           decide what to do with those unwritten bytes...
83  *
84  *   *NOTE*  alarm calls have been preserved, so this should
85  *           work equally well whether blocking or non-blocking
86  *           mode is used...
87  *
88  *   We don't use blocking anymore, that is impossible with the
89  *      net.loads today anyway. Commented out the alarms to save cpu.
90  *      --Run
91  */
92 int deliver_it(aClient *cptr, const char *str, int len)
93 {
94   int retval;
95   aClient *acpt = cptr->acpt;
96
97 #ifdef  DEBUGMODE
98   writecalls++;
99 #endif
100 #ifdef VMS
101   retval = netwrite(cptr->fd, str, len);
102 #else
103   retval = send(cptr->fd, str, len, 0);
104   /*
105    * Convert WOULDBLOCK to a return of "0 bytes moved". This
106    * should occur only if socket was non-blocking. Note, that
107    * all is Ok, if the 'write' just returns '0' instead of an
108    * error and errno=EWOULDBLOCK.
109    *
110    * ...now, would this work on VMS too? --msa
111    */
112   if (retval < 0 && (errno == EWOULDBLOCK || errno == EAGAIN ||
113 #ifdef SOL2
114       errno == ENOMEM || errno == ENOSR ||
115 #endif
116       errno == ENOBUFS))
117   {
118     retval = 0;
119     cptr->flags |= FLAGS_BLOCKED;
120   }
121   else if (retval > 0)
122   {
123 #ifdef  pyr
124     gettimeofday(&cptr->lw, NULL);
125 #endif
126     cptr->flags &= ~FLAGS_BLOCKED;
127   }
128
129 #endif
130 #ifdef DEBUGMODE
131   if (retval < 0)
132   {
133     writeb[0]++;
134     Debug((DEBUG_ERROR, "write error (%s) to %s",
135         sys_errlist[errno], cptr->name));
136   }
137   else if (retval == 0)
138     writeb[1]++;
139   else if (retval < 16)
140     writeb[2]++;
141   else if (retval < 32)
142     writeb[3]++;
143   else if (retval < 64)
144     writeb[4]++;
145   else if (retval < 128)
146     writeb[5]++;
147   else if (retval < 256)
148     writeb[6]++;
149   else if (retval < 512)
150     writeb[7]++;
151   else if (retval < 1024)
152     writeb[8]++;
153   else
154     writeb[9]++;
155 #endif
156   if (retval > 0)
157   {
158     cptr->sendB += retval;
159     me.sendB += retval;
160     if (cptr->sendB > 1023)
161     {
162       cptr->sendK += (cptr->sendB >> 10);
163       cptr->sendB &= 0x03ff;    /* 2^10 = 1024, 3ff = 1023 */
164     }
165     if (acpt != &me)
166     {
167       acpt->sendB += retval;
168       if (acpt->sendB > 1023)
169       {
170         acpt->sendK += (acpt->sendB >> 10);
171         acpt->sendB &= 0x03ff;
172       }
173     }
174     else if (me.sendB > 1023)
175     {
176       me.sendK += (me.sendB >> 10);
177       me.sendB &= 0x03ff;
178     }
179   }
180   return (retval);
181 }