/*-------------------------------------------------------------------*/ char *http_root() { obtain_lock( &http_lock_root ); /* If the HTTP root directory is not specified, use a reasonable default */ if (!http_serv.httproot) { #if defined(_MSVC_) char process_dir[HTTP_PATH_LENGTH]; if (get_process_directory(process_dir,HTTP_PATH_LENGTH) > 0) { strlcat(process_dir,"\\html",HTTP_PATH_LENGTH); http_serv.httproot = strdup(process_dir); } else #endif /*defined(WIN32)*/ http_serv.httproot = strdup(HTTP_ROOT); } /* Convert the specified HTTPROOT value to an absolute path ending with a '/' and save in http_serv.httproot. */ { char absolute_httproot_path[HTTP_PATH_LENGTH]; int rc; #if defined(_MSVC_) /* Expand any embedded %var% environ vars */ rc = expand_environ_vars( http_serv.httproot, absolute_httproot_path, sizeof(absolute_httproot_path) ); if (rc == 0) { char *p = strdup(absolute_httproot_path);; if ( http_serv.httproot != NULL ) free(http_serv.httproot); http_serv.httproot = p; } #endif /* defined(_MSVC_) */ /* Convert to absolute path */ if (!realpath(http_serv.httproot, absolute_httproot_path)) { char msgbuf[MAX_PATH+3] = { 0 }; char *p = msgbuf; if ( strchr( http_serv.httproot, SPACE ) == NULL ) p = http_serv.httproot; else MSGBUF(msgbuf, "'%s'", http_serv.httproot); WRMSG(HHC01801, "E", p, strerror(errno)); release_lock( &http_lock_root ); return NULL; } /* Verify that the absolute path is valid */ // mode: 0 = exist only, 2 = write, 4 = read, 6 = read/write // rc: 0 = success, -1 = error (errno = cause) // ENOENT = File name or path not found. if (access( absolute_httproot_path, R_OK ) != 0) { char msgbuf[MAX_PATH+3]; char *p = absolute_httproot_path; if ( strchr( absolute_httproot_path, SPACE ) != NULL ) { MSGBUF(msgbuf, "'%s'", absolute_httproot_path); p = msgbuf; } WRMSG(HHC01801, "E", p, strerror(errno)); release_lock( &http_lock_root ); return p; } /* Append trailing [back]slash, but only if needed */ rc = (int)strlen(absolute_httproot_path); if (absolute_httproot_path[rc-1] != *HTTP_PS) strlcat(absolute_httproot_path,HTTP_PS,sizeof(absolute_httproot_path)); /* Save the absolute path */ free(http_serv.httproot); if (strlen(absolute_httproot_path) > MAX_PATH ) { char msgbuf[MAX_PATH+3] = { 0 }; char *p = msgbuf; if ( strchr( absolute_httproot_path, SPACE ) == NULL ) p = absolute_httproot_path; else MSGBUF(msgbuf, "'%s'", absolute_httproot_path); WRMSG(HHC01801, "E", p, "path length too long"); release_lock( &http_lock_root ); return NULL; } else { char pathname[MAX_PATH]; /* working pathname */ char msgbuf[MAX_PATH+3]; char *p = msgbuf; memset(msgbuf,0,sizeof(msgbuf)); hostpath(pathname, absolute_httproot_path, sizeof(pathname)); http_serv.httproot = strdup(pathname); if ( strchr( http_serv.httproot, SPACE ) == NULL ) p = http_serv.httproot; else MSGBUF(msgbuf, "'%s'", http_serv.httproot); WRMSG(HHC01802, "I", p); } } release_lock( &http_lock_root ); return http_serv.httproot; }
void *http_server (void *arg) { int rc; /* Return code */ int lsock; /* Socket for listening */ int csock; /* Socket for conversation */ struct sockaddr_in server; /* Server address structure */ fd_set selset; /* Read bit map for select */ int optval; /* Argument for setsockopt */ TID httptid; /* Negotiation thread id */ UNREFERENCED(arg); /* Display thread started message on control panel */ logmsg (_("HHCHT001I HTTP listener thread started: " "tid="TIDPAT", pid=%d\n"), thread_id(), getpid()); /* If the HTTP root directory is not specified, use a reasonable default */ if (!sysblk.httproot) { #if defined(_MSVC_) char process_dir[HTTP_PATH_LENGTH]; if (get_process_directory(process_dir,HTTP_PATH_LENGTH) > 0) { strlcat(process_dir,"\\html",HTTP_PATH_LENGTH); sysblk.httproot = strdup(process_dir); } else #endif /*defined(WIN32)*/ sysblk.httproot = strdup(HTTP_ROOT); } /* Convert the specified HTTPROOT value to an absolute path ending with a '/' and save in sysblk.httproot. */ { char absolute_httproot_path[HTTP_PATH_LENGTH]; int rc; #if defined(_MSVC_) /* Expand any embedded %var% environ vars */ rc = expand_environ_vars( sysblk.httproot, absolute_httproot_path, sizeof(absolute_httproot_path) ); if (rc == 0) { free(sysblk.httproot); sysblk.httproot = strdup(absolute_httproot_path); } #endif /* defined(_MSVC_) */ /* Convert to absolute path */ if (!realpath(sysblk.httproot,absolute_httproot_path)) { logmsg( _("HHCCF066E Invalid HTTPROOT: \"%s\": %s\n"), sysblk.httproot, strerror(errno)); return NULL; } /* Verify that the absolute path is valid */ // mode: 0 = exist only, 2 = write, 4 = read, 6 = read/write // rc: 0 = success, -1 = error (errno = cause) // ENOENT = File name or path not found. if (access( absolute_httproot_path, R_OK ) != 0) { logmsg( _("HHCCF066E Invalid HTTPROOT: \"%s\": %s\n"), absolute_httproot_path, strerror(errno)); return NULL; } /* Append trailing [back]slash, but only if needed */ rc = strlen(absolute_httproot_path); if (absolute_httproot_path[rc-1] != *HTTP_PS) strlcat(absolute_httproot_path,HTTP_PS,sizeof(absolute_httproot_path)); /* Save the absolute path */ free(sysblk.httproot); sysblk.httproot = strdup(absolute_httproot_path); logmsg(_("HHCHT013I Using HTTPROOT directory \"%s\"\n"),sysblk.httproot); } /* Obtain a socket */ lsock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); if (lsock < 0) { logmsg(_("HHCHT002E socket: %s\n"), strerror(HSO_errno)); return NULL; } /* Allow previous instance of socket to be reused */ optval = 1; setsockopt (lsock, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, sizeof(optval)); /* Prepare the sockaddr structure for the bind */ memset (&server, 0, sizeof(server)); server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = sysblk.httpport; server.sin_port = htons(server.sin_port); /* Attempt to bind the socket to the port */ while (TRUE) { rc = bind (lsock, (struct sockaddr *)&server, sizeof(server)); if (rc == 0 || HSO_errno != HSO_EADDRINUSE) break; logmsg (_("HHCHT003W Waiting for port %u to become free\n"), sysblk.httpport); SLEEP(10); } /* end while */ if (rc != 0) { logmsg(_("HHCHT004E bind: %s\n"), strerror(HSO_errno)); return NULL; } /* Put the socket into listening state */ rc = listen (lsock, 32); if (rc < 0) { logmsg(_("HHCHT005E listen: %s\n"), strerror(HSO_errno)); return NULL; } logmsg(_("HHCHT006I Waiting for HTTP requests on port %u\n"), sysblk.httpport); /* Handle http requests */ while (sysblk.httpport) { /* Initialize the select parameters */ FD_ZERO (&selset); FD_SET (lsock, &selset); /* Wait for a file descriptor to become ready */ rc = select ( lsock+1, &selset, NULL, NULL, NULL ); if (rc == 0) continue; if (rc < 0 ) { if (HSO_errno == HSO_EINTR) continue; logmsg(_("HHCHT007E select: %s\n"), strerror(HSO_errno)); break; } /* If a http request has arrived then accept it */ if (FD_ISSET(lsock, &selset)) { /* Accept the connection and create conversation socket */ csock = accept (lsock, NULL, NULL); if (csock < 0) { logmsg(_("HHCHT008E accept: %s\n"), strerror(HSO_errno)); continue; } /* Create a thread to execute the http request */ if ( create_thread (&httptid, DETACHED, http_request, (void *)(uintptr_t)csock, "http_request") ) { logmsg(_("HHCHT010E http_request create_thread: %s\n"), strerror(errno)); close_socket (csock); } } /* end if(lsock) */ } /* end while */ /* Close the listening socket */ close_socket (lsock); /* Display thread started message on control panel */ logmsg (_("HHCHT009I HTTP listener thread ended: " "tid="TIDPAT", pid=%d\n"), thread_id(), getpid()); sysblk.httptid = 0; return NULL; } /* end function http_server */