Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdbool.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <signal.h>
- #include <stdint.h>
- #include <stdarg.h>
- //on success, returns a non-negative socket file descriptor,
- //and sets *clientaddr if clientaddr is not NULL
- //on failure, returns a negative error code, and errno is set accordingly
- int forklisten(uint16_t port, uint32_t* clientaddr) {
- //open socket
- int sock = socket(AF_INET, SOCK_STREAM, 0);
- if(sock < 0)
- return -1;
- //fill serv_addr_in struct
- struct sockaddr_in srvaddr;
- srvaddr.sin_family = AF_INET;
- srvaddr.sin_port = htons(port); //listen on the given port
- srvaddr.sin_addr.s_addr = htonl(INADDR_ANY); //listen on any address
- //bind the socket
- if(bind(sock, (struct sockaddr*) &srvaddr, sizeof(srvaddr)) < 0)
- return -2;
- //listen for new connections on the socket
- //the backlog value of 5 indicates that 5 outstanding connections should be allowed to remain in the listening queue
- if(listen(sock, 5) < 0)
- return -3;
- //ignore child process termination
- signal(SIGCHLD, SIG_IGN);
- int chldsock;
- //the parent process will forever stay in this loop
- while(true) {
- //wait for a new connection and accept it
- struct sockaddr_in cliaddr;
- unsigned int cliaddrlen = sizeof(cliaddr);
- if((chldsock = accept(sock, (struct sockaddr*) &cliaddr, &cliaddrlen)) < 0)
- return -4;
- //fork off a child
- switch(fork()) {
- case -1:
- //the fork() failed, so clean up the sockets and fail
- close(chldsock);
- close(sock);
- return -5;
- case 0:
- //we're the child process, so we don't need sock
- close(sock);
- //set the client address
- if(clientaddr && cliaddrlen)
- *clientaddr = ntohl(cliaddr.sin_addr.s_addr);
- return chldsock;
- default:
- //we're the parent process, so we don't need chldsock
- close(chldsock);
- }
- }
- }
- inline int fdputs(const char* str, int fd) {
- return write(fd, str, strlen(str));
- }
- //returns the number of bytes written to the fd on success
- //on failure, returns a negative error number and sets errval accordingly
- int fdprintf(int fd, const char *format, ...) {
- //basically GNU asprintf
- const unsigned buf_size = 16;
- char* buf = (char*) malloc(sizeof(char) * buf_size);
- if(!buf)
- return -1;
- va_list vl;
- //first, try to vsnprintf to a buffer of length 16
- va_start(vl, format);
- unsigned len = vsnprintf(buf, buf_size, format, vl);
- va_end(vl);
- //if that wasn't enough, allocate more memory and try again
- if (len >= buf_size) {
- buf = (char*) realloc(buf, sizeof(char) * (len + 1));
- if(!buf)
- return -1;
- va_start(vl, format);
- vsnprintf(buf, len + 1, format, vl);
- va_end(vl);
- }
- //output buf to the socket
- int result = fdputs(buf, fd);
- //free the buffer
- free(buf);
- return result;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement