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