adtools/clib2

View on GitHub
library/systeminfo_sysinfo.c

Summary

Maintainability
Test Coverage
/*
 * $Id: systeminfo_sysinfo.c,v 1.6 2010-08-20 15:33:36 obarthel Exp $
 *
 * :ts=4
 *
 * Portable ISO 'C' (1994) runtime library for the Amiga computer
 * Copyright (c) 2002-2015 by Olaf Barthel <obarthel (at) gmx.net>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Neither the name of Olaf Barthel nor the names of contributors
 *     may be used to endorse or promote products derived from this
 *     software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <sys/systeminfo.h>
#include <sys/utsname.h>

/****************************************************************************/

/* The following is not part of the ISO 'C' (1994) standard. */

/****************************************************************************/

#if defined(SOCKET_SUPPORT) && !defined(_SOCKET_HEADERS_H)
#include "socket_headers.h"
#endif /* SOCKET_SUPPORT && !_SOCKET_HEADERS_H */

#ifndef    _STDLIB_HEADERS_H
#include "stdlib_headers.h"
#endif /* _STDLIB_HEADERS_H */

/****************************************************************************/

#if !defined(__amigaos4__)
#include <exec/execbase.h>

/* The order here is important. */
static const struct { UWORD flags; char *name; } isanames[] =
{
    /* Apparently there is a 060 card sans FPU, but how to detect it without a LineF exception?
       Perhaps I should see if I can find my old MC68060 manual. */
    {AFF_68060|AFF_68060,    "68060+fpu060 "},
    {AFF_68060|AFF_68060,    "68060+fpu "},
    {AFF_68040|AFF_FPU40,    "68040+fpu040 "},
    {AFF_68040|AFF_68882,    "68040+fpu "},
    {AFF_68040|AFF_68881,    "68040+fpu "},
    {AFF_68040,                "68040 "},
    {AFF_68030|AFF_68882,    "68030+fpu "},
    {AFF_68030|AFF_68881,    "68030+fpu "},
    {AFF_68020|AFF_68882,    "68020+fpu "},
    {AFF_68020|AFF_68881,    "68020+fpu "},
    {AFF_68030,                "68030 "},
    {AFF_68020,                "68020 "},
    {AFF_68010,                "68010 "},
};
#endif /* !__amigaos4__ */

/****************************************************************************/

long
sysinfo(int cmd,char *buf,long buflen)
{
    struct utsname info;
    long ret = -1;
    
    ENTER();
    
    if(buf == NULL)
    {
        __set_errno(EFAULT);
        goto out;
    }
    
    uname(&info); /* Most of the keys use this. */

    switch(cmd)
    {
        case SI_SYSNAME:

            ret = strlcpy(buf,info.sysname,buflen);
            break;

        case SI_HOSTNAME:

            ret = strlcpy(buf,info.nodename,buflen);
            break;

        case SI_SET_HOSTNAME:

            __set_errno(EPERM);
            goto out;

        case SI_RELEASE:

            ret = strlcpy(buf,info.release,buflen);
            break;

        case SI_VERSION:

            ret = strlcpy(buf,info.version,buflen);
            break;

        case SI_MACHINE:

            ret = strlcpy(buf,"amiga",buflen);
            break;

        case SI_ARCHITECTURE:

            ret = strlcpy(buf,info.machine,buflen);
            break;

        case SI_ISALIST:

            #if defined(__amigaos4__)
            {
                /* Solaris uses "ppc" as the isa name, but gcc uses powerpc. "ppc+altivec" follows the
                   convention of specifying isa+ext from Solaris on SPARC machines. This way of implementing
                   SI_ISALIST seemed like a good idea at the time. */
                const char * s;
                uint32 vecu;

                GetCPUInfoTags(GCIT_VectorUnit,&vecu,TAG_DONE);

                if(vecu == VECTORTYPE_ALTIVEC || vecu == 2 /* VECTORTYPE_VMX == 2 */) /* AltiVec and VMX are the same. */
                    s = "ppc+altivec ppc common";
                else
                    s = "ppc common";

                ret = strlcpy(buf,s,buflen);
            }
            #else
            {
                UWORD attention_flags = ((struct ExecBase *)SysBase)->AttnFlags; 
                char * last_added = "";
                size_t i;

                ret = 0;

                strlcpy(buf,"",buflen);

                for(i = 0 ; i < NUM_ENTRIES(isanames) ; i++)
                {
                    if((attention_flags & isanames[i].flags) == isanames[i].flags)
                    {
                        if(strcmp(last_added,isanames[i].name) != SAME)
                        {
                            ret += strlcat(buf,isanames[i].name,buflen);

                            last_added = isanames[i].name;
                        }
                    }
                }

                ret += strlcat(buf,"68000",buflen);
            }
            #endif

            break;

        case SI_PLATFORM:    /* TODO: Figure out a good way of checking this. */

            ret = strlcpy(buf,"Amiga,Unknown",buflen);
            break;

        case SI_HW_PROVIDER:    /* TODO: Figure out a good way of checking this. */

            ret = strlcpy(buf,"Unknown",buflen);
            break;

        case SI_HW_SERIAL:

            #if defined(SOCKET_SUPPORT)
            {
                ret = snprintf(buf,buflen,"%lu",gethostid());
            }
            #else
            {
                ret = strlcpy(buf,"0",buflen);
            }
            #endif

            break;

        default:

            __set_errno(EINVAL);
            goto out;
    }
    
 out:
    
    RETURN(ret);
    return(ret);
}