Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Добавил exam06 - более короткую и рабочую версию. + Добавил описание проекта в README.md. #14

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 27 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
# :white_check_mark: EXAM (project 2020-2022)
Exams of the new graph.
Subjects are in the folder of each exercises, along with a solution and a test file.
At the same time, I have presented the code as a sample for solving each of the functions.if you find any bug, write to "issues".
## :white_check_mark: Exam Rank 02
Original link to the subjects repository: [click](https://github.com/Glagan/42-exam-rank-02)
At the same time, I have presented the code as a sample for solving each of the functions.if you find any bug, write to "issues".
## :white_check_mark: Exam Rank 02
Original link to the subjects repository: [click](https://github.com/Glagan/42-exam-rank-02)


| Title | Description | Allowed functions | level of difficulty |
|:-----:|-------------|-------------------|:-------------------:|
| ft_printf | Write a function named `ft_printf` that will mimic the real printf | malloc, free, write, va_start, va_arg, va_copy, va_end |:star::star::star::star:|
| get_next_line |Write a function will store, in the parameter "line", a line that has been read from the file descriptor 0|read, free, malloc|:star::star::star:|
| inter |Write a program that takes two strings and displays, without doubles, the characters that appear in both strings, in the order they appear in the first one.|write|:star::star:|
| union |Write a program that takes two strings and displays, without doubles, the characters that appear in either one of the strings.|write|:star:|

## :white_check_mark: Exam Rank 03
Original link to the subjects repository: [click](https://github.com/Glagan/42-exam-rank-03)
## :white_check_mark: Exam Rank 03
Original link to the subjects repository: [click](https://github.com/Glagan/42-exam-rank-03)


| Title | Description | Allowed functions | level of difficulty |
|:-----:|-------------|-------------------|:-------------------:|
| micro_paint |Write a program that will read an "operation file" and print the result in the terminal (rectangle)|fopen, fread, fscanf, fclose, write, malloc, calloc, realloc, free, memset, powf, sqrtf|:star::star::star:|
Expand All @@ -26,10 +26,10 @@ Original link to the subjects repository: [click](https://github.com/Glagan/42-e
![](https://github.com/markveligod/exam/raw/master/examRank03/img/micro.gif)
![](https://github.com/markveligod/exam/raw/master/examRank03/img/mini.gif)

## :white_check_mark: Exam Rank 04
Original link to the subjects repository: [click](https://github.com/Glagan/42-exam-rank-04)
## :white_check_mark: Exam Rank 04
Original link to the subjects repository: [click](https://github.com/Glagan/42-exam-rank-04)


| Title | Description | Allowed functions | level of difficulty |
|:-----:|-------------|-------------------|:-------------------:|
| microshell |Write a program that will behave like executing a shell command|malloc, free, write, close, fork, waitpid, signal, kill, exit, chdir, execve, dup, dup2, pipe, strcmp, strncmp|:star::star::star::star:|
Expand All @@ -53,11 +53,21 @@ To check for leaked file descriptors, use the command `lsof -c microshell`. Pay


## :white_check_mark: Exam Rank 06
:bangbang: Attention: on the exam on the first attempt, the 8 test will fail. Just do grademe again.
:bangbang: Attention: on the exam on the first attempt, the 8 test will fail. Just do grademe again.

Original link to the subjects repository: *in this repo*

| Title | Description | Allowed functions | level of difficulty |
|:---------:|----------------|-------------------|:----------------:|
| mini_serv | Write a program that will listen for client to connect on a certain port on 127.0.0.1 and will let clients to speak with each other |write, close, select, socket, accept, listen, send, recv, bind, strstr, malloc, realloc, free, calloc, bzero, atoi, sprintf, strlen, exit, strcpy, strcat, memset|:star::star::star:|

## 📫 Other
:bangbang: Attention: if you see any changes in the exam or there is a more elegant solution, make a pull request.

**:copyright:Authors:**

*[Mark Veligod](https://github.com/markveligod)*
**:copyright:Authors:**

*[Mark Veligod](https://github.com/markveligod)*

**Helper**

*[Belenov Andrey](https://github.com/luchikAR)*
278 changes: 75 additions & 203 deletions examRank06/mini_serv.c
Original file line number Diff line number Diff line change
@@ -1,224 +1,96 @@
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <stdio.h>

typedef struct s_client
{
int fd;
int id;
struct s_client *next;
} t_client;

t_client *g_clients = NULL;

int sock_fd, g_id = 0;
fd_set curr_sock, cpy_read, cpy_write;
char msg[42];
char str[42*4096], tmp[42*4096], buf[42*4096 + 42];

void fatal()
{
write(2, "Fatal error\n", strlen("Fatal error\n"));
close(sock_fd);
exit(1);
}

int get_id(int fd)
{
t_client *temp = g_clients;

while (temp)
{
if (temp->fd == fd)
return (temp->id);
temp = temp->next;
}
return (-1);
}

int get_max_fd()
{
int max = sock_fd;
t_client *temp = g_clients;

while (temp)
{
if (temp->fd > max)
max = temp->fd;
temp = temp->next;
}
return (max);
}

void send_all(int fd, char *str_req)
{
t_client *temp = g_clients;

while (temp)
{
if (temp->fd != fd && FD_ISSET(temp->fd, &cpy_write))
{
if (send(temp->fd, str_req, strlen(str_req), 0) < 0)
fatal();
}
temp = temp->next;
}
}

int add_client_to_list(int fd)
{
t_client *temp = g_clients;
t_client *new;

if (!(new = calloc(1, sizeof(t_client))))
fatal();
new->id = g_id++;
new->fd = fd;
new->next = NULL;
if (!g_clients)
{
g_clients = new;
}
else
{
while (temp->next)
temp = temp->next;
temp->next = new;
}
return (new->id);
}

void add_client()
{
struct sockaddr_in clientaddr;
socklen_t len = sizeof(clientaddr);
int client_fd;

if ((client_fd = accept(sock_fd, (struct sockaddr *)&clientaddr, &len)) < 0)
fatal();
sprintf(msg, "server: client %d just arrived\n", add_client_to_list(client_fd));
send_all(client_fd, msg);
FD_SET(client_fd, &curr_sock);
}

int rm_client(int fd)
{
t_client *temp = g_clients;
t_client *del;
int id = get_id(fd);

if (temp && temp->fd == fd)
{
g_clients = temp->next;
free(temp);
}
else
{
while(temp && temp->next && temp->next->fd != fd)
temp = temp->next;
del = temp->next;
temp->next = temp->next->next;
free(del);
}
return (id);
void fatal_error() {
write(2, "Fatal error\n", 12);
exit(1);
}

void ex_msg(int fd)
{
int i = 0;
int j = 0;
char str_buf[42*4096], read_buf[42*4096], write_buf[42*4096+42];
int array_fd[65536], max_fd = 0, next_fd = 0;
fd_set active, ready_read, ready_write;

while (str[i])
{
tmp[j] = str[i];
j++;
if (str[i] == '\n')
{
sprintf(buf, "client %d: %s", get_id(fd), tmp);
send_all(fd, buf);
j = 0;
bzero(&tmp, strlen(tmp));
bzero(&buf, strlen(buf));
}
i++;
void send_all(int except_sock) {
int len = strlen(write_buf);
for (int sock = 0; sock <= max_fd; ++sock) {
if (FD_ISSET(sock, &ready_write) && sock != except_sock)
send(sock, write_buf, len, 0);
}
bzero(&str, strlen(str));
return ;
}

int main(int ac, char **av)
{
if (ac != 2)
{
write(2, "Wrong number of arguments\n", strlen("Wrong number of arguments\n"));
int main(int argc, char **argv) {
if (argc != 2) {
write(2, "Wrong number of arguments\n", 26);
exit(1);
}

struct sockaddr_in servaddr;
uint16_t port = atoi(av[1]);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(2130706433); //127.0.0.1
servaddr.sin_port = htons(port);

if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
fatal();
if (bind(sock_fd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
fatal();
if (listen(sock_fd, 0) < 0)
fatal();

FD_ZERO(&curr_sock);
FD_SET(sock_fd, &curr_sock);
bzero(&tmp, sizeof(tmp));
bzero(&buf, sizeof(buf));
bzero(&str, sizeof(str));
while(1)
{
cpy_write = cpy_read = curr_sock;
if (select(get_max_fd() + 1, &cpy_read, &cpy_write, NULL, NULL) < 0)
int port = atoi(argv[1]);
FD_ZERO(&active);
bzero(array_fd, sizeof(array_fd));

int server = socket(AF_INET, SOCK_STREAM, 0);
if (server < 0)
fatal_error();
max_fd = server;
FD_SET(server, &active);

struct sockaddr_in addr;
socklen_t addr_len = sizeof(addr);
bzero(&addr, addr_len);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = (1 << 24) | 127;
addr.sin_port = (port >> 8) | (port << 8);

if (bind(server, &addr, addr_len) < 0)
fatal_error();
if (listen(server, SOMAXCONN) < 0)
fatal_error();

while (1) {
ready_read = ready_write = active;
if (select(max_fd + 1, &ready_read, &ready_write, 0, 0) < 0)
continue;
for (int fd = 0; fd <= get_max_fd(); fd++)
{
if (FD_ISSET(fd, &cpy_read))
{
if (fd == sock_fd)
{
bzero(&msg, sizeof(msg));
add_client();
break;
for (int sock = 0; sock <= max_fd; ++sock) {
if (FD_ISSET(sock, &ready_read) && sock == server) {
int client = accept(server, &addr, &addr_len);
if (client < 0)
continue ;
if (client > max_fd)
max_fd = client;
array_fd[client] = next_fd++;
FD_SET(client, &active);
sprintf(write_buf, "server: client %d just arrived\n", array_fd[client]);
send_all(client);
break ;
}
if (FD_ISSET(sock, &ready_read) && sock != server) {
int read_count = recv(sock, read_buf, 42*4096, 0);
if (read_count <= 0) {
sprintf(write_buf, "server: client %d just left\n", array_fd[sock]);
send_all(sock);
FD_CLR(sock, &active);
close(sock);
break ;
}
else
{
int ret_recv = 1000;
while (ret_recv == 1000 || str[strlen(str) - 1] != '\n')
{
ret_recv = recv(fd, str + strlen(str), 1000, 0);
if (ret_recv <= 0)
break ;
}
if (ret_recv <= 0)
{
bzero(&msg, sizeof(msg));
sprintf(msg, "server: client %d just left\n", rm_client(fd));
send_all(fd, msg);
FD_CLR(fd, &curr_sock);
close(fd);
break;
}
else
{
ex_msg(fd);
else {
for (int i = 0, j = 0; i < read_count; ++i, ++j) {
str_buf[j] = read_buf[i];
if (str_buf[j] == '\n' || i == read_count - 1) {
str_buf[j] = '\0';
sprintf(write_buf, "client %d: %s\n", array_fd[sock], str_buf);
send_all(sock);
j = -1;
}
}
}
}

}

}
return (0);
}
return 0;
}