User Tools

Site Tools


Differences

This shows you the differences between two versions of the page.

Link to this comparison view

c:m5dc [2019-05-28 15:26]
c:m5dc [2020-02-15 00:57] (current)
Line 1: Line 1:
 +
 +=====Pure C Web/​PostgreSQL service checker===
 +
 +I wrote it for support "some big corporate application"​. ​
 +
 +"Pure C" for portability. ​
 +
 +====Out sample====
 +
 +<​file>​
 +# m5dc.exe ​                                                                                                      
 +2019-02-25 11:52:10 UTC ######## THE BEGIN ########
 +                                                                  ​
 +2019-02-25 11:52:10 UTC ##############################​
 +2019-02-25 11:52:10 UTC start checking: traceroute for host web.xxxxx.lazurit.us ​                                      
 +2019-02-25 11:52:11 UTC good: host web.ost.lazurit.us have ipv4 address 172.17.8.124 ​                                
 +2019-02-25 11:52:11 UTC good: ttl= 1 icmp type 11 from 192.168.xxxx ​                                                 ​
 +2019-02-25 11:52:11 UTC good: ttl= 2 icmp type 11 from 192.168.xxxx ​                                                
 +2019-02-25 11:52:11 UTC good: ttl= 3 icmp type 11 from 10.xxxxx ​                                                  
 +2019-02-25 11:52:11 UTC good: ttl= 4 icmp type 11 from 10.xxxxx ​                                                 ​
 +2019-02-25 11:52:11 UTC good: ttl= 5 icmp type 0 from 172.xxxxx ​                                                  
 +2019-02-25 11:52:11 UTC result: ​  type ICMP_ECHOREPLY ​                                                               ​
 +2019-02-25 11:52:11 UTC result: ​  icmp id 1234                                                                       
 +2019-02-25 11:52:12 UTC result: ​  icmp seq 4567                                                                      ​
 +
 +2019-02-25 11:52:12 UTC ############################## ​                                                              
 +2019-02-25 11:52:12 UTC start checking: web connect for host webxxxx.lazurit.us ​                                     ​
 +2019-02-25 11:52:12 UTC good: host webxxxx.lazurit.us have ipv4 address 172.xxxxx
 +2019-02-25 11:52:12 UTC good: connected to 172.xxxxx port 80
 +2019-02-25 11:52:12 UTC good: wrote 143 bytes to 172.xxxxx port 80
 +2019-02-25 11:52:12 UTC good: read 319 bytes from 172.xxxx port 80
 +2019-02-25 11:52:12 UTC result: http responce code: HTTP/1.1 200 OK                                                  ​
 +
 +2019-02-25 11:52:12 UTC ############################## ​                                                              
 +2019-02-25 11:52:13 UTC start checking: traceroute for host pgxxxxx.lazurit.us ​                              
 +2019-02-25 11:52:13 UTC good: host pgdb-mosaic-ost.lazurit.us have ipv4 address 172.xxxxxx ​                        
 +2019-02-25 11:52:13 UTC good: ttl= 1 icmp type 11 from 192.168.xxxxx ​                                                 ​
 +2019-02-25 11:52:13 UTC good: ttl= 2 icmp type 11 from 192.168.xxxxx ​                                                 ​
 +2019-02-25 11:52:13 UTC good: ttl= 3 icmp type 11 from 10.xxxxx ​                                                   ​
 +2019-02-25 11:52:13 UTC good: ttl= 4 icmp type 11 from 10.xxxxx ​                                                 ​
 +2019-02-25 11:52:13 UTC good: ttl= 5 icmp type 0 from 172.xxxxx ​                                                  
 +2019-02-25 11:52:14 UTC result: ​  type ICMP_ECHOREPLY ​                                                               ​
 +2019-02-25 11:52:14 UTC result: ​  icmp id 1234                                                                       
 +2019-02-25 11:52:14 UTC result: ​  icmp seq 4567                                                                      ​
 +
 +2019-02-25 11:52:14 UTC ############################## ​                                                              
 +2019-02-25 11:52:14 UTC start checking: postgreql connect for host pgxxxx.lazurit.us ​                       ​
 +2019-02-25 11:52:14 UTC good: connection to database is successful
 +2019-02-25 11:52:14 UTC good: request SELECT project_guid FROM projects5d LIMIT 5 is successful
 +2019-02-25 11:52:14 UTC result: column 0 have name project_guid
 +2019-02-25 11:52:14 UTC result: 5c609f5a-2857-4720-8273-70a9ccf7d9ee ​                                                
 +2019-02-25 11:52:15 UTC result: b294735a-25f0-4292-aa1c-307dc898af89
 +2019-02-25 11:52:15 UTC result: c6efe350-668f-4784-a632-a9b1c9f1198a
 +2019-02-25 11:52:15 UTC result: a26abf9b-438e-46e2-b917-d147eeab985d
 +2019-02-25 11:52:15 UTC result: aaf27bb2-6d62-4458-baf8-260441a46adb
 +2019-02-25 11:52:15 UTC ######## THE END ######## ​                                                                   ​
 +</​file>​
 +
 +
 +====Code====
 +
 +<code c m5dc.c>
 +/* $Id: m5dc.c,v 1.1 2019/02/20 13:01:37 ziggi Exp ziggi $ */
 +
 +/*
 + * Copyright 2004-2019 Borodin Oleg <​onborodin@gmail.com>​
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License as published by
 + * the Free Software Foundation; either version 2 of the License, or
 + * (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ​ See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 + * MA 02110-1301, USA.
 + */
 +
 +#ifdef __WINNT__
 +#define _WIN32_WINNT 0x0600
 +#endif
 +
 +#include <​stdio.h>​
 +#include <​stdlib.h>​
 +#include <​string.h>​
 +#include <​stdint.h>​
 +#include <​stdarg.h>​
 +#include <​time.h>​
 +#include <​limits.h>​
 +#include <​unistd.h>​
 +
 +#ifdef __WINNT__
 +
 +#include <​sys/​types.h>​
 +#include <​sys/​stat.h>​
 +#include <​winsock2.h>​
 +#include <​ws2tcpip.h>​
 +#include <​pshpack1.h>​
 +
 +#else
 +
 +#include <​sys/​socket.h>​
 +#include <​arpa/​inet.h>​
 +#include <​netinet/​in.h>​
 +#include <​netinet/​ip.h>​
 +#include <​netinet/​ip_icmp.h>​
 +#include <​netdb.h>​
 +
 +#endif
 +
 +#ifdef __WINNT__
 +struct ip {
 +    u_char ip_hl:​4; ​            /* header length */
 +    u_char ip_v:​4; ​             /* version */
 +    u_char ip_tos; ​             /* type of service */
 +    u_short ip_len; ​            /* total length */
 +    u_short ip_id; ​             /* identification */
 +    u_short ip_off; ​            /* fragment offset field */
 +    u_char ip_ttl; ​             /* time to live */
 +    u_char ip_p;                /* protocol */
 +    u_short ip_sum; ​            /* checksum */
 +    struct in_addr ip_src;
 +    struct in_addr ip_dst; ​     /* source and dest address */
 +} __packed;
 +
 +struct icmp {
 +    u_char icmp_type;
 +    u_char icmp_code;
 +    u_short icmp_cksum;
 +
 +    u_short icmp_id;
 +    u_short icmp_seq;
 +};
 +#endif
 +
 +typedef struct ip ip_hdr_t;
 +typedef struct icmp icmp_hdr_t;
 +
 +#define LOG_BUFFER_SIZE 1024
 +
 +void wc_log(const char *fmt, ...) {
 +    char buffer[LOG_BUFFER_SIZE];​
 +    memset(buffer,​ 0, LOG_BUFFER_SIZE);​
 +
 +    time_t rawtime = time(NULL);
 +    struct tm *ptm = gmtime(&​rawtime);​
 +    sprintf(buffer,​ "​%04d-%02d-%02d %02d:​%02d:​%02d UTC ",
 +        ptm->​tm_year + 1900, ptm->​tm_mon + 1, ptm->​tm_mday,​
 +        ptm->​tm_hour,​ ptm->​tm_min,​ ptm->​tm_sec);​
 +
 +    char *record = buffer + strlen(buffer);​
 +
 +    va_list ap;
 +
 +    va_start(ap,​ fmt);
 +    (void) vsnprintf(record,​ LOG_BUFFER_SIZE,​ fmt, ap);
 +    va_end(ap);
 +
 +    printf("​%s",​ buffer);
 +
 +#ifdef __WINNT__
 +    FILE *log;
 +    if ((log = fopen("​c:​\\m5dc.log",​ "​a"​)) == NULL) {
 +        if ((log = fopen("​d:​\\m5dc.log",​ "​a"​)) == NULL) {
 +            printf("​error:​ cannot open log file: %s\n", strerror(errno));​
 +            return;
 +        }
 +    }
 +    fprintf(log,​ "​%s",​ buffer);
 +    fclose(log);​
 +#endif
 +}
 +
 +static const char b64_table[] = {
 +  '​A',​ '​B',​ '​C',​ '​D',​ '​E',​ '​F',​ '​G',​ '​H',​
 +  '​I',​ '​J',​ '​K',​ '​L',​ '​M',​ '​N',​ '​O',​ '​P',​
 +  '​Q',​ '​R',​ '​S',​ '​T',​ '​U',​ '​V',​ '​W',​ '​X',​
 +  '​Y',​ '​Z',​ '​a',​ '​b',​ '​c',​ '​d',​ '​e',​ '​f',​
 +  '​g',​ '​h',​ '​i',​ '​j',​ '​k',​ '​l',​ '​m',​ '​n',​
 +  '​o',​ '​p',​ '​q',​ '​r',​ '​s',​ '​t',​ '​u',​ '​v',​
 +  '​w',​ '​x',​ '​y',​ '​z',​ '​0',​ '​1',​ '​2',​ '​3',​
 +  '​4',​ '​5',​ '​6',​ '​7',​ '​8',​ '​9',​ '​+',​ '/'​
 +};
 +
 +char *b64_encode(const unsigned char *src, size_t len) {
 +    int i = 0;
 +    int j = 0;
 +    char *enc = NULL;
 +    size_t size = 0;
 +    unsigned char buf[4];
 +    unsigned char tmp[3];
 +
 +    enc = (char *)malloc(1);​
 +    if (NULL == enc) {
 +        return NULL;
 +    }
 +
 +    while (len--) {
 +        tmp[i++] = *(src++);
 +        if (3 == i) {
 +            buf[0] = (tmp[0] & 0xfc) >> 2;
 +            buf[1] = ((tmp[0] & 0x03) << 4) + ((tmp[1] & 0xf0) >> 4);
 +            buf[2] = ((tmp[1] & 0x0f) << 2) + ((tmp[2] & 0xc0) >> 6);
 +            buf[3] = tmp[2] & 0x3f;
 +
 +            enc = (char *)realloc(enc,​ size + 4);
 +            for (i = 0; i < 4; ++i) {
 +                enc[size++] = b64_table[buf[i]];​
 +            }
 +            i = 0;
 +        }
 +    }
 +    if (i > 0) {
 +
 +        for (j = i; j < 3; ++j) {
 +            tmp[j] = '​\0';​
 +        }
 +        buf[0] = (tmp[0] & 0xfc) >> 2;
 +        buf[1] = ((tmp[0] & 0x03) << 4) + ((tmp[1] & 0xf0) >> 4);
 +        buf[2] = ((tmp[1] & 0x0f) << 2) + ((tmp[2] & 0xc0) >> 6);
 +        buf[3] = tmp[2] & 0x3f;
 +
 +        for (j = 0; (j < i + 1); ++j) {
 +            enc = (char *)realloc(enc,​ size + 1);
 +            enc[size++] = b64_table[buf[j]];​
 +        }
 +
 +        while ((i++ < 3)) {
 +            enc = (char *)realloc(enc,​ size + 1);
 +            enc[size++] = '​=';​
 +        }
 +    }
 +    enc = (char *)realloc(enc,​ size + 1);
 +    enc[size] = '​\0';​
 +
 +    return enc;
 +}
 +
 +uint16_t icmpv4_checksum(const uint16_t * const data, const size_t byte_sz) {
 +    if (0 != (byte_sz & 1)) {
 +        fprintf(stderr,​ "# wrong number of bytes %u must be even", (int)byte_sz);​
 +    }
 +    uint32_t accu = 0;
 +    for (size_t i = 0; i < (byte_sz >> 1); ++i) {
 +        accu = accu + data[i];
 +    }
 +    while (accu >> 16) {
 +        accu = (accu & 0xffff) + (accu >> 16);
 +    }
 +    const uint16_t checksum = ~accu;
 +    return checksum;
 +}
 +
 +
 +int __exit(void) {
 +#ifdef __WINNT__
 +    WSACleanup();​
 +#endif
 +    exit(1);
 +}
 +
 +void wc_close(int sock) {
 +#ifdef __WINNT__
 +    shutdown(sock,​ SD_BOTH);
 +#else
 +    shutdown(sock,​ SHUT_RDWR);
 +#endif
 +    close(sock);​
 +}
 +
 +struct sockaddr_in * wc_resolve(const char *hostname) {
 +
 +    struct addrinfo hints;
 +    memset(&​hints,​ 0, sizeof(hints));​
 +
 +    hints.ai_family = AF_INET;
 +    hints.ai_socktype = SOCK_STREAM;​
 +    hints.ai_protocol = IPPROTO_TCP;​
 +
 +    struct addrinfo *result = NULL;
 +
 +    int retval;
 +    if ((retval = getaddrinfo(hostname,​ NULL, &hints, &​result)) != 0) {
 +        wc_log("​error:​ getaddrinfo() failed with error: %d\n", retval);
 +        __exit();
 +    }
 +
 +    struct sockaddr_in *sockaddr = NULL;
 +
 +    for (struct addrinfo * ptr = result; ptr != NULL; ptr = ptr->​ai_next) {
 +        switch (ptr->​ai_family) {
 +            case AF_INET:
 +                sockaddr = (struct sockaddr_in *)ptr->​ai_addr;​
 +                wc_log("​good:​ host %s have ipv4 address %s\n", hostname, inet_ntoa(sockaddr->​sin_addr));​
 +                break;
 +            default:
 +                break;
 +        }
 +        if (sockaddr != NULL) {
 +            break;
 +        }
 +    }
 +
 +    struct sockaddr_in *dest_sockaddr = NULL;
 +    if ((dest_sockaddr = malloc(sizeof(struct sockaddr))) == NULL) {
 +        wc_log("​error:​ cannot allocate memory for address\n"​);​
 +        return NULL;
 +    }
 +    memset(dest_sockaddr,​ 0, sizeof(struct sockaddr));
 +    memcpy(dest_sockaddr,​ sockaddr, sizeof(struct sockaddr_in));​
 +
 +    freeaddrinfo(result);​
 +    return dest_sockaddr;​
 +}
 +
 +#define SOCKET_ERROR (-1)
 +
 +#define PAYLOAD_LEN 4
 +#define OBUFFER_SIZE sizeof(icmp_hdr_t) + PAYLOAD_LEN
 +
 +#define ICMP_ECHOREPLY 0
 +#define ICMP_ECHO 8
 +#define ICMP_CODE 0
 +#define MAX_TTL 10
 +
 +#define ICMP_IBUFFER_SIZE 204
 +#define SLEEP_TIME 100
 +#define SOCK_TIMEOUT 100
 +#define MAX_COUNT 4
 +
 +void wping(char *hostname) {
 +
 +    wc_log("##############################​\n"​);​
 +
 +    wc_log("​start checking: traceroute for host %s\n", hostname);
 +
 +    struct sockaddr_in *dest_sockaddr;​
 +    if ((dest_sockaddr = wc_resolve(hostname)) == NULL) {
 +        wc_log("​error:​ cannot resolve hostname %s\n", hostname);
 +        return;
 +    }
 +
 +#ifdef __WINNT__
 +    char ttl;
 +#else
 +    int ttl;
 +#endif
 +
 +    for (ttl = 1; ttl < MAX_TTL; ttl++) {
 +        int sock;
 +        if ((sock = socket(AF_INET,​ SOCK_RAW, IPPROTO_ICMP)) < 0) {
 +            wc_log("​error:​ cannot create raw socker\n"​);​
 +            wc_close(sock);​
 +            return;
 +        }
 +
 +        char obuffer[OBUFFER_SIZE];​
 +        memset(obuffer,​ 0, OBUFFER_SIZE);​
 +
 +        icmp_hdr_t *icmp_hdr;
 +        icmp_hdr = (icmp_hdr_t *) obuffer;
 +
 +        icmp_hdr->​icmp_type = ICMP_ECHO;
 +        icmp_hdr->​icmp_code = ICMP_CODE;
 +        icmp_hdr->​icmp_id = htons(1234);​
 +        icmp_hdr->​icmp_cksum = 0;
 +        icmp_hdr->​icmp_seq = htons(4567);​
 +
 +        char *payload = obuffer + sizeof(icmp_hdr_t);​
 +        memset(payload,​ '<',​ PAYLOAD_LEN);​
 +
 +        icmp_hdr->​icmp_cksum = icmpv4_checksum((uint16_t *) obuffer, OBUFFER_SIZE);​
 +
 +#ifdef __WINNT__
 +        if (setsockopt(sock,​ IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)) < 0) {
 +            wc_log("​error:​ setting ttl setsockopt failed\n"​);​
 +            wc_close(sock);​
 +            return;
 +        }
 +#else
 +        if (setsockopt(sock,​ IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)) < 0) {
 +            wc_log("​error:​ setting ttl setsockopt failed\n"​);​
 +            wc_close(sock);​
 +            return;
 +        }
 +#endif
 +        //​wc_log("​debug:​ send ICMP_ECHO with ttl = %d\n", ttl);
 +        if (sendto(sock,​ (char *)obuffer, OBUFFER_SIZE,​ 0, (struct sockaddr *)dest_sockaddr,​ sizeof(struct sockaddr_in)) < 0) {
 +            wc_log("​error:​ sendto failed\n"​);​
 +            wc_close(sock);​
 +            return;
 +        }
 +
 +        char ibuffer[ICMP_IBUFFER_SIZE];​
 +        memset(ibuffer,​ 0, ICMP_IBUFFER_SIZE);​
 +
 +        struct sockaddr_in src_sockaddr;​
 +        memset(&​src_sockaddr,​ 0, sizeof(src_sockaddr));​
 +        socklen_t src_sockaddr_size = sizeof(src_sockaddr);​
 +
 +        int i = 0;
 +
 +        while (i < MAX_COUNT) {
 +            //​wc_log("​debug:​ try icmp read %d\n", i);
 +            i++;
 +#ifdef __WINNT__
 +            int read_timeout = SOCK_TIMEOUT;​
 +            if(setsockopt(sock,​ SOL_SOCKET, SO_RCVTIMEO,​ (const char *)&​read_timeout,​ sizeof(read_timeout)) < 0) {
 +                wc_log("​error:​ set socket option failed\n"​);​
 +                wc_close(sock);​
 +                return;
 +            }
 +            ssize_t res_count = recvfrom(sock,​ (char *)ibuffer, ICMP_IBUFFER_SIZE,​ 0,
 +                                         ​(struct sockaddr *)&​src_sockaddr,​ &​src_sockaddr_size);​
 +#else
 +            ssize_t res_count = recvfrom(sock,​ (char *)ibuffer, ICMP_IBUFFER_SIZE,​ MSG_DONTWAIT,​
 +                                         ​(struct sockaddr *)&​src_sockaddr,​ &​src_sockaddr_size);​
 +#endif
 +            if (res_count > 0) {
 +                ip_hdr_t *ip_hdr = (struct ip *)ibuffer;
 +                size_t ip_header_len = ip_hdr->​ip_hl >> 2;
 +                struct icmp *icmp_header = (struct icmp *)(ip_hdr + ip_header_len);​
 +
 +                wc_log("​good:​ ttl= %d icmp type %d from %s\n", ttl,
 +                       ​icmp_header->​icmp_type,​ inet_ntoa(src_sockaddr.sin_addr));​
 +
 +                if (icmp_header->​icmp_type == ICMP_ECHOREPLY) {
 +                    wc_log("​result: ​  type ICMP_ECHOREPLY\n"​);​
 +                    wc_log("​result: ​  icmp id %d\n", ntohs(icmp_header->​icmp_id));​
 +                    wc_log("​result: ​  icmp seq %d\n", ntohs(icmp_header->​icmp_seq));​
 +                    return;
 +                }
 +                break;
 +            }
 +            if (i == MAX_COUNT) {
 +                wc_log("​warning:​ ttl %d icmp timeout\n",​ ttl);
 +                break;
 +            }
 +#ifdef __WINNT__
 +            Sleep(SLEEP_TIME);​
 +#else
 +            usleep(SLEEP_TIME * 1000);
 +#endif
 +        }
 +        close(sock);​
 +    }
 +}
 +
 +
 +#define MAX_REQ_SIZE 65536
 +#define MAX_RES_SIZE 65536
 +
 +#define IBUFFER_SIZE MAX_RES_SIZE
 +#define WEBC_BUFFER_SIZE MAX_RES_SIZE
 +
 +#define LOGIN_PASSWORD_SIZE_MAX 256
 +#define ENCODED_LOGIN_SIZE_MAX 256
 +#define LOGIN_PASSWORD_DELIM ":"​
 +
 +#include <​errno.h>​
 +
 +void wclient(const char *hostname, int port, char *url, char * login, char *password) {
 +    wc_log("##############################​\n"​);​
 +    wc_log("​start checking: web connect for host %s\n", hostname);
 +
 +    struct sockaddr_in *dest_sockaddr;​
 +    if ((dest_sockaddr = wc_resolve(hostname)) == NULL) {
 +        wc_log("​error:​ cannot resolve hostname %s\n", hostname);
 +        return;
 +    }
 +
 +    int sock;
 +    if ((sock = socket(PF_INET,​ SOCK_STREAM,​ 0)) < 0) {
 +        wc_log("​error:​ cannot create socket\n"​);​
 +        return;
 +    }
 +
 +    dest_sockaddr->​sin_family = AF_INET;
 +    dest_sockaddr->​sin_port = htons(port);​
 +
 +    char *dest_addr_str = inet_ntoa(dest_sockaddr->​sin_addr);​
 +
 +    if (connect(sock,​ (struct sockaddr *)dest_sockaddr,​ sizeof(struct sockaddr_in)) < 0) {
 +        wc_log("​error:​ cannot create connect to %s port %d : %s\n",
 +                    dest_addr_str,​ port, strerror(errno));​
 +        wc_close(sock);​
 +        return;
 +    }
 +    wc_log("​good:​ connected to %s port %d\n", dest_addr_str,​ port);
 +
 +    char obuffer[WEBC_BUFFER_SIZE];​
 +    memset(obuffer,​ 0, WEBC_BUFFER_SIZE);​
 +
 +    strcpy(obuffer,​ "GET ");
 +    strcat(obuffer,​ url);
 +    strcat(obuffer,​ " HTTP/​1.1\n"​);​
 +
 +    strcat(obuffer,​ "Host: ");
 +    strcat(obuffer,​ hostname);
 +    strcat(obuffer,​ "​\n"​);​
 +
 +    strcat(obuffer,​ "​User-Agent:​ WClient/​1.0\n"​);​
 +
 +    char login_password[LOGIN_PASSWORD_SIZE_MAX];​
 +    strcpy(login_password,​ login);
 +    strcat(login_password,​ LOGIN_PASSWORD_DELIM);​
 +    strcat(login_password,​ password);
 +
 +    char *encoded_login = b64_encode((u_char *)login_password,​ strlen(login_password));​
 +    strcat(obuffer,​ "​Authorization:​ Basic ");
 +    strcat(obuffer,​ encoded_login);​
 +    strcat(obuffer,​ "​\n"​);​
 +
 +    free(encoded_login);​
 +    strcat(obuffer,​ "​Accept:​ */​*\n"​);​
 +
 +    strcat(obuffer,​ "​\n"​);​
 +    //​printf("​debug:​ web req buffer: \n%s\n",​ obuffer);
 +
 +    int wc;
 +    if ((wc = send(sock, obuffer, (int)strlen(obuffer),​ 0)) < 0) {
 +        wc_log("​error:​ cannot write data to %s port %d\n", dest_addr_str,​ port);
 +        wc_close(sock);​
 +        return;
 +    }
 +    wc_log("​good:​ wrote %d bytes to %s port %d\n", wc, dest_addr_str,​ port);
 +
 +    int rc;
 +    char ibuffer[WEBC_BUFFER_SIZE];​
 +    memset(ibuffer,​ 0, WEBC_BUFFER_SIZE);​
 +
 +    if ((rc = recv(sock, ibuffer, WEBC_BUFFER_SIZE,​ 0)) < 0) {
 +        wc_log("​error:​ read error from %s port %d\n", dest_addr_str,​ port);
 +    }
 +
 +    if (rc > 0) {
 +        wc_log("​good:​ read %d bytes from %s port %d\n", rc, dest_addr_str,​ port);
 +        char res[WEBC_BUFFER_SIZE];​
 +        memset(res, 0, WEBC_BUFFER_SIZE);​
 +        memcpy(res, ibuffer, WEBC_BUFFER_SIZE);​
 +        char *ptr = strtok(res, "​\n"​);​
 +        while(ptr != NULL) {
 +
 +            if(strstr(ptr,​ "​HTTP/​1.1"​) != NULL) {
 +                wc_log("​result:​ http responce code: %s\n", ptr);
 +                break;
 +            }
 +            //​if(strlen(ptr) < 2) {
 +            //    break;
 +            //}
 +            //​wc_log("# ​   %s\n", ptr);
 +            ptr = strtok(NULL,​ "​\n"​);​
 +        }
 +    }
 +    wc_close(sock);​
 +    return;
 +}
 +
 +#include "​libpq-fe.h"​
 +
 +#define PG_CONNINFO_SIZE 256
 +
 +void pgclient(char *hostname, char *port, char *dbname, char* user, char* password) {
 +
 +    wc_log("##############################​\n"​);​
 +    wc_log("​start checking: postgreql connect for host %s\n", hostname);
 +
 +
 +    char conninfo[PG_CONNINFO_SIZE];​
 +    strcpy(conninfo,​ "​host="​);​
 +    strcat(conninfo,​ hostname);
 +
 +    strcat(conninfo,​ " port="​);​
 +    strcat(conninfo,​ port);
 +
 +    strcat(conninfo,​ " dbname="​);​
 +    strcat(conninfo,​ dbname);
 +    strcat(conninfo,​ " user="​);​
 +    strcat(conninfo,​ user);
 +    strcat(conninfo,​ " password="​);​
 +    strcat(conninfo,​ password);
 +
 +    //​wc_log("​debug:​ pg connect info: %s\n", conninfo);
 +
 +    PGconn *conn = PQconnectdb(conninfo);​
 +
 +    if (PQstatus(conn) != CONNECTION_OK) {
 +        wc_log("​error:​ connection to database failed: %s\n", PQerrorMessage(conn));​
 +        PQfinish(conn);​
 +        return;
 +    } else {
 +        wc_log("​good:​ connection to database is successful\n"​);​
 +    }
 +
 +    const char *req = "​SELECT project_guid FROM projects5d LIMIT 5";
 +    PGresult *res = PQexec(conn,​ req);
 +
 +    if (PQresultStatus(res) != PGRES_TUPLES_OK) {
 +        wc_log("​error:​ request %s failed: %s\n", req, PQerrorMessage(conn));​
 +        PQclear(res);​
 +        PQfinish(conn);​
 +        return;
 +
 +    } else {
 +        wc_log("​good:​ request %s is successful\n",​ req);
 +    }
 +
 +    int nCols = PQnfields(res);​
 +
 +    for (int i = 0; i < nCols; i++) {
 +        char *name = PQfname(res,​ i);
 +        wc_log("​result:​ column %d have name %s\n", i, name);
 +    }
 +
 +    int nRows = PQntuples(res);​
 +    for (int i = 0; i < nRows; i++) {
 +        char *sum = PQgetvalue(res,​ i, 0);
 +        wc_log("​result:​ %s\n", sum);
 +    }
 +
 +    PQclear(res);​
 +    PQfinish(conn);​
 +    return;
 +}
 +
 +#ifndef WEBHOST
 +#define WEBHOST "​webxxxxxxx"​
 +#endif
 +
 +#ifndef WEBPORT
 +#define WEBPORT 80
 +#endif
 +
 +#ifndef WEBURL
 +#define WEBURL "/​xxxxx"​
 +#endif
 +
 +#ifndef WEBLOGIN
 +#define WEBLOGIN "​xxxxx"​
 +#endif
 +
 +#ifndef WEBPASSWORD
 +#define WEBPASSWORD "​xxxxxx"​
 +#endif
 +
 +#ifndef PGHOST
 +#define PGHOST "​xxxxxxx"​
 +#endif
 +
 +#ifndef PGPORT
 +#define PGPORT "​5432"​
 +#endif
 +
 +#ifndef DBNAME
 +#define DBNAME "​xxxxxxx"​
 +#endif
 +
 +#ifndef PGUSER
 +#define PGUSER "​xxxxxx"​
 +#endif
 +
 +#ifndef PGPASSWORD
 +#define PGPASSWORD "​xxxxxxxx"​
 +#endif
 +
 +int main(int argc, char **argv) {
 +
 +    wc_log("########​ THE BEGIN ########​\n"​);​
 +
 +#ifdef __WINNT__
 +    WSADATA wsaData;
 +
 +#define WSVERSION 0x0202
 +    int iResult = WSAStartup(WSVERSION,​ &​wsaData);​
 +    if (iResult != 0) {
 +        wc_log("​error:​ wsastartup() failed: %d\n", iResult);
 +        exit(1);
 +    }
 +#endif
 +
 +    wping(WEBHOST);​
 +    wclient(WEBHOST,​ WEBPORT, WEBURL, WEBLOGIN, WEBPASSWORD);​
 +
 +    wping(PGHOST);​
 +    pgclient(PGHOST,​ PGPORT, DBNAME, PGUSER, PGPASSWORD);​
 +
 +    wc_log("########​ THE END ########​\n\n"​);​
 +
 +#ifdef __WINNT__
 +    WSACleanup();​
 +    printf("​\nthe programm will sleep 30 sec\n"​);​
 +    Sleep(30 * 1000);
 +#endif
 +}
 +</​code>​
 +
 +----
 +[<>]