Inhaltsverzeichnis

September 2005

Aufgabe 1

Aufgabe 2

sem.c:

#include <stdlib.h>
#include <stdio.h>
#include "sem.h"
 
SEM *sem_init(int n) {
    SEM *s;
    s = (SEM *) malloc(sizeof(SEM));
    if (s == NULL) {
        perror("malloc");
        exit(EXIT_FAILURE);
    }
    pthread_mutex_init(&s->m, NULL);
    pthread_cond_init(&s->c, NULL);
    s->s = n;
 
    return s;
}
 
void P(SEM *s) {
    pthread_mutex_lock(&s->m);
    while (s->s < 1) {
        pthread_cond_wait(&s->c, &s->m);
    }
    s->s--;
    pthread_mutex_unlock(&s->m);
}
 
void V(SEM *s) {
    pthread_mutex_lock(&s->m);
    s->s++;
    pthread_cond_broadcast(&s->c);
    pthread_mutex_unlock(&s->m);
}

fdserver.c:

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <dirent.h>
#include <sys/stat.h>
#include <pthread.h>
#include <string.h>
 
#include "sem.h"
 
#define NTHREAD 25
 
void *serve(void *arg);
void handle(FILE *socket, char path[]);
void fhandle(FILE *socket, char path[]);
void dhandle(FILE *socket, char path[]);
 
struct bufinfo {
    SEM *sem_full;
    SEM *sem_free;
    pthread_mutex_t lock;
 
    int socks[NTHREAD];
    int writep;
    int readp;
};
 
int main(int argc, char *argv[]) {
    struct bufinfo b;
    pthread_t tid[NTHREAD];
    int i;
    int sock;
    struct sockaddr_in saddr;
 
    b.writep = 0;
    b.readp = 0;
    b.sem_full = sem_init(0);
    b.sem_free = sem_init(NTHREAD);
    pthread_mutex_init(&b.lock, NULL);
 
    for (i = 0; i < NTHREAD; i++) {
        pthread_create(&tid[i], NULL, serve, &b);
    }
 
    sock = socket(PF_INET, SOCK_STREAM, 0);
    if (sock == -1) {
        perror("socket");
        return EXIT_FAILURE;
    }
 
    saddr.sin_family = AF_INET;
    saddr.sin_port = argc > 1 ? htons(atoi(argv[1])) : htons(31337);
    saddr.sin_addr.s_addr = htonl(INADDR_ANY);
 
    if (bind(sock, (struct sockaddr *) &saddr, sizeof(saddr)) == -1) {
        perror("bind");
        return EXIT_FAILURE;
    }
    if (listen(sock, 20) == -1) {
        perror("listen");
        return EXIT_FAILURE;
    }
 
    while (1) {
        int clsock;
        struct sockaddr clsaddr;
        socklen_t clsaddr_len = sizeof(clsaddr);
 
        clsock = accept(sock, &clsaddr, &clsaddr_len);
        if (clsock == -1) {
            perror("accept");
            continue;
        }
 
        P(b.sem_free);
        b.socks[b.writep] = clsock;
        b.writep = (b.writep + 1) % NTHREAD;
        V(b.sem_full);
 
    }
 
    return 0;
}
 
void *serve(void *arg) {
    struct bufinfo *b = (struct bufinfo *) arg;
    int s;
    FILE *fd;
    char buffer[1024+2];
 
    P(b->sem_full);
    pthread_mutex_lock(&b->lock); 
    s = b->socks[b->readp];
    b->readp = (b->readp + 1) % NTHREAD;
    pthread_mutex_unlock(&b->lock);
    V(b->sem_free);
 
    fd = fdopen(s, "r+");
 
    while (fgets(buffer, 1024+2, fd) != NULL) {
        buffer[strlen(buffer)-1] = '\0';
        handle(fd, buffer);
    }
 
    return NULL;
}
 
void handle(FILE *socket, char path[]) {
    struct stat statinfo;
 
    if (stat(path, &statinfo) == -1) {
        fprintf(socket, "%s\n", strerror(errno));
        return;
    }
 
    if (S_ISDIR(statinfo.st_mode)) {
        dhandle(socket, path);
    } else if (S_ISREG(statinfo.st_mode)) {
        fhandle(socket, path);
    } else {
        fprintf(socket, "Error: Something special, but not a file or directory\n");
        return;
    }
}
 
void fhandle(FILE *socket, char path[]) {
    char buf[1024+2];
    FILE *fd;
 
    fd = fopen(path, "r");
    if (fd == NULL) {
        fprintf(socket, "%s\n", strerror(errno));
        return;
    }
 
    while (fgets(buf, 1024+2, fd) != NULL) {
        if (fputs(buf, socket) == EOF) {
            perror("errno");
            return;
        }
    } 
}
 
void dhandle(FILE *socket, char path[]) {
    DIR *dir;
    struct dirent entry;
    struct dirent *result;
    int err;
 
    dir = opendir(path);
    if (dir == NULL) {
       fprintf(socket, "Error: %s\n", strerror(errno));
    }
 
    while(((err = readdir_r(dir, &entry, &result)) == 0) && result != NULL) {
        fprintf(socket, "%s\n", entry.d_name);
    }
}

Aufgabe 3