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