This code can be called by a login program to get a username and
password. It expects that the world has been prepared by an
init_dialog()
before it’s called, and it leaves it up to the
caller to call end_dialog()
when it wants to.
/*
* cc -c getuser.o getuser.c
*/
#include <ndialog.h>
#include <pwd.h>
#include <sys/types.h>
#include <unistd.h>
#define ESIZE 20
static char user[ESIZE];
static char pass[ESIZE];
static struct passwd *pw;
static int retries;
/*
* pwcallback() is a local function that authenticates the user after they
* enter a password.
*/
static int
pwcallback(void* obj, void* display)
{
char *ency;
if ((pw = getpwnam(user)) != 0) {
if (pw->pw_passwd[0] == 0 && pass[0] == 0) {
/* no password, so don't even check */
return -1;
}
ency = crypt(pass, pw->pw_passwd);
memset(pass, 0, ESIZE);
if (strcmp(ency, pw->pw_passwd) == 0) {
/* password matched; we can leave now */
return -1;
}
}
/* complain bitterly and return */
Error("login incorrect");
return (--retries >= 0) ? 0 : -1;
} /* pwcallback */
/*
* getuser() asks for a username and password. If it's given a valid username
* and password, it returns a pwent for that user, otherwise it spits up a
* `login incorrect' error box and asks again, up to login_attempts times.
* After that, it returns 0 and leaves the proper punishment up to the caller.
*/
struct passwd *
getuser(int login_attempts)
{
int rc;
void *u_obj, *p_obj, *cancel, *chain;
/* allocate the display fields */
u_obj = newString( 0,0, ESIZE, ESIZE, user, 0, "Username", 0, 0);
p_obj = newPWString(0,3, ESIZE, ESIZE, pass, 0, "Password", pwcallback, 0);
cancel= newCancelButton(0, "Forget it", 0, 0);
retries = login_attempts;
/* build them into a ObjChain */
chain = ObjChain(ObjChain(u_obj, p_obj), cancel);
/* get the user input and clean up */
rc = MENU(chain, -1, -1, 0, "Enter your username and password", 0);
deleteObjChain(chain);
/* and return the user info if there is any */
return (rc == MENU_OK) ? pw : 0;
} /* getuser */