#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

#define MAXLINE 256
#define MAX_PASSWORD 10

#define SUCCESS "Password verified\n"
#define INVALID "Invalid password\n"
#define NO_USER "No such user\n"

#define PASSWORD_FILE "pass.txt"

/* Reads two chunks from stdin, and checks if they match a user id
 * and password pair from a password file. The first chunk (MAX_PASSWORD bytes)
 * will contain a user id, and the second chunk (MAX_PASSWORD bytes) will 
 * contain a password.
 * 
 * The program exits with a value of 
 *      0 if the user id and password match,
 *      1 if there is an error, 
 *      2 if the user id is found but the password does not match, and 
 *      3 if the user id is not found in the password file. 
 */


/* Note that read will read at most MAX_PASSWORD bytes. This means that the
 * longest password we can support is MAX_PASSWORD.  We can't count on the
 * caller to send the null termination character, so we have to ensure
 * that we terminate the string that is sent anyway.
 *
 * If the input is coming from the console/keyboard, then the write calls
 * are managed by the shell which will process each piece of input 
 * separately.
 * However, if the input is coming from a pipe, there is no guarantee that
 * two writes generated by checkpasswd will send the data such that it
 * will be read by the two reads below.  The means that it is important for
 * checkpasswd to send exactly as many bytes that validate is expecting.
 * Otherwise the behaviour may be unpredicatable.
 *
 * This also means that checkpasswd should report an invalid password
 * or no user_id if the user input is longer than MAX_PASSWORD.
 */

int main(void){
    int n, user_length;
    char userid[MAXLINE];
    char password[MAXLINE];

    if((n = read(STDIN_FILENO, userid, MAX_PASSWORD)) == -1) {
        perror("read");
        exit(1);
    } else if(n == 0) {
        fprintf(stderr, "Error: could not read from stdin");
        exit(1);
    }

    // Make sure user id is null-terminated
    if(n <= MAX_PASSWORD) {
        userid[n] ='\0';
    }

    // Remove newline character if it exists
    char *newline;
    if((newline = strchr(userid, '\n')) != NULL) {
        *newline = '\0';
    }

    if((n = read(STDIN_FILENO, password, MAX_PASSWORD)) == -1) {
        perror("read");
        exit(1);
    } else if(n == 0) {
        fprintf(stderr, "Error: could not read from stdin");
        exit(1);
    }

    // Make sure password is null-terminated
    if(n <= MAX_PASSWORD) {
        password[n] ='\0';
    } 

    // Remove newline character if it exists
    if((newline = strchr(password, '\n')) != NULL) {
        *newline = '\0';
    }


    // Prepare the userid:password string to compare to password file entries.
    // We expect userid to have enough space to concatenate ":" + password
    // but we will play it safe and use strncat
    strncat(userid, ":", MAXLINE - strlen(userid) - 1);
    user_length = strlen(userid);
    strncat(userid, password, MAXLINE - strlen(userid) - 1);

    FILE *fp = fopen(PASSWORD_FILE, "r");
    if(!fp) {
        perror("fopen");
        exit(1);
    }
    
    char line[MAXLINE];
    while(fgets(line, sizeof(line) - 1, fp)) {
        line[strlen(line) - 1] = '\0';
        if (strcmp(userid, line) == 0) {
            fclose(fp);
            exit(0); // found match
        }
        else if(strncmp(userid, line, user_length) == 0) {
            fclose(fp);
            exit (2); // invalid password
        }
    }
    fclose(fp);
    exit(3); // no such user
}


int main(void) {
  char user_id[MAXLINE];
  char password[MAXLINE];

  /* The user will type in a user name on one line followed by a password 
     on the next.
     DO NOT add any prompts.  The only output of this program will be one 
	 of the messages defined above.
     Please read the comments in validate carefully
   */

  if(fgets(user_id, MAXLINE, stdin) == NULL) {
      perror("fgets");
      exit(1);
  }
  if(fgets(password, MAXLINE, stdin) == NULL) {
      perror("fgets");
      exit(1);
  }
  
  // TODO

  if(strlen(password) > MAX_PASSWORD){
    printf("password too long");
    exit(1); // password too long
  }else if(strlen(user_id) > MAX_PASSWORD){
    printf("user_id too long"); // user_id too long
    exit(1);
  }

  int p = fork();
  char *arg_Ptr[2];
  arg_Ptr[] = {validate.c, user_id, password, NULL};
  execv(__FILE__, arg_Ptr);


  return 0;
}

checkpasswd.c creates a new process to run the validate program