/* print - print a message */ void print(int msg) { int ch; msg_open(msg); while (ch = msg_byte()) trm_chr(ch); }
/* * PUBLIC: int f_msgcat __P((SCR *, OPTION *, char *, u_long *)); */ int f_msgcat( SCR *sp, OPTION *op, char *str, u_long *valp) { (void)msg_open(sp, str); return (0); }
extern void daemon_init(msg_dest_t log_dest, const char *program, int facility, const char *pidfile, const char *username, const char *groupname) { pid_t pid; int i; FILE *pid_fp; int sigs[] = { SIGHUP, SIGINT, SIGQUIT, SIGTSTP, SIGTTIN, SIGTTOU }; struct passwd *pw; struct group *grp; /* make sure all those nice signals are going to be ignored */ for (i = 0; i < sizeof(sigs) / sizeof(int); i++) { if (!_daemon_handle_signal(sigs[i], SIG_IGN)) { msg_log(LOG_ERR, "Fatal error in daemon_init(): %s\n", strerror(errno)); exit(EXIT_FAILURE); } } /* stalking off to background... */ switch (pid = fork()) { case -1: msg_log(LOG_ERR, "Fatal error in fork(): %s\n", strerror(errno)); exit(EXIT_FAILURE); break; case 0: msg_close(); msg_open(log_dest, program, LOG_PID, facility); break; default: exit(EXIT_SUCCESS); break; } /* get rid of the associated terminal */ if (setsid() < 0) { msg_log(LOG_ERR, "Fatal error in setsid(): %s\n", strerror(errno)); exit(EXIT_FAILURE); } /* make sure we cannot be prosecuted by a not yet controlling terminal */ switch (pid = fork()) { case -1: msg_log(LOG_ERR, "Fatal error in fork(): %s\n", strerror(errno)); exit(EXIT_FAILURE); break; case 0: break; default: exit(EXIT_SUCCESS); break; } /* close unnecessary file descriptors */ close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); /* change working directory */ chdir("/"); /* set default file mode creation mask */ umask(0); /* write PID to pidfile */ if (NULL != pidfile) { pid_fp = fopen(pidfile, "w"); if (NULL == pid_fp) { msg_log(LOG_ERR, "Fatal error in fopen(): %s\n", strerror(errno)); exit(EXIT_FAILURE); } fprintf(pid_fp, "%d", (int)getpid()); fclose(pid_fp); } /* change user and group id */ if (NULL != groupname) { grp = getgrnam(groupname); /* using a non-threadsafe function is ok here */ if (0 != setgid(grp->gr_gid)) msg_log(LOG_WARNING, "Unable to change GID to %d (%s): %s\n", (int)grp->gr_gid, groupname, strerror(errno)); else msg_log(LOG_INFO, "Changed GID to %d (%s)\n", (int)grp->gr_gid, groupname); } if (NULL != username) { pw = getpwnam(username); /* using a non-threadsafe function is ok here */ if (0 != setuid(pw->pw_uid)) msg_log(LOG_WARNING, "Unable to change UID to %d (%s): %s\n", (int)pw->pw_uid, username, strerror(errno)); else msg_log(LOG_INFO, "Changed UID to %d (%s)\n", (int)pw->pw_uid, username); } }
void exread( int sockfd ) { void* ptr; conn_data_t* conn_data = connections[ sockfd ]; if ( !conn_data->buffer ) { conn_data->buffer = malloc(PACK_DATA_SIZE); conn_data->bufferlen = 0; memset( conn_data->buffer, 0, PACK_DATA_SIZE ); } website_t* website; ssize_t len = zs_read( sockfd, conn_data->buffer + conn_data->bufferlen, PACK_DATA_SIZE - conn_data->bufferlen ); // TODO: wait for entire header before looking up website if ( len <= 0 ) { cleanup: // cleanup cleanup_connection( sockfd ); return; } if ( conn_data->postlen == -1 ) /* if we have received all the data already, ignore */ return; conn_data->bufferlen += len; //printf( "%d: read %zu\n", sockfd, len ); ptr = conn_data->buffer; if ( conn_data->website_sockfd == -1 ) { /* If req_info is NULL this is the start of a request and the HTTP request headers need to be parsed. */ struct hostent* hp; hp = NULL;//gethostbyaddr( (char*) &conn_data->addr, sizeof( conn_data->addr ), AF_INET ); char* endofhdrs; if ( !( endofhdrs = strnstr( conn_data->buffer, HTTP_HDR_ENDL HTTP_HDR_ENDL, PACK_DATA_SIZE ) ) ) { if ( conn_data->bufferlen == PACK_DATA_SIZE ) { /* If the end of the headers was not found the request was either malformatted or too long, DO NOT send to website. */ zs_write( sockfd, html_error_414, sizeof( html_error_414 ) ); syslog( LOG_WARNING, "exread: headers to long" ); goto cleanup; } // Have not received the full header yet, wait zs_set_read( sockfd ); return; } endofhdrs += sizeof( HTTP_HDR_ENDL HTTP_HDR_ENDL ) - 1; /* Get HTTP request type */ if ( startswith( conn_data->buffer, HTTP_GET ) ) conn_data->request_type = HTTP_GET_TYPE; else if ( startswith( conn_data->buffer, HTTP_POST ) ) conn_data->request_type = HTTP_POST_TYPE; else { zs_write( sockfd, html_error_400, sizeof( html_error_400 ) ); goto cleanup; } /* Find website for request from HTTP header */ char urlbuf[ PACK_DATA_SIZE ]; if ( !get_url_from_http_header( conn_data->buffer, urlbuf, sizeof( urlbuf ) ) ) { //syslog( LOG_WARNING, "exread: no url found in http request headers: %s %s", // inet_ntoa( conn_data->addr.sin_addr ), hp ? hp->h_name : "" ); zs_write( sockfd, html_error_400, sizeof( html_error_400 ) ); goto cleanup; } if ( !( website = website_find( urlbuf, conn_data->is_https ? "https://" : "http://", inet_ntoa( zs_get_addr( conn_data->exlisnfd )->sin_addr ) ) ) ) { //syslog( LOG_WARNING, "exread: no website to service request: %s %s %s", // inet_ntoa( conn_data->addr.sin_addr ), hp ? hp->h_name : "", urlbuf ); zs_write( sockfd, html_error_404, sizeof( html_error_404 ) ); goto cleanup; } /* Set the website id so that furthur sections of this request can check if the website is still alive. */ conn_data->website_sockfd = website->sockfd; /* Check the websites socket to make sure the request came in on the right socket. */ website_data_t* website_data = website->udata; if ( website_data->exlisnfd != conn_data->exlisnfd ) { //syslog( LOG_WARNING, "exread: no website to service request: %s %s %s", // inet_ntoa( conn_data->addr.sin_addr ), hp ? hp->h_name : "", urlbuf ); zs_write( sockfd, html_error_404, sizeof( html_error_404 ) ); goto cleanup; } //printf( "%s\n", buffer ); /* Create a new message to send the request to the corresponding website. The msgid should be set to the external file descriptor to send the response back to. */ conn_data->msgid = msg_open( website->sockfd, sockfd ); zs_set_write( sockfd ); // If request_type is POST check if there is content after the HTTP header char postlenbuf[ 32 ]; memset( postlenbuf, 0, sizeof( postlenbuf ) ); if ( conn_data->request_type == HTTP_POST_TYPE && ( ptr = strnstr( conn_data->buffer, "Content-Length: ", PACK_DATA_SIZE ) ) ) { char* tmp = strnstr( ptr + 16, HTTP_HDR_ENDL, PACK_DATA_SIZE - ( (long)ptr + 16 - (long)conn_data->buffer ) ); if ( !tmp ) { zs_write( sockfd, html_error_400, sizeof( html_error_400 ) ); goto cleanup; } memcpy( postlenbuf, ptr + 16, (long) tmp - (long) ( ptr + 16 ) ); conn_data->postlen = strtoumax( postlenbuf, NULL, 0 ); if ( conn_data->postlen < 0 ) { zs_write( sockfd, html_error_400, sizeof( html_error_400 ) ); goto cleanup; } } // Write the message length size_t msglen = ( endofhdrs - conn_data->buffer ) + conn_data->postlen + sizeof( conn_data->addr.sin_addr ) + 1; if ( hp ) msglen += strlen( hp->h_name ); if ( msg_write( website->sockfd, conn_data->msgid, (void*) &msglen, sizeof( size_t ) ) == -1 ) { zs_write( sockfd, html_error_502, sizeof( html_error_502 ) ); goto cleanup; } // Write the ip address and hostname of the request if ( msg_write( website->sockfd, conn_data->msgid, (void*) &conn_data->addr.sin_addr, sizeof( conn_data->addr.sin_addr ) ) == -1 || ( hp && msg_write( website->sockfd, conn_data->msgid, (void*) hp->h_name, strlen( hp->h_name ) ) == -1 ) || msg_write( website->sockfd, conn_data->msgid, (void*) "\0", 1 ) == -1 ) { zs_write( sockfd, html_error_502, sizeof( html_error_502 ) ); goto cleanup; } // Send the whole header to the website if ( msg_write( website->sockfd, conn_data->msgid, (void*) conn_data->buffer, ( endofhdrs - conn_data->buffer ) ) == -1 ) { zs_write( sockfd, html_error_502, sizeof( html_error_502 ) ); goto cleanup; } ptr = endofhdrs; } else { if ( !( website = website_get_by_sockfd( conn_data->website_sockfd ) ) ) { // syslog( LOG_WARNING, "exread: no website to service request" ); zs_write( sockfd, html_error_502, sizeof( html_error_502 ) ); goto cleanup; } } if ( conn_data->request_type == HTTP_POST_TYPE && conn_data->postlen ) { int left = conn_data->bufferlen - ( ptr - (void*)conn_data->buffer ); if ( left > conn_data->postlen ) conn_data->postlen = left; if ( msg_write( website->sockfd, conn_data->msgid, (void*) ptr, left ) == -1 ) { zs_write( sockfd, html_error_502, sizeof( html_error_502 ) ); goto cleanup; } conn_data->postlen -= left; } if ( !conn_data->postlen ) { /* If there isn't more data coming, */ msg_flush( website->sockfd, conn_data->msgid ); /* must make sure to keep sockfd in read mode to detect a connection close from the other end */ conn_data->postlen = -1; zs_set_read( sockfd ); } else msg_set_write( website->sockfd, conn_data->msgid ); free( conn_data->buffer ); conn_data->buffer = NULL; //printf( "%d: still needs %d post data\n", sockfd, conn_data->postlen ); }