/* change system id on IRIX 6.2 (IP28)
   consider this a very early alpha - ratatosk@mail2me.com 

   Placed in the public domain by the author - 1996

   since the system ID on different types of SGI hardware is obtained in
   different ways, YMMV. This may even crash your machine.

   compile by   --  cc -o change-sid62-ip28 change-sid62-ip28.c -lelf 
 
   run this with no parameters first and make sure it reports the
   correct system id
 
   if all is well, you can run it with the system id you want

  e.g.
    marmot:/home/mch/tmp> cc -o change-sid62-ip28 change-sid62-ip28.c -lelf
    marmot:/home/mch/tmp> su
    Password:
    marmot# /sbin/sysinfo
    System ID:
    12  34  56  78  00  00  00  00  00  00  00  00  00  00  00  00  
    00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  
    00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  
    00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  
    marmot# ./change-sid62-ip28
    hexadecimal system id seems to be 12345678
    marmot# ./change-sid62-ip28 69c0ffee
    marmot# /sbin/sysinfo
    System ID:
    69  c0  ff  ee  00  00  00  00  00  00  00  00  00  00  00  00  
    00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  
    00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  
    00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  
    marmot#

 */


#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <nlist.h>
struct nlist64 nl[2];
 
main(argc,argv)
int argc;
char *argv[];
{
    int kmem;
    int just_read = 0;
    unsigned int new_id, cur_id;
    off_t where;
    just_read = (argc <= 1);
    if (argc > 1) 
         new_id = strtoul(argv[1], NULL, 16);

    if ((kmem = open("/dev/kmem", O_RDWR)) < 0) {
        fprintf(stderr, "cannot open /dev/kmem\n");
        exit(1);
    }
    nl[0].n_name="enet_collision";
    nl[1].n_name = NULL;
    if (nlist64("/unix", nl) < 0) {
        fprintf(stderr, "cannot read namelist out of /dev/ksyms\n");
        exit(1);
    }
    if ((where = nl[0].n_value) == 0) {
        fprintf(stderr, "unknown kernel variable enet_collision\n");
        exit(1);
    }
    if (lseek(kmem, where + 4, SEEK_SET) == (-1)) {
        fprintf(stderr, "lseek on /dev/kmem failed\n");
        exit(1);
    }
    if (!just_read) {
        if (write (kmem, &new_id, 4) < 4) {
            fprintf(stderr, "write to /dev/kmem failed\n");
            exit(1);
        }
    }
    else {
        if (read(kmem, &cur_id, 4) < 4) {
            fprintf(stderr, "read failed\n");
            exit(1);
        }
        printf("hexadecimal system id seems to be %08x\n", cur_id);
    }
    close(kmem);
    exit(0);
}

