view lib/password.c @ 665:0ed044e9e5ca

gethostname: Tighten up error messages slightly, switch to default "y".
author Rob Landley <rob@landley.net>
date Sun, 09 Sep 2012 18:44:12 -0500
parents 9aeea680acc7
children 786841fdb1e0
line wrap: on
line source

/* vi: set sw=4 ts=4 :                                                                                                                                                          
 * pwdutils.c - password read/update helper functions.
 *
 * Copyright 2012 Ashwini Kumar <ak.ashwini@gmail.com>
 */

#include "toys.h"
#include <time.h>


int read_password(char * buff, int buflen, char* mesg)
{           
    int i = 0;
    struct termios termio, oldtermio;
    tcgetattr(0, &oldtermio);
    tcflush(0, TCIFLUSH);
    termio = oldtermio;

    termio.c_iflag &= ~(IUCLC|IXON|IXOFF|IXANY);
    termio.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|TOSTOP);
    tcsetattr(0, TCSANOW, &termio);

    fputs(mesg, stdout);
    fflush(stdout);

    while (1) {
        int ret = read(0, &buff[i], 1);
        if ( ret < 0 ) {   
            buff[0] = 0;
            tcsetattr(0, TCSANOW, &oldtermio);
            return 1;
        }   
        else if ( ret == 0 || buff[i] == '\n' ||
                buff[i] == '\r' || buflen == i+1) {   
            buff[i] = '\0';
            break;
        }   
        i++;
    }       

    tcsetattr(0, TCSANOW, &oldtermio);
    puts("");
    fflush(stdout);
    return 0;
}

static char *get_nextcolon(const char *line, char delim)
{
    char *current_ptr = NULL;
    if((current_ptr = strchr(line, ':')) == NULL) 
        error_exit("Invalid Entry\n");      
    return current_ptr;
}

int update_password(char *filename, char* username, char* encrypted)
{
    char *filenamesfx = NULL, *namesfx = NULL;
    char *shadow = NULL, *sfx = NULL;
    FILE *exfp, *newfp;
    int ret = -1; //fail
    struct flock lock;
    char *line = NULL;

    shadow = strstr(filename, "shadow");
    filenamesfx = xmsprintf("%s+", filename);
    sfx = strchr(filenamesfx, '+');

    exfp = fopen(filename, "r+");
    if(!exfp) {      
        perror_msg("Couldn't open file %s",filename);
        goto free_storage;
    }

    *sfx = '-';
    ret = unlink(filenamesfx);
    ret = link(filename, filenamesfx);
    if(ret < 0) error_msg("can't create backup file");

    *sfx = '+';
    lock.l_type = F_WRLCK;
    lock.l_whence = SEEK_SET;
    lock.l_start = 0;
    lock.l_len = 0;

    ret = fcntl(fileno(exfp), F_SETLK, &lock);
    if(ret < 0) perror_msg("Couldn't lock file %s",filename);

    lock.l_type = F_UNLCK; //unlocking at a later stage                                                                                                                         

    newfp = fopen(filenamesfx, "w+");
    if(!newfp) {       
        error_msg("couldn't open file for writing");
        ret = -1;
        fclose(exfp);
        goto free_storage;
    }       

    ret = 0;
    namesfx = xmsprintf("%s:",username);
    while((line = get_line(fileno(exfp))) != NULL)
    {
        if(strncmp(line, namesfx, strlen(namesfx)) != 0)
            fprintf(newfp, "%s\n", line);
        else {
            char *current_ptr = NULL;
            fprintf(newfp, "%s%s:",namesfx,encrypted);
            current_ptr = get_nextcolon(line, ':'); //past username
            current_ptr++; //past colon ':' after username
            current_ptr = get_nextcolon(current_ptr, ':'); //past passwd
            current_ptr++; //past colon ':' after passwd
            if(shadow) {
                fprintf(newfp, "%u:",(unsigned)(time(NULL))/(24*60*60));
                current_ptr = get_nextcolon(current_ptr, ':'); 
                current_ptr++; //past time stamp colon.
                fprintf(newfp, "%s\n",current_ptr);
            }
            else {
                fprintf(newfp, "%s\n",current_ptr);
            }
        }

        free(line);
    }
    free(namesfx);
    fcntl(fileno(exfp), F_SETLK, &lock);
    fclose(exfp);
    
    errno = 0;
    fflush(newfp);
    fsync(fileno(newfp));
    fclose(newfp);
    rename(filenamesfx, filename);
    if(errno) {
        perror_msg("File Writing/Saving failed: ");
        unlink(filenamesfx);
        ret = -1;
    }      

free_storage:
    free(filenamesfx);
    return ret;
}