Exemplo n.º 1
0
static size_t pantheios_getHostName_body_(pan_char_t* buffer, size_t cchBuffer)
{
#if defined(PLATFORMSTL_OS_IS_UNIX)

    if(0 == cchBuffer)
    {
        errno = ENAMETOOLONG;

        return 0;
    }
    else
    {
        int res;

        PANTHEIOS_CONTRACT_ENFORCE_ASSUMPTION(NULL != buffer);

        /* First, we mark the last available character in the buffer with
         * the nul terminator, to test later
         */
        buffer[cchBuffer - 1] = '\0';

        errno = 0;

        res = gethostname(&buffer[0], cchBuffer);

        /* Test for ENAMETOOLONG, to avoid any implementation-dependent
         * behaviour wrt whether this it is set on a 0 or a -1 return
         */
        if(ENAMETOOLONG == errno)
        {
            /* To homogenise platform behaviour, we ensure that no fragment is filled out */
            buffer[0] = '\0';

            return cchBuffer;
        }
        else
        {
            if(0 != res)
            {
                /* Was a failure, so return 0 */
                return 0;
            }
            else if('\0' != buffer[cchBuffer - 1])
            {
                /* Was insufficient buffer, so we return the given size (which is the
                 * failure indicator for that condition
                 *
                 * Also, to homogenise platform behaviour, we ensure that no fragment
                 * of the buffer is returned as filled out.
                 */
                buffer[0] = '\0';

                return cchBuffer;
            }
            else
            {
                /* Buffer was sufficient, and the value has been written. The only
                 * way to return the length is to do strlen on it
                 */

                return pan_strlen_(buffer);
            }
        }
    }

#elif defined(PLATFORMSTL_OS_IS_WINDOWS)

    DWORD cchSize = stlsoft_static_cast(DWORD, cchBuffer);

    if(!pan_GetComputerName_(&buffer[0], &cchSize))
    {
        DWORD   err = GetLastError();

        if(ERROR_BUFFER_OVERFLOW == err)
        {
            return cchBuffer;
        }
        else
        {
            return 0;
        }
    }
    else
    {
        return cchSize;
    }

#else /* ? PLATFORMSTL_OS_IS_???? */
# error Platform not discriminated
#endif /* PLATFORMSTL_OS_IS_???? */
}
Exemplo n.º 2
0
static int pantheios_be_WindowsSyslog_init_a_(
    char const*                         processIdentity
,   int                                 id
,   pan_be_WindowsSyslog_init_t const*  init
,   void*                               reserved
,   void**                              ptoken
)
{
    WindowsSysLog_Context* ctxt = static_cast<WindowsSysLog_Context*>(::calloc(1, sizeof(WindowsSysLog_Context)));

    PANTHEIOS_CONTRACT_ENFORCE_PRECONDITION_PARAMS_API(NULL != processIdentity, "process identity may not be the null string");
    PANTHEIOS_CONTRACT_ENFORCE_PRECONDITION_PARAMS_API('\0' != 0[processIdentity], "process identity may not be the empty string");
    STLSOFT_SUPPRESS_UNUSED(reserved);
    PANTHEIOS_CONTRACT_ENFORCE_PRECONDITION_PARAMS_API(NULL != ptoken, "token pointer may not be null");

    *ptoken = NULL;

    if(NULL == ctxt)
    {
        return PANTHEIOS_INIT_RC_OUT_OF_MEMORY;
    }
    else if(NULL != ::strpbrk(processIdentity, " \t\r\n\b\v"))
    {
        return PANTHEIOS_BE_INIT_RC_INVALID_PROCESSID;
    }
    else
    {
        WSADATA                     wsadata;
        pan_be_WindowsSyslog_init_t init_;
        struct sockaddr_in          addr_in;
        const unsigned long         ADDR_BROADCAST  =   INADDR_BROADCAST;
        BOOL                        bBroadcast      =   TRUE;

        if(0 != ::WSAStartup(0x0202, &wsadata))
        {
            goto error_startup;
        }

        /* (i) apply Null Object (Variable) pattern */

        if(NULL == init)
        {
            pantheios_be_WindowsSyslog_getDefaultAppInit(&init_);

#ifdef PANTHEIOS_BE_USE_CALLBACK
            pantheios_be_WindowsSyslog_getAppInit(id, &init_);
#endif /* PANTHEIOS_BE_USE_CALLBACK */

            init = &init_;
        }

        ctxt->id    =   id;
        ctxt->flags =   init->flags;

        memset(&addr_in, 0, sizeof(addr_in));
        if( 0 == init->addrSize &&
            NULL != init->hostName)
        {
            unsigned long   addr = ::inet_addr(init->hostName);
            struct hostent* he;

            if( INADDR_BROADCAST == addr &&
                0 != ::strcmp(init->hostName, "255.255.255.255") &&
                NULL != (he = ::gethostbyname(init->hostName)))
            {
                memcpy(&addr_in.sin_addr, he->h_addr, he->h_length);
            }
            else
            {
                memcpy(&addr_in.sin_addr, &addr, sizeof(addr));
            }
        }
        else
        {
            switch(init->addrSize)
            {
                case    16:
                default:
                    OutputDebugStringA("Invalid/unsupported address size: currently only 4 (IPv4) is supported\n");
                    memcpy(&addr_in.sin_addr, &ADDR_BROADCAST, sizeof(ADDR_BROADCAST));
                    break;
                case    4:
                    addr_in.sin_addr.S_un.S_un_b.s_b1   =   init->bytes[0];
                    addr_in.sin_addr.S_un.S_un_b.s_b2   =   init->bytes[1];
                    addr_in.sin_addr.S_un.S_un_b.s_b3   =   init->bytes[2];
                    addr_in.sin_addr.S_un.S_un_b.s_b4   =   init->bytes[3];

                    if(addr_in.sin_addr.s_addr != 0xffffffff)
                    {
                        bBroadcast = FALSE;
                    }
                    break;
            }
        }
        addr_in.sin_family  =   AF_INET;
        addr_in.sin_port    =   ::htons(init->port);

        ctxt->sk = ::socket(AF_INET, SOCK_DGRAM, 0);
        if(stlsoft_static_cast(SOCKET, SOCKET_ERROR) == ctxt->sk)
        {
            goto error_sock;
        }

        ctxt->processIdentity       =   pantheios_util_strdup_nothrow_m(processIdentity);
        if(NULL == ctxt->processIdentity)
        {
            goto error_procId;
        }
        ctxt->cchProcessIdentity    =   ::strlen(ctxt->processIdentity);

        ctxt->hostIdentity          =   pan_make_hostIdentity_();
        if(NULL == ctxt->hostIdentity)
        {
            goto error_hostId;
        }
        ctxt->cchHostIdentity       =   ::strlen(ctxt->hostIdentity);

        if(bBroadcast)
        {
            ::setsockopt(ctxt->sk, SOL_SOCKET, SO_BROADCAST, (char const*)&bBroadcast, sizeof(bBroadcast));
        }

        if(SOCKET_ERROR == ::connect(ctxt->sk, (struct sockaddr const*)&addr_in, sizeof(addr_in)))
        {
            goto error_connect;
        }

        ctxt->facility              =   static_cast<unsigned char>(init->facility % 124);   // Any more than 124 will overflow priority of <999>

        *ptoken = ctxt;

        return PANTHEIOS_INIT_RC_SUCCESS;

// NOTE: This goto lark is a vestige of the original C implementation.

error_connect:
        pantheios_util_strfree_m(ctxt->hostIdentity);
error_hostId:
        pantheios_util_strfree_m(ctxt->processIdentity);
error_procId:
        ::closesocket(ctxt->sk);
error_sock:
        ::WSACleanup();
error_startup:
        ::free(ctxt);
        return PANTHEIOS_INIT_RC_UNSPECIFIED_FAILURE;
    }
}