Files
CS-LABS/mine/lab_6/kirill/server.c
2025-12-10 16:50:28 +07:00

186 lines
4.7 KiB
C

// server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <semaphore.h>
#include <unistd.h>
#define SHM_BUFFER_SIZE 1024
typedef struct {
int has_data;
int result_code;
char buffer[SHM_BUFFER_SIZE];
} shared_block_t;
static void process_line(char *s) {
if (!s) return;
for (size_t i = 0; s[i] != '\0'; ++i) {
if ((i + 1) % 3 == 0) {
s[i] = ' ';
}
}
}
int main(int argc, char *argv[]) {
if (argc < 4) {
fprintf(stderr,
"Usage: %s <shm_name> <sem_client_name> <sem_server_name> [iterations]\n",
argv[0]);
return -1;
}
const char *shm_name = argv[1];
const char *sem_client_name = argv[2];
const char *sem_server_name = argv[3];
int iterations = -1;
if (argc >= 5) {
char *endptr = NULL;
unsigned long tmp = strtoul(argv[4], &endptr, 10);
if (endptr == argv[4] || *endptr != '\0') {
fprintf(stderr, "Invalid iterations value: '%s'\n", argv[4]);
return -1;
}
iterations = (int) tmp;
}
shm_unlink(shm_name);
sem_unlink(sem_client_name);
sem_unlink(sem_server_name);
int shm_fd = shm_open(shm_name,
O_CREAT | O_EXCL | O_RDWR,
S_IRUSR | S_IWUSR);
if (shm_fd == -1) {
perror("shm_open");
return -1;
}
if (ftruncate(shm_fd, sizeof(shared_block_t)) == -1) {
perror("ftruncate");
close(shm_fd);
shm_unlink(shm_name);
return -1;
}
shared_block_t *shm_ptr = mmap(NULL,
sizeof(shared_block_t),
PROT_READ | PROT_WRITE,
MAP_SHARED,
shm_fd,
0);
if (shm_ptr == MAP_FAILED) {
perror("mmap");
close(shm_fd);
shm_unlink(shm_name);
return -1;
}
if (close(shm_fd) == -1) {
perror("close");
}
shm_ptr->has_data = 0;
shm_ptr->result_code = 0;
memset(shm_ptr->buffer, 0, sizeof(shm_ptr->buffer));
sem_t *sem_client = sem_open(sem_client_name,
O_CREAT | O_EXCL,
S_IRUSR | S_IWUSR,
0);
if (sem_client == SEM_FAILED) {
perror("sem_open(sem_client)");
munmap(shm_ptr, sizeof(shared_block_t));
shm_unlink(shm_name);
return -1;
}
sem_t *sem_server = sem_open(sem_server_name,
O_CREAT | O_EXCL,
S_IRUSR | S_IWUSR,
0);
if (sem_server == SEM_FAILED) {
perror("sem_open(sem_server)");
sem_close(sem_client);
sem_unlink(sem_client_name);
munmap(shm_ptr, sizeof(shared_block_t));
shm_unlink(shm_name);
return -1;
}
FILE *fout = fopen("output.txt", "w");
if (!fout) {
perror("fopen(output.txt)");
}
int processed_count = 0;
while (iterations < 0 || processed_count < iterations) {
if (sem_wait(sem_client) == -1) {
perror("sem_wait(sem_client)");
processed_count = -1;
break;
}
if (!shm_ptr->has_data) {
fprintf(stderr, "Warning: sem_client posted, but has_data == 0\n");
shm_ptr->result_code = -1;
} else {
process_line(shm_ptr->buffer);
shm_ptr->result_code = 0;
shm_ptr->has_data = 0;
processed_count++;
if (fout) {
fprintf(fout, "%s\n", shm_ptr->buffer);
fflush(fout);
}
}
if (sem_post(sem_server) == -1) {
perror("sem_post(sem_server)");
processed_count = -1;
break;
}
}
if (fout && fclose(fout) == EOF) {
perror("fclose(output.txt)");
}
if (processed_count >= 0) {
printf("%d\n", processed_count);
} else {
printf("-1\n");
}
if (sem_close(sem_client) == -1) {
perror("sem_close(sem_client)");
}
if (sem_close(sem_server) == -1) {
perror("sem_close(sem_server)");
}
if (sem_unlink(sem_client_name) == -1) {
perror("sem_unlink(sem_client)");
}
if (sem_unlink(sem_server_name) == -1) {
perror("sem_unlink(sem_server)");
}
if (munmap(shm_ptr, sizeof(shared_block_t)) == -1) {
perror("munmap");
}
if (shm_unlink(shm_name) == -1) {
perror("shm_unlink");
}
return 0;
}