mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
This commit fixes a bug in the ksh uname builtin's -d option that could
change the output of -o (I was only able to reproduce this on Linux):
$ builtin uname
$ uname -o
GNU/Linux
$ uname -d
(none)
$ uname -o
(none)
I identified this patch from ksh2020 as a fix for this bug:
<https://github.com/att/ast/pull/1187>
The linked patch was meant to fix a crash in 'uname -d', although I've
had no luck reproducing it: <https://github.com/att/ast/issues/1184>
src/lib/libcmd/uname.c:
- Pass correct buffer to getdomainname() while executing uname -d.
src/cmd/ksh93/tests/builtins.sh:
- Add a regression test for the reported 'uname -d' crash.
- Add a regression test for the output of 'uname -o' after 'uname -d'.
- To handle potential crashes when running the regression tests in older
versions of ksh, fork the command substitutions that run 'uname -d'.
562 lines
13 KiB
C
562 lines
13 KiB
C
/***********************************************************************
|
|
* *
|
|
* This software is part of the ast package *
|
|
* Copyright (c) 1992-2012 AT&T Intellectual Property *
|
|
* and is licensed under the *
|
|
* Eclipse Public License, Version 1.0 *
|
|
* by AT&T Intellectual Property *
|
|
* *
|
|
* A copy of the License is available at *
|
|
* http://www.eclipse.org/org/documents/epl-v10.html *
|
|
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
|
|
* *
|
|
* Information and Software Systems Research *
|
|
* AT&T Research *
|
|
* Florham Park NJ *
|
|
* *
|
|
* Glenn Fowler <gsf@research.att.com> *
|
|
* David Korn <dgk@research.att.com> *
|
|
* *
|
|
***********************************************************************/
|
|
#pragma prototyped
|
|
/*
|
|
* David Korn
|
|
* Glenn Fowler
|
|
* AT&T Research
|
|
*
|
|
* uname
|
|
*/
|
|
|
|
static const char usage[] =
|
|
"[-?\n@(#)$Id: uname (AT&T Research) 2007-04-19 $\n]"
|
|
"[--catalog?" ERROR_CATALOG "]"
|
|
"[+NAME?uname - identify the current system ]"
|
|
"[+DESCRIPTION?By default \buname\b writes the operating system name to"
|
|
" standard output. When options are specified, one or more"
|
|
" system characteristics are written to standard output, space"
|
|
" separated, on a single line. When more than one option is specified"
|
|
" the output is in the order specified by the \b-A\b option below."
|
|
" Unsupported option values are listed as \a[option]]\a. If any unknown"
|
|
" options are specified, the OS default \buname\b(1) is called.]"
|
|
"[+?If any \aname\a operands are specified then the \bsysinfo\b(2) values"
|
|
" for each \aname\a are listed, separated by space, on one line."
|
|
" \bgetconf\b(1), a pre-existing \astandard\a interface, provides"
|
|
" access to the same information; vendors should spend more time"
|
|
" using standards than inventing them.]"
|
|
"[+?Selected information is printed in the same order as the options below.]"
|
|
"[a:all?Equivalent to \b-snrvmpio\b.]"
|
|
"[s:system|sysname|kernel-name?The detailed kernel name. This is the default.]"
|
|
"[n:nodename?The hostname or nodename.]"
|
|
"[r:release|kernel-release?The kernel release level.]"
|
|
"[v:version|kernel-version?The kernel version level.]"
|
|
"[m:machine?The name of the hardware type the system is running on.]"
|
|
"[p:processor?The name of the processor instruction set architecture.]"
|
|
"[i:implementation|platform|hardware-platform?The hardware implementation;"
|
|
" this is \b--host-id\b on some systems.]"
|
|
"[o:operating-system?The generic operating system name.]"
|
|
"[h:host-id|id?The host id in hex.]"
|
|
"[d:domain?The domain name returned by \agetdomainname\a(2).]"
|
|
"[R:extended-release?The extended release name.]"
|
|
"[A:everything?Equivalent to \b-snrvmpiohdR\b.]"
|
|
"[f:list?List all \bsysinfo\b(2) names and values, one per line.]"
|
|
"[S:sethost?Set the hostname or nodename to \aname\a. No output is"
|
|
" written to standard output.]:[name]"
|
|
"\n"
|
|
"\n[ name ... ]\n"
|
|
"\n"
|
|
"[+SEE ALSO?\bhostname\b(1), \bgetconf\b(1), \buname\b(2),"
|
|
" \bsysconf\b(2), \bsysinfo\b(2)]"
|
|
;
|
|
|
|
#if defined(__STDPP__directive) && defined(__STDPP__hide)
|
|
__STDPP__directive pragma pp:hide getdomainname gethostid gethostname sethostname
|
|
#else
|
|
#define getdomainname ______getdomainname
|
|
#define gethostid ______gethostid
|
|
#define gethostname ______gethostname
|
|
#define sethostname ______sethostname
|
|
#endif
|
|
|
|
#include <cmd.h>
|
|
#include <ctype.h>
|
|
#include <stdio.h>
|
|
#include <proc.h>
|
|
|
|
#include "FEATURE/utsname"
|
|
|
|
#define MAXHOSTNAME 64
|
|
|
|
#if _lib_uname && _sys_utsname
|
|
# include <sys/utsname.h>
|
|
#endif
|
|
|
|
#if defined(__STDPP__directive) && defined(__STDPP__hide)
|
|
__STDPP__directive pragma pp:nohide getdomainname gethostid gethostname sethostname
|
|
#else
|
|
#undef getdomainname
|
|
#undef gethostid
|
|
#undef gethostname
|
|
#undef sethostname
|
|
#endif
|
|
|
|
#if _lib_getdomainname
|
|
extern int getdomainname(char*, size_t);
|
|
#endif
|
|
#if _lib_gethostid
|
|
extern long gethostid(void);
|
|
#endif
|
|
#if _lib_gethostname
|
|
extern int gethostname(char*, size_t);
|
|
#endif
|
|
#if _lib_sethostname
|
|
extern int sethostname(const char*, size_t);
|
|
#endif
|
|
|
|
#ifndef HOSTTYPE
|
|
#define HOSTTYPE "unknown"
|
|
#endif
|
|
|
|
static const char hosttype[] = HOSTTYPE;
|
|
|
|
#if !_lib_uname || !_sys_utsname
|
|
|
|
#if defined(__STDPP__)
|
|
#define SYSNAME #(getprd machine)
|
|
#define RELEASE #(getprd release)
|
|
#define VERSION #(getprd version)
|
|
#define MACHINE #(getprd architecture)
|
|
#else
|
|
#define SYSNAME ""
|
|
#define RELEASE ""
|
|
#define VERSION ""
|
|
#define MACHINE ""
|
|
#endif
|
|
|
|
struct utsname
|
|
{
|
|
char* sysname;
|
|
char nodename[MAXHOSTNAME];
|
|
char* release;
|
|
char* version;
|
|
char* machine;
|
|
};
|
|
|
|
int
|
|
uname(register struct utsname* ut)
|
|
{
|
|
#ifdef HOSTTYPE
|
|
char* sys = 0;
|
|
char* arch = 0;
|
|
|
|
if (*hosttype)
|
|
{
|
|
static char buf[sizeof(hosttype)];
|
|
|
|
strcpy(buf, hosttype);
|
|
sys = buf;
|
|
if (arch = strchr(sys, '.'))
|
|
{
|
|
*arch++ = 0;
|
|
if (!*arch)
|
|
arch = 0;
|
|
}
|
|
if (!*sys)
|
|
sys = 0;
|
|
}
|
|
#endif
|
|
#ifdef _lib_gethostname
|
|
if (gethostname(ut->nodename, sizeof(ut->nodename) - 1))
|
|
return -1;
|
|
#else
|
|
strncpy(ut->nodename, "local", sizeof(ut->nodename) - 1);
|
|
#endif
|
|
#ifdef HOSTTYPE
|
|
if (!(ut->sysname = sys))
|
|
#endif
|
|
if (!*(ut->sysname = SYSNAME))
|
|
ut->sysname = ut->nodename;
|
|
#ifdef HOSTTYPE
|
|
if (!(ut->machine = arch))
|
|
#endif
|
|
ut->machine = MACHINE;
|
|
ut->release = RELEASE;
|
|
ut->version = VERSION;
|
|
return 0;
|
|
}
|
|
|
|
#endif
|
|
|
|
#define OPT_system (1<<0)
|
|
#define OPT_nodename (1<<1)
|
|
#define OPT_release (1<<2)
|
|
#define OPT_version (1<<3)
|
|
#define OPT_machine (1<<4)
|
|
#define OPT_processor (1<<5)
|
|
|
|
#define OPT_STANDARD 6
|
|
|
|
#define OPT_implementation (1<<6)
|
|
#define OPT_operating_system (1<<7)
|
|
|
|
#define OPT_ALL 8
|
|
|
|
#define OPT_hostid (1<<8)
|
|
#define OPT_vendor (1<<9)
|
|
#define OPT_domain (1<<10)
|
|
#define OPT_machine_type (1<<11)
|
|
#define OPT_base (1<<12)
|
|
#define OPT_extended_release (1<<13)
|
|
#define OPT_extra (1<<14)
|
|
|
|
#define OPT_TOTAL 15
|
|
|
|
#define OPT_all (1L<<29)
|
|
#define OPT_total (1L<<30)
|
|
#define OPT_standard ((1<<OPT_STANDARD)-1)
|
|
|
|
#ifndef MACHINE
|
|
#if defined(__STDPP__)
|
|
#define MACHINE #(getprd architecture)
|
|
#else
|
|
#define MACHINE ""
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef HOSTTYPE
|
|
#define HOSTTYPE "unknown"
|
|
#endif
|
|
|
|
#define extra(m) do \
|
|
{ \
|
|
if ((char*)&ut.m[sizeof(ut.m)] > last) \
|
|
last = (char*)&ut.m[sizeof(ut.m)]; \
|
|
} while(0)
|
|
|
|
#define output(f,v,u) do \
|
|
{ \
|
|
if ((flags&(f))&&(*(v)||(flags&(OPT_all|OPT_total))==OPT_all&&((f)&OPT_standard)||!(flags&(OPT_all|OPT_total)))) \
|
|
{ \
|
|
if (sep) \
|
|
sfputc(sfstdout, ' '); \
|
|
else \
|
|
sep = 1; \
|
|
if (*(v)) \
|
|
sfputr(sfstdout, v, -1); \
|
|
else \
|
|
sfprintf(sfstdout, "[%s]", u); \
|
|
} \
|
|
} while (0)
|
|
|
|
int
|
|
b_uname(int argc, char** argv, Shbltin_t* context)
|
|
{
|
|
register long flags = 0;
|
|
register int sep = 0;
|
|
register int n;
|
|
register char* s;
|
|
char* t;
|
|
char* e;
|
|
char* sethost = 0;
|
|
int list = 0;
|
|
struct utsname ut;
|
|
char buf[257];
|
|
|
|
cmdinit(argc, argv, context, ERROR_CATALOG, 0);
|
|
for (;;)
|
|
{
|
|
switch (optget(argv, usage))
|
|
{
|
|
case 'a':
|
|
flags |= OPT_all|((1L<<OPT_ALL)-1);
|
|
#ifdef __linux__
|
|
flags |= OPT_implementation;
|
|
#endif
|
|
continue;
|
|
case 'b':
|
|
flags |= OPT_base;
|
|
continue;
|
|
case 'c':
|
|
flags |= OPT_vendor;
|
|
continue;
|
|
case 'd':
|
|
flags |= OPT_domain;
|
|
continue;
|
|
case 'f':
|
|
list = 1;
|
|
continue;
|
|
case 'h':
|
|
flags |= OPT_hostid;
|
|
continue;
|
|
case 'i':
|
|
flags |= OPT_implementation;
|
|
continue;
|
|
case 'm':
|
|
flags |= OPT_machine;
|
|
continue;
|
|
case 'n':
|
|
flags |= OPT_nodename;
|
|
continue;
|
|
case 'o':
|
|
flags |= OPT_operating_system;
|
|
continue;
|
|
case 'p':
|
|
flags |= OPT_processor;
|
|
continue;
|
|
case 'r':
|
|
flags |= OPT_release;
|
|
continue;
|
|
case 's':
|
|
flags |= OPT_system;
|
|
continue;
|
|
case 't':
|
|
flags |= OPT_machine_type;
|
|
continue;
|
|
case 'v':
|
|
flags |= OPT_version;
|
|
continue;
|
|
case 'x':
|
|
flags |= OPT_extra;
|
|
continue;
|
|
case 'A':
|
|
flags |= OPT_total|((1L<<OPT_TOTAL)-1);
|
|
continue;
|
|
case 'R':
|
|
flags |= OPT_extended_release;
|
|
continue;
|
|
case 'S':
|
|
sethost = opt_info.arg;
|
|
continue;
|
|
case ':':
|
|
{
|
|
char **new_argv = (char **)stakalloc((argc + 3) * sizeof(char*));
|
|
new_argv[0] = "command";
|
|
new_argv[1] = "-px";
|
|
for (n = 0; n <= argc; n++)
|
|
new_argv[n + 2] = argv[n];
|
|
return sh_run(context, argc + 2, new_argv);
|
|
}
|
|
case '?':
|
|
error(ERROR_usage(2), "%s", opt_info.arg);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
argv += opt_info.index;
|
|
if (error_info.errors || *argv && (flags || sethost) || sethost && flags)
|
|
error(ERROR_usage(2), "%s", optusage(NiL));
|
|
if (sethost)
|
|
{
|
|
#if _lib_sethostname
|
|
if (sethostname(sethost, strlen(sethost) + 1))
|
|
#else
|
|
#ifdef ENOSYS
|
|
errno = ENOSYS;
|
|
#else
|
|
errno = EPERM;
|
|
#endif
|
|
#endif
|
|
error(ERROR_system(1), "%s: cannot set host name", sethost);
|
|
}
|
|
else if (list)
|
|
astconflist(sfstdout, NiL, ASTCONF_base|ASTCONF_defined|ASTCONF_lower|ASTCONF_quote|ASTCONF_matchcall, "CS|SI");
|
|
else if (*argv)
|
|
{
|
|
e = &buf[sizeof(buf)-1];
|
|
while (s = *argv++)
|
|
{
|
|
t = buf;
|
|
*t++ = 'C';
|
|
*t++ = 'S';
|
|
*t++ = '_';
|
|
while (t < e && (n = *s++))
|
|
*t++ = islower(n) ? toupper(n) : n;
|
|
*t = 0;
|
|
sfprintf(sfstdout, "%s%c", *(t = astconf(buf, NiL, NiL)) ? t : *(t = astconf(buf+3, NiL, NiL)) ? t : "unknown", *argv ? ' ' : '\n');
|
|
}
|
|
}
|
|
else
|
|
{
|
|
s = buf;
|
|
if (!flags)
|
|
flags = OPT_system;
|
|
memzero(&ut, sizeof(ut));
|
|
if (uname(&ut) < 0)
|
|
error(ERROR_usage(2), "information unavailable");
|
|
output(OPT_system, ut.sysname, "sysname");
|
|
if (flags & OPT_nodename)
|
|
{
|
|
#if !_mem_nodeext_utsname && _lib_gethostname
|
|
if (sizeof(ut.nodename) > 9 || gethostname(s, sizeof(buf)))
|
|
#endif
|
|
s = ut.nodename;
|
|
output(OPT_nodename, s, "nodename");
|
|
}
|
|
output(OPT_release, ut.release, "release");
|
|
output(OPT_version, ut.version, "version");
|
|
output(OPT_machine, ut.machine, "machine");
|
|
if (flags & OPT_processor)
|
|
{
|
|
s = NULL;
|
|
#ifdef __linux__
|
|
# ifdef UNAME_PROCESSOR
|
|
if (!s)
|
|
{
|
|
size_t len = sizeof(buf) - 1;
|
|
int ctl[] = {CTL_HW, UNAME_PROCESSOR};
|
|
if (sysctl(ctl, 2, buf, &len, 0, 0) == 0)
|
|
s = buf;
|
|
}
|
|
# endif
|
|
if (!s)
|
|
{
|
|
strcpy((s = buf), ut.machine);
|
|
if (strcmp(s, "i686") == 0)
|
|
{
|
|
char line[1024];
|
|
Sfio_t *io = sfopen((Sfio_t*)0, "/proc/cpuinfo", "r");
|
|
if (io)
|
|
{
|
|
while (fgets(line, sizeof(line), io) > 0)
|
|
{
|
|
if (strncmp(line, "vendor_id", 9) == 0)
|
|
{
|
|
if (strstr(line, "AuthenticAMD"))
|
|
s = "athlon";
|
|
break;
|
|
}
|
|
}
|
|
sfclose(io);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
if (!s && !*(s = astconf("ARCHITECTURE", NiL, NiL)))
|
|
s = ut.machine;
|
|
output(OPT_processor, s, "processor");
|
|
}
|
|
if (flags & OPT_implementation)
|
|
{
|
|
s = NULL;
|
|
#ifdef __linux__
|
|
if (!s)
|
|
{
|
|
strcpy((s = buf), ut.machine);
|
|
if (s[0] == 'i' && s[2] == '8' && s[3] == '6' && s[4] == '\0')
|
|
s[1] = '3';
|
|
}
|
|
#endif
|
|
if (!s && !*(s = astconf("PLATFORM", NiL, NiL)) && !*(s = astconf("HW_NAME", NiL, NiL)))
|
|
{
|
|
if (t = strchr(hosttype, '.'))
|
|
t++;
|
|
else
|
|
t = (char*)hosttype;
|
|
strncpy(s = buf, t, sizeof(buf) - 1);
|
|
}
|
|
output(OPT_implementation, s, "implementation");
|
|
}
|
|
if (flags & OPT_operating_system)
|
|
{
|
|
s = astconf("OPERATING_SYSTEM", NiL, NiL);
|
|
if (!*s)
|
|
#ifdef _UNAME_os_DEFAULT
|
|
s = _UNAME_os_DEFAULT;
|
|
#else
|
|
s = ut.sysname;
|
|
#endif
|
|
output(OPT_operating_system, s, "operating-system");
|
|
}
|
|
if (flags & OPT_extended_release)
|
|
{
|
|
s = astconf("RELEASE", NiL, NiL);
|
|
output(OPT_extended_release, s, "extended-release");
|
|
}
|
|
#if _mem_idnumber_utsname
|
|
output(OPT_hostid, ut.idnumber, "hostid");
|
|
#else
|
|
if (flags & OPT_hostid)
|
|
{
|
|
if (!*(s = astconf("HW_SERIAL", NiL, NiL)))
|
|
#if _lib_gethostid
|
|
sfsprintf(s = buf, sizeof(buf), "%08x", gethostid());
|
|
#else
|
|
/*NOP*/;
|
|
#endif
|
|
output(OPT_hostid, s, "hostid");
|
|
}
|
|
#endif
|
|
if (flags & OPT_vendor)
|
|
{
|
|
s = astconf("HW_PROVIDER", NiL, NiL);
|
|
output(OPT_vendor, s, "vendor");
|
|
}
|
|
if (flags & OPT_domain)
|
|
{
|
|
if (!*(s = astconf("SRPC_DOMAIN", NiL, NiL)))
|
|
{
|
|
#if _lib_getdomainname
|
|
getdomainname(buf, sizeof(buf));
|
|
s = buf;
|
|
#else
|
|
/*NOP*/;
|
|
#endif
|
|
}
|
|
output(OPT_domain, s, "domain");
|
|
}
|
|
#if _mem_m_type_utsname
|
|
s = ut.m_type;
|
|
#else
|
|
s = astconf("MACHINE", NiL, NiL);
|
|
#endif
|
|
output(OPT_machine_type, s, "m_type");
|
|
#if _mem_base_rel_utsname
|
|
s = ut.base_rel;
|
|
#else
|
|
s = astconf("BASE", NiL, NiL);
|
|
#endif
|
|
output(OPT_base, s, "base_rel");
|
|
if (flags & OPT_extra)
|
|
{
|
|
char* last = (char*)&ut;
|
|
|
|
extra(sysname);
|
|
extra(nodename);
|
|
extra(release);
|
|
extra(version);
|
|
extra(machine);
|
|
#if _mem_idnumber_utsname
|
|
extra(idnumber);
|
|
#endif
|
|
#if _mem_m_type_utsname
|
|
extra(m_type);
|
|
#endif
|
|
#if _mem_base_rel_utsname
|
|
extra(base_rel);
|
|
#endif
|
|
if (last < ((char*)(&ut + 1)))
|
|
{
|
|
s = t = last;
|
|
while (s < (char*)(&ut + 1))
|
|
{
|
|
if (!(n = *s++))
|
|
{
|
|
if ((s - t) > 1)
|
|
{
|
|
if (sep)
|
|
sfputc(sfstdout, ' ');
|
|
else
|
|
sep = 1;
|
|
sfputr(sfstdout, t, -1);
|
|
}
|
|
t = s;
|
|
}
|
|
else if (!isprint(n))
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (sep)
|
|
sfputc(sfstdout, '\n');
|
|
}
|
|
return error_info.errors;
|
|
}
|