/* An example of uname using Ssystem(). Also works with old kernels,
   but for that old uname is better. Done 6.XII.1997. by Draco.
   Later fixes March 1998. */

#include <stdio.h>
#include <stdlib.h>
#include <mintbind.h>
#include <ssystem.h>

void help(char *cmd)
{
	printf("Usage: %s [OPTION]...\n\n",cmd);
	printf("  -a, --all        print all information\n");
  	printf("  -m, --machine    print the machine (hardware) type\n");
	printf("  -n, --nodename   print the machine's network node hostname\n");
	printf("  -r, --release    print the operating system release\n");
	printf("  -s, --sysname    print the operating system name\n");
	printf("  -v               print the operating system version\n");
	printf("      --help       display this help and exit\n\n");
	printf("Without any OPTION, assume -s.\n");
}

int main(int argc, char *argv[])
{
	char *hostname,*machine,*vendor,*s,*c,*sysname,*moy,*dow,*beta;
	
	long unsigned int osvers = 0, osdate = 0, ostime = 0, core = 0;
	long unsigned int tosver = 0;

	int r,mm,nn,rr,ss,vv;

	int majver = 0, day = 0, hour = 0, dayofweek = 0;
	int minver = 0, month = 0, minute = 0;
	int plnum = 0, year = 0, second = 0;
	char s_core[5];

	char mach[16],node[16],release[32],version[32],system[16];

	beta = '\0';
	sysname = "unknown";

	/* First we check if the Ssystem() exists ... */

	r = (int)Ssystem(-1, NULL, NULL);

	/* OK, lets go */

	if (r == 0)
	{
		osvers = Ssystem(OSVERSION, NULL, NULL);
		osdate = Ssystem(OS_BUILD_DATE, NULL, NULL);
		ostime = Ssystem(OS_BUILD_TIME, NULL, NULL);
		core = Ssystem(COMPILE_TYPE, NULL, NULL);
		tosver = Ssystem(TOSHEADER, 0L, NULL);

		if (Ssystem(OSNAME, NULL, NULL) == 0x4d694e54)
		{
			if (Ssystem(OSXNAME, NULL, NULL) == 0x46726565)
				sysname = "FreeMiNT";
			else
				sysname = "MiNT";
		}

	}
	/* OSVERSION returns version number encoded as follows:
	   mmnnppbb, where:
	   mm = major version number (1.xx.xx)
	   nn = minor version number (x.14.xx)
	   pp = patchlevel (x.xx.6)
	   bb contains $62 for beta kernel and $00 for 'normal' kernel */

	majver = osvers >> 24;
	minver = (osvers >> 16) & 0x000000ff;
	plnum = (osvers >> 8) & 0x000000ff;
	if ((osvers & 0x000000ff) == 0x62)
		beta = "BETA";

	/* Core contains coprocessor identification (0x0882 for 68882)
	   in the high word. Actually NULL because the kernel needn't
           FPU to run */

	sprintf(s_core, "680%02ld", core&0x0000ffff);

	/* Day of week code (1 for Monday etc) is returned in the highest
           byte of ostime. OSDATE returns compile date as ddmmyyyy */

	year = osdate & 0x0000ffff;
	month = (osdate>>16) & 0x000000ff;
	day = osdate>>24;
	dayofweek = (ostime>>24) & 0x00000007;

	/* Yes, I know lines below are lame... */

	switch(dayofweek)
	{
		case 1: dow = "Mon"; break;
		case 2: dow = "Tue"; break;
		case 3: dow = "Wed"; break;
		case 4: dow = "Thu"; break;
		case 5: dow = "Fri"; break;
		case 6: dow = "Sat"; break;
		default: dow = "Sun"; break;
	}

	switch(month)
	{
		case 1: moy = "Jan"; break;
		case 2: moy = "Feb"; break;
		case 3: moy = "Mar"; break;
		case 4: moy = "Apr"; break;
		case 5: moy = "May"; break;
		case 6: moy = "Jun"; break;
		case 7: moy = "Jul"; break;
		case 8: moy = "Aug"; break;
		case 9: moy = "Sep"; break;
		case 10: moy = "Oct"; break;
		case 11: moy = "Nov"; break;
		default: moy = "Dec"; break;
	}
	
	/* OSTIME returns compile time as hhmmss */

	second = ostime & 0x000000ff;
	minute = (ostime>>8)&0x00ff;
	hour = (ostime>>16)&0x00ff;

	if ((hostname = getenv("HOST")) == NULL)
		hostname = "unknown";

	if ((machine = getenv("MACHTYPE")) == NULL)
		machine = "unknown";

	if ((vendor = getenv("VENDOR")) == NULL)
		vendor = "unknown";

	sprintf(mach,"%s %s",machine,vendor);

	if (r == 0)
	{
		sprintf(system,"%s",sysname);
		sprintf(version,"%d.%d.%d %s (%ld.%02lx)",majver,minver,plnum,beta,(tosver&0x0000ff00)>>8,tosver&0x000000ff);
		sprintf(release,"%s %d %s %d %02d:%02d.%02d (%s)", \
			dow,day,moy,year,hour,minute,second,s_core);
	}
	else
	{
		if((getenv("OSTYPE")) == NULL)
			sysname = "unknown";
		sprintf(system,"%s",sysname);
		*version = '\0';
		*release = '\0';
	}		

	ss = mm = nn = rr = vv = 0;
	c = argv[0];

	if (argc > 1)
	{
		if ((*++argv)[0] == '-')
		{
			for (s = argv[0]+1; *s != '\0'; s++)
			{
				switch(*s)
				{
					case 'm':
						mm = 1;
						break;
					case 'n':
						nn = 1;
						break;
					case 'r':
						rr = 1;
						break;
					case 's':
						ss = 1;
						break;
					case 'v':
						vv = 1;
						break;
					case 'a':
						vv = ss = rr = nn = mm = 1;
						break;
					case '-':
						help(c);
						return r;
					default:
						ss = 1;
						break;
				}

			}

		}

	}
	else
		ss = 1;		/* -s is default */

	if (nn)	printf("%s ",hostname);
	if (mm) printf("%s ",mach);
	if (ss) printf("%s ",system);
	if (vv) printf("%s ",version);
	if (rr) printf("%s",release);
	printf("\n");

	return r;
}
