/*
 * callbacks.c - callback functions for Linux System Manager
 * Copyright Michael McNeil 1995
 * Released Under the GNU Public License.
 */

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
#include <ctype.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <unistd.h>
#include <assert.h>

/* X-window stuff */
#include <Xm/BulletinB.h>
#include <Xm/PushB.h>
#include <Xm/RowColumn.h>
#include <Xm/DialogS.h>
#include <Xm/MessageB.h>
#include <Xm/Label.h>
#include <Xm/Text.h>
#include <Xm/List.h>

#define SYSTEM   1
#define NETWORK  2
#define USER     3
#define DISK     4
#define SUCCESS  1
#define FAILURE  0

/* we gotta change this to something more portable  */
/*  I think the following will only work on a 32 bit machine */
#define ascii_to_bin(c) ((c)>='a'?(c-59):(c)>='A'?((c)-53):(c)-'.')
#define bin_to_ascii(c) ((c)>=38?((c)-38+'a'):(c)>=12?((c)-12+'A'):(c)+'.')

/* Function defs  <--- start sysmgr.h here */
void swap_mgr( void );
void swap_sys( Widget, XtPointer, XtPointer );
void swap_net( Widget, XtPointer, XtPointer );
void swap_usr( Widget, XtPointer, XtPointer );
void bad_user( Widget, XtPointer, XtPointer );
void bad_homedir( Widget, XtPointer, XtPointer );
void bad_userid( Widget, XtPointer, XtPointer );
void bad_group( Widget, XtPointer, XtPointer );
void no_user( Widget, XtPointer, XtPointer );

/* Global Variables and Widgets */
extern int curr_mgr;
extern int next_mgr;

/* sysboard widgets global so that we can unmanage them later */
extern Widget sysbboard;
extern Widget usrbboard;
extern Widget netbboard;
extern Widget dskbboard;
extern Widget Ufname_te;
extern Widget Ulgname_te;
extern Widget Uhmdir_te;
extern Widget Ushell_te;
extern Widget Uusrid_te;
extern Widget Ugroup_te;
extern Widget Upasswd_te;
extern Widget Uscrlist;

/* User widgets */
extern Widget usrscrlst;

void
finish( w, client_data, call_data )
Widget w;
XtPointer client_data;
XtPointer call_data;
{
	Widget exit_dialog, yes_button, no_button;
	extern void dlg_callback();
	Arg args[5];
	int ac=0;
	XmString m = XmStringCreateLocalized("     Exit xusermgr?    ");
	XmString yes = XmStringCreateLocalized("Yes");
	XmString no = XmStringCreateLocalized("No");
	XtSetArg( args[ac], XmNtitle, "Exit" ); ac++;
	XtSetArg( args[ac], XmNautoUnmanage, False); ac++;
	XtSetArg( args[ac], XmNmessageString, m ); ac++;
	XtSetArg( args[ac], XmNokLabelString, yes ); ac++;
	XtSetArg( args[ac], XmNcancelLabelString, no ); ac++;
	exit_dialog = XmCreateQuestionDialog( w, "Exit xusermgr", args, ac);
	XtAddCallback( exit_dialog, XmNokCallback, dlg_callback, NULL );
	XtAddCallback( exit_dialog, XmNcancelCallback, dlg_callback, NULL );
	XmStringFree(m);
	XmStringFree(yes);


	XtManageChild( exit_dialog );
	XtUnmanageChild( XmMessageBoxGetChild( exit_dialog, XmDIALOG_HELP_BUTTON));
	XtPopup( XtParent( exit_dialog), XtGrabNone );
}

void
dlg_callback( w, client_data, call_data )
Widget w;
XtPointer client_data;
XtPointer call_data;
{
	XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *) call_data;

	switch (cbs->reason) {
	    case XmCR_OK:
		exit(0);
	    case XmCR_CANCEL:
		XtPopdown (XtParent (w));
		break;
	    case XmCR_ACTIVATE:
		XtPopdown( XtParent (w));
		break;
	}
}


