Adventures in uname land
#1
Adventures in uname land
So as part of neweoe, IRIX needed a new uname command. The old command is problematic for a variety of reasons.

Firstly -r only reports 6.5 -- not a minor version. You have to use the -R to get a more specific version, which is not POSIX compliant or inline with what Linux or BSD does.

Secondly, uname -a does not report the minor version.

Thirdly, it lacks the -X flag found on some BSDs and Solaris (and possibly linux, who knows?)

Here's my findings, and my methods for solving various challenges. Follow along with me down the rabbit hole of SGI programming.

Warning! I share CDDL (Common Development and Distribution License) code here. If you're somehow offended by the anti-GPL nature of it's operation or your employer doesn't want you to, click away now. Everything from this point is that.

Illumos-Gate version of uname:

https://raw.githubusercontent.com/illumo...me/uname.c

I'll go through my diff chunk by chunk:

Code:
% cat uname.diff                       
--- uname.orig  Wed Dec 22 20:03:14 2021                                        
+++ uname.c     Wed Dec 22 20:03:35 2021                                        
@@ -35,7 +35,7 @@                                                               
  * contributors.                                                               
  */                                                                            
                                                                                
-#define        __EXTENSIONS__                                                  
+#include <sys/syssgi.h>                                                        
#include <sys/types.h>                                                         
#include <stdio.h>                                                             
#include <string.h>

Ok, this is simply the addition of an extra header. illumos (and Solaris) really share a close relationship with IRIX, so other than removing the GCC preprocessor directive and <sys/syssgi.h> (The purpose of which will be discussed soon) there's little to talk about here.

Code:
@@ -48,7 +48,7 @@                                                               
#include <sys/utsname.h>                                                       
#include <sys/systeminfo.h>                                                    
                                                                                
-#define        OS_NAME "illumos"                                               
+#define        OS_NAME "IRIX"                                                  
                                                                                
static void usage(void);

Simple change. The primary OS_NAME definition is hard coded in the C file, ostensibly for portability.

