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