void
usrselc_cb( list_w, client_data, call_data )
Widget list_w;
XtPointer client_data;
XtPointer call_data;
{
	struct passwd *pwd_ptr;
	struct group *group_ptr;
	gid_t gid;
	char *choice;
	char *result;
	char userid[10];
	char grpid[10];

	XmListCallbackStruct *cbs = (XmListCallbackStruct *)call_data;

	XmStringGetLtoR( cbs->item, XmFONTLIST_DEFAULT_TAG, &choice );

	setpwent();

	while( (pwd_ptr = getpwent()) != NULL )
	  {
	  if( strcmp( choice, pwd_ptr->pw_name) == 0 ) break;
	  }

	XmTextSetString( Ulgname_te, pwd_ptr->pw_name );
	XmTextSetString( Ufname_te, pwd_ptr->pw_gecos );
	XmTextSetString( Uhmdir_te, pwd_ptr->pw_dir);

	sprintf( userid, "%d", pwd_ptr->pw_uid );

	gid = pwd_ptr->pw_gid;

	group_ptr = getgrgid( gid );

	sprintf( grpid,  "%s", group_ptr->gr_name );
	XmTextSetString( Ugroup_te, grpid );
	XmTextSetString( Uusrid_te, userid );
	XmTextSetString( Ushell_te, pwd_ptr->pw_shell );

	if( pwd_ptr->pw_passwd[0] == 0 ){
		XmTextSetString( Upasswd_te, "NO PASSWORD");
	}
	else{
		result = crypt( pwd_ptr->pw_name, pwd_ptr->pw_passwd );
		if( !strcmp( result, pwd_ptr->pw_passwd )){
			XmTextSetString( Upasswd_te, pwd_ptr->pw_name );
		}
		else{
			XmTextSetString( Upasswd_te, "" );
		}
	}

	endpwent();
	XtFree( choice );
}

