Login.c

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 */