/********************************************************************-*-C-*-
 *
 * mitcookie.c - Copyright (C) 1997 Pat Thoyts <Pat.Thoyts@bbsrc.ac.uk>
 *
 * A real quick way to generate an MIT-MAGIC-COOKIE-1 string. This is for
 * use in 'startx' scripts to enable cookie based authorisation instead of
 * the usual default host based authorisation.
 *
 * You use it like this:
 *
 * xauth add unix:0 MIT-MAGIC-COOKIE-1 `mitcookie`
 * xauth add `hostname -f`:0 MIT-MAGIC-COOKIE-1 `mitcookie`
 *
 * Then make sure that your server command line has -auth $XAUTHORITY in
 * it (or -auth $HOME/.Xauthority which is the xauth default) otherwise
 * no clients will be able to connect to the server.
 *
 * Now you will have a (reasonably) secure X display.
 *
 * See the accompanying file for suitable modifications to your startx 
 * script to make sure this works properly for all your users (or setup
 * xdm - but then if you're using xdm - you don't need this do you!)
 *
 **************************************************************************/

const char* copyright = "
    mitcookie.c  -- generate MIT-MAGIC-COOKIE-1 cookies for xauth.

    Copyright (C) 1997 Pat Thoyts <Pat.Thoyts@bbsrc.ac.uk>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

";


#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include <limits.h>

int
main ( int argc, char** argv )
{
  struct timeval tod;
  char buffer[33];
  unsigned long number = 0;
  unsigned long cn, countbits, longbits;
  unsigned long mask = 0xF;
  static char hexchars[16] = "0123456789abcdef";

  /* We try and use the fine timers to seed the random number generator
   * with a different value no matter how fast two consecutive commands are
   * run.
   */
  if ( gettimeofday(&tod, 0) == 0 ) {
    srandom(tod.tv_sec + tod.tv_usec);
  }
  else {
    /*
     * We can quite happily use time(0) to continue, but the chances are high
     * that two cookies created quickly will end up the same.
     */
    srandom(time(0));
  }

  /*
   * Get a nice 32 bit random number taking care in case we somehow end up
   * doing this on a 16 bit machine (unthinkable?) and allowing for the
   * possibility of an architecture with 64 bit long (more likely)
   * We generate a hex character by panning an 8bit window across the 
   * value we've created. Possibly twice.
   */
  longbits = sizeof(long) * 8;
  countbits = 0;

  while ( countbits < 32) {

    number = (unsigned long)(random()*INT_MAX+random());

    for (cn = 0; cn < longbits && countbits < 32; cn++, countbits++) {
      buffer[countbits] = hexchars[((number>>cn) & mask)];
    }

  }

  /* Well, that's all! Output the answer. */
  puts(buffer);

  return 0;

}