void add_user( w, client_data, call_data )
Widget w;
XtPointer client_data;
XtPointer call_data;
{

	struct passwd *pe;
	struct passwd tpw;
	struct group *gid;
	char *cryptstr;
	time_t tm;
	char salt[2];
	FILE *fd_in, *fd_out;
	char line[1024];

	int status = SUCCESS;
	int error = 0;
	char *lnname;
	char *fname;
	char *hmdir;
	char *tuid;
	char *tgid;
	char *shll;
	char *pswd;
	char loginname[40];
	char fullname[40];
	char homedir[40];
	char usrid[10];
	char grid[10];
	char shell[33];
	char passwd[40];
	uid_t userid;
	int update =0;
	char commandbuf[1024];

	XmString str;
	int foundit = 0;

	if( lnname = XmTextGetString( Ulgname_te )) {
		strncpy( loginname, lnname, 8 );
		XtFree( lnname );

	tpw.pw_name = loginname;

		if( strlen( loginname ) == 0 ){
			no_user( w, client_data, call_data );
			return;
		}

		/* check and see if this name already exists */
		if(getpwnam( loginname )){
			/* user already exists, so we update */
			update = 1;
		}

		/* let's make sure that the first letter is not
		  an unprintable character or a space or punctuation */
		if( iscntrl(loginname[0]) || ispunct(loginname[0])
		    || isspace(loginname[0])){
			bad_user(w, client_data, call_data );
			/* then return */
			return;
		}

	}

	if( fname = XmTextGetString( Ufname_te )) {
		strcpy( fullname, fname );
		XtFree( fname );
		tpw.pw_gecos = fullname;

	/* not every user wants his/her name on his/her account,
	   so we don't complain if one isn't there */

	}

	if( hmdir = XmTextGetString( Uhmdir_te )) {
		strcpy( homedir, hmdir );
		XtFree( hmdir );
		tpw.pw_dir = homedir;

	/* we do, however, care if there is no home directory */
		if( strlen( homedir ) == 0 ){
		/* if it's zero length, then the field is blank.
		   it is theoretical that the path to the home
		   directory is just 1 byte long, say /  
		fprintf( stderr,"No home directory specified\n"); */
		bad_homedir( w, client_data, call_data );
		return;
		}
	}

	if( tuid = XmTextGetString( Uusrid_te )) {
		strcpy( usrid, tuid );
		XtFree( tuid );
		if( strlen( usrid ) == 0 ){
			bad_userid( w, client_data, call_data );
			return;
		}

		userid = atoi( usrid );

	tpw.pw_uid = ( uid_t ) userid;

	/* if the specified user id is 0, ie. root, but the login name
	   isn't root, then warn the user of what he is about to do */
		if( usrid == 0 && strcmp( loginname, "root") != 0 ){
		/* okay, it's userid 0, but not root, Maybe they
		   are adding a user named shutdown or something? */
		fprintf(stderr,"You are creating a user with super ");
		fprintf(stderr,"user priviledges that is NOT root\n");
		}

	}

	if( tgid = XmTextGetString( Ugroup_te )) {
		strcpy( grid, tgid );
		XtFree( tgid );

		/* convert the string back into a valid group id */	
		if((gid = getgrnam( grid )) == NULL ){
			bad_group( w, client_data, call_data );
			return;
		}
		sprintf( grid,"%d", gid->gr_gid );

	tpw.pw_gid = gid->gr_gid;

	}

	if( shll = XmTextGetString( Ushell_te )) {
		strcpy( shell, shll );
		XtFree( shll );
	tpw.pw_shell = shell;
	}

	if( pswd = XmTextGetString( Upasswd_te )) {
		strcpy( passwd, pswd );
		XtFree( pswd );
	}

        time(&tm);
        salt[0] = bin_to_ascii(tm & 0x3f);
        salt[1] = bin_to_ascii((tm >> 5) & 0x3f);
        tpw.pw_passwd = crypt(passwd, salt);

        if(!(fd_out = fopen("/etc/ptmp", "w"))) {
                puts("xusermgr: Can't open /etc/ptmp, can't update password");
                exit(1);
        }

        if(!(fd_in = fopen("/etc/passwd", "r"))) {
                puts("xusermgr: Can't read /etc/passwd, can't update password");
                exit(1);
        }

        setpwent();
        while(pe = getpwent()) {

		/* if we are updating, look for the user to update */
		if( update )
		{
        	    /* find the user's line and update it */
        	    if( strcmp(pe->pw_name,tpw.pw_name) == 0){
			putpwent( &tpw, fd_out );
			continue;
		    }
        	 }

        /* otherwise just copy it out */
        putpwent( pe, fd_out );
        }

	/* if we're not updating, then add it */
	if( !update ) putpwent( &tpw, fd_out );

        fclose(fd_in);
        fclose(fd_out);

	/* The following code borrowed shamelessly from Patrick Volkerding's
	   code from his adduser utility. Eventually, I plan to change all of
	   these system calls to actual unix calls.
	 */

	if( !update ){
		/* First, we "give" the /etc/skel directory to the new user: */
		sprintf(commandbuf,"chown --recursive %d.%d /etc/skel 2> /dev/null",tpw.pw_uid,tpw.pw_gid);
		system(commandbuf);
		/* Then, we copy the files owned by the new user into the new user's home
		   directory. This way, if there are already files in the user's home
		   directory (say, from a backup), the ownership of those files won't be
		   changed. Some say this is progress. ;^) */
/*		sprintf(commandbuf,"( cd /etc/skel ; cp -a --verbose . %s )",homedir); */
		sprintf(commandbuf,"( cd /etc/skel ; cp -a . %s )",homedir);
		system(commandbuf);
		/* It's useful to give the new home directory a current
		   creation date rather than the one from /etc/skel. */
		sprintf(commandbuf,"touch %s",homedir);
		system(commandbuf);
		/* Give this stuff back to root. By sure to put the uid/gid you want for the
		   default ownership of /etc/skel into the line below if 0.0 isn't good. */
		sprintf(commandbuf,"chown --recursive 0.0 /etc/skel 2> /dev/null");
		system(commandbuf);
		sprintf(commandbuf,"touch /var/spool/mail/%s",tpw.pw_name);
		system(commandbuf);
		sprintf(commandbuf,"chown %d.mail /var/spool/mail/%s",tpw.pw_uid,tpw.pw_name);
		system(commandbuf);
		sprintf(commandbuf,"chmod 660 /var/spool/mail/%s",tpw.pw_name);
		system(commandbuf);
	}

        endpwent();

        unlink("/etc/passwd.OLD");
        link("/etc/passwd", "/etc/passwd.OLD");
        unlink("/etc/passwd");
        link("/etc/ptmp", "/etc/passwd");
        unlink("/etc/ptmp");
        chmod("/etc/passwd", 0644);
        chown("/etc/passwd", 0, 0);

	/* clear out all the text fields */
	XmTextSetString( Uusrid_te, "" );
	XmTextSetString( Ulgname_te, "" );
	XmTextSetString( Ufname_te, "" );
	XmTextSetString( Uhmdir_te, "" );
	XmTextSetString( Ugroup_te, "" );
	XmTextSetString( Ushell_te, "" );
	XmTextSetString( Upasswd_te, "" );

	/* if we're not updating, add the new user entry to the bottom of the list */
	if( !update ){
	str = XmStringCreateLocalized( loginname );
	XmListAddItem( Uscrlist, str, 0 );
	XmStringFree( str );
	}
}



