/* uname - an implementation of uname for NeXTSTEP
 * Written by Graham Lee 2005-01-07
 * must be compiled with cc -posix
 * Ought to have considered a licence - we'll go with MIT
 */

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/utsname.h>

#define SYSNAME 1
#define NODENAME 2
#define RELEASE 4
#define VERSION 8
#define MACHINE 16

void usage();

int main(int argc, char **argv)
{
  struct utsname unameInfo;
  extern char *optarg;
  extern int optind;
  extern int optopt;
  extern int opterr;
  extern int optreset;
  extern int errno;
  int opt,toPrint=0,uFlags=0;

  if(uname(&unameInfo)!=0)
    {
      fprintf(stderr,"Unable to obtain uname info: %s\n",strerror(errno));
      exit(EXIT_FAILURE);
    }

  if(argc==1)
    {
      uFlags+=SYSNAME;
    }

  while((opt=getopt(argc,argv,"amnpsrv"))!=-1)
    {
      switch (opt)
	{
	case 'a':
	  uFlags = uFlags | (SYSNAME|NODENAME|RELEASE|VERSION|MACHINE);
	  break;
	case 'm':
	  uFlags = uFlags | MACHINE;
	  break;
	case 'n':
	  uFlags = uFlags | NODENAME;
	  break;
	case 'r':
	  uFlags = uFlags | RELEASE;
	  break;
	case 's':
	  uFlags = uFlags | SYSNAME;
	  break;
	case 'v':
	  uFlags = uFlags | VERSION;
	  break;
	default:
	  usage();
	  break;
	}
    }

  toPrint=(uFlags&MACHINE)+(uFlags&NODENAME)+(uFlags&RELEASE)+(uFlags&SYSNAME)+(uFlags&VERSION);

  if(toPrint==1)
    {
      printf("%s%s%s%s%s\n",uFlags&MACHINE?unameInfo.machine:"",uFlags&NODENAME?unameInfo.nodename:"",uFlags&RELEASE?unameInfo.release:"",uFlags&SYSNAME?unameInfo.sysname:"",uFlags&VERSION?unameInfo.version:"");
    }
  else
    {
      if(uFlags&MACHINE) printf("%s ",unameInfo.machine);
      if(uFlags&NODENAME) printf("%s ",unameInfo.nodename);
      if(uFlags&RELEASE) printf("%s ",unameInfo.release);
      if(uFlags&SYSNAME) printf("%s ",unameInfo.sysname);
      if(uFlags&VERSION) printf("%s",unameInfo.version);
      printf("\n");
    }

  exit(EXIT_SUCCESS);
}

void usage()
{
  fprintf(stderr,"usage: uname [-amnrsv]\n");
  exit(EXIT_FAILURE);
}