Code:
@@ -57,9 +57,9 @@                                                               
main(int argc, char *argv[], char *envp[])                                     
{                                                                              
        char *nodename;                                                         
-       char *optstring = "asnrpvmioS:X";                                       
+       char *optstring = "asnrpvmoS:X";                                        
        int sflg = 0, nflg = 0, rflg = 0, vflg = 0, mflg = 0;                   
-       int pflg = 0, iflg = 0, oflg = 0, Sflg = 0;                             
+       int pflg = 0, oflg = 0, Sflg = 0;                                       
        int errflg = 0, optlet;                                                 
        int Xflg = 0;                                                           
        struct utsname  unstr, *un; 

The first line (optstring) is a getopt bit. I removed -i from this for reasons I'll discuss later when we get to that section.

Same with the iflg!

Code:
@@ -71,18 +71,11 @@                                                             
        un = &unstr;                                                            
        (void) uname(un);                                                       
                                                                                
-       (void) setlocale(LC_ALL, "");                                           
-#if !defined(TEXT_DOMAIN)                                                      
-#define        TEXT_DOMAIN "SYS_TEST"                                          
-#endif                                                                         
-       (void) textdomain(TEXT_DOMAIN);
-
        while ((optlet = getopt(argc, argv, optstring)) != EOF)
                switch (optlet) {
                case 'a':
                        sflg++; nflg++; rflg++; vflg++; mflg++;
                        pflg++;
-                       iflg++;
                        break;
                case 's':
                        sflg++;

Two changes here: Removed gettext() related code, and removed the now absent iflg variable from part of the getopt.

I have nothing against gettext(), or err.h (which I often change to straight fprintf or perror calls) -- but they're extra dependencies that would need to be accounted for in it. I have gettext(), but I prefer to not overuse it, and for uname gettext() is 100% overkill. err.h too, but solaris doesn't use err.h. That's a BSDism.

The other change is self-explanatory.

Code:
@@ -102,9 +95,6 @@
                case 'p':
                        pflg++;
                        break;
-               case 'i':
-                       iflg++;
-                       break;
                case 'o':
                        oflg++;
                        break;
@@ -124,7 +114,7 @@
                usage();
 
        if ((Sflg > 1) ||
-           (Sflg && (sflg || nflg || rflg || vflg || mflg || pflg || iflg ||
+           (Sflg && (sflg || nflg || rflg || vflg || mflg || pflg ||
            oflg || Xflg))) {
                usage();
        }

Similar stuff here i'm breezing through. More iflg stuff. We're getting to juicier stuff.

Code:
@@ -134,15 +124,15 @@                                                           
                int len = strlen(nodename);                                     
                                                                                
                if (len > SYS_NMLN - 1) {                                       
-                       (void) fprintf(stderr, gettext(                         
-                           "uname: name must be <= %d letters\n"),             
+                       (void) fprintf(stderr,                                  
+                           "uname: name must be <= %d letters\n",              
                            SYS_NMLN-1);                                        
                        exit(1);                                                
                }                                                               
                if (sysinfo(SI_SET_HOSTNAME, nodename, len) < 0) {              
                        int err = errno;                                        
-                       (void) fprintf(stderr, gettext(                         
-                           "uname: error in setting name: %s\n"),              
+                       (void) fprintf(stderr,                                  
+                           "uname: error in setting name: %s\n",               
                            strerror(err));
                        exit(1);
                }                                                               
@@ -152,7 +142,7 @@                    
        /*                             
         * "uname -s" is the default                                            
         */                            
-       if (!(sflg || nflg || rflg || vflg || mflg || pflg || iflg ||
+       if (!(sflg || nflg || rflg || vflg || mflg || pflg ||
            oflg || Xflg))
                sflg++;       
        if (sflg) {

Two more changes. The first is an example of gettext() being used typically for error messages. Removed. Another iflg reference. Whenever you delete a variable, you gotta remove all references to it or the compiler will be like "WTF MAN!"

Code:
@@ -165,7 +155,9 @@                    
                fs = fmt_string;
        }                              
        if (rflg) {                    
-               (void) fprintf(stdout, fs, sizeof (un->release), un->release);
+               char releasename[256];
+               syssgi(SGI_RELEASE_NAME, sizeof(releasename), releasename);
+               (void) fprintf(stdout, fs, sizeof (releasename), releasename);
                fs = fmt_string;
        }         
        if (vflg) { 

Ok. So here's where we get into a lengthy C discussion. I'll try to break it down. What the first fprintf statement (the removed one) does is:

Print to standard output, use the fs format string, make the buffer the size of the part of the un struct named release, and print the contents of the un->release.

Ok, so what is un you're asking? Well it's mapped to the utsname struct in sys/utsname.h, and yes, uname is short for utsname ostensibly. I don't know what exactly is the origin of the "uts" part but it's something I see in sysv all the time. in the struct located there is a char string called release. This releases ALWAYS prints 6.5 on any 6.5 release. This is problematic -- IRIX was at 6.5 from 1998-2006 so this varies greatly on C capabilities. Scripts expect -r to print this info, so this could cause issues.

Anyways, the correct way to fix this is to use sys/syssgi.h -- it has a great many options in its functionality. So you then can retrieve it after creating a buffer (I set it arbitrarily at 256, but this could likely be reduced.) and running syssgi(), then printing its stored string.

Ok, so that fixes -r. Solaris uname includes -X, so other stuff is easy in that regard, but we're not outta the woods yet!

Code:
@@ -178,17 +170,8 @@                                                            
        }                                                                       
        if (pflg) {                                                             
                if (sysinfo(SI_ARCHITECTURE, procbuf, sizeof (procbuf)) == -1) {
-                       (void) fprintf(stderr, gettext(                         
-                           "uname: sysinfo failed\n"));                        
-                       exit(1);                                                
-               }                                                               
-               (void) fprintf(stdout, fs, strlen(procbuf), procbuf);           
-               fs = fmt_string;                                                
-       }                                                                       
-       if (iflg) {                                                             
-               if (sysinfo(SI_PLATFORM, procbuf, sizeof (procbuf)) == -1) {    
-                       (void) fprintf(stderr, gettext(                         
-                           "uname: sysinfo failed\n"));                        
+                       (void) fprintf(stderr,                                  
+                           "uname: sysinfo failed\n");                         
                        exit(1);                                                
                }                                                               
                (void) fprintf(stdout, fs, strlen(procbuf), procbuf);


The -i command uses Solaris-specific calls and isn't even used by IRIX's uname or any other part of the POSIX specification that I can see. 

These calls are really janky, so I just deleted the code for it. That's why the iflg stuff is missing! Also a stray gettext().

Code:
@@ -200,28 +183,22 @@
        }
        if (Xflg) {
                int     val;
+               char releasename[256];
+               
+               syssgi(SGI_RELEASE_NAME, sizeof(releasename), releasename);
 
                (void) fprintf(stdout, "System = %.*s\n", sizeof (un->sysname),
                    un->sysname);
                (void) fprintf(stdout, "Node = %.*s\n", sizeof (un->nodename),
                    un->nodename);
-               (void) fprintf(stdout, "Release = %.*s\n", sizeof (un->release),
-                   un->release);
+               (void) fprintf(stdout, "Release = %.*s\n", sizeof (releasename),
+                   releasename);
                (void) fprintf(stdout, "KernelID = %.*s\n",
                    sizeof (un->version), un->version);
                (void) fprintf(stdout, "Machine = %.*s\n", sizeof (un->machine),
                    un->machine);
 
-               /* Not availible on Solaris so hardcode the output */
-               (void) fprintf(stdout, "BusType = <unknown>\n");
-
-               /* Serialization is not supported in 2.6, so hard code output */
-               (void) fprintf(stdout, "Serial = <unknown>\n");
-               (void) fprintf(stdout, "Users = <unknown>\n");
-               (void) fprintf(stdout, "OEM# = 0\n");
-               (void) fprintf(stdout, "Origin# = 1\n");
-
-               val = sysconf(_SC_NPROCESSORS_CONF);
+               val = sysconf(_SC_NPROC_CONF);
                (void) fprintf(stdout, "NumCPU = %d\n", val);
        }
        (void) putchar('\n');

Ok, so here's some other stuff to look at. I was thankful that for sysconf() it's very similar between IRIX and Solaris code. Easy to update that little bit.

Everything else, well, I first deleted the hardcoded stuff that illumos itself can't even use. If anyone has any suggestions, once I get the code submitted to neweoe, you can submit a pull req or something or reply here. I did duplicate the release code including buffer, probably bad form, but I didn't get any compiler warnings. I could probably move the variables up with the others though. Thoughts guys? Was that bad form?

Code:
@@ -232,9 +209,9 @@
usage(void)
{
        {
-               (void) fprintf(stderr, gettext(
+               (void) fprintf(stderr,
                    "usage:     uname [-snrvmapioX]\n"
-                   "   uname [-S system_name]\n"));
+                   "   uname [-S system_name]\n");
        }
        exit(1);
}

gettext() code removal here. That's it, other than a minor issue (I forgot to remove the i flag from usage).

Conclusions:

I hope everyone was able to learn something. I wanna do more of these, if you guys find it helpful. I would like to go through libxg functions, neweoe commands I build from scratch or gank from elsewhere and modify.

Can someone more familiar with sysv stuff explain to me if gettxt() (no e) is similar in capabilities on IRIX? If so, it may be possible to substitute/map some calls to it? Maybe? I don't know.

I have learned an AWFUL lot about kernel and sysconf variables, and may build a, well, /special/ command for IRIX. I dunno.

I'm the system admin of this site. Private security technician, licensed locksmith, hack of a c developer and vintage computer enthusiast. 

https://contrib.irixnet.org/raion/ -- contributions and pieces that I'm working on currently. 

https://codeberg.org/SolusRaion -- Code repos I control

Technical problems should be sent my way.
Raion
Chief IRIX Officer

Trade Count: (9)
Posts: 4,239
Threads: 533
Joined: Nov 2017
Location: Eastern Virginia
Website Find Reply
12-23-2021, 01:51 AM
#2
RE: Adventures in uname land
(12-23-2021, 01:51 AM)Raion Wrote:  Thirdly, it lacks the -X flag found on some BSDs and Solaris (and possibly linux, who knows?)

Not Linux.  No mention of it in the manpage and trying it outputs an "invalid option" message.

(12-23-2021, 01:51 AM)Raion Wrote:  The -i command uses Solaris-specific calls and isn't even used by IRIX's uname or any other part of the POSIX specification that I can see. 

In GNU coreutils, -i is documented to "print the hardware platform (non-portable)".  So, you're right that it's non-standard.  On a multi-architecture OS, it's necessary.  Pretty pointless for IRIX, IMHO.  But if you really want to support -i, then just hard code it to print "MIPS" and be done with it.

FWIW, on x86_64 Linux, 'uname -i' prints 'unknown'.  So not particularly helpful even on a platform where it is supported!

All in all, nice work and nice write up.

SGI:  Indigo, Indigo2, Octane, Origin 300
Sun:  SPARCstation 20 (x4), Ultra 2, Blade 2500, T5240
HP:  9000/380, 425e, C8000
Digital: DECstation 5000/125, PWS 600au
jpstewart
Developer

Trade Count: (1)
Posts: 444
Threads: 6
Joined: May 2018
Location: SW Ontario, CA
Find Reply
12-24-2021, 12:52 AM
#3
RE: Adventures in uname land
Yeah, I don't regularly use GNU/Linux and don't even have an active box so yeah, not sure what Linux does wrt gnu uname.

Thanks for commenting on this -- I like to know I did something right. Gonna update that code slightly probably to consolidate the char array declarations

I'm the system admin of this site. Private security technician, licensed locksmith, hack of a c developer and vintage computer enthusiast. 

https://contrib.irixnet.org/raion/ -- contributions and pieces that I'm working on currently. 

https://codeberg.org/SolusRaion -- Code repos I control

Technical problems should be sent my way.
Raion
Chief IRIX Officer

Trade Count: (9)
Posts: 4,239
Threads: 533
Joined: Nov 2017
Location: Eastern Virginia
Website Find Reply
12-24-2021, 04:12 AM
#4
RE: Adventures in uname land
(12-23-2021, 01:51 AM)Raion Wrote:  Ok, so what is un you're asking? Well it's mapped to the utsname struct in sys/utsname.h, and yes, uname is short for utsname ostensibly. I don't know what exactly is the origin of the "uts" part but it's something I see in sysv all the time. in the struct located there is a char string called release. This releases ALWAYS prints 6.5 on any 6.5 release. This is problematic -- IRIX was at 6.5 from 1998-2006 so this varies greatly on C capabilities. Scripts expect -r to print this info, so this could cause issues.

here, you are a probably introducing more problems than you are solving, because lots of scripts test for this and will fail if they get 6.5.22m instead of 6.5.
lunatic
insane in the mainframe

Trade Count: (0)
Posts: 150
Threads: 1
Joined: Apr 2019
Find Reply
12-24-2021, 10:59 AM
#5
RE: Adventures in uname land
I've had scripts have issues, not the other way around..

We'll see I guess

I'm the system admin of this site. Private security technician, licensed locksmith, hack of a c developer and vintage computer enthusiast. 

https://contrib.irixnet.org/raion/ -- contributions and pieces that I'm working on currently. 

https://codeberg.org/SolusRaion -- Code repos I control

Technical problems should be sent my way.
Raion
Chief IRIX Officer

Trade Count: (9)
Posts: 4,239
Threads: 533
Joined: Nov 2017
Location: Eastern Virginia
Website Find Reply
12-24-2021, 02:45 PM
#6
RE: Adventures in uname land
(12-24-2021, 10:59 AM)lunatic Wrote:  
(12-23-2021, 01:51 AM)Raion Wrote:  Ok, so what is un you're asking? Well it's mapped to the utsname struct in sys/utsname.h, and yes, uname is short for utsname ostensibly. I don't know what exactly is the origin of the "uts" part but it's something I see in sysv all the time. in the struct located there is a char string called release. This releases ALWAYS prints 6.5 on any 6.5 release. This is problematic -- IRIX was at 6.5 from 1998-2006 so this varies greatly on C capabilities. Scripts expect -r to print this info, so this could cause issues.

here, you are a probably introducing more problems than you are solving, because lots of scripts test for this and will fail if they get 6.5.22m instead of 6.5.


A way of maintaining compatibility and still introduce new features/behaviour could be by just installing the new uname in a different path than current uname (/sbin/uname).

Users wanting to use the newer one, would just prefix the new path in its PATH or use FQPN in their scripts, or a mix of both.

We do this all the time with GNU software installing by default under /usr/local, or IRIX freeware distributions under /usr/freeware.
TruHobbyist
Developer

Trade Count: (0)
Posts: 195
Threads: 21
Joined: May 2018
Find Reply
12-24-2021, 04:57 PM
#7
RE: Adventures in uname land
I appreciate the concern/input on me fixing the -r. I am at this time not changing it back or "masking" /sbin/uname. Rather, like all neweoe commands, it will replace the one of the same name. This is because a non-open source command cannot be serviced, audited or configured.

If it presents issues, I will probably look into/deploy solutions, but as to my current testing nothing has failed because of the change. I have considered chopping off the letter portion, and may do so, but that remains to be seen.

I'm the system admin of this site. Private security technician, licensed locksmith, hack of a c developer and vintage computer enthusiast. 

https://contrib.irixnet.org/raion/ -- contributions and pieces that I'm working on currently. 

https://codeberg.org/SolusRaion -- Code repos I control

Technical problems should be sent my way.
Raion
Chief IRIX Officer

Trade Count: (9)
Posts: 4,239
Threads: 533
Joined: Nov 2017
Location: Eastern Virginia
Website Find Reply
12-24-2021, 05:06 PM
#8
RE: Adventures in uname land
(12-23-2021, 01:51 AM)Raion Wrote:  ...

Ok, so what is un you're asking? Well it's mapped to the utsname struct in sys/utsname.h, and yes, uname is short for utsname ostensibly. I don't know what exactly is the origin of the "uts" part but it's something I see in sysv all the time. in the struct located there is a char string called release.

...


lwn UTS Namespace:

The name of that structure in turn derives from "UNIX Time-sharing System".
TruHobbyist
Developer

Trade Count: (0)
Posts: 195
Threads: 21
Joined: May 2018
Find Reply
12-24-2021, 05:10 PM
#9
RE: Adventures in uname land
heh, gotta love that '80sness.

I'm the system admin of this site. Private security technician, licensed locksmith, hack of a c developer and vintage computer enthusiast. 

https://contrib.irixnet.org/raion/ -- contributions and pieces that I'm working on currently. 

https://codeberg.org/SolusRaion -- Code repos I control

Technical problems should be sent my way.
Raion
Chief IRIX Officer

Trade Count: (9)
Posts: 4,239
Threads: 533
Joined: Nov 2017
Location: Eastern Virginia
Website Find Reply
12-24-2021, 05:21 PM
#10
RE: Adventures in uname land
(12-24-2021, 05:06 PM)Raion Wrote:  This is because a non-open source command cannot be serviced, audited or configured.
This obviously is not an argument for gratuitous incompatible changes in behavior.

Personaliris O2 Indigo2 R10000/IMPACT Indigo2 R10000/IMPACT Indigo2 Indy   (past: 4D70GT)
robespierre
refector peritus

Trade Count: (0)
Posts: 640
Threads: 3
Joined: Nov 2020
Location: Massholium
Find Reply
12-24-2021, 07:11 PM


Forum Jump:


Users browsing this thread: 1 Guest(s)