void new_user( w, client_data, call_data )
Widget w;
XtPointer client_data;
XtPointer call_data;
{
	XmString str;
	char newusrid[10];
	int unused_uid = find_unused( 500 );;

	sprintf( newusrid,"%d", unused_uid ); 

	XmTextSetString( Uusrid_te, newusrid );
	XmTextSetString( Ulgname_te, "" );
	XmTextSetString( Ufname_te, "" );
	XmTextSetString( Uhmdir_te, "" );
	XmTextSetString( Ugroup_te, "users" );
	XmTextSetString( Ushell_te, "/bin/bash" );
	XmTextSetString( Upasswd_te, "" );

	/* unselect the list for a new entry */
	XmListDeselectAllItems( Uscrlist );
}


find_unused(begin)
        int begin;
{
        int trial;
        struct passwd *pw;
        trial = begin - 1;

        while ((pw = getpwuid(++trial)) != NULL)
        {
	/* don't do anything, just keep looking */
        }

        return(trial);
} 


rem_user( w, client_data, call_data )
Widget w;
XtPointer client_data;
XtPointer call_data;
{
	int error = 0;
	char *user;
	struct passwd *pwd;
	FILE *fd_in, *fd_out;
	char line[1024];
	char command[1024];
	XmString list_text;

	user =  XmTextGetString( Ulgname_te );

	if( strlen( user ) == 0 ){
		no_user( w, client_data, call_data );
		return;
	}

        if(!(fd_out = fopen("/etc/ptmp", "w"))) {
                puts("Can't open /etc/ptmp, can't update password");
                exit(1);
        }

        if(!(fd_in = fopen("/etc/passwd", "r"))) {
                puts("Can't read /etc/passwd, can't update password");
                exit(1);
        }

	/* Never, ever, EVER directly read the passwd file! */

	setpwent();
        while(pwd = getpwent()) {

	/* when we find the user's line, don't print it, just continue */
        if( strcmp(pwd->pw_name,user) == 0) continue;

	/* actually deleting the home directory here is too dangerous,
	 * what if the home directory was "/" ?
	 */

	/* otherwise just copy it out */
	putpwent( pwd, fd_out );

        }

        if(error) {
        fprintf(stderr,
		"Error while writing new password file, password not changed.");
			fclose(fd_out);
        		fclose(fd_in);
			endpwent();
			unlink("/etc/ptmp");
			return;
                }
        fclose(fd_in);
        fclose(fd_out);

	/* get the user name so we can delete it from the scrolled list */
	list_text = XmStringCreateLocalized( user );
	XmListDeleteItem( Uscrlist, list_text );
	XmStringFree( list_text );

        unlink("/etc/passwd.OLD");
        link("/etc/passwd", "/etc/passwd.OLD");
        unlink("/etc/passwd");
        link("/etc/ptmp", "/etc/passwd");
        unlink("/etc/ptmp");
        chmod("/etc/passwd", 0644);
        chown("/etc/passwd", 0, 0);

	XmTextSetString( Uusrid_te, "" );
	XmTextSetString( Ulgname_te, "" );
	XmTextSetString( Ufname_te, "" );
	XmTextSetString( Uhmdir_te, "" );
	XmTextSetString( Ugroup_te, "" );
	XmTextSetString( Ushell_te, "" );
	XmTextSetString( Upasswd_te, "" );

	/* we are through with the user name now, so free it */
	XtFree( user );
}

