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