xref: /PHP-8.3/sapi/litespeed/lsapilib.c (revision 0d1bf582)
1 /*
2    +----------------------------------------------------------------------+
3    | Copyright (c) The PHP Group                                          |
4    +----------------------------------------------------------------------+
5    | This source file is subject to version 3.01 of the PHP license,      |
6    | that is bundled with this package in the file LICENSE, and is        |
7    | available through the world-wide-web at the following url:           |
8    | https://www.php.net/license/3_01.txt                                 |
9    | If you did not receive a copy of the PHP license and are unable to   |
10    | obtain it through the world-wide-web, please send a note to          |
11    | license@php.net so we can mail you a copy immediately.               |
12    +----------------------------------------------------------------------+
13    | Author: George Wang <gwang@litespeedtech.com>                        |
14    +----------------------------------------------------------------------+
15 */
16 
17 /*
18 Copyright (c) 2002-2018, Lite Speed Technologies Inc.
19 All rights reserved.
20 
21 Redistribution and use in source and binary forms, with or without
22 modification, are permitted provided that the following conditions are
23 met:
24 
25     * Redistributions of source code must retain the above copyright
26       notice, this list of conditions and the following disclaimer.
27     * Redistributions in binary form must reproduce the above
28       copyright notice, this list of conditions and the following
29       disclaimer in the documentation and/or other materials provided
30       with the distribution.
31     * Neither the name of the Lite Speed Technologies Inc nor the
32       names of its contributors may be used to endorse or promote
33       products derived from this software without specific prior
34       written permission.
35 
36 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
37 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
38 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
39 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
40 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
43 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
45 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
46 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47 */
48 
49 
50 #include <ctype.h>
51 #include <dlfcn.h>
52 #include <errno.h>
53 #include <fcntl.h>
54 #include <limits.h>
55 #include <sys/stat.h>
56 #include <sched.h>
57 #include <signal.h>
58 #include <stdlib.h>
59 #include <stdio.h>
60 #include <stdarg.h>
61 #include <string.h>
62 #include <sys/mman.h>
63 #include <sys/resource.h>
64 #include <sys/socket.h>
65 #include <sys/time.h>
66 #include <sys/uio.h>
67 #include <sys/wait.h>
68 #include <grp.h>
69 #include <pwd.h>
70 #include <time.h>
71 #include <unistd.h>
72 #include <arpa/inet.h>
73 #include <netdb.h>
74 #include <netinet/in.h>
75 #include <netinet/tcp.h>
76 #include <sys/un.h>
77 #include <php_config.h>
78 
79 #include "lsapilib.h"
80 
81 #ifdef HAVE_PRCTL
82 #include <sys/prctl.h>
83 #endif
84 
85 #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \
86     || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
87 #include <sys/sysctl.h>
88 #endif
89 
90 #include <inttypes.h>
91 #ifndef uint32
92 #define uint32 uint32_t
93 #endif
94 
95 #include <Zend/zend_portability.h>
96 
97 struct lsapi_MD5Context {
98     uint32 buf[4];
99     uint32 bits[2];
100     unsigned char in[64];
101 };
102 
103 void lsapi_MD5Init(struct lsapi_MD5Context *context);
104 void lsapi_MD5Update(struct lsapi_MD5Context *context, unsigned char const *buf,
105            unsigned len);
106 void lsapi_MD5Final(unsigned char digest[16], struct lsapi_MD5Context *context);
107 
108 /*
109  * This is needed to make RSAREF happy on some MS-DOS compilers.
110  */
111 typedef struct lsapi_MD5Context lsapi_MD5_CTX;
112 
113 
114 #define LSAPI_ST_REQ_HEADER     1
115 #define LSAPI_ST_REQ_BODY       2
116 #define LSAPI_ST_RESP_HEADER    4
117 #define LSAPI_ST_RESP_BODY      8
118 #define LSAPI_ST_BACKGROUND     16
119 
120 #define LSAPI_RESP_BUF_SIZE     8192
121 #define LSAPI_INIT_RESP_HEADER_LEN 4096
122 
123 enum
124 {
125     LSAPI_STATE_IDLE,
126     LSAPI_STATE_CONNECTED,
127     LSAPI_STATE_ACCEPTING,
128 };
129 
130 typedef struct lsapi_child_status
131 {
132     int     m_pid;
133     long    m_tmStart;
134 
135     volatile short   m_iKillSent;
136     volatile char    m_inProcess;
137     volatile char    m_state;
138     volatile int     m_iReqCounter;
139 
140     volatile long    m_tmWaitBegin;
141     volatile long    m_tmReqBegin;
142     volatile long    m_tmLastCheckPoint;
143 }
144 lsapi_child_status;
145 
146 static lsapi_child_status * s_worker_status = NULL;
147 
148 static int g_inited = 0;
149 static int g_running = 1;
150 static int s_ppid;
151 static int s_restored_ppid = 0;
152 static int s_pid = 0;
153 static int s_slow_req_msecs = 0;
154 static int s_keep_listener = 1;
155 static int s_dump_debug_info = 0;
156 static int s_pid_dump_debug_info = 0;
157 static int s_req_processed = 0;
158 static int s_skip_write = 0;
159 static int (*pthread_atfork_func)(void (*prepare)(void), void (*parent)(void),
160                                   void (*child)(void)) = NULL;
161 
162 static int *s_busy_workers = NULL;
163 static int *s_accepting_workers = NULL;
164 static int *s_global_counter = &s_req_processed;
165 static int s_max_busy_workers = -1;
166 static char *s_stderr_log_path = NULL;
167 static int s_stderr_is_pipe = 0;
168 static int s_ignore_pid = -1;
169 static size_t s_total_pages = 1;
170 static size_t s_min_avail_pages = 256 * 1024;
171 static size_t *s_avail_pages = &s_total_pages;
172 
173 LSAPI_Request g_req =
174 { .m_fdListen = -1, .m_fd = -1 };
175 
176 static char         s_secret[24];
177 
178 static LSAPI_On_Timer_pf s_proc_group_timer_cb = NULL;
179 
180 void Flush_RespBuf_r( LSAPI_Request * pReq );
181 static int lsapi_reopen_stderr(const char *p);
182 
183 static const char *CGI_HEADERS[H_TRANSFER_ENCODING+1] =
184 {
185     "HTTP_ACCEPT", "HTTP_ACCEPT_CHARSET",
186     "HTTP_ACCEPT_ENCODING",
187     "HTTP_ACCEPT_LANGUAGE", "HTTP_AUTHORIZATION",
188     "HTTP_CONNECTION", "CONTENT_TYPE",
189     "CONTENT_LENGTH", "HTTP_COOKIE", "HTTP_COOKIE2",
190     "HTTP_HOST", "HTTP_PRAGMA",
191     "HTTP_REFERER", "HTTP_USER_AGENT",
192     "HTTP_CACHE_CONTROL",
193     "HTTP_IF_MODIFIED_SINCE", "HTTP_IF_MATCH",
194     "HTTP_IF_NONE_MATCH",
195     "HTTP_IF_RANGE",
196     "HTTP_IF_UNMODIFIED_SINCE",
197     "HTTP_KEEP_ALIVE",
198     "HTTP_RANGE",
199     "HTTP_X_FORWARDED_FOR",
200     "HTTP_VIA",
201     "HTTP_TRANSFER_ENCODING"
202 };
203 
204 static int CGI_HEADER_LEN[H_TRANSFER_ENCODING+1] =
205 {    11, 19, 20, 20, 18, 15, 12, 14, 11, 12, 9, 11, 12, 15, 18,
206      22, 13, 18, 13, 24, 15, 10, 20, 8, 22 };
207 
208 
209 static const char *HTTP_HEADERS[H_TRANSFER_ENCODING+1] =
210 {
211     "Accept", "Accept-Charset",
212     "Accept-Encoding",
213     "Accept-Language", "Authorization",
214     "Connection", "Content-Type",
215     "Content-Length", "Cookie", "Cookie2",
216     "Host", "Pragma",
217     "Referer", "User-Agent",
218     "Cache-Control",
219     "If-Modified-Since", "If-Match",
220     "If-None-Match",
221     "If-Range",
222     "If-Unmodified-Since",
223     "Keep-Alive",
224     "Range",
225     "X-Forwarded-For",
226     "Via",
227     "Transfer-Encoding"
228 };
229 
230 static int HTTP_HEADER_LEN[H_TRANSFER_ENCODING+1] =
231 {   6, 14, 15, 15, 13, 10, 12, 14, 6, 7, 4, 6, 7, 10, //user-agent
232     13,17, 8, 13, 8, 19, 10, 5, 15, 3, 17
233 };
234 
235 
236 static const char *s_log_level_names[8] =
237 {
238     "", "DEBUG","INFO", "NOTICE", "WARN", "ERROR", "CRIT", "FATAL"
239 };
240 
241 
LSAPI_Log(int flag,const char * fmt,...)242 void LSAPI_Log(int flag, const char * fmt, ...)
243 {
244     char buf[1024];
245     char *p = buf;
246     if ((flag & LSAPI_LOG_TIMESTAMP_BITS)
247         && !(s_stderr_is_pipe))
248     {
249         struct timeval  tv;
250         struct tm       tm;
251         gettimeofday(&tv, NULL);
252         localtime_r(&tv.tv_sec, &tm);
253         if (flag & LSAPI_LOG_TIMESTAMP_FULL)
254         {
255             p += snprintf(p, 1024, "%04d-%02d-%02d %02d:%02d:%02d.%06d ",
256                 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
257                 tm.tm_hour, tm.tm_min, tm.tm_sec, (int)tv.tv_usec);
258         }
259         else if (flag & LSAPI_LOG_TIMESTAMP_HMS)
260         {
261             p += snprintf(p, 1024, "%02d:%02d:%02d ",
262                 tm.tm_hour, tm.tm_min, tm.tm_sec);
263         }
264     }
265 
266     int level = flag & LSAPI_LOG_LEVEL_BITS;
267     if (level && level <= LSAPI_LOG_FLAG_FATAL)
268     {
269         p += snprintf(p, 100, "[%s] ", s_log_level_names[level]);
270     }
271 
272     if (flag & LSAPI_LOG_PID)
273     {
274         p += snprintf(p, 100, "[UID:%d][%d] ", getuid(), s_pid);
275     }
276 
277     if (p > buf)
278         fprintf(stderr, "%.*s", (int)(p - buf), buf);
279     va_list ap;
280     va_start(ap, fmt);
281     vfprintf(stderr, fmt, ap);
282     va_end(ap);
283 }
284 
285 #ifdef LSAPI_DEBUG
286 
287 #define DBGLOG_FLAG (LSAPI_LOG_TIMESTAMP_FULL|LSAPI_LOG_FLAG_DEBUG|LSAPI_LOG_PID)
288 #define lsapi_dbg(...)   LSAPI_Log(DBGLOG_FLAG, __VA_ARGS__)
289 
290 #else
291 
292 #define lsapi_dbg(...)
293 
294 #endif
295 
296 #define lsapi_log(...)  LSAPI_Log(LSAPI_LOG_TIMESTAMP_FULL|LSAPI_LOG_PID, __VA_ARGS__)
297 
298 
lsapi_perror(const char * pMessage,int err_no)299 void lsapi_perror(const char * pMessage, int err_no)
300 {
301     lsapi_log("%s, errno: %d (%s)\n", pMessage, err_no, strerror(err_no));
302 }
303 
304 
lsapi_parent_dead(void)305 static int lsapi_parent_dead(void)
306 {
307     // Return non-zero if the parent is dead.  0 if still alive.
308     if (!s_ppid) {
309         // not checking, so not dead
310         return(0);
311     }
312     if (s_restored_ppid) {
313         if (kill(s_restored_ppid,0) == -1) {
314             if (errno == EPERM) {
315                 return(0); // no permission, but it's still there.
316             }
317             return(1); // Dead
318         }
319         return(0); // it worked, so it's not dead
320     }
321     return(s_ppid != getppid());
322 }
323 
324 
lsapi_sigpipe(int sig)325 static void lsapi_sigpipe( int sig )
326 {
327 }
328 
329 
lsapi_siguser1(int sig)330 static void lsapi_siguser1( int sig )
331 {
332     g_running = 0;
333 }
334 
335 #ifndef sighandler_t
336 typedef void (*sighandler_t)(int);
337 #endif
338 
lsapi_signal(int signo,sighandler_t handler)339 static void lsapi_signal(int signo, sighandler_t handler)
340 {
341     struct sigaction sa;
342 
343     sigaction(signo, NULL, &sa);
344 
345     if (sa.sa_handler == SIG_DFL)
346     {
347         sigemptyset(&sa.sa_mask);
348         sa.sa_flags = 0;
349         sa.sa_handler = handler;
350         sigaction(signo, &sa, NULL);
351     }
352 }
353 
354 
355 static int s_enable_core_dump = 0;
lsapi_enable_core_dump(void)356 static void lsapi_enable_core_dump(void)
357 {
358 #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \
359     || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
360     int  mib[2];
361     size_t len;
362 
363 #if !defined(__OpenBSD__)
364     len = 2;
365     if ( sysctlnametomib("kern.sugid_coredump", mib, &len) == 0 )
366     {
367         len = sizeof(s_enable_core_dump);
368         if (sysctl(mib, 2, NULL, 0, &s_enable_core_dump, len) == -1)
369             perror( "sysctl: Failed to set 'kern.sugid_coredump', "
370                     "core dump may not be available!");
371     }
372 #else
373     int set = 3;
374     len = sizeof(set);
375     mib[0] = CTL_KERN;
376     mib[1] = KERN_NOSUIDCOREDUMP;
377     if (sysctl(mib, 2, NULL, 0, &set, len) == 0) {
378 	    s_enable_core_dump = 1;
379     }
380 #endif
381 
382 
383 #endif
384 
385 #ifdef HAVE_PRCTL
386     if (prctl(PR_SET_DUMPABLE, s_enable_core_dump,0,0,0) == -1)
387         perror( "prctl: Failed to set dumpable, "
388                     "core dump may not be available!");
389 #endif
390 }
391 
392 
lsapi_buildPacketHeader(struct lsapi_packet_header * pHeader,char type,int len)393 static inline void lsapi_buildPacketHeader( struct lsapi_packet_header * pHeader,
394                                 char type, int len )
395 {
396     pHeader->m_versionB0 = LSAPI_VERSION_B0;  /* LSAPI protocol version */
397     pHeader->m_versionB1 = LSAPI_VERSION_B1;
398     pHeader->m_type      = type;
399     pHeader->m_flag      = LSAPI_ENDIAN;
400     pHeader->m_packetLen.m_iLen = len;
401 }
402 
403 
lsapi_set_nblock(int fd,int nonblock)404 static  int lsapi_set_nblock( int fd, int nonblock )
405 {
406     int val = fcntl( fd, F_GETFL, 0 );
407     if ( nonblock )
408     {
409         if (!( val & O_NONBLOCK ))
410         {
411             return fcntl( fd, F_SETFL, val | O_NONBLOCK );
412         }
413     }
414     else
415     {
416         if ( val & O_NONBLOCK )
417         {
418             return fcntl( fd, F_SETFL, val &(~O_NONBLOCK) );
419         }
420     }
421     return 0;
422 }
423 
424 
lsapi_close(int fd)425 static int lsapi_close( int fd )
426 {
427     int ret;
428     while( 1 )
429     {
430         ret = close( fd );
431         if (( ret == -1 )&&( errno == EINTR )&&(g_running))
432             continue;
433         return ret;
434     }
435 }
436 
437 
lsapi_close_connection(LSAPI_Request * pReq)438 static void lsapi_close_connection(LSAPI_Request *pReq)
439 {
440     if (pReq->m_fd == -1)
441         return;
442     lsapi_close(pReq->m_fd);
443     pReq->m_fd = -1;
444     if (s_busy_workers)
445         __atomic_fetch_sub(s_busy_workers, 1, __ATOMIC_SEQ_CST);
446     if (s_worker_status)
447         __atomic_store_n(&s_worker_status->m_state, LSAPI_STATE_IDLE,
448                          __ATOMIC_SEQ_CST);
449 }
450 
451 
lsapi_read(int fd,void * pBuf,size_t len)452 static inline ssize_t lsapi_read( int fd, void * pBuf, size_t len )
453 {
454     ssize_t ret;
455     while( 1 )
456     {
457         ret = read( fd, (char *)pBuf, len );
458         if (( ret == -1 )&&( errno == EINTR )&&(g_running))
459             continue;
460         return ret;
461     }
462 }
463 
464 
465 /*
466 static int lsapi_write( int fd, const void * pBuf, int len )
467 {
468    int ret;
469    const char * pCur;
470    const char * pEnd;
471    if ( len == 0 )
472        return 0;
473    pCur = (const char *)pBuf;
474    pEnd = pCur + len;
475    while( g_running && (pCur < pEnd) )
476    {
477        ret = write( fd, pCur, pEnd - pCur );
478        if ( ret >= 0)
479            pCur += ret;
480        else if (( ret == -1 )&&( errno != EINTR ))
481            return ret;
482    }
483    return pCur - (const char *)pBuf;
484 }
485 */
486 
487 
lsapi_writev(int fd,struct iovec ** pVec,int count,int totalLen)488 static int lsapi_writev( int fd, struct iovec ** pVec, int count, int totalLen )
489 {
490     int ret;
491     int left = totalLen;
492     int n = count;
493 
494     if (s_skip_write)
495         return totalLen;
496 
497     while(( left > 0 )&&g_running )
498     {
499         ret = writev( fd, *pVec, n );
500         if ( ret > 0 )
501         {
502             left -= ret;
503             if (( left <= 0)||( !g_running ))
504                 return totalLen - left;
505             while( ret > 0 )
506             {
507                 if ( (*pVec)->iov_len <= (unsigned int )ret )
508                 {
509                     ret -= (*pVec)->iov_len;
510                     ++(*pVec);
511                 }
512                 else
513                 {
514                     (*pVec)->iov_base = (char *)(*pVec)->iov_base + ret;
515                     (*pVec)->iov_len -= ret;
516                     break;
517                 }
518             }
519         }
520         else if ( ret == -1 )
521         {
522             if ( errno == EAGAIN )
523             {
524                 if ( totalLen - left > 0 )
525                     return totalLen - left;
526                 else
527                     return -1;
528             }
529             else if ( errno != EINTR )
530                 return ret;
531         }
532     }
533     return totalLen - left;
534 }
535 
536 
537 /*
538 static int getTotalLen( struct iovec * pVec, int count )
539 {
540    struct iovec * pEnd = pVec + count;
541    int total = 0;
542    while( pVec < pEnd )
543    {
544        total += pVec->iov_len;
545        ++pVec;
546    }
547    return total;
548 }
549 */
550 
551 
allocateBuf(LSAPI_Request * pReq,int size)552 static inline int allocateBuf( LSAPI_Request * pReq, int size )
553 {
554     char * pBuf = (char *)realloc( pReq->m_pReqBuf, size );
555     if ( pBuf )
556     {
557         pReq->m_pReqBuf = pBuf;
558         pReq->m_reqBufSize = size;
559         pReq->m_pHeader = (struct lsapi_req_header *)pReq->m_pReqBuf;
560         return 0;
561     }
562     return -1;
563 }
564 
565 
allocateIovec(LSAPI_Request * pReq,int n)566 static int allocateIovec( LSAPI_Request * pReq, int n )
567 {
568     struct iovec * p = (struct iovec *)realloc(
569                 pReq->m_pIovec, sizeof(struct iovec) * n );
570     if ( !p )
571         return -1;
572     pReq->m_pIovecToWrite = p + ( pReq->m_pIovecToWrite - pReq->m_pIovec );
573     pReq->m_pIovecCur = p + ( pReq->m_pIovecCur - pReq->m_pIovec );
574     pReq->m_pIovec = p;
575     pReq->m_pIovecEnd = p + n;
576     return 0;
577 }
578 
579 
allocateRespHeaderBuf(LSAPI_Request * pReq,int size)580 static int allocateRespHeaderBuf( LSAPI_Request * pReq, int size )
581 {
582     char * p = (char *)realloc( pReq->m_pRespHeaderBuf, size );
583     if ( !p )
584         return -1;
585     pReq->m_pRespHeaderBufPos   = p + ( pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf );
586     pReq->m_pRespHeaderBuf      = p;
587     pReq->m_pRespHeaderBufEnd   = p + size;
588     return 0;
589 }
590 
591 
verifyHeader(struct lsapi_packet_header * pHeader,char pktType)592 static inline int verifyHeader( struct lsapi_packet_header * pHeader, char pktType )
593 {
594     if (( LSAPI_VERSION_B0 != pHeader->m_versionB0 )||
595         ( LSAPI_VERSION_B1 != pHeader->m_versionB1 )||
596         ( pktType != pHeader->m_type ))
597         return -1;
598     if ( LSAPI_ENDIAN != (pHeader->m_flag & LSAPI_ENDIAN_BIT ))
599     {
600         register char b;
601         b = pHeader->m_packetLen.m_bytes[0];
602         pHeader->m_packetLen.m_bytes[0] = pHeader->m_packetLen.m_bytes[3];
603         pHeader->m_packetLen.m_bytes[3] = b;
604         b = pHeader->m_packetLen.m_bytes[1];
605         pHeader->m_packetLen.m_bytes[1] = pHeader->m_packetLen.m_bytes[2];
606         pHeader->m_packetLen.m_bytes[2] = b;
607     }
608     return pHeader->m_packetLen.m_iLen;
609 }
610 
611 
allocateEnvList(struct LSAPI_key_value_pair ** pEnvList,int * curSize,int newSize)612 static int allocateEnvList( struct LSAPI_key_value_pair ** pEnvList,
613                         int *curSize, int newSize )
614 {
615     struct LSAPI_key_value_pair * pBuf;
616     if ( *curSize >= newSize )
617         return 0;
618     if ( newSize > 8192 )
619         return -1;
620     pBuf = (struct LSAPI_key_value_pair *)realloc( *pEnvList, newSize *
621                     sizeof(struct LSAPI_key_value_pair) );
622     if ( pBuf )
623     {
624         *pEnvList = pBuf;
625         *curSize  = newSize;
626         return 0;
627     }
628     else
629         return -1;
630 
631 }
632 
633 
isPipe(int fd)634 static inline int isPipe( int fd )
635 {
636     char        achPeer[128];
637     socklen_t   len = 128;
638     if (( getpeername( fd, (struct sockaddr *)achPeer, &len ) != 0 )&&
639         ( errno == ENOTCONN ))
640         return 0;
641     else
642         return 1;
643 }
644 
645 
parseEnv(struct LSAPI_key_value_pair * pEnvList,int count,char ** pBegin,char * pEnd)646 static int parseEnv( struct LSAPI_key_value_pair * pEnvList, int count,
647             char **pBegin, char * pEnd )
648 {
649     struct LSAPI_key_value_pair * pEnvEnd;
650         int keyLen = 0, valLen = 0;
651     if ( count > 8192 )
652         return -1;
653     pEnvEnd = pEnvList + count;
654     while( pEnvList != pEnvEnd )
655     {
656         if ( pEnd - *pBegin < 4 )
657             return -1;
658         keyLen = *((unsigned char *)((*pBegin)++));
659         keyLen = (keyLen << 8) + *((unsigned char *)((*pBegin)++));
660         valLen = *((unsigned char *)((*pBegin)++));
661         valLen = (valLen << 8) + *((unsigned char *)((*pBegin)++));
662         if ( *pBegin + keyLen + valLen > pEnd )
663             return -1;
664         if (( !keyLen )||( !valLen ))
665             return -1;
666 
667         pEnvList->pKey = *pBegin;
668         *pBegin += keyLen;
669         pEnvList->pValue = *pBegin;
670         *pBegin += valLen;
671 
672         pEnvList->keyLen = keyLen - 1;
673         pEnvList->valLen = valLen - 1;
674         ++pEnvList;
675     }
676     if ( memcmp( *pBegin, "\0\0\0\0", 4 ) != 0 )
677         return -1;
678     *pBegin += 4;
679     return 0;
680 }
681 
682 
swapIntEndian(int * pInteger)683 static inline void swapIntEndian( int * pInteger )
684 {
685     char * p = (char *)pInteger;
686     register char b;
687     b = p[0];
688     p[0] = p[3];
689     p[3] = b;
690     b = p[1];
691     p[1] = p[2];
692     p[2] = b;
693 
694 }
695 
696 
fixEndian(LSAPI_Request * pReq)697 static inline void fixEndian( LSAPI_Request * pReq )
698 {
699     struct lsapi_req_header *p= pReq->m_pHeader;
700     swapIntEndian( &p->m_httpHeaderLen );
701     swapIntEndian( &p->m_reqBodyLen );
702     swapIntEndian( &p->m_scriptFileOff );
703     swapIntEndian( &p->m_scriptNameOff );
704     swapIntEndian( &p->m_queryStringOff );
705     swapIntEndian( &p->m_requestMethodOff );
706     swapIntEndian( &p->m_cntUnknownHeaders );
707     swapIntEndian( &p->m_cntEnv );
708     swapIntEndian( &p->m_cntSpecialEnv );
709 }
710 
711 
fixHeaderIndexEndian(LSAPI_Request * pReq)712 static void fixHeaderIndexEndian( LSAPI_Request * pReq )
713 {
714     int i;
715     for( i = 0; i < H_TRANSFER_ENCODING; ++i )
716     {
717         if ( pReq->m_pHeaderIndex->m_headerOff[i] )
718         {
719             register char b;
720             char * p = (char *)(&pReq->m_pHeaderIndex->m_headerLen[i]);
721             b = p[0];
722             p[0] = p[1];
723             p[1] = b;
724             swapIntEndian( &pReq->m_pHeaderIndex->m_headerOff[i] );
725         }
726     }
727     if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
728     {
729         struct lsapi_header_offset * pCur, *pEnd;
730         pCur = pReq->m_pUnknownHeader;
731         pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
732         while( pCur < pEnd )
733         {
734             swapIntEndian( &pCur->nameOff );
735             swapIntEndian( &pCur->nameLen );
736             swapIntEndian( &pCur->valueOff );
737             swapIntEndian( &pCur->valueLen );
738             ++pCur;
739         }
740     }
741 }
742 
743 
validateHeaders(LSAPI_Request * pReq)744 static int validateHeaders( LSAPI_Request * pReq )
745 {
746     int totalLen = pReq->m_pHeader->m_httpHeaderLen;
747     int i;
748     for(i = 0; i < H_TRANSFER_ENCODING; ++i)
749     {
750         if ( pReq->m_pHeaderIndex->m_headerOff[i] )
751         {
752             if (pReq->m_pHeaderIndex->m_headerOff[i] > totalLen
753                 || pReq->m_pHeaderIndex->m_headerLen[i]
754                     + pReq->m_pHeaderIndex->m_headerOff[i] > totalLen)
755                 return -1;
756         }
757     }
758     if (pReq->m_pHeader->m_cntUnknownHeaders > 0)
759     {
760         struct lsapi_header_offset * pCur, *pEnd;
761         pCur = pReq->m_pUnknownHeader;
762         pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
763         while( pCur < pEnd )
764         {
765             if (pCur->nameOff > totalLen
766                 || pCur->nameOff + pCur->nameLen > totalLen
767                 || pCur->valueOff > totalLen
768                 || pCur->valueOff + pCur->valueLen > totalLen)
769                 return -1;
770             ++pCur;
771         }
772     }
773     return 0;
774 }
775 
776 
777 static uid_t s_uid = 0;
778 static uid_t s_defaultUid;  //web server need set this
779 static gid_t s_defaultGid;
780 
781 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
782 
783 #define LSAPI_LVE_DISABLED  0
784 #define LSAPI_LVE_ENABLED   1
785 #define LSAPI_CAGEFS_ENABLED 2
786 #define LSAPI_CAGEFS_NO_SUEXEC 3
787 struct liblve;
788 static int s_enable_lve = LSAPI_LVE_DISABLED;
789 static struct liblve * s_lve = NULL;
790 
791 static void *s_liblve;
792 static int (*fp_lve_is_available)(void) = NULL;
793 static int (*fp_lve_instance_init)(struct liblve *) = NULL;
794 static int (*fp_lve_destroy)(struct liblve *) = NULL;
795 static int (*fp_lve_enter)(struct liblve *, uint32_t, int32_t, int32_t, uint32_t *) = NULL;
796 static int (*fp_lve_leave)(struct liblve *, uint32_t *) = NULL;
797 static int (*fp_lve_jail)( struct passwd *, char *) = NULL;
lsapi_load_lve_lib(void)798 static int lsapi_load_lve_lib(void)
799 {
800     s_liblve = DL_LOAD("liblve.so.0");
801     if (s_liblve)
802     {
803         fp_lve_is_available = dlsym(s_liblve, "lve_is_available");
804         if (dlerror() == NULL)
805         {
806             if ( !(*fp_lve_is_available)() )
807             {
808                 int uid = getuid();
809                 if ( uid )
810                 {
811                     if (setreuid( s_uid, uid )) {};
812                     if ( !(*fp_lve_is_available)() )
813                         s_enable_lve = 0;
814                     if (setreuid( uid, s_uid )) {};
815                 }
816             }
817         }
818     }
819     else
820     {
821         s_enable_lve = LSAPI_LVE_DISABLED;
822     }
823     return (s_liblve)? 0 : -1;
824 }
825 
826 
init_lve_ex(void)827 static int init_lve_ex(void)
828 {
829     int rc;
830     if ( !s_liblve )
831         return -1;
832     fp_lve_instance_init = dlsym(s_liblve, "lve_instance_init");
833     fp_lve_destroy = dlsym(s_liblve, "lve_destroy");
834     fp_lve_enter = dlsym(s_liblve, "lve_enter");
835     fp_lve_leave = dlsym(s_liblve, "lve_leave");
836     if ( s_enable_lve >= LSAPI_CAGEFS_ENABLED )
837         fp_lve_jail = dlsym(s_liblve, "jail" );
838 
839     if ( s_lve == NULL )
840     {
841         rc = (*fp_lve_instance_init)(NULL);
842         s_lve = malloc(rc);
843     }
844     rc = (*fp_lve_instance_init)(s_lve);
845     if (rc != 0)
846     {
847         perror( "LSAPI: Unable to initialize LVE" );
848         free( s_lve );
849         s_lve = NULL;
850         return -1;
851     }
852     return 0;
853 
854 }
855 
856 #endif
857 
858 
859 
readSecret(const char * pSecretFile)860 static int readSecret( const char * pSecretFile )
861 {
862     struct stat st;
863     int fd = open( pSecretFile, O_RDONLY , 0600 );
864     if ( fd == -1 )
865     {
866         lsapi_log("LSAPI: failed to open secret file: %s!\n", pSecretFile );
867         return -1;
868     }
869     if ( fstat( fd, &st ) == -1 )
870     {
871         lsapi_log("LSAPI: failed to check state of file: %s!\n", pSecretFile );
872         close( fd );
873         return -1;
874     }
875 /*
876     if ( st.st_uid != s_uid )
877     {
878         lsapi_log("LSAPI: file owner check failure: %s!\n", pSecretFile );
879         close( fd );
880         return -1;
881     }
882 */
883     if ( st.st_mode & 0077 )
884     {
885         lsapi_log("LSAPI: file permission check failure: %s\n", pSecretFile );
886         close( fd );
887         return -1;
888     }
889     if ( read( fd, s_secret, 16 ) < 16 )
890     {
891         lsapi_log("LSAPI: failed to read secret from secret file: %s\n", pSecretFile );
892         close( fd );
893         return -1;
894     }
895     close( fd );
896     return 0;
897 }
898 
899 
LSAPI_is_suEXEC_Daemon(void)900 int LSAPI_is_suEXEC_Daemon(void)
901 {
902     if (( !s_uid )&&( s_secret[0] ))
903         return 1;
904     else
905         return 0;
906 }
907 
908 
LSAPI_perror_r(LSAPI_Request * pReq,const char * pErr1,const char * pErr2)909 static int LSAPI_perror_r( LSAPI_Request * pReq, const char * pErr1, const char *pErr2 )
910 {
911     char achError[4096];
912     int n = snprintf(achError, sizeof(achError), "[UID:%d][%d] %s:%s: %s\n",
913                      getuid(), getpid(),
914                      pErr1, (pErr2)?pErr2:"", strerror(errno));
915     if (n > (int)sizeof(achError))
916         n = sizeof(achError);
917     if ( pReq )
918         LSAPI_Write_Stderr_r( pReq, achError, n );
919     else
920         if (write( STDERR_FILENO, achError, n )) {};
921     return 0;
922 }
923 
924 
925 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
lsapi_lve_error(LSAPI_Request * pReq)926 static int lsapi_lve_error( LSAPI_Request * pReq )
927 {
928     static const char * headers[] =
929     {
930         "Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0",
931         "Pragma: no-cache",
932         "Retry-After: 60",
933         "Content-Type: text/html",
934         NULL
935     };
936     static const char achBody[] =
937         "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n"
938         "<HTML><HEAD>\n<TITLE>508 Resource Limit Is Reached</TITLE>\n"
939         "</HEAD><BODY>\n" "<H1>Resource Limit Is Reached</H1>\n"
940         "The website is temporarily unable to service your request as it exceeded resource limit.\n"
941         "Please try again later.\n"
942         "<HR>\n"
943         "</BODY></HTML>\n";
944 
945     LSAPI_ErrResponse_r( pReq, 508, headers, achBody, sizeof( achBody ) - 1 );
946     return 0;
947 }
948 
lsapi_enterLVE(LSAPI_Request * pReq,uid_t uid)949 static int lsapi_enterLVE( LSAPI_Request * pReq, uid_t uid )
950 {
951     if ( s_lve && uid ) //root user should not do that
952     {
953         uint32_t cookie;
954         int ret = -1;
955         ret = (*fp_lve_enter)(s_lve, uid, -1, -1, &cookie);
956         if ( ret < 0 )
957         {
958             //lsapi_log("enter LVE (%d) : result: %d !\n", uid, ret );
959             LSAPI_perror_r(pReq, "LSAPI: lve_enter() failure, reached resource limit.", NULL );
960             lsapi_lve_error( pReq );
961             return -1;
962         }
963     }
964 
965     return 0;
966 }
967 
lsapi_jailLVE(LSAPI_Request * pReq,uid_t uid,struct passwd * pw)968 static int lsapi_jailLVE( LSAPI_Request * pReq, uid_t uid, struct passwd * pw )
969 {
970     int ret = 0;
971     char  error_msg[1024] = "";
972     ret = (*fp_lve_jail)( pw, error_msg );
973     if ( ret < 0 )
974     {
975         lsapi_log("LSAPI: LVE jail(%d) result: %d, error: %s !\n",
976                   uid, ret, error_msg );
977         LSAPI_perror_r( pReq, "LSAPI: jail() failure.", NULL );
978         return -1;
979     }
980     return ret;
981 }
982 
983 
lsapi_initLVE(void)984 static int lsapi_initLVE(void)
985 {
986     const char * pEnv;
987     if ( (pEnv = getenv( "LSAPI_LVE_ENABLE" ))!= NULL )
988     {
989         s_enable_lve = atol( pEnv );
990         pEnv = NULL;
991     }
992     else if ( (pEnv = getenv( "LVE_ENABLE" ))!= NULL )
993     {
994         s_enable_lve = atol( pEnv );
995         pEnv = NULL;
996     }
997     if ( s_enable_lve && !s_uid )
998     {
999         lsapi_load_lve_lib();
1000         if ( s_enable_lve )
1001         {
1002             return init_lve_ex();
1003         }
1004 
1005     }
1006     return 0;
1007 }
1008 #endif
1009 
1010 
setUID_LVE(LSAPI_Request * pReq,uid_t uid,gid_t gid,const char * pChroot)1011 static int setUID_LVE(LSAPI_Request * pReq, uid_t uid, gid_t gid, const char * pChroot)
1012 {
1013     int rv;
1014     struct passwd * pw;
1015     pw = getpwuid( uid );
1016 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
1017     if ( s_lve )
1018     {
1019         if( lsapi_enterLVE( pReq, uid ) == -1 )
1020             return -1;
1021         if ( pw && fp_lve_jail)
1022         {
1023             rv = lsapi_jailLVE( pReq, uid, pw );
1024             if ( rv == -1 )
1025                 return -1;
1026             if (( rv == 1 )&&(s_enable_lve == LSAPI_CAGEFS_NO_SUEXEC ))    //this mode only use cageFS, does not use suEXEC
1027             {
1028                 uid = s_defaultUid;
1029                 gid = s_defaultGid;
1030                 pw = getpwuid( uid );
1031             }
1032         }
1033     }
1034 #endif
1035     //if ( !uid || !gid )  //do not allow root
1036     //{
1037     //    return -1;
1038     //}
1039 
1040 #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \
1041     || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
1042     if ( s_enable_core_dump )
1043         lsapi_enable_core_dump();
1044 #endif
1045 
1046     rv = setgid(gid);
1047     if (rv == -1)
1048     {
1049         LSAPI_perror_r(pReq, "LSAPI: setgid()", NULL);
1050         return -1;
1051     }
1052     if ( pw && (pw->pw_gid == gid ))
1053     {
1054         rv = initgroups( pw->pw_name, gid );
1055         if (rv == -1)
1056         {
1057             LSAPI_perror_r(pReq, "LSAPI: initgroups()", NULL);
1058             return -1;
1059         }
1060     }
1061     else
1062     {
1063         rv = setgroups(1, &gid);
1064         if (rv == -1)
1065         {
1066             LSAPI_perror_r(pReq, "LSAPI: setgroups()", NULL);
1067         }
1068     }
1069     if ( pChroot )
1070     {
1071         rv = chroot( pChroot );
1072         if ( rv == -1 )
1073         {
1074             LSAPI_perror_r(pReq, "LSAPI: chroot()", NULL);
1075             return -1;
1076         }
1077     }
1078     rv = setuid(uid);
1079     if (rv == -1)
1080     {
1081         LSAPI_perror_r(pReq, "LSAPI: setuid()", NULL);
1082         return -1;
1083     }
1084 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
1085     if ( s_enable_core_dump )
1086         lsapi_enable_core_dump();
1087 #endif
1088     return 0;
1089 }
1090 
lsapi_suexec_auth(LSAPI_Request * pReq,char * pAuth,int len,char * pUgid,int ugidLen)1091 static int lsapi_suexec_auth( LSAPI_Request *pReq,
1092             char * pAuth, int len, char * pUgid, int ugidLen )
1093 {
1094     lsapi_MD5_CTX md5ctx;
1095     unsigned char achMD5[16];
1096     if ( len < 32 )
1097         return -1;
1098     memmove( achMD5, pAuth + 16, 16 );
1099     memmove( pAuth + 16, s_secret, 16 );
1100     lsapi_MD5Init( &md5ctx );
1101     lsapi_MD5Update( &md5ctx, (unsigned char *)pAuth, 32 );
1102     lsapi_MD5Update( &md5ctx, (unsigned char *)pUgid, 8 );
1103     lsapi_MD5Final( (unsigned char *)pAuth + 16, &md5ctx);
1104     if ( memcmp( achMD5, pAuth + 16, 16 ) == 0 )
1105         return 0;
1106     return 1;
1107 }
1108 
1109 
lsapi_changeUGid(LSAPI_Request * pReq)1110 static int lsapi_changeUGid( LSAPI_Request * pReq )
1111 {
1112     int uid = s_defaultUid;
1113     int gid = s_defaultGid;
1114     const char *pStderrLog;
1115     const char *pChroot = NULL;
1116     struct LSAPI_key_value_pair * pEnv;
1117     struct LSAPI_key_value_pair * pAuth;
1118     int i;
1119     if ( s_uid )
1120         return 0;
1121     //with special ID  0x00
1122     //authenticate the suEXEC request;
1123     //first one should be MD5( nonce + lscgid secret )
1124     //remember to clear the secret after verification
1125     //it should be set at the end of special env
1126     i = pReq->m_pHeader->m_cntSpecialEnv - 1;
1127     if ( i >= 0 )
1128     {
1129         pEnv = pReq->m_pSpecialEnvList + i;
1130         if (( *pEnv->pKey == '\000' )&&
1131             ( strcmp( pEnv->pKey+1, "SUEXEC_AUTH" ) == 0 ))
1132         {
1133             --pReq->m_pHeader->m_cntSpecialEnv;
1134             pAuth = pEnv--;
1135             if (( *pEnv->pKey == '\000' )&&
1136                 ( strcmp( pEnv->pKey+1, "SUEXEC_UGID" ) == 0 ))
1137             {
1138                 --pReq->m_pHeader->m_cntSpecialEnv;
1139                 uid = *(uint32_t *)pEnv->pValue;
1140                 gid = *(((uint32_t *)pEnv->pValue) + 1 );
1141                 //lsapi_log("LSAPI: SUEXEC_UGID set UID: %d, GID: %d\n", uid, gid );
1142             }
1143             else
1144             {
1145                 lsapi_log("LSAPI: missing SUEXEC_UGID env, use default user!\n" );
1146                 pEnv = NULL;
1147             }
1148             if ( pEnv&& lsapi_suexec_auth( pReq, pAuth->pValue, pAuth->valLen, pEnv->pValue, pEnv->valLen ) == 0 )
1149             {
1150                 //read UID, GID from specialEnv
1151 
1152             }
1153             else
1154             {
1155                 //authentication error
1156                 lsapi_log("LSAPI: SUEXEC_AUTH authentication failed, use default user!\n" );
1157                 uid = 0;
1158             }
1159         }
1160         else
1161         {
1162             //lsapi_log("LSAPI: no SUEXEC_AUTH env, use default user!\n" );
1163         }
1164     }
1165 
1166 
1167     if ( !uid )
1168     {
1169         uid = s_defaultUid;
1170         gid = s_defaultGid;
1171     }
1172 
1173     //change uid
1174     if ( setUID_LVE( pReq, uid, gid, pChroot ) == -1 )
1175     {
1176         return -1;
1177     }
1178 
1179     s_uid = uid;
1180 
1181     if ( pReq->m_fdListen != -1 )
1182     {
1183         close( pReq->m_fdListen );
1184         pReq->m_fdListen = -1;
1185     }
1186 
1187     pStderrLog = LSAPI_GetEnv_r( pReq, "LSAPI_STDERR_LOG");
1188     if (pStderrLog)
1189         lsapi_reopen_stderr(pStderrLog);
1190 
1191     return 0;
1192 
1193 }
1194 
1195 
parseContentLenFromHeader(LSAPI_Request * pReq)1196 static int parseContentLenFromHeader(LSAPI_Request * pReq)
1197 {
1198     const char * pContentLen = LSAPI_GetHeader_r( pReq, H_CONTENT_LENGTH );
1199     if ( pContentLen )
1200         pReq->m_reqBodyLen = strtoll( pContentLen, NULL, 10 );
1201     return 0;
1202 }
1203 
1204 
parseRequest(LSAPI_Request * pReq,int totalLen)1205 static int parseRequest( LSAPI_Request * pReq, int totalLen )
1206 {
1207     int shouldFixEndian;
1208     char * pBegin = pReq->m_pReqBuf + sizeof( struct lsapi_req_header );
1209     char * pEnd = pReq->m_pReqBuf + totalLen;
1210     shouldFixEndian = ( LSAPI_ENDIAN != (
1211                 pReq->m_pHeader->m_pktHeader.m_flag & LSAPI_ENDIAN_BIT ) );
1212     if ( shouldFixEndian )
1213     {
1214         fixEndian( pReq );
1215     }
1216     if ( (pReq->m_specialEnvListSize < pReq->m_pHeader->m_cntSpecialEnv )&&
1217             allocateEnvList( &pReq->m_pSpecialEnvList,
1218                 &pReq->m_specialEnvListSize,
1219                 pReq->m_pHeader->m_cntSpecialEnv ) == -1 )
1220         return -1;
1221     if ( (pReq->m_envListSize < pReq->m_pHeader->m_cntEnv )&&
1222             allocateEnvList( &pReq->m_pEnvList, &pReq->m_envListSize,
1223                 pReq->m_pHeader->m_cntEnv ) == -1 )
1224         return -1;
1225 
1226     if ( parseEnv( pReq->m_pSpecialEnvList,
1227                 pReq->m_pHeader->m_cntSpecialEnv,
1228                 &pBegin, pEnd ) == -1 )
1229         return -1;
1230     if ( parseEnv( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv,
1231                 &pBegin, pEnd ) == -1 )
1232         return -1;
1233     if (pReq->m_pHeader->m_scriptFileOff < 0
1234         || pReq->m_pHeader->m_scriptFileOff >= totalLen
1235         || pReq->m_pHeader->m_scriptNameOff < 0
1236         || pReq->m_pHeader->m_scriptNameOff >= totalLen
1237         || pReq->m_pHeader->m_queryStringOff < 0
1238         || pReq->m_pHeader->m_queryStringOff >= totalLen
1239         || pReq->m_pHeader->m_requestMethodOff < 0
1240         || pReq->m_pHeader->m_requestMethodOff >= totalLen)
1241     {
1242         lsapi_log("Bad request header - ERROR#1\n");
1243         return -1;
1244     }
1245     pReq->m_pScriptFile     = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptFileOff;
1246     pReq->m_pScriptName     = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptNameOff;
1247     pReq->m_pQueryString    = pReq->m_pReqBuf + pReq->m_pHeader->m_queryStringOff;
1248     pReq->m_pRequestMethod  = pReq->m_pReqBuf + pReq->m_pHeader->m_requestMethodOff;
1249 
1250     pBegin = pReq->m_pReqBuf + (( pBegin - pReq->m_pReqBuf + 7 ) & (~0x7));
1251     pReq->m_pHeaderIndex = ( struct lsapi_http_header_index * )pBegin;
1252     pBegin += sizeof( struct lsapi_http_header_index );
1253 
1254     pReq->m_pUnknownHeader = (struct lsapi_header_offset *)pBegin;
1255     pBegin += sizeof( struct lsapi_header_offset) *
1256                     pReq->m_pHeader->m_cntUnknownHeaders;
1257 
1258     pReq->m_pHttpHeader = pBegin;
1259     pBegin += pReq->m_pHeader->m_httpHeaderLen;
1260     if ( pBegin != pEnd )
1261     {
1262         lsapi_log("Request header does match total size, total: %d, "
1263                  "real: %ld\n", totalLen, pBegin - pReq->m_pReqBuf );
1264         return -1;
1265     }
1266     if ( shouldFixEndian )
1267     {
1268         fixHeaderIndexEndian( pReq );
1269     }
1270 
1271     if (validateHeaders(pReq) == -1)
1272     {
1273         lsapi_log("Bad request header - ERROR#2\n");
1274         return -1;
1275     }
1276 
1277     pReq->m_reqBodyLen = pReq->m_pHeader->m_reqBodyLen;
1278     if ( pReq->m_reqBodyLen == -2 )
1279     {
1280         parseContentLenFromHeader(pReq);
1281     }
1282 
1283     return 0;
1284 }
1285 
1286 
1287 //OPTIMIZATION
1288 static char s_accept_notify = 0;
1289 static char s_schedule_notify = 0;
1290 static char s_notify_scheduled = 0;
1291 static char s_notified_pid = 0;
1292 
1293 static struct lsapi_packet_header s_ack = {'L', 'S',
1294                 LSAPI_REQ_RECEIVED, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} };
1295 static struct lsapi_packet_header s_conn_close_pkt = {'L', 'S',
1296                 LSAPI_CONN_CLOSE, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} };
1297 
1298 
send_notification_pkt(int fd,struct lsapi_packet_header * pkt)1299 static inline int send_notification_pkt( int fd, struct lsapi_packet_header *pkt )
1300 {
1301     if ( write( fd, pkt, LSAPI_PACKET_HEADER_LEN ) < LSAPI_PACKET_HEADER_LEN )
1302         return -1;
1303     return 0;
1304 }
1305 
1306 
send_req_received_notification(int fd)1307 static inline int send_req_received_notification( int fd )
1308 {
1309     return send_notification_pkt(fd, &s_ack);
1310 }
1311 
1312 
send_conn_close_notification(int fd)1313 static inline int send_conn_close_notification( int fd )
1314 {
1315     return send_notification_pkt(fd, &s_conn_close_pkt);
1316 }
1317 
1318 
1319 //static void lsapi_sigalarm( int sig )
1320 //{
1321 //    if ( s_notify_scheduled )
1322 //    {
1323 //        s_notify_scheduled = 0;
1324 //        if ( g_req.m_fd != -1 )
1325 //            write_req_received_notification( g_req.m_fd );
1326 //    }
1327 //}
1328 
1329 
lsapi_schedule_notify(void)1330 static inline int lsapi_schedule_notify(void)
1331 {
1332     if ( !s_notify_scheduled )
1333     {
1334         alarm( 2 );
1335         s_notify_scheduled = 1;
1336     }
1337     return 0;
1338 }
1339 
1340 
notify_req_received(int fd)1341 static inline int notify_req_received( int fd )
1342 {
1343     if ( s_schedule_notify )
1344         return lsapi_schedule_notify();
1345     return send_req_received_notification( fd );
1346 
1347 }
1348 
1349 
lsapi_notify_pid(int fd)1350 static inline int lsapi_notify_pid( int fd )
1351 {
1352     char achBuf[16];
1353     lsapi_buildPacketHeader( (struct lsapi_packet_header *)achBuf, LSAPI_STDERR_STREAM,
1354                         8 + LSAPI_PACKET_HEADER_LEN );
1355     memmove( &achBuf[8], "\0PID", 4 );
1356     *((int *)&achBuf[12]) = getpid();
1357 
1358     if ( write( fd, achBuf, 16 ) < 16 )
1359         return -1;
1360     return 0;
1361 }
1362 
readReq(LSAPI_Request * pReq)1363 static int readReq( LSAPI_Request * pReq )
1364 {
1365     int len;
1366     int packetLen;
1367     if ( !pReq )
1368         return -1;
1369     if ( pReq->m_reqBufSize < 8192 )
1370     {
1371         if ( allocateBuf( pReq, 8192 ) == -1 )
1372             return -1;
1373     }
1374 
1375     while ( pReq->m_bufRead < LSAPI_PACKET_HEADER_LEN )
1376     {
1377         len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf, pReq->m_reqBufSize );
1378         if ( len <= 0 )
1379             return -1;
1380         pReq->m_bufRead += len;
1381     }
1382     pReq->m_reqState = LSAPI_ST_REQ_HEADER;
1383 
1384     packetLen = verifyHeader( &pReq->m_pHeader->m_pktHeader, LSAPI_BEGIN_REQUEST );
1385     if ( packetLen < 0 )
1386     {
1387         lsapi_log("packetLen < 0\n");
1388         return -1;
1389     }
1390     if ( packetLen > LSAPI_MAX_HEADER_LEN )
1391     {
1392         lsapi_log("packetLen > %d\n", LSAPI_MAX_HEADER_LEN );
1393         return -1;
1394     }
1395 
1396     if ( packetLen + 1024 > pReq->m_reqBufSize )
1397     {
1398         if ( allocateBuf( pReq, packetLen + 1024 ) == -1 )
1399             return -1;
1400     }
1401     while( packetLen > pReq->m_bufRead )
1402     {
1403         len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, packetLen - pReq->m_bufRead );
1404         if ( len <= 0 )
1405             return -1;
1406         pReq->m_bufRead += len;
1407     }
1408     if ( parseRequest( pReq, packetLen ) < 0 )
1409     {
1410         lsapi_log("ParseRequest error\n");
1411         return -1;
1412     }
1413 
1414     pReq->m_reqState = LSAPI_ST_REQ_BODY | LSAPI_ST_RESP_HEADER;
1415 
1416     if ( !s_uid )
1417     {
1418         if ( lsapi_changeUGid( pReq ) )
1419             return -1;
1420         memset(s_secret, 0, sizeof(s_secret));
1421     }
1422     pReq->m_bufProcessed = packetLen;
1423 
1424     //OPTIMIZATION
1425     if ( !s_accept_notify && !s_notified_pid )
1426         return notify_req_received( pReq->m_fd );
1427     else
1428     {
1429         s_notified_pid = 0;
1430         return 0;
1431     }
1432 }
1433 
1434 
LSAPI_Init(void)1435 int LSAPI_Init(void)
1436 {
1437     if ( !g_inited )
1438     {
1439         s_uid = geteuid();
1440         s_secret[0] = 0;
1441         lsapi_signal(SIGPIPE, lsapi_sigpipe);
1442         lsapi_signal(SIGUSR1, lsapi_siguser1);
1443 
1444 #if defined(SIGXFSZ) && defined(SIG_IGN)
1445         signal(SIGXFSZ, SIG_IGN);
1446 #endif
1447         /* let STDOUT function as STDERR,
1448            just in case writing to STDOUT directly */
1449         dup2( 2, 1 );
1450         if ( LSAPI_InitRequest( &g_req, LSAPI_SOCK_FILENO ) == -1 )
1451             return -1;
1452         g_inited = 1;
1453         s_ppid = getppid();
1454         void *pthread_lib = dlopen("libpthread.so", RTLD_LAZY);
1455         if (pthread_lib)
1456             pthread_atfork_func = dlsym(pthread_lib, "pthread_atfork");
1457 
1458     }
1459     return 0;
1460 }
1461 
1462 
LSAPI_Stop(void)1463 void LSAPI_Stop(void)
1464 {
1465     g_running = 0;
1466 }
1467 
1468 
LSAPI_IsRunning(void)1469 int LSAPI_IsRunning(void)
1470 {
1471     return g_running;
1472 }
1473 
1474 
LSAPI_Register_Pgrp_Timer_Callback(LSAPI_On_Timer_pf cb)1475 void LSAPI_Register_Pgrp_Timer_Callback(LSAPI_On_Timer_pf cb)
1476 {
1477     s_proc_group_timer_cb = cb;
1478 }
1479 
1480 
LSAPI_InitRequest(LSAPI_Request * pReq,int fd)1481 int LSAPI_InitRequest( LSAPI_Request * pReq, int fd )
1482 {
1483     int newfd;
1484     if ( !pReq )
1485         return -1;
1486     memset( pReq, 0, sizeof( LSAPI_Request ) );
1487     if ( allocateIovec( pReq, 16 ) == -1 )
1488         return -1;
1489     pReq->m_pRespBuf = pReq->m_pRespBufPos = (char *)malloc( LSAPI_RESP_BUF_SIZE );
1490     if ( !pReq->m_pRespBuf )
1491         return -1;
1492     pReq->m_pRespBufEnd = pReq->m_pRespBuf + LSAPI_RESP_BUF_SIZE;
1493     pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec + 1;
1494     pReq->m_respPktHeaderEnd = &pReq->m_respPktHeader[5];
1495     if ( allocateRespHeaderBuf( pReq, LSAPI_INIT_RESP_HEADER_LEN ) == -1 )
1496         return -1;
1497 
1498     if ( fd == STDIN_FILENO )
1499     {
1500         fd = dup( fd );
1501         newfd = open( "/dev/null", O_RDWR );
1502         dup2( newfd, STDIN_FILENO );
1503     }
1504 
1505     if ( isPipe( fd ) )
1506     {
1507         pReq->m_fdListen = -1;
1508         pReq->m_fd = fd;
1509     }
1510     else
1511     {
1512         pReq->m_fdListen = fd;
1513         pReq->m_fd = -1;
1514         lsapi_set_nblock( fd, 1 );
1515     }
1516     return 0;
1517 }
1518 
1519 
LSAPI_Is_Listen(void)1520 int LSAPI_Is_Listen( void )
1521 {
1522     return LSAPI_Is_Listen_r( &g_req );
1523 }
1524 
1525 
LSAPI_Is_Listen_r(LSAPI_Request * pReq)1526 int LSAPI_Is_Listen_r( LSAPI_Request * pReq)
1527 {
1528     return pReq->m_fdListen != -1;
1529 }
1530 
1531 
LSAPI_Accept_r(LSAPI_Request * pReq)1532 int LSAPI_Accept_r( LSAPI_Request * pReq )
1533 {
1534     char        achPeer[128];
1535     socklen_t   len;
1536     int         nodelay = 1;
1537 
1538     if ( !pReq )
1539         return -1;
1540     if ( LSAPI_Finish_r( pReq ) == -1 )
1541         return -1;
1542     lsapi_set_nblock( pReq->m_fdListen , 0 );
1543     while( g_running )
1544     {
1545         if ( pReq->m_fd == -1 )
1546         {
1547             if ( pReq->m_fdListen != -1)
1548             {
1549                 len = sizeof( achPeer );
1550                 pReq->m_fd = accept( pReq->m_fdListen,
1551                             (struct sockaddr *)&achPeer, &len );
1552                 if ( pReq->m_fd == -1 )
1553                 {
1554                     if (( errno == EINTR )||( errno == EAGAIN))
1555                         continue;
1556                     else
1557                         return -1;
1558                 }
1559                 else
1560                 {
1561                     if (s_worker_status)
1562                         __atomic_store_n(&s_worker_status->m_state,
1563                                        LSAPI_STATE_CONNECTED, __ATOMIC_SEQ_CST);
1564                     if (s_busy_workers)
1565                         __atomic_fetch_add(s_busy_workers, 1, __ATOMIC_SEQ_CST);
1566                     lsapi_set_nblock( pReq->m_fd , 0 );
1567                     if (((struct sockaddr *)&achPeer)->sa_family == AF_INET )
1568                     {
1569                         setsockopt(pReq->m_fd, IPPROTO_TCP, TCP_NODELAY,
1570                                    (char *)&nodelay, sizeof(nodelay));
1571                     }
1572                     //init_conn_key( pReq->m_fd );
1573                     //OPTIMIZATION
1574                     if ( s_accept_notify )
1575                         if ( notify_req_received( pReq->m_fd ) == -1 )
1576                                 return -1;
1577                 }
1578             }
1579             else
1580                 return -1;
1581         }
1582         if ( !readReq( pReq ) )
1583             break;
1584         //abort();
1585         lsapi_close_connection(pReq);
1586         LSAPI_Reset_r( pReq );
1587     }
1588     return 0;
1589 }
1590 
1591 
1592 static struct lsapi_packet_header   finish_close[2] =
1593 {
1594     {'L', 'S', LSAPI_RESP_END, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} },
1595     {'L', 'S', LSAPI_CONN_CLOSE, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} }
1596 };
1597 
1598 
LSAPI_Finish_r(LSAPI_Request * pReq)1599 int LSAPI_Finish_r( LSAPI_Request * pReq )
1600 {
1601     /* finish req body */
1602     if ( !pReq )
1603         return -1;
1604     if (pReq->m_reqState)
1605     {
1606         if ( pReq->m_fd != -1 )
1607         {
1608             if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
1609             {
1610                 LSAPI_FinalizeRespHeaders_r( pReq );
1611             }
1612             if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
1613             {
1614                 Flush_RespBuf_r( pReq );
1615             }
1616 
1617             pReq->m_pIovecCur->iov_base = (void *)finish_close;
1618             pReq->m_pIovecCur->iov_len  = LSAPI_PACKET_HEADER_LEN;
1619             pReq->m_totalLen += LSAPI_PACKET_HEADER_LEN;
1620             ++pReq->m_pIovecCur;
1621             LSAPI_Flush_r( pReq );
1622         }
1623         LSAPI_Reset_r( pReq );
1624     }
1625     return 0;
1626 }
1627 
1628 
LSAPI_End_Response_r(LSAPI_Request * pReq)1629 int LSAPI_End_Response_r(LSAPI_Request * pReq)
1630 {
1631     if (!pReq)
1632         return -1;
1633     if (pReq->m_reqState & LSAPI_ST_BACKGROUND)
1634         return 0;
1635     if (pReq->m_reqState)
1636     {
1637         if ( pReq->m_fd != -1 )
1638         {
1639             if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
1640             {
1641                 if ( pReq->m_pRespHeaderBufPos <= pReq->m_pRespHeaderBuf )
1642                     return 0;
1643 
1644                 LSAPI_FinalizeRespHeaders_r( pReq );
1645             }
1646             if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
1647             {
1648                 Flush_RespBuf_r( pReq );
1649             }
1650 
1651             pReq->m_pIovecCur->iov_base = (void *)finish_close;
1652             pReq->m_pIovecCur->iov_len  = LSAPI_PACKET_HEADER_LEN << 1;
1653             pReq->m_totalLen += LSAPI_PACKET_HEADER_LEN << 1;
1654             ++pReq->m_pIovecCur;
1655             LSAPI_Flush_r( pReq );
1656             lsapi_close_connection(pReq);
1657         }
1658         pReq->m_reqState |= LSAPI_ST_BACKGROUND;
1659     }
1660     return 0;
1661 }
1662 
1663 
LSAPI_Reset_r(LSAPI_Request * pReq)1664 void LSAPI_Reset_r( LSAPI_Request * pReq )
1665 {
1666     pReq->m_pRespBufPos         = pReq->m_pRespBuf;
1667     pReq->m_pIovecCur           = pReq->m_pIovecToWrite = pReq->m_pIovec + 1;
1668     pReq->m_pRespHeaderBufPos   = pReq->m_pRespHeaderBuf;
1669 
1670     memset( &pReq->m_pHeaderIndex, 0,
1671             (char *)(pReq->m_respHeaderLen) - (char *)&pReq->m_pHeaderIndex );
1672 }
1673 
1674 
LSAPI_Release_r(LSAPI_Request * pReq)1675 int LSAPI_Release_r( LSAPI_Request * pReq )
1676 {
1677     if ( pReq->m_pReqBuf )
1678         free( pReq->m_pReqBuf );
1679     if ( pReq->m_pSpecialEnvList )
1680         free( pReq->m_pSpecialEnvList );
1681     if ( pReq->m_pEnvList )
1682         free( pReq->m_pEnvList );
1683     if ( pReq->m_pRespHeaderBuf )
1684         free( pReq->m_pRespHeaderBuf );
1685     return 0;
1686 }
1687 
1688 
LSAPI_GetHeader_r(LSAPI_Request * pReq,int headerIndex)1689 char * LSAPI_GetHeader_r( LSAPI_Request * pReq, int headerIndex )
1690 {
1691     int off;
1692     if ( !pReq || ((unsigned int)headerIndex > H_TRANSFER_ENCODING) )
1693         return NULL;
1694     off = pReq->m_pHeaderIndex->m_headerOff[ headerIndex ];
1695     if ( !off )
1696         return NULL;
1697     if ( *(pReq->m_pHttpHeader + off
1698         + pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) )
1699     {
1700         *( pReq->m_pHttpHeader + off
1701             + pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) = 0;
1702     }
1703     return pReq->m_pHttpHeader + off;
1704 }
1705 
1706 
readBodyToReqBuf(LSAPI_Request * pReq)1707 static int readBodyToReqBuf( LSAPI_Request * pReq )
1708 {
1709     off_t bodyLeft;
1710     ssize_t len = pReq->m_bufRead - pReq->m_bufProcessed;
1711     if ( len > 0 )
1712         return len;
1713     pReq->m_bufRead = pReq->m_bufProcessed = pReq->m_pHeader->m_pktHeader.m_packetLen.m_iLen;
1714 
1715     bodyLeft = pReq->m_reqBodyLen - pReq->m_reqBodyRead;
1716     len = pReq->m_reqBufSize - pReq->m_bufRead;
1717     if ( len < 0 )
1718         return -1;
1719     if ( len > bodyLeft )
1720         len = bodyLeft;
1721 
1722     len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, len );
1723     if ( len > 0 )
1724         pReq->m_bufRead += len;
1725     return len;
1726 }
1727 
1728 
LSAPI_ReqBodyGetChar_r(LSAPI_Request * pReq)1729 int LSAPI_ReqBodyGetChar_r( LSAPI_Request * pReq )
1730 {
1731     if (!pReq || (pReq->m_fd ==-1) )
1732         return EOF;
1733     if ( pReq->m_bufProcessed >= pReq->m_bufRead )
1734     {
1735         if ( readBodyToReqBuf( pReq ) <= 0 )
1736             return EOF;
1737     }
1738     ++pReq->m_reqBodyRead;
1739     return (unsigned char)*(pReq->m_pReqBuf + pReq->m_bufProcessed++);
1740 }
1741 
1742 
LSAPI_ReqBodyGetLine_r(LSAPI_Request * pReq,char * pBuf,size_t bufLen,int * getLF)1743 int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen, int *getLF )
1744 {
1745     ssize_t len;
1746     ssize_t left;
1747     char * pBufEnd = pBuf + bufLen - 1;
1748     char * pBufCur = pBuf;
1749     char * pCur;
1750     char * p;
1751     if (!pReq || pReq->m_fd == -1 || !pBuf || !getLF)
1752         return -1;
1753     *getLF = 0;
1754     while( (left = pBufEnd - pBufCur ) > 0 )
1755     {
1756 
1757         len = pReq->m_bufRead - pReq->m_bufProcessed;
1758         if ( len <= 0 )
1759         {
1760             if ( (len = readBodyToReqBuf( pReq )) <= 0 )
1761             {
1762                 *getLF = 1;
1763                 break;
1764             }
1765         }
1766         if ( len > left )
1767             len = left;
1768         pCur = pReq->m_pReqBuf + pReq->m_bufProcessed;
1769         p = memchr( pCur, '\n', len );
1770         if ( p )
1771             len = p - pCur + 1;
1772         memmove( pBufCur, pCur, len );
1773         pBufCur += len;
1774         pReq->m_bufProcessed += len;
1775 
1776         pReq->m_reqBodyRead += len;
1777 
1778         if ( p )
1779         {
1780             *getLF = 1;
1781             break;
1782         }
1783     }
1784     *pBufCur = 0;
1785 
1786     return pBufCur - pBuf;
1787 }
1788 
1789 
LSAPI_ReadReqBody_r(LSAPI_Request * pReq,char * pBuf,size_t bufLen)1790 ssize_t LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen )
1791 {
1792     ssize_t len;
1793     off_t total;
1794     /* char *pOldBuf = pBuf; */
1795     if (!pReq || pReq->m_fd == -1 || !pBuf || (ssize_t)bufLen < 0)
1796         return -1;
1797 
1798     total = pReq->m_reqBodyLen - pReq->m_reqBodyRead;
1799 
1800     if ( total <= 0 )
1801         return 0;
1802     if ( total < (ssize_t)bufLen )
1803         bufLen = total;
1804 
1805     total = 0;
1806     len = pReq->m_bufRead - pReq->m_bufProcessed;
1807     if ( len > 0 )
1808     {
1809         if ( len > (ssize_t)bufLen )
1810             len = bufLen;
1811         memmove( pBuf, pReq->m_pReqBuf + pReq->m_bufProcessed, len );
1812         pReq->m_bufProcessed += len;
1813         total += len;
1814         pBuf += len;
1815         bufLen -= len;
1816     }
1817     while( bufLen > 0 )
1818     {
1819         len = lsapi_read( pReq->m_fd, pBuf, bufLen );
1820         if ( len > 0 )
1821         {
1822             total += len;
1823             pBuf += len;
1824             bufLen -= len;
1825         }
1826         else if ( len <= 0 )
1827         {
1828             if ( !total)
1829                 return -1;
1830             break;
1831         }
1832     }
1833     pReq->m_reqBodyRead += total;
1834     return total;
1835 
1836 }
1837 
1838 
LSAPI_Write_r(LSAPI_Request * pReq,const char * pBuf,size_t len)1839 ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len )
1840 {
1841     struct lsapi_packet_header * pHeader;
1842     const char * pEnd;
1843     const char * p;
1844     ssize_t bufLen;
1845     ssize_t toWrite;
1846     ssize_t packetLen;
1847     int skip = 0;
1848 
1849     if (!pReq || !pBuf)
1850         return -1;
1851     if (pReq->m_reqState & LSAPI_ST_BACKGROUND)
1852         return len;
1853     if (pReq->m_fd == -1)
1854         return -1;
1855     if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
1856     {
1857         LSAPI_FinalizeRespHeaders_r( pReq );
1858 /*
1859         if ( *pBuf == '\r' )
1860         {
1861             ++skip;
1862         }
1863         if ( *pBuf == '\n' )
1864         {
1865             ++skip;
1866         }
1867 */
1868     }
1869     pReq->m_reqState |= LSAPI_ST_RESP_BODY;
1870 
1871     if ( ((ssize_t)len - skip) < pReq->m_pRespBufEnd - pReq->m_pRespBufPos )
1872     {
1873         memmove( pReq->m_pRespBufPos, pBuf + skip, len - skip );
1874         pReq->m_pRespBufPos += len - skip;
1875         return len;
1876     }
1877 
1878 
1879     pHeader = pReq->m_respPktHeader;
1880     p       = pBuf + skip;
1881     pEnd    = pBuf + len;
1882     bufLen  = pReq->m_pRespBufPos - pReq->m_pRespBuf;
1883 
1884     while( ( toWrite = pEnd - p ) > 0 )
1885     {
1886         packetLen = toWrite + bufLen;
1887         if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen)
1888         {
1889             packetLen = LSAPI_MAX_DATA_PACKET_LEN;
1890             toWrite = packetLen - bufLen;
1891         }
1892 
1893         lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
1894                             packetLen + LSAPI_PACKET_HEADER_LEN );
1895         pReq->m_totalLen += packetLen + LSAPI_PACKET_HEADER_LEN;
1896 
1897         pReq->m_pIovecCur->iov_base = (void *)pHeader;
1898         pReq->m_pIovecCur->iov_len  = LSAPI_PACKET_HEADER_LEN;
1899         ++pReq->m_pIovecCur;
1900         ++pHeader;
1901         if ( bufLen > 0 )
1902         {
1903             pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf;
1904             pReq->m_pIovecCur->iov_len  = bufLen;
1905             pReq->m_pRespBufPos = pReq->m_pRespBuf;
1906             ++pReq->m_pIovecCur;
1907             bufLen = 0;
1908         }
1909 
1910         pReq->m_pIovecCur->iov_base = (void *)p;
1911         pReq->m_pIovecCur->iov_len  = toWrite;
1912         ++pReq->m_pIovecCur;
1913         p += toWrite;
1914 
1915         if ( pHeader >= pReq->m_respPktHeaderEnd - 1)
1916         {
1917             if ( LSAPI_Flush_r( pReq ) == -1 )
1918                 return -1;
1919             pHeader = pReq->m_respPktHeader;
1920         }
1921     }
1922     if ( pHeader != pReq->m_respPktHeader )
1923         if ( LSAPI_Flush_r( pReq ) == -1 )
1924             return -1;
1925     return p - pBuf;
1926 }
1927 
1928 
1929 #if defined(__FreeBSD__ )
gsendfile(int fdOut,int fdIn,off_t * off,size_t size)1930 ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size )
1931 {
1932     ssize_t ret;
1933     off_t written;
1934     ret = sendfile( fdIn, fdOut, *off, size, NULL, &written, 0 );
1935     if ( written > 0 )
1936     {
1937         ret = written;
1938         *off += ret;
1939     }
1940     return ret;
1941 }
1942 #endif
1943 
1944 #if defined(__OpenBSD__) || defined(__NetBSD__)
gsendfile(int fdOut,int fdIn,off_t * off,size_t size)1945 ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size )
1946 {
1947     ssize_t ret;
1948     off_t written = 0;
1949     const size_t bufsiz = 16384;
1950     unsigned char in[bufsiz] = {0};
1951 
1952     if (lseek(fdIn, *off, SEEK_SET) == -1) {
1953         return -1;
1954     }
1955 
1956     while (size > 0) {
1957 	    size_t tor = size > sizeof(in) ? sizeof(in) : size;
1958 	    ssize_t c = read(fdIn, in, tor);
1959 	    if (c <= 0) {
1960 		    goto end;
1961 	    }
1962 
1963 	    ssize_t w = write(fdOut, in, c);
1964 	    if (w != c) {
1965 		    goto end;
1966 	    }
1967 
1968 	    written += w;
1969 	    size -= c;
1970     }
1971 
1972 end:
1973     *off += written;
1974     return 0;
1975 }
1976 #endif
1977 
1978 
1979 #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
gsendfile(int fdOut,int fdIn,off_t * off,size_t size)1980 ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size )
1981 {
1982     ssize_t ret;
1983     off_t len = size;
1984     ret = sendfile( fdIn, fdOut, *off, &len, NULL, 0 );
1985     if (( ret == 0 )&&( len > 0 ))
1986     {
1987         ret = len;
1988         *off += len;
1989     }
1990     return ret;
1991 }
1992 #endif
1993 
1994 
1995 #if defined(sun) || defined(__sun)
1996 #include <sys/sendfile.h>
gsendfile(int fdOut,int fdIn,off_t * off,size_t size)1997 ssize_t gsendfile( int fdOut, int fdIn, off_t *off, size_t size )
1998 {
1999     int n = 0 ;
2000     sendfilevec_t vec[1];
2001 
2002     vec[n].sfv_fd   = fdIn;
2003     vec[n].sfv_flag = 0;
2004     vec[n].sfv_off  = *off;
2005     vec[n].sfv_len  = size;
2006     ++n;
2007 
2008     size_t written;
2009     ssize_t ret = sendfilev( fdOut, vec, n, &written );
2010     if (( !ret )||( errno == EAGAIN ))
2011         ret = written;
2012     if ( ret > 0 )
2013         *off += ret;
2014     return ret;
2015 }
2016 #endif
2017 
2018 
2019 #if defined(linux) || defined(__linux) || defined(__linux__) || \
2020     defined(__gnu_linux__)
2021 #include <sys/sendfile.h>
2022 #define gsendfile sendfile
2023 #endif
2024 
2025 
2026 #if defined(HPUX)
gsendfile(int fdOut,int fdIn,off_t * off,size_t size)2027 ssize_t gsendfile( int fdOut, int fdIn, off_t * off, size_t size )
2028 {
2029     return sendfile( fdOut, fdIn, off, size, NULL, 0 );
2030 }
2031 #endif
2032 
2033 
LSAPI_sendfile_r(LSAPI_Request * pReq,int fdIn,off_t * off,size_t size)2034 ssize_t LSAPI_sendfile_r( LSAPI_Request * pReq, int fdIn, off_t* off, size_t size )
2035 {
2036     struct lsapi_packet_header * pHeader = pReq->m_respPktHeader;
2037     if ( !pReq || (pReq->m_fd == -1) || fdIn == -1 )
2038         return -1;
2039     if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
2040     {
2041         LSAPI_FinalizeRespHeaders_r( pReq );
2042     }
2043     pReq->m_reqState |= LSAPI_ST_RESP_BODY;
2044 
2045     LSAPI_Flush_r(pReq);
2046 
2047     lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
2048                             size + LSAPI_PACKET_HEADER_LEN );
2049 
2050 
2051     if (write(pReq->m_fd,  (const char *) pHeader, LSAPI_PACKET_HEADER_LEN ) != LSAPI_PACKET_HEADER_LEN)
2052         return -1;
2053 
2054     return gsendfile( pReq->m_fd, fdIn, off, size );
2055 }
2056 
2057 
Flush_RespBuf_r(LSAPI_Request * pReq)2058 void Flush_RespBuf_r( LSAPI_Request * pReq )
2059 {
2060     struct lsapi_packet_header * pHeader = pReq->m_respPktHeader;
2061     int bufLen = pReq->m_pRespBufPos - pReq->m_pRespBuf;
2062     pReq->m_reqState |= LSAPI_ST_RESP_BODY;
2063     lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
2064                         bufLen + LSAPI_PACKET_HEADER_LEN );
2065     pReq->m_totalLen += bufLen + LSAPI_PACKET_HEADER_LEN;
2066 
2067     pReq->m_pIovecCur->iov_base = (void *)pHeader;
2068     pReq->m_pIovecCur->iov_len  = LSAPI_PACKET_HEADER_LEN;
2069     ++pReq->m_pIovecCur;
2070     ++pHeader;
2071     if ( bufLen > 0 )
2072     {
2073         pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf;
2074         pReq->m_pIovecCur->iov_len  = bufLen;
2075         pReq->m_pRespBufPos = pReq->m_pRespBuf;
2076         ++pReq->m_pIovecCur;
2077         bufLen = 0;
2078     }
2079 }
2080 
2081 
LSAPI_Flush_r(LSAPI_Request * pReq)2082 int LSAPI_Flush_r( LSAPI_Request * pReq )
2083 {
2084     int ret = 0;
2085     int n;
2086     if ( !pReq )
2087         return -1;
2088     n = pReq->m_pIovecCur - pReq->m_pIovecToWrite;
2089     if (( 0 == n )&&( pReq->m_pRespBufPos == pReq->m_pRespBuf ))
2090         return 0;
2091     if ( pReq->m_fd == -1 )
2092     {
2093         pReq->m_pRespBufPos = pReq->m_pRespBuf;
2094         pReq->m_totalLen = 0;
2095         pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec;
2096         return -1;
2097     }
2098     if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
2099     {
2100         LSAPI_FinalizeRespHeaders_r( pReq );
2101     }
2102     if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
2103     {
2104         Flush_RespBuf_r( pReq );
2105     }
2106 
2107     n = pReq->m_pIovecCur - pReq->m_pIovecToWrite;
2108     if ( n > 0 )
2109     {
2110 
2111         ret = lsapi_writev( pReq->m_fd, &pReq->m_pIovecToWrite,
2112                   n, pReq->m_totalLen );
2113         if ( ret < pReq->m_totalLen )
2114         {
2115             lsapi_close_connection(pReq);
2116             ret = -1;
2117         }
2118         pReq->m_totalLen = 0;
2119         pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec;
2120     }
2121     return ret;
2122 }
2123 
2124 
LSAPI_Write_Stderr_r(LSAPI_Request * pReq,const char * pBuf,size_t len)2125 ssize_t LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, size_t len )
2126 {
2127     struct lsapi_packet_header header;
2128     const char * pEnd;
2129     const char * p;
2130     ssize_t packetLen;
2131     ssize_t totalLen;
2132     int ret;
2133     struct iovec iov[2];
2134     struct iovec *pIov;
2135 
2136     if ( !pReq )
2137         return -1;
2138     if (s_stderr_log_path || pReq->m_fd == -1 || pReq->m_fd == pReq->m_fdListen)
2139         return write( 2, pBuf, len );
2140     if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
2141     {
2142         LSAPI_Flush_r( pReq );
2143     }
2144 
2145     p       = pBuf;
2146     pEnd    = pBuf + len;
2147 
2148     while( ( packetLen = pEnd - p ) > 0 )
2149     {
2150         if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen)
2151         {
2152             packetLen = LSAPI_MAX_DATA_PACKET_LEN;
2153         }
2154 
2155         lsapi_buildPacketHeader( &header, LSAPI_STDERR_STREAM,
2156                             packetLen + LSAPI_PACKET_HEADER_LEN );
2157         totalLen = packetLen + LSAPI_PACKET_HEADER_LEN;
2158 
2159         iov[0].iov_base = (void *)&header;
2160         iov[0].iov_len  = LSAPI_PACKET_HEADER_LEN;
2161 
2162         iov[1].iov_base = (void *)p;
2163         iov[1].iov_len  = packetLen;
2164         p += packetLen;
2165         pIov = iov;
2166         ret = lsapi_writev( pReq->m_fd, &pIov,
2167                   2, totalLen );
2168         if ( ret < totalLen )
2169         {
2170             lsapi_close_connection(pReq);
2171             ret = -1;
2172         }
2173     }
2174     return p - pBuf;
2175 }
2176 
2177 
GetHeaderVar(LSAPI_Request * pReq,const char * name)2178 static char * GetHeaderVar( LSAPI_Request * pReq, const char * name )
2179 {
2180     int i;
2181     char * pValue;
2182     for( i = 0; i < H_TRANSFER_ENCODING; ++i )
2183     {
2184         if ( pReq->m_pHeaderIndex->m_headerOff[i] )
2185         {
2186             if ( strcmp( name, CGI_HEADERS[i] ) == 0 )
2187             {
2188                 pValue = pReq->m_pHttpHeader
2189                          + pReq->m_pHeaderIndex->m_headerOff[i];
2190                 if ( *(pValue + pReq->m_pHeaderIndex->m_headerLen[i]) != '\0')
2191                 {
2192                     *(pValue + pReq->m_pHeaderIndex->m_headerLen[i]) = '\0';
2193                 }
2194                 return pValue;
2195             }
2196         }
2197     }
2198     if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
2199     {
2200         const char *p;
2201         char *pKey;
2202         char *pKeyEnd;
2203         int  keyLen;
2204         struct lsapi_header_offset * pCur, *pEnd;
2205         pCur = pReq->m_pUnknownHeader;
2206         pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
2207         while( pCur < pEnd )
2208         {
2209             pKey = pReq->m_pHttpHeader + pCur->nameOff;
2210             keyLen = pCur->nameLen;
2211             pKeyEnd = pKey + keyLen;
2212             p = &name[5];
2213 
2214             while(( pKey < pKeyEnd )&&( *p ))
2215             {
2216                 char ch = toupper( *pKey );
2217                 if ((ch != *p )||(( *p == '_' )&&( ch != '-')))
2218                     break;
2219                 ++p; ++pKey;
2220             }
2221             if (( pKey == pKeyEnd )&& (!*p ))
2222             {
2223                 pValue = pReq->m_pHttpHeader + pCur->valueOff;
2224 
2225                 if ( *(pValue + pCur->valueLen) != '\0')
2226                 {
2227                     *(pValue + pCur->valueLen) = '\0';
2228                 }
2229                 return pValue;
2230             }
2231             ++pCur;
2232         }
2233     }
2234     return NULL;
2235 }
2236 
2237 
LSAPI_GetEnv_r(LSAPI_Request * pReq,const char * name)2238 char * LSAPI_GetEnv_r( LSAPI_Request * pReq, const char * name )
2239 {
2240     struct LSAPI_key_value_pair * pBegin = pReq->m_pEnvList;
2241     struct LSAPI_key_value_pair * pEnd = pBegin + pReq->m_pHeader->m_cntEnv;
2242     if ( !pReq || !name )
2243         return NULL;
2244     if ( strncmp( name, "HTTP_", 5 ) == 0 )
2245     {
2246         return GetHeaderVar( pReq, name );
2247     }
2248     while( pBegin < pEnd )
2249     {
2250         if ( strcmp( name, pBegin->pKey ) == 0 )
2251             return pBegin->pValue;
2252         ++pBegin;
2253     }
2254     return NULL;
2255 }
2256 
2257 
2258 struct _headerInfo
2259 {
2260     const char * _name;
2261     int          _nameLen;
2262     const char * _value;
2263     int          _valueLen;
2264 };
2265 
2266 
compareValueLocation(const void * v1,const void * v2)2267 int compareValueLocation(const void * v1, const void *v2 )
2268 {
2269     return ((const struct _headerInfo *)v1)->_value -
2270            ((const struct _headerInfo *)v2)->_value;
2271 }
2272 
2273 
LSAPI_ForeachOrgHeader_r(LSAPI_Request * pReq,LSAPI_CB_EnvHandler fn,void * arg)2274 int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq,
2275             LSAPI_CB_EnvHandler fn, void * arg )
2276 {
2277     int i;
2278     int len = 0;
2279     char * pValue;
2280     int ret;
2281     int count = 0;
2282     struct _headerInfo headers[512];
2283 
2284     if ( !pReq || !fn )
2285         return -1;
2286 
2287     if ( !pReq->m_pHeaderIndex )
2288         return 0;
2289 
2290     for( i = 0; i < H_TRANSFER_ENCODING; ++i )
2291     {
2292         if ( pReq->m_pHeaderIndex->m_headerOff[i] )
2293         {
2294             len = pReq->m_pHeaderIndex->m_headerLen[i];
2295             pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i];
2296             *(pValue + len ) = 0;
2297             headers[count]._name = HTTP_HEADERS[i];
2298             headers[count]._nameLen = HTTP_HEADER_LEN[i];
2299             headers[count]._value = pValue;
2300             headers[count]._valueLen = len;
2301             ++count;
2302 
2303             //ret = (*fn)( HTTP_HEADERS[i], HTTP_HEADER_LEN[i],
2304             //            pValue, len, arg );
2305             //if ( ret <= 0 )
2306             //    return ret;
2307         }
2308     }
2309     if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
2310     {
2311         char *pKey;
2312         int  keyLen;
2313         struct lsapi_header_offset * pCur, *pEnd;
2314         pCur = pReq->m_pUnknownHeader;
2315         pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
2316         while( pCur < pEnd )
2317         {
2318             pKey = pReq->m_pHttpHeader + pCur->nameOff;
2319             keyLen = pCur->nameLen;
2320             *(pKey + keyLen ) = 0;
2321 
2322             pValue = pReq->m_pHttpHeader + pCur->valueOff;
2323             *(pValue + pCur->valueLen ) = 0;
2324             headers[count]._name = pKey;
2325             headers[count]._nameLen = keyLen;
2326             headers[count]._value = pValue;
2327             headers[count]._valueLen = pCur->valueLen;
2328             ++count;
2329             if ( count == 512 )
2330                 break;
2331             //ret = (*fn)( pKey, keyLen,
2332             //            pValue, pCur->valueLen, arg );
2333             //if ( ret <= 0 )
2334             //    return ret;
2335             ++pCur;
2336         }
2337     }
2338     qsort( headers, count, sizeof( struct _headerInfo ), compareValueLocation );
2339     for( i = 0; i < count; ++i )
2340     {
2341         ret = (*fn)( headers[i]._name, headers[i]._nameLen,
2342                     headers[i]._value, headers[i]._valueLen, arg );
2343         if ( ret <= 0 )
2344             return ret;
2345     }
2346     return count;
2347 }
2348 
2349 
LSAPI_ForeachHeader_r(LSAPI_Request * pReq,LSAPI_CB_EnvHandler fn,void * arg)2350 int LSAPI_ForeachHeader_r( LSAPI_Request * pReq,
2351             LSAPI_CB_EnvHandler fn, void * arg )
2352 {
2353     int i;
2354     int len = 0;
2355     char * pValue;
2356     int ret;
2357     int count = 0;
2358     if ( !pReq || !fn )
2359         return -1;
2360     for( i = 0; i < H_TRANSFER_ENCODING; ++i )
2361     {
2362         if ( pReq->m_pHeaderIndex->m_headerOff[i] )
2363         {
2364             len = pReq->m_pHeaderIndex->m_headerLen[i];
2365             pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i];
2366             *(pValue + len ) = 0;
2367             ret = (*fn)( CGI_HEADERS[i], CGI_HEADER_LEN[i],
2368                         pValue, len, arg );
2369             ++count;
2370             if ( ret <= 0 )
2371                 return ret;
2372         }
2373     }
2374     if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
2375     {
2376         char achHeaderName[256];
2377         char *p;
2378         char *pKey;
2379         char *pKeyEnd ;
2380         int  keyLen;
2381         struct lsapi_header_offset * pCur, *pEnd;
2382         pCur = pReq->m_pUnknownHeader;
2383         pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
2384         while( pCur < pEnd )
2385         {
2386             pKey = pReq->m_pHttpHeader + pCur->nameOff;
2387             keyLen = pCur->nameLen;
2388             if ( keyLen > 250 )
2389                 keyLen = 250;
2390             pKeyEnd = pKey + keyLen;
2391             memcpy( achHeaderName, "HTTP_", 5 );
2392             p = &achHeaderName[5];
2393 
2394             while( pKey < pKeyEnd )
2395             {
2396                 char ch = *pKey++;
2397                 if ( ch == '-' )
2398                     *p++ = '_';
2399                 else
2400                     *p++ = toupper( ch );
2401             }
2402             *p = 0;
2403             keyLen += 5;
2404 
2405             pValue = pReq->m_pHttpHeader + pCur->valueOff;
2406             *(pValue + pCur->valueLen ) = 0;
2407             ret = (*fn)( achHeaderName, keyLen,
2408                         pValue, pCur->valueLen, arg );
2409             if ( ret <= 0 )
2410                 return ret;
2411             ++pCur;
2412         }
2413     }
2414     return count + pReq->m_pHeader->m_cntUnknownHeaders;
2415 }
2416 
2417 
EnvForeach(struct LSAPI_key_value_pair * pEnv,int n,LSAPI_CB_EnvHandler fn,void * arg)2418 static int EnvForeach( struct LSAPI_key_value_pair * pEnv,
2419             int n, LSAPI_CB_EnvHandler fn, void * arg )
2420 {
2421     struct LSAPI_key_value_pair * pEnd = pEnv + n;
2422     int ret;
2423     if ( !pEnv || !fn )
2424         return -1;
2425     while( pEnv < pEnd )
2426     {
2427         ret = (*fn)( pEnv->pKey, pEnv->keyLen,
2428                     pEnv->pValue, pEnv->valLen, arg );
2429         if ( ret <= 0 )
2430             return ret;
2431         ++pEnv;
2432     }
2433     return n;
2434 }
2435 
2436 
LSAPI_ForeachEnv_r(LSAPI_Request * pReq,LSAPI_CB_EnvHandler fn,void * arg)2437 int LSAPI_ForeachEnv_r( LSAPI_Request * pReq,
2438             LSAPI_CB_EnvHandler fn, void * arg )
2439 {
2440     if ( !pReq || !fn )
2441         return -1;
2442     if ( pReq->m_pHeader->m_cntEnv > 0 )
2443     {
2444         return EnvForeach( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv,
2445                     fn, arg );
2446     }
2447     return 0;
2448 }
2449 
2450 
LSAPI_ForeachSpecialEnv_r(LSAPI_Request * pReq,LSAPI_CB_EnvHandler fn,void * arg)2451 int LSAPI_ForeachSpecialEnv_r( LSAPI_Request * pReq,
2452             LSAPI_CB_EnvHandler fn, void * arg )
2453 {
2454     if ( !pReq || !fn )
2455         return -1;
2456     if ( pReq->m_pHeader->m_cntSpecialEnv > 0 )
2457     {
2458         return EnvForeach( pReq->m_pSpecialEnvList,
2459                 pReq->m_pHeader->m_cntSpecialEnv,
2460                     fn, arg );
2461     }
2462     return 0;
2463 
2464 }
2465 
2466 
LSAPI_FinalizeRespHeaders_r(LSAPI_Request * pReq)2467 int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq )
2468 {
2469     if ( !pReq || !pReq->m_pIovec )
2470         return -1;
2471     if ( !( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) )
2472         return 0;
2473     pReq->m_reqState &= ~LSAPI_ST_RESP_HEADER;
2474     if ( pReq->m_pRespHeaderBufPos > pReq->m_pRespHeaderBuf )
2475     {
2476         pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespHeaderBuf;
2477         pReq->m_pIovecCur->iov_len  = pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf;
2478         pReq->m_totalLen += pReq->m_pIovecCur->iov_len;
2479         ++pReq->m_pIovecCur;
2480     }
2481 
2482     pReq->m_pIovec->iov_len  = sizeof( struct lsapi_resp_header)
2483             + pReq->m_respHeader.m_respInfo.m_cntHeaders * sizeof( short );
2484     pReq->m_totalLen += pReq->m_pIovec->iov_len;
2485 
2486     lsapi_buildPacketHeader( &pReq->m_respHeader.m_pktHeader,
2487                     LSAPI_RESP_HEADER, pReq->m_totalLen  );
2488     pReq->m_pIovec->iov_base = (void *)&pReq->m_respHeader;
2489     pReq->m_pIovecToWrite = pReq->m_pIovec;
2490     return 0;
2491 }
2492 
2493 
LSAPI_AppendRespHeader2_r(LSAPI_Request * pReq,const char * pHeaderName,const char * pHeaderValue)2494 int LSAPI_AppendRespHeader2_r( LSAPI_Request * pReq, const char * pHeaderName,
2495                               const char * pHeaderValue )
2496 {
2497     int nameLen, valLen, len;
2498     if ( !pReq || !pHeaderName || !pHeaderValue )
2499         return -1;
2500     if ( pReq->m_reqState & LSAPI_ST_RESP_BODY )
2501         return -1;
2502     if ( pReq->m_respHeader.m_respInfo.m_cntHeaders >= LSAPI_MAX_RESP_HEADERS )
2503         return -1;
2504     nameLen = strlen( pHeaderName );
2505     valLen = strlen( pHeaderValue );
2506     if ( nameLen == 0 )
2507         return -1;
2508     while( nameLen > 0 )
2509     {
2510         char ch = *(pHeaderName + nameLen - 1 );
2511         if (( ch == '\n' )||( ch == '\r' ))
2512             --nameLen;
2513         else
2514             break;
2515     }
2516     if ( nameLen <= 0 )
2517         return 0;
2518     while( valLen > 0 )
2519     {
2520         char ch = *(pHeaderValue + valLen - 1 );
2521         if (( ch == '\n' )||( ch == '\r' ))
2522             --valLen;
2523         else
2524             break;
2525     }
2526     len = nameLen + valLen + 1;
2527     if ( len > LSAPI_RESP_HTTP_HEADER_MAX )
2528         return -1;
2529 
2530     if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd )
2531     {
2532         int newlen = pReq->m_pRespHeaderBufPos + len + 4096 - pReq->m_pRespHeaderBuf;
2533         newlen -= newlen % 4096;
2534         if ( allocateRespHeaderBuf( pReq, newlen ) == -1 )
2535             return -1;
2536     }
2537     memmove( pReq->m_pRespHeaderBufPos, pHeaderName, nameLen );
2538     pReq->m_pRespHeaderBufPos += nameLen;
2539     *pReq->m_pRespHeaderBufPos++ = ':';
2540     memmove( pReq->m_pRespHeaderBufPos, pHeaderValue, valLen );
2541     pReq->m_pRespHeaderBufPos += valLen;
2542     *pReq->m_pRespHeaderBufPos++ = 0;
2543     ++len;  /* add one byte padding for \0 */
2544     pReq->m_respHeaderLen[pReq->m_respHeader.m_respInfo.m_cntHeaders] = len;
2545     ++pReq->m_respHeader.m_respInfo.m_cntHeaders;
2546     return 0;
2547 }
2548 
2549 
LSAPI_AppendRespHeader_r(LSAPI_Request * pReq,const char * pBuf,int len)2550 int LSAPI_AppendRespHeader_r( LSAPI_Request * pReq, const char * pBuf, int len )
2551 {
2552     if ( !pReq || !pBuf || len <= 0 || len > LSAPI_RESP_HTTP_HEADER_MAX )
2553         return -1;
2554     if ( pReq->m_reqState & LSAPI_ST_RESP_BODY )
2555         return -1;
2556     if ( pReq->m_respHeader.m_respInfo.m_cntHeaders >= LSAPI_MAX_RESP_HEADERS )
2557         return -1;
2558     while( len > 0 )
2559     {
2560         char ch = *(pBuf + len - 1 );
2561         if (( ch == '\n' )||( ch == '\r' ))
2562             --len;
2563         else
2564             break;
2565     }
2566     if ( len <= 0 )
2567         return 0;
2568     if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd )
2569     {
2570         int newlen = pReq->m_pRespHeaderBufPos + len + 4096 - pReq->m_pRespHeaderBuf;
2571         newlen -= newlen % 4096;
2572         if ( allocateRespHeaderBuf( pReq, newlen ) == -1 )
2573             return -1;
2574     }
2575     memmove( pReq->m_pRespHeaderBufPos, pBuf, len );
2576     pReq->m_pRespHeaderBufPos += len;
2577     *pReq->m_pRespHeaderBufPos++ = 0;
2578     ++len;  /* add one byte padding for \0 */
2579     pReq->m_respHeaderLen[pReq->m_respHeader.m_respInfo.m_cntHeaders] = len;
2580     ++pReq->m_respHeader.m_respInfo.m_cntHeaders;
2581     return 0;
2582 }
2583 
2584 
LSAPI_CreateListenSock2(const struct sockaddr * pServerAddr,int backlog)2585 int LSAPI_CreateListenSock2( const struct sockaddr * pServerAddr, int backlog )
2586 {
2587     int ret;
2588     int fd;
2589     int flag = 1;
2590     int addr_len;
2591 
2592     switch( pServerAddr->sa_family )
2593     {
2594     case AF_INET:
2595         addr_len = 16;
2596         break;
2597     case AF_INET6:
2598         addr_len = sizeof( struct sockaddr_in6 );
2599         break;
2600     case AF_UNIX:
2601         addr_len = sizeof( struct sockaddr_un );
2602         unlink( ((struct sockaddr_un *)pServerAddr)->sun_path );
2603         break;
2604     default:
2605         return -1;
2606     }
2607 
2608     fd = socket( pServerAddr->sa_family, SOCK_STREAM, 0 );
2609     if ( fd == -1 )
2610         return -1;
2611 
2612     fcntl( fd, F_SETFD, FD_CLOEXEC );
2613 
2614     if(setsockopt( fd, SOL_SOCKET, SO_REUSEADDR,
2615                 (char *)( &flag ), sizeof(flag)) == 0)
2616     {
2617         ret = bind( fd, pServerAddr, addr_len );
2618         if ( !ret )
2619         {
2620             ret = listen( fd, backlog );
2621             if ( !ret )
2622                 return fd;
2623         }
2624     }
2625 
2626     ret = errno;
2627     close(fd);
2628     errno = ret;
2629     return -1;
2630 }
2631 
2632 
LSAPI_ParseSockAddr(const char * pBind,struct sockaddr * pAddr)2633 int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr )
2634 {
2635     char achAddr[256];
2636     char * p = achAddr;
2637     char * pEnd;
2638     struct addrinfo *res, hints;
2639     int  doAddrInfo = 0;
2640     int port;
2641 
2642     if ( !pBind )
2643         return -1;
2644 
2645     while( isspace( *pBind ) )
2646         ++pBind;
2647 
2648     strncpy(achAddr, pBind, 255);
2649     achAddr[255] = 0;
2650 
2651     switch( *p )
2652     {
2653     case '/':
2654         pAddr->sa_family = AF_UNIX;
2655         strncpy( ((struct sockaddr_un *)pAddr)->sun_path, p,
2656                 sizeof(((struct sockaddr_un *)pAddr)->sun_path) );
2657         return 0;
2658 
2659     case '[':
2660         pAddr->sa_family = AF_INET6;
2661         ++p;
2662         pEnd = strchr( p, ']' );
2663         if ( !pEnd )
2664             return -1;
2665         *pEnd++ = 0;
2666 
2667         if ( *p == '*' )
2668         {
2669             strcpy( achAddr, "::" );
2670             p = achAddr;
2671         }
2672         doAddrInfo = 1;
2673         break;
2674 
2675     default:
2676         pAddr->sa_family = AF_INET;
2677         pEnd = strchr( p, ':' );
2678         if ( !pEnd )
2679             return -1;
2680         *pEnd++ = 0;
2681 
2682         doAddrInfo = 0;
2683         if ( *p == '*' )
2684         {
2685             ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = htonl(INADDR_ANY);
2686         }
2687         else if (!strcasecmp( p, "localhost" ) )
2688             ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = htonl( INADDR_LOOPBACK );
2689         else
2690         {
2691 #ifdef HAVE_INET_PTON
2692             if (!inet_pton(AF_INET, p, &((struct sockaddr_in *)pAddr)->sin_addr))
2693 #else
2694             ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = inet_addr( p );
2695             if ( ((struct sockaddr_in *)pAddr)->sin_addr.s_addr == INADDR_BROADCAST)
2696 #endif
2697             {
2698                 doAddrInfo = 1;
2699             }
2700         }
2701         break;
2702     }
2703     if ( *pEnd == ':' )
2704         ++pEnd;
2705 
2706     port = atoi( pEnd );
2707     if (( port <= 0 )||( port > 65535 ))
2708         return -1;
2709     if ( doAddrInfo )
2710     {
2711 
2712         memset(&hints, 0, sizeof(hints));
2713 
2714         hints.ai_family   = pAddr->sa_family;
2715         hints.ai_socktype = SOCK_STREAM;
2716         hints.ai_protocol = IPPROTO_TCP;
2717 
2718         if ( getaddrinfo(p, NULL, &hints, &res) )
2719         {
2720             return -1;
2721         }
2722 
2723         memcpy(pAddr, res->ai_addr, res->ai_addrlen);
2724         freeaddrinfo(res);
2725     }
2726 
2727     if ( pAddr->sa_family == AF_INET )
2728         ((struct sockaddr_in *)pAddr)->sin_port = htons( port );
2729     else
2730         ((struct sockaddr_in6 *)pAddr)->sin6_port = htons( port );
2731     return 0;
2732 
2733 }
2734 
2735 
LSAPI_CreateListenSock(const char * pBind,int backlog)2736 int LSAPI_CreateListenSock( const char * pBind, int backlog )
2737 {
2738     char serverAddr[128];
2739     int ret;
2740     int fd = -1;
2741     ret = LSAPI_ParseSockAddr( pBind, (struct sockaddr *)serverAddr );
2742     if ( !ret )
2743     {
2744         fd = LSAPI_CreateListenSock2( (struct sockaddr *)serverAddr, backlog );
2745     }
2746     return fd;
2747 }
2748 
2749 
2750 static fn_select_t g_fnSelect = select;
2751 typedef struct _lsapi_prefork_server
2752 {
2753     int m_fd;
2754     int m_iMaxChildren;
2755     int m_iExtraChildren;
2756     int m_iCurChildren;
2757     int m_iMaxIdleChildren;
2758     int m_iServerMaxIdle;
2759     int m_iChildrenMaxIdleTime;
2760     int m_iMaxReqProcessTime;
2761     int m_iAvoidFork;
2762 
2763     lsapi_child_status * m_pChildrenStatus;
2764     lsapi_child_status * m_pChildrenStatusCur;
2765     lsapi_child_status * m_pChildrenStatusEnd;
2766 
2767 }lsapi_prefork_server;
2768 static lsapi_prefork_server * g_prefork_server = NULL;
2769 
2770 
LSAPI_Init_Prefork_Server(int max_children,fn_select_t fp,int avoidFork)2771 int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork )
2772 {
2773     if ( g_prefork_server )
2774         return 0;
2775     if ( max_children <= 1 )
2776         return -1;
2777     if ( max_children >= 10000)
2778         max_children = 10000;
2779 
2780     if (s_max_busy_workers == 0)
2781         s_max_busy_workers = max_children / 2 + 1;
2782 
2783     g_prefork_server = (lsapi_prefork_server *)malloc( sizeof( lsapi_prefork_server ) );
2784     if ( !g_prefork_server )
2785         return -1;
2786     memset( g_prefork_server, 0, sizeof( lsapi_prefork_server ) );
2787 
2788     if ( fp != NULL )
2789         g_fnSelect = fp;
2790 
2791     s_ppid = getppid();
2792     s_pid = getpid();
2793     setpgid( s_pid, s_pid );
2794 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
2795     s_total_pages = sysconf(_SC_PHYS_PAGES);
2796 #endif
2797     g_prefork_server->m_iAvoidFork = avoidFork;
2798     g_prefork_server->m_iMaxChildren = max_children;
2799 
2800     g_prefork_server->m_iExtraChildren = ( avoidFork ) ? 0 : (max_children / 3) ;
2801     g_prefork_server->m_iMaxIdleChildren = ( avoidFork ) ? (max_children + 1) : (max_children / 3);
2802     if ( g_prefork_server->m_iMaxIdleChildren == 0 )
2803         g_prefork_server->m_iMaxIdleChildren = 1;
2804     g_prefork_server->m_iChildrenMaxIdleTime = 300;
2805     g_prefork_server->m_iMaxReqProcessTime = 3600;
2806 
2807     setsid();
2808 
2809     return 0;
2810 }
2811 
2812 
LSAPI_Set_Server_fd(int fd)2813 void LSAPI_Set_Server_fd( int fd )
2814 {
2815     if( g_prefork_server )
2816         g_prefork_server->m_fd = fd;
2817 }
2818 
2819 
lsapi_accept(int fdListen)2820 static int lsapi_accept( int fdListen )
2821 {
2822     int         fd;
2823     int         nodelay = 1;
2824     socklen_t   len;
2825     char        achPeer[128];
2826 
2827     len = sizeof( achPeer );
2828     fd = accept( fdListen, (struct sockaddr *)&achPeer, &len );
2829     if ( fd != -1 )
2830     {
2831         if (((struct sockaddr *)&achPeer)->sa_family == AF_INET )
2832         {
2833             setsockopt( fd, IPPROTO_TCP, TCP_NODELAY,
2834                     (char *)&nodelay, sizeof(nodelay));
2835         }
2836 
2837         //OPTIMIZATION
2838         //if ( s_accept_notify )
2839         //    notify_req_received( fd );
2840     }
2841     return fd;
2842 
2843 }
2844 
2845 
2846 static unsigned int s_max_reqs = UINT_MAX;
2847 static int s_max_idle_secs = 300;
2848 static int s_stop;
2849 
lsapi_cleanup(int signal)2850 static void lsapi_cleanup(int signal)
2851 {
2852     s_stop = signal;
2853 }
2854 
2855 
find_child_status(int pid)2856 static lsapi_child_status * find_child_status( int pid )
2857 {
2858     lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
2859     lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusEnd;
2860     while( pStatus < pEnd )
2861     {
2862         if ( pStatus->m_pid == pid )
2863         {
2864             if (pid == 0)
2865             {
2866                 memset(pStatus, 0, sizeof( *pStatus ) );
2867                 pStatus->m_pid = -1;
2868             }
2869             if ( pStatus + 1 > g_prefork_server->m_pChildrenStatusCur )
2870                 g_prefork_server->m_pChildrenStatusCur = pStatus + 1;
2871             return pStatus;
2872         }
2873         ++pStatus;
2874     }
2875     return NULL;
2876 }
2877 
2878 
LSAPI_reset_server_state(void)2879 void LSAPI_reset_server_state( void )
2880 {
2881     /*
2882        Reset child status
2883     */
2884     g_prefork_server->m_iCurChildren = 0;
2885     lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
2886     lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusEnd;
2887     while( pStatus < pEnd )
2888     {
2889         pStatus->m_pid = 0;
2890         ++pStatus;
2891     }
2892     if (s_busy_workers)
2893         __atomic_store_n(s_busy_workers, 0, __ATOMIC_SEQ_CST);
2894     if (s_accepting_workers)
2895         __atomic_store_n(s_accepting_workers, 0, __ATOMIC_SEQ_CST);
2896 
2897 }
2898 
2899 
lsapi_sigchild(int signal)2900 static void lsapi_sigchild( int signal )
2901 {
2902     int status, pid;
2903     char expect_connected = LSAPI_STATE_CONNECTED;
2904     char expect_accepting = LSAPI_STATE_ACCEPTING;
2905     lsapi_child_status * child_status;
2906     if (g_prefork_server == NULL)
2907         return;
2908     while( 1 )
2909     {
2910         pid = waitpid( -1, &status, WNOHANG|WUNTRACED );
2911         if ( pid <= 0 )
2912         {
2913             break;
2914         }
2915         if ( WIFSIGNALED( status ))
2916         {
2917             int sig_num = WTERMSIG( status );
2918 
2919 #ifdef WCOREDUMP
2920             const char * dump = WCOREDUMP( status ) ? "yes" : "no";
2921 #else
2922             const char * dump = "unknown";
2923 #endif
2924             lsapi_log("Child process with pid: %d was killed by signal: "
2925                      "%d, core dumped: %s\n", pid, sig_num, dump );
2926         }
2927         if ( pid == s_pid_dump_debug_info )
2928         {
2929             pid = 0;
2930             continue;
2931         }
2932         if ( pid == s_ignore_pid )
2933         {
2934             pid = 0;
2935             s_ignore_pid = -1;
2936             continue;
2937         }
2938         child_status = find_child_status( pid );
2939         if ( child_status )
2940         {
2941             if (__atomic_compare_exchange_n(&child_status->m_state,
2942                                             &expect_connected,
2943                                             LSAPI_STATE_IDLE, 1,
2944                                             __ATOMIC_SEQ_CST,
2945                                             __ATOMIC_SEQ_CST))
2946             {
2947                 if (s_busy_workers)
2948                     __atomic_fetch_sub(s_busy_workers, 1, __ATOMIC_SEQ_CST);
2949             }
2950             else if (__atomic_compare_exchange_n(&child_status->m_state,
2951                                                  &expect_accepting,
2952                                                  LSAPI_STATE_IDLE, 1,
2953                                                  __ATOMIC_SEQ_CST,
2954                                                  __ATOMIC_SEQ_CST))
2955             {
2956                 if (s_accepting_workers)
2957                     __atomic_fetch_sub(s_accepting_workers, 1, __ATOMIC_SEQ_CST);
2958             }
2959             child_status->m_pid = 0;
2960             --g_prefork_server->m_iCurChildren;
2961         }
2962     }
2963     while(( g_prefork_server->m_pChildrenStatusCur > g_prefork_server->m_pChildrenStatus )
2964             &&( g_prefork_server->m_pChildrenStatusCur[-1].m_pid == 0 ))
2965         --g_prefork_server->m_pChildrenStatusCur;
2966 
2967 }
2968 
2969 
lsapi_init_children_status(void)2970 static int lsapi_init_children_status(void)
2971 {
2972     char * pBuf;
2973     int size = 4096;
2974     int max_children;
2975     if (g_prefork_server->m_pChildrenStatus)
2976         return 0;
2977     max_children = g_prefork_server->m_iMaxChildren
2978                         + g_prefork_server->m_iExtraChildren;
2979 
2980     size = max_children * sizeof( lsapi_child_status ) * 2 + 3 * sizeof(int);
2981     size = (size + 4095) / 4096 * 4096;
2982     pBuf =( char*) mmap( NULL, size, PROT_READ | PROT_WRITE,
2983         MAP_ANON | MAP_SHARED, -1, 0 );
2984     if ( pBuf == MAP_FAILED )
2985     {
2986         perror( "Anonymous mmap() failed" );
2987         return -1;
2988     }
2989     memset( pBuf, 0, size );
2990     g_prefork_server->m_pChildrenStatus = (lsapi_child_status *)pBuf;
2991     g_prefork_server->m_pChildrenStatusCur = (lsapi_child_status *)pBuf;
2992     g_prefork_server->m_pChildrenStatusEnd = (lsapi_child_status *)pBuf + max_children;
2993     s_busy_workers = (int *)g_prefork_server->m_pChildrenStatusEnd;
2994     s_accepting_workers = s_busy_workers + 1;
2995     s_global_counter = s_accepting_workers + 1;
2996     s_avail_pages = (size_t *)(s_global_counter + 1);
2997 
2998     setsid();
2999     return 0;
3000 }
3001 
3002 
dump_debug_info(lsapi_child_status * pStatus,long tmCur)3003 static void dump_debug_info( lsapi_child_status * pStatus, long tmCur )
3004 {
3005     char achCmd[1024];
3006     if ( s_pid_dump_debug_info )
3007     {
3008         if ( kill( s_pid_dump_debug_info, 0 ) == 0 )
3009             return;
3010     }
3011 
3012     lsapi_log("Possible runaway process, UID: %d, PPID: %d, PID: %d, "
3013              "reqCount: %d, process time: %ld, checkpoint time: %ld, start "
3014              "time: %ld\n", getuid(), getppid(), pStatus->m_pid,
3015              pStatus->m_iReqCounter, tmCur - pStatus->m_tmReqBegin,
3016              tmCur - pStatus->m_tmLastCheckPoint, tmCur - pStatus->m_tmStart );
3017 
3018     s_pid_dump_debug_info = fork();
3019     if (s_pid_dump_debug_info == 0)
3020     {
3021         snprintf( achCmd, 1024, "gdb --batch -ex \"attach %d\" -ex \"set height 0\" "
3022                 "-ex \"bt\" >&2;PATH=$PATH:/usr/sbin lsof -p %d >&2",
3023                 pStatus->m_pid, pStatus->m_pid );
3024         if ( system( achCmd ) == -1 )
3025             perror( "system()" );
3026         exit( 0 );
3027     }
3028 }
3029 
3030 
lsapi_check_child_status(long tmCur)3031 static void lsapi_check_child_status( long tmCur )
3032 {
3033     int idle = 0;
3034     int tobekilled;
3035     int dying = 0;
3036     int count = 0;
3037     lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
3038     lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusCur;
3039     while( pStatus < pEnd )
3040     {
3041         tobekilled = 0;
3042         if ( pStatus->m_pid != 0 && pStatus->m_pid != -1)
3043         {
3044             ++count;
3045             if ( !pStatus->m_inProcess )
3046             {
3047                 if (g_prefork_server->m_iCurChildren - dying
3048                         > g_prefork_server->m_iMaxChildren
3049                     || idle > g_prefork_server->m_iMaxIdleChildren)
3050                 {
3051                     ++pStatus->m_iKillSent;
3052                     //tobekilled = SIGUSR1;
3053                 }
3054                 else
3055                 {
3056                     if (s_max_idle_secs> 0
3057                         && tmCur - pStatus->m_tmWaitBegin > s_max_idle_secs + 5)
3058                     {
3059                         ++pStatus->m_iKillSent;
3060                         //tobekilled = SIGUSR1;
3061                     }
3062                 }
3063                 if (!pStatus->m_iKillSent)
3064                     ++idle;
3065             }
3066             else
3067             {
3068                 if (tmCur - pStatus->m_tmReqBegin >
3069                         g_prefork_server->m_iMaxReqProcessTime)
3070                 {
3071                     if ((pStatus->m_iKillSent % 5) == 0 && s_dump_debug_info)
3072                         dump_debug_info( pStatus, tmCur );
3073                     if ( pStatus->m_iKillSent > 5 )
3074                     {
3075                         tobekilled = SIGKILL;
3076                         lsapi_log("Force killing runaway process PID: %d"
3077                                  " with SIGKILL\n", pStatus->m_pid );
3078                     }
3079                     else
3080                     {
3081                         tobekilled = SIGTERM;
3082                         lsapi_log("Killing runaway process PID: %d with "
3083                                  "SIGTERM\n", pStatus->m_pid );
3084                     }
3085                 }
3086             }
3087             if ( tobekilled )
3088             {
3089                 if (( kill( pStatus->m_pid, tobekilled ) == -1 ) &&
3090                     ( errno == ESRCH ))
3091                 {
3092                     pStatus->m_pid = 0;
3093                     --count;
3094                 }
3095                 else
3096                 {
3097                     ++pStatus->m_iKillSent;
3098                     ++dying;
3099                 }
3100             }
3101         }
3102         ++pStatus;
3103     }
3104     if ( abs( g_prefork_server->m_iCurChildren - count ) > 1 )
3105     {
3106         lsapi_log("Children tracking is wrong: Cur Children: %d,"
3107                   " count: %d, idle: %d, dying: %d\n",
3108                   g_prefork_server->m_iCurChildren, count, idle, dying );
3109     }
3110 }
3111 
3112 
3113 //static int lsapi_all_children_must_die(void)
3114 //{
3115 //    int maxWait;
3116 //    int sec =0;
3117 //    g_prefork_server->m_iMaxReqProcessTime = 10;
3118 //    g_prefork_server->m_iMaxIdleChildren = -1;
3119 //    maxWait = 15;
3120 //
3121 //    while( g_prefork_server->m_iCurChildren && (sec < maxWait) )
3122 //    {
3123 //        lsapi_check_child_status(time(NULL));
3124 //        sleep( 1 );
3125 //        sec++;
3126 //    }
3127 //    if ( g_prefork_server->m_iCurChildren != 0 )
3128 //        kill( -getpgrp(), SIGKILL );
3129 //    return 0;
3130 //}
3131 
3132 
set_skip_write(void)3133 void set_skip_write(void)
3134 {   s_skip_write = 1;   }
3135 
3136 
is_enough_free_mem(void)3137 int is_enough_free_mem(void)
3138 {
3139 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
3140     //minimum 1GB or 10% available free memory
3141     return (*s_avail_pages > s_min_avail_pages
3142             || (*s_avail_pages * 10) / s_total_pages > 0);
3143 #endif
3144     return 1;
3145 }
3146 
3147 
lsapi_prefork_server_accept(lsapi_prefork_server * pServer,LSAPI_Request * pReq)3148 static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer,
3149                                         LSAPI_Request * pReq )
3150 {
3151     struct sigaction act, old_term, old_quit, old_int,
3152                     old_usr1, old_child;
3153     lsapi_child_status * child_status;
3154     int             wait_secs = 0;
3155     int             ret = 0;
3156     int             pid;
3157     time_t          lastTime = 0;
3158     time_t          curTime = 0;
3159     fd_set          readfds;
3160     struct timeval  timeout;
3161 
3162     sigset_t mask;
3163     sigset_t orig_mask;
3164 
3165     lsapi_init_children_status();
3166 
3167     act.sa_flags = 0;
3168     act.sa_handler = lsapi_sigchild;
3169     sigemptyset(&(act.sa_mask));
3170     if( sigaction( SIGCHLD, &act, &old_child ) )
3171     {
3172         perror( "Can't set signal handler for SIGCHILD" );
3173         return -1;
3174     }
3175 
3176     /* Set up handler to kill children upon exit */
3177     act.sa_flags = 0;
3178     act.sa_handler = lsapi_cleanup;
3179     sigemptyset(&(act.sa_mask));
3180     if( sigaction( SIGTERM, &act, &old_term ) ||
3181         sigaction( SIGINT,  &act, &old_int  ) ||
3182         sigaction( SIGUSR1, &act, &old_usr1 ) ||
3183         sigaction( SIGQUIT, &act, &old_quit ))
3184     {
3185         perror( "Can't set signals" );
3186         return -1;
3187     }
3188 
3189     while( !s_stop )
3190     {
3191         if (s_proc_group_timer_cb != NULL) {
3192             s_proc_group_timer_cb(&s_ignore_pid);
3193         }
3194 
3195         curTime = time( NULL );
3196         if (curTime != lastTime )
3197         {
3198             lastTime = curTime;
3199             if (lsapi_parent_dead())
3200                 break;
3201             lsapi_check_child_status(curTime );
3202             if (pServer->m_iServerMaxIdle)
3203             {
3204                 if ( pServer->m_iCurChildren <= 0 )
3205                 {
3206                     ++wait_secs;
3207                     if ( wait_secs > pServer->m_iServerMaxIdle )
3208                         return -1;
3209                 }
3210                 else
3211                     wait_secs = 0;
3212             }
3213         }
3214 
3215 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
3216         *s_avail_pages = sysconf(_SC_AVPHYS_PAGES);
3217 //        lsapi_log("Memory total: %zd, free: %zd, free %%%zd\n",
3218 //                  s_total_pages, *s_avail_pages, *s_avail_pages * 100 / s_total_pages);
3219 
3220 #endif
3221         FD_ZERO( &readfds );
3222         FD_SET( pServer->m_fd, &readfds );
3223         timeout.tv_sec = 1;
3224         timeout.tv_usec = 0;
3225         ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout);
3226         if (ret == 1 )
3227         {
3228             int accepting = 0;
3229             if (s_accepting_workers)
3230                 accepting = __atomic_load_n(s_accepting_workers, __ATOMIC_SEQ_CST);
3231 
3232             if (pServer->m_iCurChildren > 0
3233                 && accepting > 0)
3234             {
3235                 usleep(400);
3236                 while(accepting-- > 0)
3237                     sched_yield();
3238                 continue;
3239             }
3240         }
3241         else if ( ret == -1 )
3242         {
3243             if ( errno == EINTR )
3244                 continue;
3245             /* perror( "select()" ); */
3246             break;
3247         }
3248         else
3249         {
3250             continue;
3251         }
3252 
3253         if (pServer->m_iCurChildren >=
3254             pServer->m_iMaxChildren + pServer->m_iExtraChildren)
3255         {
3256             lsapi_log("Reached max children process limit: %d, extra: %d,"
3257                      " current: %d, busy: %d, please increase LSAPI_CHILDREN.\n",
3258                      pServer->m_iMaxChildren, pServer->m_iExtraChildren,
3259                      pServer->m_iCurChildren,
3260                      s_busy_workers ? *s_busy_workers : -1 );
3261             usleep( 100000 );
3262             continue;
3263         }
3264 
3265         pReq->m_fd = lsapi_accept( pServer->m_fd );
3266         if ( pReq->m_fd != -1 )
3267         {
3268             wait_secs = 0;
3269             child_status = find_child_status( 0 );
3270 
3271             sigemptyset( &mask );
3272             sigaddset( &mask, SIGCHLD );
3273 
3274             if ( sigprocmask(SIG_BLOCK, &mask, &orig_mask) < 0 )
3275             {
3276                 perror( "sigprocmask(SIG_BLOCK) to block SIGCHLD" );
3277             }
3278 
3279             pid = fork();
3280 
3281             if ( !pid )
3282             {
3283                 setsid();
3284                 if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0)
3285                     perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK in child" );
3286                 g_prefork_server = NULL;
3287                 s_ppid = getppid();
3288                 s_pid = getpid();
3289                 s_req_processed = 0;
3290                 s_proc_group_timer_cb = NULL;
3291                 s_worker_status = child_status;
3292 
3293                 if (pthread_atfork_func)
3294                     (*pthread_atfork_func)(NULL, NULL, set_skip_write);
3295 
3296                 __atomic_store_n(&s_worker_status->m_state,
3297                                  LSAPI_STATE_CONNECTED, __ATOMIC_SEQ_CST);
3298                 if (s_busy_workers)
3299                     __atomic_add_fetch(s_busy_workers, 1, __ATOMIC_SEQ_CST);
3300                 lsapi_set_nblock( pReq->m_fd, 0 );
3301                 //keep it open if busy_count is used.
3302                 if (!s_keep_listener && s_busy_workers
3303                     && *s_busy_workers > (pServer->m_iMaxChildren >> 1))
3304                     s_keep_listener = 1;
3305                 if ((s_uid == 0 || !s_keep_listener || !is_enough_free_mem())
3306                     && pReq->m_fdListen != -1 )
3307                 {
3308                     close( pReq->m_fdListen );
3309                     pReq->m_fdListen = -1;
3310                 }
3311                 /* don't catch our signals */
3312                 sigaction( SIGCHLD, &old_child, 0 );
3313                 sigaction( SIGTERM, &old_term, 0 );
3314                 sigaction( SIGQUIT, &old_quit, 0 );
3315                 sigaction( SIGINT,  &old_int,  0 );
3316                 sigaction( SIGUSR1, &old_usr1, 0 );
3317                 //init_conn_key( pReq->m_fd );
3318                 lsapi_notify_pid( pReq->m_fd );
3319                 s_notified_pid = 1;
3320                 //if ( s_accept_notify )
3321                 //    return notify_req_received( pReq->m_fd );
3322                 return 0;
3323             }
3324             else if ( pid == -1 )
3325             {
3326                 lsapi_perror("fork() failed, please increase process limit", errno);
3327                 if (child_status)
3328                     child_status->m_pid = 0;
3329             }
3330             else
3331             {
3332                 ++pServer->m_iCurChildren;
3333                 if ( child_status )
3334                 {
3335                     child_status->m_pid = pid;
3336                     child_status->m_tmWaitBegin = curTime;
3337                     child_status->m_tmStart = curTime;
3338                 }
3339             }
3340             close( pReq->m_fd );
3341             pReq->m_fd = -1;
3342 
3343             if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0)
3344                 perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK" );
3345 
3346         }
3347         else
3348         {
3349             if (( errno == EINTR )||( errno == EAGAIN))
3350                 continue;
3351             lsapi_perror("accept() failed", errno);
3352             return -1;
3353         }
3354     }
3355     sigaction( SIGUSR1, &old_usr1, 0 );
3356     //kill( -getpgrp(), SIGUSR1 );
3357     //lsapi_all_children_must_die();  /* Sorry, children ;-) */
3358     return -1;
3359 
3360 }
3361 
3362 
3363 static struct sigaction old_term, old_quit, old_int,
3364                     old_usr1, old_child;
3365 
3366 
LSAPI_Postfork_Child(LSAPI_Request * pReq)3367 int LSAPI_Postfork_Child(LSAPI_Request * pReq)
3368 {
3369     int max_children = g_prefork_server->m_iMaxChildren;
3370     s_pid = getpid();
3371     __atomic_store_n(&pReq->child_status->m_pid, s_pid, __ATOMIC_SEQ_CST);
3372     s_worker_status = pReq->child_status;
3373 
3374     setsid();
3375     g_prefork_server = NULL;
3376     s_ppid = getppid();
3377     s_req_processed = 0;
3378     s_proc_group_timer_cb = NULL;
3379 
3380     if (pthread_atfork_func)
3381         (*pthread_atfork_func)(NULL, NULL, set_skip_write);
3382 
3383     __atomic_store_n(&s_worker_status->m_state,
3384                      LSAPI_STATE_CONNECTED, __ATOMIC_SEQ_CST);
3385     if (s_busy_workers)
3386         __atomic_add_fetch(s_busy_workers, 1, __ATOMIC_SEQ_CST);
3387     lsapi_set_nblock( pReq->m_fd, 0 );
3388     //keep it open if busy_count is used.
3389     if (!s_keep_listener && s_busy_workers
3390         && *s_busy_workers > (max_children >> 1))
3391         s_keep_listener = 1;
3392     if ((s_uid == 0 || !s_keep_listener || !is_enough_free_mem())
3393         && pReq->m_fdListen != -1 )
3394     {
3395         close(pReq->m_fdListen);
3396         pReq->m_fdListen = -1;
3397     }
3398 
3399     //init_conn_key( pReq->m_fd );
3400     lsapi_notify_pid(pReq->m_fd);
3401     s_notified_pid = 1;
3402     //if ( s_accept_notify )
3403     //    return notify_req_received( pReq->m_fd );
3404     return 0;
3405 }
3406 
3407 
LSAPI_Postfork_Parent(LSAPI_Request * pReq)3408 int LSAPI_Postfork_Parent(LSAPI_Request * pReq)
3409 {
3410     ++g_prefork_server->m_iCurChildren;
3411     if (pReq->child_status)
3412     {
3413         time_t curTime = time( NULL );
3414         pReq->child_status->m_tmWaitBegin = curTime;
3415         pReq->child_status->m_tmStart = curTime;
3416     }
3417     close(pReq->m_fd);
3418     pReq->m_fd = -1;
3419     return 0;
3420 }
3421 
3422 
LSAPI_Accept_Before_Fork(LSAPI_Request * pReq)3423 int LSAPI_Accept_Before_Fork(LSAPI_Request * pReq)
3424 {
3425     time_t          lastTime = 0;
3426     time_t          curTime = 0;
3427     fd_set          readfds;
3428     struct timeval  timeout;
3429     int             wait_secs = 0;
3430     int             ret = 0;
3431 
3432     lsapi_prefork_server * pServer = g_prefork_server;
3433 
3434     struct sigaction act;
3435 
3436     lsapi_init_children_status();
3437 
3438     act.sa_flags = 0;
3439     act.sa_handler = lsapi_sigchild;
3440     sigemptyset(&(act.sa_mask));
3441     if (sigaction(SIGCHLD, &act, &old_child))
3442     {
3443         perror( "Can't set signal handler for SIGCHILD" );
3444         return -1;
3445     }
3446 
3447     /* Set up handler to kill children upon exit */
3448     act.sa_flags = 0;
3449     act.sa_handler = lsapi_cleanup;
3450     sigemptyset(&(act.sa_mask));
3451     if (sigaction(SIGTERM, &act, &old_term) ||
3452         sigaction(SIGINT,  &act, &old_int ) ||
3453         sigaction(SIGUSR1, &act, &old_usr1) ||
3454         sigaction(SIGQUIT, &act, &old_quit))
3455     {
3456         perror( "Can't set signals" );
3457         return -1;
3458     }
3459     s_stop = 0;
3460     pReq->m_reqState = 0;
3461 
3462     while(!s_stop)
3463     {
3464         if (s_proc_group_timer_cb != NULL) {
3465             s_proc_group_timer_cb(&s_ignore_pid);
3466         }
3467 
3468         curTime = time(NULL);
3469         if (curTime != lastTime)
3470         {
3471             lastTime = curTime;
3472             if (lsapi_parent_dead())
3473                 break;
3474             lsapi_check_child_status(curTime);
3475             if (pServer->m_iServerMaxIdle)
3476             {
3477                 if (pServer->m_iCurChildren <= 0)
3478                 {
3479                     ++wait_secs;
3480                     if ( wait_secs > pServer->m_iServerMaxIdle )
3481                         return -1;
3482                 }
3483                 else
3484                     wait_secs = 0;
3485             }
3486         }
3487 
3488 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
3489         *s_avail_pages = sysconf(_SC_AVPHYS_PAGES);
3490 //        lsapi_log("Memory total: %zd, free: %zd, free %%%zd\n",
3491 //                  s_total_pages, *s_avail_pages, *s_avail_pages * 100 / s_total_pages);
3492 
3493 #endif
3494         FD_ZERO(&readfds);
3495         FD_SET(pServer->m_fd, &readfds);
3496         timeout.tv_sec = 1;
3497         timeout.tv_usec = 0;
3498         ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout);
3499         if (ret == 1 )
3500         {
3501             int accepting = 0;
3502             if (s_accepting_workers)
3503                 accepting = __atomic_load_n(s_accepting_workers, __ATOMIC_SEQ_CST);
3504 
3505             if (pServer->m_iCurChildren > 0
3506                 && accepting > 0)
3507             {
3508                 usleep( 400);
3509                 while(accepting-- > 0)
3510                     sched_yield();
3511                 continue;
3512             }
3513         }
3514         else if (ret == -1)
3515         {
3516             if (errno == EINTR)
3517                 continue;
3518             /* perror( "select()" ); */
3519             break;
3520         }
3521         else
3522         {
3523             continue;
3524         }
3525 
3526         if (pServer->m_iCurChildren >=
3527             pServer->m_iMaxChildren + pServer->m_iExtraChildren)
3528         {
3529             lsapi_log("Reached max children process limit: %d, extra: %d,"
3530                      " current: %d, busy: %d, please increase LSAPI_CHILDREN.\n",
3531                      pServer->m_iMaxChildren, pServer->m_iExtraChildren,
3532                      pServer->m_iCurChildren,
3533                      s_busy_workers ? *s_busy_workers : -1);
3534             usleep(100000);
3535             continue;
3536         }
3537 
3538         pReq->m_fd = lsapi_accept(pServer->m_fd);
3539         if (pReq->m_fd != -1)
3540         {
3541             wait_secs = 0;
3542             pReq->child_status = find_child_status(0);
3543 
3544             ret = 0;
3545             break;
3546         }
3547         else
3548         {
3549             if ((errno == EINTR) || (errno == EAGAIN))
3550                 continue;
3551             lsapi_perror("accept() failed", errno);
3552             ret = -1;
3553             break;
3554         }
3555     }
3556 
3557     sigaction(SIGCHLD, &old_child, 0);
3558     sigaction(SIGTERM, &old_term, 0);
3559     sigaction(SIGQUIT, &old_quit, 0);
3560     sigaction(SIGINT,  &old_int,  0);
3561     sigaction(SIGUSR1, &old_usr1, 0);
3562 
3563     return ret;
3564 }
3565 
3566 
LSAPI_Prefork_Accept_r(LSAPI_Request * pReq)3567 int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
3568 {
3569     int             fd;
3570     int             ret;
3571     int             wait_secs;
3572     fd_set          readfds;
3573     struct timeval  timeout;
3574 
3575     if (s_skip_write)
3576         return -1;
3577 
3578     LSAPI_Finish_r( pReq );
3579 
3580     if ( g_prefork_server )
3581     {
3582         if ( g_prefork_server->m_fd != -1 )
3583             if ( lsapi_prefork_server_accept( g_prefork_server, pReq ) == -1 )
3584                 return -1;
3585     }
3586     else if (s_req_processed > 0 && s_max_busy_workers > 0 && s_busy_workers)
3587     {
3588         ret = __atomic_load_n(s_busy_workers, __ATOMIC_SEQ_CST);
3589         if (ret >= s_max_busy_workers)
3590         {
3591             send_conn_close_notification(pReq->m_fd);
3592             lsapi_close_connection(pReq);
3593         }
3594     }
3595 
3596     if ( (unsigned int)s_req_processed > s_max_reqs )
3597         return -1;
3598 
3599     if ( s_worker_status )
3600     {
3601         s_worker_status->m_tmWaitBegin = time( NULL );
3602     }
3603 
3604 
3605     while( g_running )
3606     {
3607         if ( pReq->m_fd != -1 )
3608         {
3609             fd = pReq->m_fd;
3610         }
3611         else if ( pReq->m_fdListen != -1 )
3612             fd = pReq->m_fdListen;
3613         else
3614         {
3615             break;
3616         }
3617         wait_secs = 0;
3618         while( 1 )
3619         {
3620             if ( !g_running )
3621                 return -1;
3622             if (s_req_processed && s_worker_status
3623                 && s_worker_status->m_iKillSent)
3624                 return -1;
3625             FD_ZERO( &readfds );
3626             FD_SET( fd, &readfds );
3627             timeout.tv_sec = 1;
3628             timeout.tv_usec = 0;
3629             if (fd == pReq->m_fdListen)
3630             {
3631                 if (s_worker_status)
3632                     __atomic_store_n(&s_worker_status->m_state,
3633                                      LSAPI_STATE_ACCEPTING, __ATOMIC_SEQ_CST);
3634                 if (s_accepting_workers)
3635                     __atomic_fetch_add(s_accepting_workers, 1, __ATOMIC_SEQ_CST);
3636             }
3637             ret = (*g_fnSelect)(fd+1, &readfds, NULL, NULL, &timeout);
3638             if (fd == pReq->m_fdListen)
3639             {
3640                 if (s_accepting_workers)
3641                     __atomic_fetch_sub(s_accepting_workers, 1, __ATOMIC_SEQ_CST);
3642                 if (s_worker_status)
3643                     __atomic_store_n(&s_worker_status->m_state,
3644                                      LSAPI_STATE_IDLE, __ATOMIC_SEQ_CST);
3645             }
3646 
3647             if ( ret == 0 )
3648             {
3649                 if ( s_worker_status )
3650                 {
3651                     s_worker_status->m_inProcess = 0;
3652                     if (fd == pReq->m_fdListen)
3653                     {
3654                         if (s_keep_listener == 0 || !is_enough_free_mem())
3655                             return -1;
3656                         if (s_keep_listener == 1)
3657                         {
3658                             int wait_time = 10;
3659                             if (s_busy_workers)
3660                                 wait_time += *s_busy_workers * 10;
3661                             if (s_accepting_workers)
3662                                 wait_time >>= (*s_accepting_workers);
3663                             if (wait_secs >= wait_time)
3664                                 return -1;
3665                         }
3666                     }
3667                 }
3668                 ++wait_secs;
3669                 if (( s_max_idle_secs > 0 )&&(wait_secs >= s_max_idle_secs ))
3670                     return -1;
3671                 if ( lsapi_parent_dead() )
3672                     return -1;
3673             }
3674             else if ( ret == -1 )
3675             {
3676                 if ( errno == EINTR )
3677                     continue;
3678                 else
3679                     return -1;
3680             }
3681             else if ( ret >= 1 )
3682             {
3683                 if (s_req_processed && s_worker_status
3684                     && s_worker_status->m_iKillSent)
3685                     return -1;
3686                 if ( fd == pReq->m_fdListen )
3687                 {
3688                     pReq->m_fd = lsapi_accept( pReq->m_fdListen );
3689                     if ( pReq->m_fd != -1 )
3690                     {
3691                         if (s_worker_status)
3692                             __atomic_store_n(&s_worker_status->m_state,
3693                                              LSAPI_STATE_CONNECTED,
3694                                              __ATOMIC_SEQ_CST);
3695                         if (s_busy_workers)
3696                             __atomic_fetch_add(s_busy_workers, 1, __ATOMIC_SEQ_CST);
3697 
3698                         fd = pReq->m_fd;
3699 
3700                         lsapi_set_nblock( fd, 0 );
3701                         //init_conn_key( pReq->m_fd );
3702                         if (!s_keep_listener)
3703                         {
3704                             close( pReq->m_fdListen );
3705                             pReq->m_fdListen = -1;
3706                         }
3707                         if ( s_accept_notify )
3708                             if ( notify_req_received( pReq->m_fd ) == -1 )
3709                                 return -1;
3710                     }
3711                     else
3712                     {
3713                         if (( errno == EINTR )||( errno == EAGAIN))
3714                             continue;
3715                         lsapi_perror( "lsapi_accept() error", errno );
3716                         return -1;
3717                     }
3718                 }
3719                 else
3720                     break;
3721             }
3722         }
3723 
3724         if ( !readReq( pReq ) )
3725         {
3726             if ( s_worker_status )
3727             {
3728                 s_worker_status->m_iKillSent = 0;
3729                 s_worker_status->m_inProcess = 1;
3730                 ++s_worker_status->m_iReqCounter;
3731                 s_worker_status->m_tmReqBegin =
3732                 s_worker_status->m_tmLastCheckPoint = time(NULL);
3733             }
3734             ++s_req_processed;
3735             return 0;
3736         }
3737         lsapi_close_connection(pReq);
3738         LSAPI_Reset_r( pReq );
3739     }
3740     return -1;
3741 
3742 }
3743 
3744 
LSAPI_Set_Max_Reqs(int reqs)3745 void LSAPI_Set_Max_Reqs( int reqs )
3746 {   s_max_reqs = reqs - 1;      }
3747 
LSAPI_Set_Max_Idle(int secs)3748 void LSAPI_Set_Max_Idle( int secs )
3749 {   s_max_idle_secs = secs;     }
3750 
3751 
LSAPI_Set_Max_Children(int maxChildren)3752 void LSAPI_Set_Max_Children( int maxChildren )
3753 {
3754     if ( g_prefork_server )
3755         g_prefork_server->m_iMaxChildren = maxChildren;
3756 }
3757 
3758 
LSAPI_Set_Extra_Children(int extraChildren)3759 void LSAPI_Set_Extra_Children( int extraChildren )
3760 {
3761     if (( g_prefork_server )&&( extraChildren >= 0 ))
3762         g_prefork_server->m_iExtraChildren = extraChildren;
3763 }
3764 
3765 
LSAPI_Set_Max_Process_Time(int secs)3766 void LSAPI_Set_Max_Process_Time( int secs )
3767 {
3768     if (( g_prefork_server )&&( secs > 0 ))
3769         g_prefork_server->m_iMaxReqProcessTime = secs;
3770 }
3771 
3772 
LSAPI_Set_Max_Idle_Children(int maxIdleChld)3773 void LSAPI_Set_Max_Idle_Children( int maxIdleChld )
3774 {
3775     if (( g_prefork_server )&&( maxIdleChld > 0 ))
3776         g_prefork_server->m_iMaxIdleChildren = maxIdleChld;
3777 }
3778 
3779 
LSAPI_Set_Server_Max_Idle_Secs(int serverMaxIdle)3780 void LSAPI_Set_Server_Max_Idle_Secs( int serverMaxIdle )
3781 {
3782     if ( g_prefork_server )
3783         g_prefork_server->m_iServerMaxIdle = serverMaxIdle;
3784 }
3785 
3786 
LSAPI_Set_Slow_Req_Msecs(int msecs)3787 void LSAPI_Set_Slow_Req_Msecs( int msecs )
3788 {
3789     s_slow_req_msecs = msecs;
3790 }
3791 
3792 
LSAPI_Get_Slow_Req_Msecs(void)3793 int  LSAPI_Get_Slow_Req_Msecs(void)
3794 {
3795     return s_slow_req_msecs;
3796 }
3797 
3798 
LSAPI_No_Check_ppid(void)3799 void LSAPI_No_Check_ppid(void)
3800 {
3801     s_ppid = 0;
3802 }
3803 
3804 
LSAPI_Get_ppid(void)3805 int LSAPI_Get_ppid(void)
3806 {
3807     return(s_ppid);
3808 }
3809 
3810 
3811 #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
3812 #include <crt_externs.h>
3813 #else
3814 extern char ** environ;
3815 #endif
unset_lsapi_envs(void)3816 static void unset_lsapi_envs(void)
3817 {
3818     char **env;
3819 #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
3820     env = *_NSGetEnviron();
3821 #else
3822     env = environ;
3823 #endif
3824     while( env != NULL && *env != NULL )
3825     {
3826         if (!strncmp(*env, "LSAPI_", 6) || !strncmp( *env, "PHP_LSAPI_", 10 )
3827             || (!strncmp( *env, "PHPRC=", 6 )&&(!s_uid)))
3828         {
3829             char ** del = env;
3830             do
3831                 *del = del[1];
3832             while( *del++ );
3833         }
3834         else
3835             ++env;
3836     }
3837 }
3838 
3839 
lsapi_initSuEXEC(void)3840 static int lsapi_initSuEXEC(void)
3841 {
3842     int i;
3843     struct passwd * pw;
3844     s_defaultUid = 0;
3845     s_defaultGid = 0;
3846     if ( s_uid == 0 )
3847     {
3848         const char * p = getenv( "LSAPI_DEFAULT_UID" );
3849         if ( p )
3850         {
3851             i = atoi( p );
3852             if ( i > 0 )
3853                 s_defaultUid = i;
3854         }
3855         p = getenv( "LSAPI_DEFAULT_GID" );
3856         if ( p )
3857         {
3858             i = atoi( p );
3859             if ( i > 0 )
3860                 s_defaultGid = i;
3861         }
3862         p = getenv( "LSAPI_SECRET" );
3863         if (( !p )||( readSecret(p) == -1 ))
3864                 return -1;
3865         if ( g_prefork_server )
3866         {
3867             if ( g_prefork_server->m_iMaxChildren < 100 )
3868                 g_prefork_server->m_iMaxChildren = 100;
3869             if ( g_prefork_server->m_iExtraChildren < 1000 )
3870                 g_prefork_server->m_iExtraChildren = 1000;
3871         }
3872     }
3873     if ( !s_defaultUid || !s_defaultGid )
3874     {
3875         pw = getpwnam( "nobody" );
3876         if ( pw )
3877         {
3878             if ( !s_defaultUid )
3879                 s_defaultUid = pw->pw_uid;
3880             if ( !s_defaultGid )
3881                 s_defaultGid = pw->pw_gid;
3882         }
3883         else
3884         {
3885             if ( !s_defaultUid )
3886                 s_defaultUid = 10000;
3887             if ( !s_defaultGid )
3888                 s_defaultGid = 10000;
3889         }
3890     }
3891     return 0;
3892 }
3893 
3894 
lsapi_check_path(const char * p,char * final,int max_len)3895 static int lsapi_check_path(const char *p, char *final, int max_len)
3896 {
3897     char resolved_path[PATH_MAX+1];
3898     int len = 0;
3899     char *end;
3900     if (*p != '/')
3901     {
3902         if (getcwd(final, max_len) == NULL)
3903             return -1;
3904         len = strlen(final);
3905         *(final + len) = '/';
3906         ++len;
3907     }
3908     end = memccpy(&final[len], p, '\0', PATH_MAX - len);
3909     if (!end)
3910     {
3911         errno = EINVAL;
3912         return -1;
3913     }
3914     p = final;
3915     if (realpath(p, resolved_path) == NULL
3916         && errno != ENOENT && errno != EACCES)
3917         return -1;
3918     if (strncmp(resolved_path, "/etc/", 5) == 0)
3919     {
3920         errno = EPERM;
3921         return -1;
3922     }
3923     return 0;
3924 }
3925 
3926 
lsapi_reopen_stderr2(const char * full_path)3927 static int lsapi_reopen_stderr2(const char *full_path)
3928 {
3929     int newfd = open(full_path, O_WRONLY | O_CREAT | O_APPEND, 0644);
3930     if (newfd == -1)
3931     {
3932         LSAPI_perror_r(NULL, "Failed to open custom stderr log", full_path);
3933         return -1;
3934     }
3935     if (newfd != 2)
3936     {
3937         dup2(newfd, 2);
3938         close(newfd);
3939         dup2(2, 1);
3940     }
3941     if (s_stderr_log_path && full_path != s_stderr_log_path)
3942     {
3943         free(s_stderr_log_path);
3944         s_stderr_log_path = NULL;
3945     }
3946     s_stderr_log_path = strdup(full_path);
3947     return 0;
3948 }
3949 
3950 
lsapi_reopen_stderr(const char * p)3951 static int lsapi_reopen_stderr(const char *p)
3952 {
3953     char full_path[PATH_MAX];
3954     if (s_uid == 0)
3955         return -1;
3956     if (lsapi_check_path(p, full_path, PATH_MAX) == -1)
3957     {
3958         LSAPI_perror_r(NULL, "Invalid custom stderr log path", p);
3959         return -1;
3960     }
3961     return lsapi_reopen_stderr2(full_path);
3962 }
3963 
3964 
LSAPI_Init_Env_Parameters(fn_select_t fp)3965 int LSAPI_Init_Env_Parameters( fn_select_t fp )
3966 {
3967     const char *p;
3968     char ch;
3969     int n;
3970     int avoidFork = 0;
3971 
3972     p = getenv("LSAPI_STDERR_LOG");
3973     if (p)
3974     {
3975         lsapi_reopen_stderr(p);
3976     }
3977     if (!s_stderr_log_path)
3978         s_stderr_is_pipe = isPipe(STDERR_FILENO);
3979 
3980     p = getenv( "PHP_LSAPI_MAX_REQUESTS" );
3981     if ( !p )
3982         p = getenv( "LSAPI_MAX_REQS" );
3983     if ( p )
3984     {
3985         n = atoi( p );
3986         if ( n > 0 )
3987             LSAPI_Set_Max_Reqs( n );
3988     }
3989 
3990     p = getenv( "LSAPI_KEEP_LISTEN" );
3991     if ( p )
3992     {
3993         n = atoi( p );
3994         s_keep_listener = n;
3995     }
3996 
3997     p = getenv( "LSAPI_AVOID_FORK" );
3998     if ( p )
3999     {
4000         avoidFork = atoi( p );
4001         if (avoidFork)
4002         {
4003             s_keep_listener = 2;
4004             ch = *(p + strlen(p) - 1);
4005             if (  ch == 'G' || ch == 'g' )
4006                 avoidFork *= 1024 * 1024 * 1024;
4007             else if (  ch == 'M' || ch == 'm' )
4008                 avoidFork *= 1024 * 1024;
4009             if (avoidFork >= 1024 * 10240)
4010                 s_min_avail_pages = avoidFork / 4096;
4011         }
4012     }
4013 
4014     p = getenv( "LSAPI_ACCEPT_NOTIFY" );
4015     if ( p )
4016     {
4017         s_accept_notify = atoi( p );
4018     }
4019 
4020     p = getenv( "LSAPI_SLOW_REQ_MSECS" );
4021     if ( p )
4022     {
4023         n = atoi( p );
4024         LSAPI_Set_Slow_Req_Msecs( n );
4025     }
4026 
4027 #if defined( RLIMIT_CORE )
4028     p = getenv( "LSAPI_ALLOW_CORE_DUMP" );
4029     if ( !p )
4030     {
4031         struct rlimit limit = { 0, 0 };
4032         setrlimit( RLIMIT_CORE, &limit );
4033     }
4034     else
4035         s_enable_core_dump = 1;
4036 
4037 #endif
4038 
4039     p = getenv( "LSAPI_MAX_IDLE" );
4040     if ( p )
4041     {
4042         n = atoi( p );
4043         LSAPI_Set_Max_Idle( n );
4044     }
4045 
4046     if ( LSAPI_Is_Listen() )
4047     {
4048         n = 0;
4049         p = getenv( "PHP_LSAPI_CHILDREN" );
4050         if ( !p )
4051             p = getenv( "LSAPI_CHILDREN" );
4052         if ( p )
4053             n = atoi( p );
4054         if ( n > 1 )
4055         {
4056             LSAPI_Init_Prefork_Server( n, fp, avoidFork != 0 );
4057             LSAPI_Set_Server_fd( g_req.m_fdListen );
4058         }
4059 
4060         p = getenv( "LSAPI_EXTRA_CHILDREN" );
4061         if ( p )
4062             LSAPI_Set_Extra_Children( atoi( p ) );
4063 
4064         p = getenv( "LSAPI_MAX_IDLE_CHILDREN" );
4065         if ( p )
4066             LSAPI_Set_Max_Idle_Children( atoi( p ) );
4067 
4068         p = getenv( "LSAPI_PGRP_MAX_IDLE" );
4069         if ( p )
4070         {
4071             LSAPI_Set_Server_Max_Idle_Secs( atoi( p ) );
4072         }
4073 
4074         p = getenv( "LSAPI_MAX_PROCESS_TIME" );
4075         if ( p )
4076             LSAPI_Set_Max_Process_Time( atoi( p ) );
4077 
4078         if ( getenv( "LSAPI_PPID_NO_CHECK" ) )
4079         {
4080             LSAPI_No_Check_ppid();
4081         }
4082 
4083         p = getenv("LSAPI_MAX_BUSY_WORKER");
4084         if (p)
4085         {
4086             n = atoi(p);
4087             s_max_busy_workers = n;
4088             if (n >= 0)
4089                 LSAPI_No_Check_ppid();
4090         }
4091 
4092 
4093         p = getenv( "LSAPI_DUMP_DEBUG_INFO" );
4094         if ( p )
4095             s_dump_debug_info = atoi( p );
4096 
4097         if ( lsapi_initSuEXEC() == -1 )
4098             return -1;
4099 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
4100         lsapi_initLVE();
4101 #endif
4102     }
4103     unset_lsapi_envs();
4104     return 0;
4105 }
4106 
4107 
LSAPI_ErrResponse_r(LSAPI_Request * pReq,int code,const char ** pRespHeaders,const char * pBody,int bodyLen)4108 int LSAPI_ErrResponse_r( LSAPI_Request * pReq, int code, const char ** pRespHeaders,
4109                          const char * pBody, int bodyLen )
4110 {
4111     LSAPI_SetRespStatus_r( pReq, code );
4112     if ( pRespHeaders )
4113     {
4114         while( *pRespHeaders )
4115         {
4116             LSAPI_AppendRespHeader_r( pReq, *pRespHeaders, strlen( *pRespHeaders ) );
4117             ++pRespHeaders;
4118         }
4119     }
4120     if ( pBody &&( bodyLen > 0 ))
4121     {
4122         LSAPI_Write_r( pReq, pBody, bodyLen );
4123     }
4124     LSAPI_Finish_r( pReq );
4125     return 0;
4126 }
4127 
4128 
4129 static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16]);
4130 
4131 /*
4132  * Note: this code is harmless on little-endian machines.
4133  */
byteReverse(unsigned char * buf,unsigned longs)4134 static void byteReverse(unsigned char *buf, unsigned longs)
4135 {
4136     uint32 t;
4137     do {
4138         t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
4139             ((unsigned) buf[1] << 8 | buf[0]);
4140         *(uint32 *) buf = t;
4141         buf += 4;
4142     } while (--longs);
4143 }
4144 
4145 
4146 /*
4147  * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
4148  * initialization constants.
4149  */
lsapi_MD5Init(struct lsapi_MD5Context * ctx)4150 void lsapi_MD5Init(struct lsapi_MD5Context *ctx)
4151 {
4152     ctx->buf[0] = 0x67452301;
4153     ctx->buf[1] = 0xefcdab89;
4154     ctx->buf[2] = 0x98badcfe;
4155     ctx->buf[3] = 0x10325476;
4156 
4157     ctx->bits[0] = 0;
4158     ctx->bits[1] = 0;
4159 }
4160 
4161 /*
4162  * Update context to reflect the concatenation of another buffer full
4163  * of bytes.
4164  */
lsapi_MD5Update(struct lsapi_MD5Context * ctx,unsigned char const * buf,unsigned len)4165 void lsapi_MD5Update(struct lsapi_MD5Context *ctx, unsigned char const *buf, unsigned len)
4166 {
4167     register uint32 t;
4168 
4169     /* Update bitcount */
4170 
4171     t = ctx->bits[0];
4172     if ((ctx->bits[0] = t + ((uint32) len << 3)) < t)
4173         ctx->bits[1]++;                /* Carry from low to high */
4174     ctx->bits[1] += len >> 29;
4175 
4176     t = (t >> 3) & 0x3f;        /* Bytes already in shsInfo->data */
4177 
4178     /* Handle any leading odd-sized chunks */
4179 
4180     if (t) {
4181         unsigned char *p = (unsigned char *) ctx->in + t;
4182 
4183         t = 64 - t;
4184         if (len < t) {
4185             memmove(p, buf, len);
4186             return;
4187         }
4188         memmove(p, buf, t);
4189         byteReverse(ctx->in, 16);
4190         lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
4191         buf += t;
4192         len -= t;
4193     }
4194     /* Process data in 64-byte chunks */
4195 
4196     while (len >= 64) {
4197         memmove(ctx->in, buf, 64);
4198         byteReverse(ctx->in, 16);
4199         lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
4200         buf += 64;
4201         len -= 64;
4202     }
4203 
4204     /* Handle any remaining bytes of data. */
4205 
4206     memmove(ctx->in, buf, len);
4207 }
4208 
4209 
4210 /*
4211  * Final wrap-up - pad to 64-byte boundary with the bit pattern
4212  * 1 0* (64-bit count of bits processed, MSB-first)
4213  */
lsapi_MD5Final(unsigned char digest[16],struct lsapi_MD5Context * ctx)4214 void lsapi_MD5Final(unsigned char digest[16], struct lsapi_MD5Context *ctx)
4215 {
4216     unsigned int count;
4217     unsigned char *p;
4218 
4219     /* Compute number of bytes mod 64 */
4220     count = (ctx->bits[0] >> 3) & 0x3F;
4221 
4222     /* Set the first char of padding to 0x80.  This is safe since there is
4223        always at least one byte free */
4224     p = ctx->in + count;
4225     *p++ = 0x80;
4226 
4227     /* Bytes of padding needed to make 64 bytes */
4228     count = 64 - 1 - count;
4229 
4230     /* Pad out to 56 mod 64 */
4231     if (count < 8) {
4232         /* Two lots of padding:  Pad the first block to 64 bytes */
4233         memset(p, 0, count);
4234         byteReverse(ctx->in, 16);
4235         lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
4236 
4237         /* Now fill the next block with 56 bytes */
4238         memset(ctx->in, 0, 56);
4239     } else {
4240         /* Pad block to 56 bytes */
4241         memset(p, 0, count - 8);
4242     }
4243     byteReverse(ctx->in, 14);
4244 
4245     /* Append length in bits and transform */
4246     ((uint32 *) ctx->in)[14] = ctx->bits[0];
4247     ((uint32 *) ctx->in)[15] = ctx->bits[1];
4248 
4249     lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
4250     byteReverse((unsigned char *) ctx->buf, 4);
4251     memmove(digest, ctx->buf, 16);
4252     memset(ctx, 0, sizeof(*ctx));        /* In case it's sensitive */
4253 }
4254 
4255 
4256 /* The four core functions - F1 is optimized somewhat */
4257 
4258 /* #define F1(x, y, z) (x & y | ~x & z) */
4259 #define F1(x, y, z) (z ^ (x & (y ^ z)))
4260 #define F2(x, y, z) F1(z, x, y)
4261 #define F3(x, y, z) (x ^ y ^ z)
4262 #define F4(x, y, z) (y ^ (x | ~z))
4263 
4264 /* This is the central step in the MD5 algorithm. */
4265 #define MD5STEP(f, w, x, y, z, data, s) \
4266         ( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
4267 
4268 /*
4269  * The core of the MD5 algorithm, this alters an existing MD5 hash to
4270  * reflect the addition of 16 longwords of new data.  MD5Update blocks
4271  * the data and converts bytes into longwords for this routine.
4272  */
lsapi_MD5Transform(uint32 buf[4],uint32 const in[16])4273 static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16])
4274 {
4275     register uint32 a, b, c, d;
4276 
4277     a = buf[0];
4278     b = buf[1];
4279     c = buf[2];
4280     d = buf[3];
4281 
4282     MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
4283     MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
4284     MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
4285     MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
4286     MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
4287     MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
4288     MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
4289     MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
4290     MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
4291     MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
4292     MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
4293     MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
4294     MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
4295     MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
4296     MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
4297     MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
4298 
4299     MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
4300     MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
4301     MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
4302     MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
4303     MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
4304     MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
4305     MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
4306     MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
4307     MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
4308     MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
4309     MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
4310     MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
4311     MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
4312     MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
4313     MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
4314     MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
4315 
4316     MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
4317     MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
4318     MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
4319     MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
4320     MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
4321     MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
4322     MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
4323     MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
4324     MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
4325     MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
4326     MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
4327     MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
4328     MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
4329     MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
4330     MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
4331     MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
4332 
4333     MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
4334     MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
4335     MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
4336     MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
4337     MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
4338     MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
4339     MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
4340     MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
4341     MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
4342     MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
4343     MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
4344     MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
4345     MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
4346     MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
4347     MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
4348     MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
4349 
4350     buf[0] += a;
4351     buf[1] += b;
4352     buf[2] += c;
4353     buf[3] += d;
4354 }
4355 
4356 
LSAPI_Set_Restored_Parent_Pid(int pid)4357 int LSAPI_Set_Restored_Parent_Pid(int pid)
4358 {
4359     int old_ppid = s_ppid;
4360     s_restored_ppid = pid;
4361     return old_ppid;
4362 }
4363 
4364 
LSAPI_Inc_Req_Processed(int cnt)4365 int LSAPI_Inc_Req_Processed(int cnt)
4366 {
4367     return __atomic_add_fetch(s_global_counter, cnt, __ATOMIC_SEQ_CST);
4368 }
4369