#define _POSIX_C_SOURCE 200809L #include #include #include struct entry { struct entry *next; int fd; FILE *f; char *buf; }; struct entry *table[64]; #define K (sizeof table / sizeof table[0]) pthread_rwlock_t lock = PTHREAD_RWLOCK_INITIALIZER; char *fgetln(FILE *f, size_t *l) { int fd, h; struct entry *p; ssize_t cnt; char *ret = 0; flockfile(f); fd = fileno(f); h = fd % K; pthread_rwlock_rdlock(&lock); for (p=table[h]; p && (p->fd!=fd || (fd<0 && p->f!=f)); p=p->next); if (!p) { if (!(p = calloc(sizeof *p, 1))) { pthread_rwlock_unlock(&lock); funlockfile(f); return 0; } p->fd = fd; p->f = f; pthread_rwlock_unlock(&lock); pthread_rwlock_wrlock(&lock); p->next = table[h]; table[h] = p; } pthread_rwlock_unlock(&lock); cnt = getline(&p->buf, (size_t[]){0}, f); if (cnt >= 0) { *l = cnt; ret = p->buf; } funlockfile(f); return ret; }