#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <malloc.h>

struct record {
  int uid;
  char uname[32];
};

struct record *parse(FILE* passwd, /*out*/ size_t *size)
{
  char* line = NULL;
  size_t linesize = 0;
  size_t mem_size = 256;
  size_t elements = 0;
  struct record* base = malloc( sizeof(struct record) * mem_size );
  struct record* r = base;

  while (getline(&line, &linesize, passwd) != -1) {
    char *lname, *p, *luids;
    size_t name_len;
    
    lname = line;
    p = strchr(line, ':');
    *p = '\0'; /* terminate user name*/
    
    name_len = p - lname;
    strncpy( r->uname, lname, name_len);
    r->uname[name_len] = '\0';
    
    p = strchr(p + 1, ':'); /* passwd field */
    
    luids = p + 1;
    p = strchr(p + 1, ':'); /* passwd field */
    *p = '\0'; /* terminate uid */
    
    
    r->uid = strtol(luids, NULL, 10);

    ++ r; ++ elements;
    
    
    if (mem_size == elements) {
      mem_size *= 2;
      base = realloc(base, sizeof(struct record) * mem_size );
      r = &base[elements];
    }
  }

  *size = elements;
  return base;
}

char *uid2name(int uid, struct record* r, size_t r_size)
/* returns the account name corresponding to uid; the name is valid
   until the next call to uid2name */
{
  while ( r_size -- ) {
    if (r->uid == uid)
      return r->uname;
    
    ++ r;
  }

  return "uid not found";
}

int main()
{
  char* line = NULL;
  size_t linesize = 0;
  struct mallinfo m;
  struct record* r;
  size_t r_size;
  
  
  FILE *passwd = fopen("./passwd","r");
  if (passwd == NULL) {
    fprintf(stderr, "could not open passwd\n");
    exit(1);
  }
  
  r = parse(passwd, &r_size);
  
  fclose(passwd);
  
  while (getline(&line, &linesize, stdin) != -1) {
    puts(uid2name(strtol(line, NULL, 10), r, r_size));
  }
  
  /* Folgendes gibt nur den von malloc() verbrauchten Speicher aus.
     Wenn Ihr Programm nennenswerte Mengen an statisch allokiertem
     Speicher verwendet oder z.B. mit mmap einen Speicherbereich
     allokiert, in den es hineinschreibt (z.B. bei Verwendung von
     strtok), zaehlen Sie die entsprechenden Groessen bitte dazu und
     geben Sie die Summe aus. */
  m = mallinfo();
  fprintf(stderr,"%d\n",m.uordblks + m.hblkhd);
  
  exit(0);
}