void dis_user( w, client_data, call_data )
Widget w;
XtPointer client_data;
XtPointer call_data;
{
	XmString str;
	int error = 0;
	char *user;
	struct passwd *pwd;
	FILE *fd_in, *fd_out;
	char line[1024];

	user =  XmTextGetString( Ulgname_te );
	if( strlen( user ) == 0 ){
		no_user( w, client_data, call_data );
		return;
	}

        if(!(fd_out = fopen("/etc/ptmp", "w"))) {
                puts("Can't open /etc/ptmp, can't update password");
                exit(1);
        }

        if(!(fd_in = fopen("/etc/passwd", "r"))) {
                puts("Can't read /etc/passwd, can't update password");
                exit(1);
        }


	/* Never, ever, EVER directly read the passwd file! */

	setpwent();
        while(pwd = getpwent()) {

		/* when we find the user's line,     */
		/* stick an "*" in the passwd field  */
		if( strcmp(pwd->pw_name,user) == 0) 
		{
			strcpy( pwd->pw_passwd, "*" );
			putpwent( pwd, fd_out );
		}else
		{
		/* otherwise just copy it out */
		putpwent( pwd, fd_out );
		}

        }

        if(error) {
        puts("Error while writing new password file, password not changed.");
                        fclose(fd_out);
                        endpwent();
                        unlink("/etc/ptmp");
                        exit(1);
        }

        fclose(fd_in);
        fclose(fd_out);

        unlink("/etc/passwd.OLD");
        link("/etc/passwd", "/etc/passwd.OLD");
        unlink("/etc/passwd");
        link("/etc/ptmp", "/etc/passwd");
        unlink("/etc/ptmp");
        chmod("/etc/passwd", 0644);
        chown("/etc/passwd", 0, 0);

	/* we are through with the user name now, so free it */
	XtFree( user );
	XmTextSetString( Upasswd_te, "" );
}

void reset_user( w, client_data, call_data )
Widget w;
XtPointer client_data;
XtPointer call_data;
{
	/* clear out all the text fields */
	XmTextSetString( Uusrid_te, "" );
	XmTextSetString( Ulgname_te, "" );
	XmTextSetString( Ufname_te, "" );
	XmTextSetString( Uhmdir_te, "" );
	XmTextSetString( Ugroup_te, "" );
	XmTextSetString( Ushell_te, "" );
	XmTextSetString( Upasswd_te, "" );

	/* unselect the scrolled list also */
	XmListDeselectAllItems( Uscrlist );
}

void
bad_user( w, client_data, call_data )
Widget w;
XtPointer client_data;
XtPointer call_data;
{
        Widget user_dialog, yes_button, no_button;
        extern void baduser_dlg();
        Arg args[5];
        int ac=0;
        XmString m = XmStringCreateLocalized("Invalid Login Name. Please try again.");
        XmString yes = XmStringCreateLocalized("OK");
        XtSetArg( args[ac], XmNautoUnmanage, False); ac++;
        XtSetArg( args[ac], XmNmessageString, m ); ac++;
        XtSetArg( args[ac], XmNokLabelString, yes ); ac++;
	XtSetArg( args[ac], XmNtitle, "Error" ); ac++;
        user_dialog = XmCreateQuestionDialog( w, "bad_user", args, ac);
        XtAddCallback( user_dialog, XmNokCallback, baduser_dlg, NULL );
        XmStringFree(m);
        XmStringFree(yes);

        XtManageChild( user_dialog );
        XtUnmanageChild( XmMessageBoxGetChild( user_dialog, XmDIALOG_HELP_BUTTON));
        XtUnmanageChild( XmMessageBoxGetChild( user_dialog, XmDIALOG_CANCEL_BUTTON));
        XtPopup( XtParent( user_dialog), XtGrabNone );
}


void
baduser_dlg( w, client_data, call_data )
Widget w;
XtPointer client_data;
XtPointer call_data;
{
        XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *) call_data;

        switch (cbs->reason) {
            case XmCR_OK:
                XtPopdown( XtParent (w));
                break;
            case XmCR_ACTIVATE:
                XtPopdown( XtParent (w));
                break;
        }
}

void
bad_homedir( w, client_data, call_data )
Widget w;
XtPointer client_data;
XtPointer call_data;
{
        Widget homedir_dialog, yes_button, no_button;
        extern void baduser_dlg();
        Arg args[5];
        int ac=0;
        XmString m = XmStringCreateLocalized("No Home Directory Specified.");
        XmString yes = XmStringCreateLocalized("OK");
        XtSetArg( args[ac], XmNautoUnmanage, False); ac++;
        XtSetArg( args[ac], XmNmessageString, m ); ac++;
        XtSetArg( args[ac], XmNokLabelString, yes ); ac++;
	XtSetArg( args[ac], XmNtitle, "Error" ); ac++;
        homedir_dialog = XmCreateQuestionDialog( w, "bad_homedir", args, ac);
        XtAddCallback( homedir_dialog, XmNokCallback, baduser_dlg, NULL );
        XmStringFree(m);
        XmStringFree(yes);

        XtManageChild( homedir_dialog );
        XtUnmanageChild( XmMessageBoxGetChild( homedir_dialog, XmDIALOG_HELP_BUTTON));
        XtUnmanageChild( XmMessageBoxGetChild( homedir_dialog, XmDIALOG_CANCEL_BUTTON));
        XtPopup( XtParent( homedir_dialog), XtGrabNone );
}


