1 #include "syshdrs.h" 2 3 #ifndef NO_SIGNALS 4 extern volatile Sjmp_buf gNetTimeoutJmp; 5 extern volatile Sjmp_buf gPipeJmp; 6 #endif 7 8 #ifndef NO_SIGNALS 9 10 int 11 SSend(int sfd, char *buf0, size_t size, int fl, int tlen) 12 { 13 volatile int nleft; 14 char *volatile buf = buf0; 15 int nwrote, tleft; 16 vsio_sigproc_t sigalrm, sigpipe; 17 time_t done, now; 18 19 if (SSetjmp(gNetTimeoutJmp) != 0) { 20 alarm(0); 21 (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm); 22 (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe); 23 nwrote = size - nleft; 24 if (nwrote > 0) 25 return (nwrote); 26 errno = ETIMEDOUT; 27 return (kTimeoutErr); 28 } 29 30 if (SSetjmp(gPipeJmp) != 0) { 31 alarm(0); 32 (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm); 33 (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe); 34 nwrote = size - nleft; 35 if (nwrote > 0) 36 return (nwrote); 37 errno = EPIPE; 38 return (kBrokenPipeErr); 39 } 40 41 sigalrm = (vsio_sigproc_t) SSignal(SIGALRM, SIOHandler); 42 sigpipe = (vsio_sigproc_t) SSignal(SIGPIPE, SIOHandler); 43 44 nleft = (int) size; 45 time(&now); 46 done = now + tlen; 47 forever { 48 tleft = (int) (done - now); 49 if (tleft < 1) { 50 nwrote = size - nleft; 51 if (nwrote == 0) { 52 nwrote = kTimeoutErr; 53 errno = ETIMEDOUT; 54 } 55 goto done; 56 } 57 (void) alarm((unsigned int) tleft); 58 nwrote = send(sfd, buf, size, fl); 59 (void) alarm(0); 60 if (nwrote < 0) { 61 if (errno != EINTR) { 62 nwrote = size - nleft; 63 if (nwrote == 0) 64 nwrote = -1; 65 goto done; 66 } else { 67 errno = 0; 68 nwrote = 0; 69 /* Try again. */ 70 } 71 } 72 nleft -= nwrote; 73 if (nleft <= 0) 74 break; 75 buf += nwrote; 76 time(&now); 77 } 78 nwrote = size - nleft; 79 80 done: 81 (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm); 82 (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe); 83 84 return (nwrote); 85 } /* SSend */ 86 87 #else 88 89 int 90 SSend(int sfd, char *buf0, size_t size, int fl, int tlen) 91 { 92 int nleft; 93 char *buf = buf0; 94 int nwrote, tleft; 95 time_t done, now; 96 fd_set ss; 97 struct timeval tv; 98 int result; 99 100 nleft = (int) size; 101 time(&now); 102 done = now + tlen; 103 forever { 104 tleft = (int) (done - now); 105 if (tleft < 1) { 106 nwrote = size - nleft; 107 if (nwrote == 0) { 108 nwrote = kTimeoutErr; 109 errno = ETIMEDOUT; 110 SETWSATIMEOUTERR 111 } 112 goto done; 113 } 114 115 116 /* Unfortunately this doesn't help when the 117 * send buffer fills during the time we're 118 * writing to it, so you could still be 119 * blocked after breaking this loop and starting 120 * the write. 121 */ 122 123 forever { 124 errno = 0; 125 FD_ZERO(&ss); 126 FD_SET(sfd, &ss); 127 tv.tv_sec = tlen; 128 tv.tv_usec = 0; 129 result = select(sfd + 1, NULL, SELECT_TYPE_ARG234 &ss, NULL, SELECT_TYPE_ARG5 &tv); 130 if (result == 1) { 131 /* ready */ 132 break; 133 } else if (result == 0) { 134 /* timeout */ 135 nwrote = size - nleft; 136 if (nwrote > 0) 137 return (nwrote); 138 errno = ETIMEDOUT; 139 SETWSATIMEOUTERR 140 return (kTimeoutErr); 141 } else if (errno != EINTR) { 142 return (-1); 143 } 144 } 145 146 nwrote = send(sfd, buf, size, fl); 147 148 if (nwrote < 0) { 149 if (errno != EINTR) { 150 nwrote = size - nleft; 151 if (nwrote == 0) 152 nwrote = -1; 153 goto done; 154 } else { 155 errno = 0; 156 nwrote = 0; 157 /* Try again. */ 158 } 159 } 160 nleft -= nwrote; 161 if (nleft <= 0) 162 break; 163 buf += nwrote; 164 time(&now); 165 } 166 nwrote = size - nleft; 167 168 done: 169 return (nwrote); 170 } /* SSend */ 171 172 #endif 173