void
bad_userid( w, client_data, call_data )
Widget w;
XtPointer client_data;
XtPointer call_data;
{
        Widget userid_dialog, yes_button, no_button;
        extern void baduser_dlg();
        Arg args[5];
        int ac=0;
        XmString m = XmStringCreateLocalized("    No User id Specified.   ");
        XmString yes = XmStringCreateLocalized("OK");
        XtSetArg( args[ac], XmNautoUnmanage, False); ac++;
        XtSetArg( args[ac], XmNmessageString, m ); ac++;
        XtSetArg( args[ac], XmNokLabelString, yes ); ac++;
	XtSetArg( args[ac], XmNtitle, "Error" ); ac++;
        userid_dialog = XmCreateQuestionDialog( w, "bad_userid", args, ac);
        XtAddCallback( userid_dialog, XmNokCallback, baduser_dlg, NULL );
        XmStringFree(m);
        XmStringFree(yes);

        XtManageChild( userid_dialog );
        XtUnmanageChild( XmMessageBoxGetChild( userid_dialog, XmDIALOG_HELP_BUTTON));
        XtUnmanageChild( XmMessageBoxGetChild( userid_dialog, XmDIALOG_CANCEL_BUTTON));
        XtPopup( XtParent( userid_dialog ), XtGrabNone );
} 


void
bad_group( w, client_data, call_data )
Widget w;
XtPointer client_data;
XtPointer call_data;
{
        Widget group_dialog, yes_button, no_button;
        extern void baduser_dlg();
        Arg args[5];
        int ac=0;
        XmString m = XmStringCreateLocalized("   Invalid Group Specified.   ");
        XmString yes = XmStringCreateLocalized("OK");
        XtSetArg( args[ac], XmNautoUnmanage, False); ac++;
        XtSetArg( args[ac], XmNmessageString, m ); ac++;
        XtSetArg( args[ac], XmNokLabelString, yes ); ac++;
	XtSetArg( args[ac], XmNtitle, "Error" ); ac++;
        group_dialog = XmCreateQuestionDialog( w, "bad_group", args, ac);
        XtAddCallback( group_dialog, XmNokCallback, baduser_dlg, NULL );
        XmStringFree(m);
        XmStringFree(yes);

        XtManageChild( group_dialog );
        XtUnmanageChild( XmMessageBoxGetChild( group_dialog, XmDIALOG_HELP_BUTTON));
        XtUnmanageChild( XmMessageBoxGetChild( group_dialog, XmDIALOG_CANCEL_BUTTON));
        XtPopup( XtParent( group_dialog ), XtGrabNone );
}



void
no_user( w, client_data, call_data )
Widget w;
XtPointer client_data;
XtPointer call_data;
{
        Widget nouser_dialog, yes_button, no_button;
        extern void baduser_dlg();
        Arg args[5];
        int ac=0;
        XmString m = XmStringCreateLocalized("    No User Specified.   ");
        XmString yes = XmStringCreateLocalized("OK");
        XtSetArg( args[ac], XmNautoUnmanage, False); ac++;
        XtSetArg( args[ac], XmNmessageString, m ); ac++;
        XtSetArg( args[ac], XmNokLabelString, yes ); ac++;
	XtSetArg( args[ac], XmNtitle, "Error" ); ac++;
        nouser_dialog = XmCreateQuestionDialog( w, "no_user", args, ac);
        XtAddCallback( nouser_dialog, XmNokCallback, baduser_dlg, NULL );
        XmStringFree(m);
        XmStringFree(yes);

        XtManageChild( nouser_dialog );
        XtUnmanageChild( XmMessageBoxGetChild( nouser_dialog, XmDIALOG_HELP_BUTTON));
        XtUnmanageChild( XmMessageBoxGetChild( nouser_dialog, XmDIALOG_CANCEL_BUTTON));
        XtPopup( XtParent( nouser_dialog ), XtGrabNone );
} 
