/* * write lines of text * * return -1 on error or bytecount */ static int writeline(char *buf, int len, netbuf *nData) { int x, nb=0, w; char *ubp = buf, *nbp; char lc=0; if (nData->dir != FTPLIB_WRITE) return -1; nbp = nData->buf; for (x=0; x < len; x++) { if ((*ubp == '\n') && (lc != '\r')) { if (nb == FTPLIB_BUFSIZ) { if (!socket_wait(nData)) return x; w = net_write(nData->handle, nbp, FTPLIB_BUFSIZ); if (w != FTPLIB_BUFSIZ) { printf("net_write(1) returned %d, errno = %d\n", w, errno); return(-1); } nb = 0; } nbp[nb++] = '\r'; } if (nb == FTPLIB_BUFSIZ) { if (!socket_wait(nData)) return x; w = net_write(nData->handle, nbp, FTPLIB_BUFSIZ); if (w != FTPLIB_BUFSIZ) { printf("net_write(2) returned %d, errno = %d\n", w, errno); return(-1); } nb = 0; } nbp[nb++] = lc = *ubp++; } if (nb) { if (!socket_wait(nData)) return x; w = net_write(nData->handle, nbp, nb); if (w != nb) { printf("net_write(3) returned %d, errno = %d\n", w, errno); return(-1); } } return len; }
/* * HttpSendCmd - send a command * * return 1 if proper response received, 0 otherwise */ static int HttpSendCmd(const char *cmd, char expresp, netbuf *nControl) { int ret = 0; char *buf = nControl->response; /* if (nControl->dir != FTPLIB_CONTROL) return 0; */ if (ftplib_debug > 2) fprintf(stderr,"%s\n",cmd); if (net_write(nControl->handle,cmd,strlen(cmd)) <= 0) { perror("write"); return 0; } while (ret < 256) { if (socket_wait(nControl) != 1) return 0; if (net_read(nControl->handle,buf,1) != 1) { break; } ret++; if (*buf == '\r') continue; if (*buf == '\n') break; buf++; } *buf = 0; if (nControl->response[9] == expresp) return 1; return 0; }
/* * FtpWrite - write to a data connection */ GLOBALDEF int FtpWrite(void *buf, int len, netbuf *nData) { int i; if (nData->dir != FTPLIB_WRITE) return 0; if (nData->buf) i = writeline(buf, len, nData); else { socket_wait(nData); i = net_write(nData->handle, buf, len); } if (i == -1) return 0; nData->xfered += i; if (nData->idlecb && nData->cbbytes) { nData->xfered1 += i; if (nData->xfered1 > nData->cbbytes) { nData->idlecb(nData, nData->xfered, nData->idlearg); nData->xfered1 = 0; } } return i; }
T_ERRCODE socket_recv( p_socket sock, char *data, size_t len, int timeout, int *received) { int err, got = 0; if (*sock < 0) { return CLOSED; } int flags = fcntl(*sock, F_GETFL, 0); do { got = recv(*sock, data, len, 0); if (got > 0) { *received = got; return SUCCESS; } err = errno; // Connection has been closed by peer if (got == 0) { return CLOSED; } } while (err != EINTR); if (err == EAGAIN) { return socket_wait(sock, WAIT_MODE_R, timeout); } return err; }
/* * read a line of text * * return -1 on error or bytecount */ static int readline (char *buf, int max, netbuf *ctl) { int x, retval = 0; char *end, *bp = buf; int eof = 0; if ((ctl->dir != FTPLIB_CONTROL) && (ctl->dir != FTPLIB_READ)) return -1; if (max == 0) return 0; do { if (ctl->cavail > 0) { x = (max >= ctl->cavail) ? ctl->cavail : max - 1; end = (char *) memccpy(bp, ctl->cget, '\n', x); if (end != NULL) x = end - bp; retval += x; bp += x; *bp = '\0'; max -= x; ctl->cget += x; ctl->cavail -= x; if (end != NULL) { bp -= 2; if (strcmp(bp, "\r\n") == 0) { *bp++ = '\n'; *bp++ = '\0'; --retval; } break; } } if (max == 1) { *buf = '\0'; break; } if (ctl->cput == ctl->cget) { ctl->cput = ctl->cget = ctl->buf; ctl->cavail = 0; ctl->cleft = FTPLIB_BUFSIZ; } if (eof) { if (retval == 0) retval = -1; break; } if (!socket_wait(ctl)) return retval; if ((x = net_read(ctl->handle, ctl->cput, ctl->cleft)) == -1) { perror("read"); retval = -1; break; } if (x == 0) eof = 1; ctl->cleft -= x; ctl->cavail += x; ctl->cput += x; } while (1); return retval; }
static int kftp_get_response(knetFile *ftp) { #ifndef _WIN32 unsigned char c; #else char c; #endif int n = 0; char *p; if (socket_wait(ftp->ctrl_fd, 1) <= 0) return 0; while (netread(ftp->ctrl_fd, &c, 1)) { // FIXME: this is *VERY BAD* for unbuffered I/O //fputc(c, stderr); if (n >= ftp->max_response) { ftp->max_response = ftp->max_response? ftp->max_response<<1 : 256; ftp->response = (char*)realloc(ftp->response, ftp->max_response); } ftp->response[n++] = c; if (c == '\n') { if (n >= 4 && isdigit(ftp->response[0]) && isdigit(ftp->response[1]) && isdigit(ftp->response[2]) && ftp->response[3] != '-') break; n = 0; continue; } } if (n < 2) return -1; ftp->response[n-2] = 0; return strtol(ftp->response, &p, 0); }
/* * FtpRead - read from a data connection */ GLOBALDEF int FtpRead(void *buf, int max, netbuf *nData) { int i; if (nData->dir != FTPLIB_READ) return 0; if (nData->buf) i = readline(buf, max, nData); else { i = socket_wait(nData); if (i != 1) return 0; i = net_read(nData->handle, buf, max); } if (i == -1) return 0; nData->xfered += i; if (nData->idlecb && nData->cbbytes) { nData->xfered1 += i; if (nData->xfered1 > nData->cbbytes) { if (nData->idlecb(nData, nData->xfered, nData->idlearg) == 0) return 0; nData->xfered1 = 0; } } return i; }
static int kftp_send_cmd(knetFile *ftp, const char *cmd, int is_get) { if (socket_wait(ftp->ctrl_fd, 0) <= 0) return -1; // socket is not ready for writing int len = strlen(cmd); if ( netwrite(ftp->ctrl_fd, cmd, len) != len ) return -1; return is_get? kftp_get_response(ftp) : 0; }
/** @brief Wait on the client socket connected to Jabber, and process any resulting input. @param session Pointer to the transport_session. @param timeout How seconds to wait before timing out (see notes). @return 0 if successful, or -1 if a timeout or other error occurs, or if the server closes the connection at the other end. If @a timeout is -1, wait indefinitely for input activity to appear. If @a timeout is zero, don't wait at all. If @a timeout is positive, wait that number of seconds before timing out. If @a timeout has a negative value other than -1, the results are not well defined. Read all available input from the socket and pass it through grab_incoming() (a callback function previously installed in the socket_manager). There is no guarantee that we will get a complete message from a single call. As a result, the calling code should call this function in a loop until it gets a complete message, or until an error occurs. */ int session_wait( transport_session* session, int timeout ) { if( ! session || ! session->sock_mgr ) { return 0; } int ret = socket_wait( session->sock_mgr, timeout, session->sock_id ); if( ret ) { osrfLogDebug(OSRF_LOG_MARK, "socket_wait returned error code %d", ret); } return ret; }
static int kftp_send_cmd(knetFile *ftp, const char *cmd, int is_get) { ssize_t byteswritten; /* tabix/knetfile.c:252:2: warning: ISO C90 forbids mixed declarations and code [-Wpedantic] */ if (socket_wait(ftp->ctrl_fd, 0) <= 0) return -1; /* socket is not ready for writing */ byteswritten = netwrite(ftp->ctrl_fd, cmd, strlen(cmd)); if( 0 >= byteswritten ) /* @ubw fixed unused result warning */ { PRINT_ERROR( "[kftp_send_cmd] no (%d) bytes written!\n", byteswritten); return -1; } return is_get? kftp_get_response(ftp) : 0; }
T_ERRCODE socket_connect(p_socket sock, p_sa addr, int addr_len, int timeout) { int err; if (*sock < 0) { return CLOSED; } do { if (connect(*sock, addr, addr_len) == 0) { return SUCCESS; } } while ((err = errno) == EINTR); if (err != EINPROGRESS && err != EAGAIN) { return err; } return socket_wait(sock, WAIT_MODE_C, timeout); }
/* * create a socket on sock_path and accept one client * require that connected client have UID of peer_uid * if authentication succeds, pass current process' * stdin and stdout, then wait for client to tell us to quit. */ void start_server ( char* sock_path, int sock_path_len, int peer_uid ) { int sock_serv, sock_client; sock_serv = socket_create( sock_path, sock_path_len ); if( sock_serv < 0 ) { LOGE( "start_server: sock_serv error" ); goto error; } sock_client = socket_accept( sock_serv ); if( sock_client < 0 ) { LOGE( "start_server: sock_client error, sock=%s",sock_path ); goto error; } struct ucred credentials; int ucred_length = sizeof( struct ucred ); if( getsockopt( sock_client, SOL_SOCKET, SO_PEERCRED, &credentials, &ucred_length ) ) { LOGE( "start_server: couldn't obtain peer's credentials" ); goto error; } if( peer_uid != credentials.uid ) { LOGE( "start_server: authentication error, expected uid %d, but found %d", peer_uid, credentials.uid ); goto error; } if( socket_send_sdtio( sock_client ) != 0 ) { LOGE( "sending stdio failed" ); goto error; } // gpg-agent and the real pinentry are now communicating // but our process must stay alive until they're finished // so we can exit with the actual return code int rc = socket_wait( sock_client ); close( sock_client ); close( sock_serv ); socket_cleanup( sock_path ); exit( rc ); error: close( sock_client ); close( sock_serv ); socket_cleanup( sock_path ); exit( EXIT_FAILURE ); }
static off_t my_netread(int fd, void *buf, off_t len) { off_t rest = len, curr, l = 0; /* recv() and read() may not read the required length of data with * one call. They have to be called repeatedly. */ while (rest) { if (socket_wait(fd, 1) <= 0) break; // socket is not ready for reading curr = netread(fd, (void*)((char*)buf + l), rest); /* According to the glibc manual, section 13.2, a zero returned * value indicates end-of-file (EOF), which should mean that * read() will not return zero if EOF has not been met but data * are not immediately available. */ if (curr == 0) break; l += curr; rest -= curr; } return l; }
T_ERRCODE socket_accept(p_socket sock, p_socket client, p_sa addr, socklen_t *addrlen, int timeout) { int err; if (*sock < 0) { return CLOSED; } do { *client = accept(*sock, addr, addrlen); if (*client > 0) { return SUCCESS; } err = errno; } while (err != EINTR); if (err == EAGAIN || err == ECONNABORTED) { return socket_wait(sock, WAIT_MODE_R, timeout); } return err; }
/* * HttpGet - issue a GET command and write received data to output * * return 1 if successful, 0 otherwise */ GLOBALREF int HttpGet(const char *host, const char *outputfile, const char *path, int *size, netbuf *nControl, unsigned int offset) { char buf[256]; if(offset > 0) sprintf(buf, "GET %s HTTP/1.1\r\nHost: %s\r\nRange: bytes=%d-\r\n\r\n", path, host, offset); else sprintf(buf, "GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", path, host); if(!HttpSendCmd(buf,'2',nControl)) { if (nControl->response[9] == '3') printf("redirection not supported\n"); return 0; } while (1) { int ret = 0; char *buf = nControl->response; while (ret < 256) { if (socket_wait(nControl) != 1) return 0; if (net_read(nControl->handle,buf,1) != 1) break; ret++; if (*buf == '\r') continue; if (*buf == '\n') break; buf++; } *buf = 0; if (strstr(nControl->response,"Content-Length")) { sscanf(nControl->response,"Content-Length: %d",size); if(offset > 0) *size += offset; } if (strlen(nControl->response) == 0) break; } return HttpXfer(outputfile, path, size, nControl, FTPLIB_FILE_READ, FTPLIB_IMAGE); }
T_ERRCODE socket_send( p_socket sock, const char *data, size_t len, int timeout) { int err, put = 0; if (*sock < 0) { return CLOSED; } do { put = send(*sock, data, len, 0); if (put > 0) { return SUCCESS; } err = errno; } while (err != EINTR); if (err == EAGAIN) { return socket_wait(sock, WAIT_MODE_W, timeout); } return err; }
/* * Main entry point */ int main(int argc, char **argv) { int opt_v = 0; char *opt_c = NULL; char *opt_s = NULL; int ch; /* check we're running as root */ if(getuid() != 0) { errno = EACCES; ERR("I must be run as root\n"); return -1; } /* handle command line arguments */ while ((ch = getopt(argc, argv, "hvc:s:")) != -1) { switch (ch) { case 'v': // enables verbose logging opt_v++; break; case 'c': // allows use to override location of config opt_c = strdup(optarg); break; case 's': // changes location of unix socket opt_s = strdup(optarg); break; case 'h': // help! default: usage(argc, argv); } } argc -= optind; argv += optind; /* set the logging level */ if (opt_v == 0) { opt_v = LOG_LEVEL_DEFAULT; } log_level(opt_v); INF("thermal manager starting...\n"); /* bring up "subsystems" */ sensor_init(); hwmon_init(); actions_init(); /* read and parse sensor config file */ if (opt_c == NULL) { opt_c = strdup(DEFAULT_CONFIG_FILE_PATH); if (opt_c == NULL) { ERR("unable to allocate memory\n"); return -1; } } INF("parsing thermal.conf...\n"); if (parse_config(opt_c) < 0) { ERR("failed to parse config file\n"); return -1; } /* discover HWMON sensors */ INF("discovering platform HWMON sensors...\n"); if (hwmon_find_sensors()) { ERR("failed to find platform HWMON sensors\n"); return -1; } /* startup client socket */ if (opt_s != NULL) { INF("overriding default socket path (%s)!\n", opt_s); socket_setunixsocket(opt_s); } INF("starting client communication socket...\n"); if (socket_init()) { ERR("unable to start socket communication\n"); return -1; } /* set sensor values & start monitoring */ INF("configuring initial sensor value...\n"); if (sensor_configure_all()) { ERR("Unable to configure HWMON sensors\n"); return -1; } /* finally stop and wait for the server thread to * shutdown (ie a catostrophic error has occured) */ socket_wait(); INF("thermal manager going down!\n"); free(opt_c); if (opt_s) { free(opt_s); } return 0; }
int server_getline ( char *buf, int buf_size ) { int msglen = -1; char *p; if (g_sock == NULL) return -1; strcpy(buf, ""); while (1) { if (g_buf_ptr == NULL) { if (socket_wait(g_sock) <= 0) { ErrMsg("server_getline: wait error\n"); return -1; } if (socket_accept(g_sock) <= 0) { ErrMsg("server_getline: accept failed\n"); return -1; } if (g_buf_offset >= sizeof(g_buf) - 1) { g_buf_offset = 0; } if ((msglen = socket_read(g_sock, g_buf + g_buf_offset, sizeof(g_buf) - g_buf_offset)) == -1) { continue; } else if (msglen <= 0) { continue; } else { g_buf[g_buf_offset + msglen] = '\0'; g_buf_ptr = g_buf; g_buf_offset = 0; } } if (g_buf_ptr != NULL) { if ((p = strstr(g_buf_ptr, "./")) != NULL && (p[2] == '\r' || p[2] == '\n')) { /* "./\n" was found */ p[0] = '\n'; p[1] = '\0'; msglen = strlen(g_buf_ptr); strncpy(buf, g_buf_ptr, buf_size); if (p[2] == '\r' && p[3] == '\n') { /* Windows newline "\r\n" was found */ p++; } if (p[3] == '\0') { /* single line was included */ g_buf_ptr = NULL; } else { /* multiple lines were included */ g_buf_ptr = p + 3; } g_buf_offset = 0; g_buf[0] = '\0'; break; } else { /* "./\n" was not found */ msglen = 0; g_buf_offset = strlen(g_buf); if (g_buf_offset > 0 && g_buf[g_buf_offset - 1] == '\n') { /* remove newline char */ if (g_buf_offset > 1 && g_buf[g_buf_offset - 2] == '\r') { g_buf_offset--; } g_buf[g_buf_offset - 1] = ' '; } g_buf_ptr = NULL; } } } return msglen; }
/** @brief Connect to the Jabber server as a client and open a Jabber session. @param session Pointer to a transport_session. @param username Jabber user name. @param password Jabber password. @param resource name of Jabber resource. @param connect_timeout Timeout interval, in seconds, for receiving data (see notes). @param auth_type An enum: either AUTH_PLAIN or AUTH_DIGEST (see notes). @return 1 if successful, or 0 upon error. If @a connect_timeout is -1, wait indefinitely for the Jabber server to respond. If @a connect_timeout is zero, don't wait at all. If @a timeout is positive, wait that number of seconds before timing out. If @a connect_timeout has a negative value other than -1, the results are not well defined. The value of @a connect_timeout applies to each of two stages in the logon procedure. Hence the logon may take up to twice the amount of time indicated. If we connect as a Jabber component, we send the password as an SHA1 hash. Otherwise we look at the @a auth_type. If it's AUTH_PLAIN, we send the password as plaintext; if it's AUTH_DIGEST, we send it as a hash. At this writing, we only use AUTH_DIGEST. */ int session_connect( transport_session* session, const char* username, const char* password, const char* resource, int connect_timeout, enum TRANSPORT_AUTH_TYPE auth_type ) { // Sanity checks if( ! session ) { osrfLogWarning(OSRF_LOG_MARK, "session is null in session_connect()" ); return 0; } if( session->sock_id != 0 ) { osrfLogWarning(OSRF_LOG_MARK, "transport session is already open, on socket %d", session->sock_id ); return 0; } // Open a client socket connecting to the Jabber server if(session->port > 0) { // use TCP session->sock_id = socket_open_tcp_client( session->sock_mgr, session->port, session->server ); if( session->sock_id <= 0 ) { session->sock_id = 0; return 0; } } else if(session->unix_path != NULL) { // use UNIX domain session->sock_id = socket_open_unix_client( session->sock_mgr, session->unix_path ); if( session->sock_id <= 0 ) { session->sock_id = 0; return 0; } } else { osrfLogWarning( OSRF_LOG_MARK, "Can't open session: no port or unix path" ); return 0; } const char* server = session->server; int size1 = 0; int size2 = 0; /* We establish the session in two stages. First we establish an XMPP stream with the Jabber server by sending an opening tag of stream:stream. This is not a complete XML document. We don't send the corresponding closing tag until we close the session. If the Jabber server responds by sending an opening stream:stream tag of its own, we can proceed to the second stage by sending a second stanza to log in. This stanza is an XML element with the tag <handshake> (if we're a Jabber component) or <iq> (if we're not), enclosing the username, password, and resource. If all goes well, the Jabber server responds with a <handshake> or <iq> stanza of its own, and we're logged in. If authentication fails, the Jabber server returns a <stream:error> (if we used a <handshake> or an <iq> of type "error" (if we used an <iq>). */ if( session->component ) { /* the first Jabber connect stanza */ char our_hostname[HOST_NAME_MAX + 1] = ""; gethostname(our_hostname, sizeof(our_hostname) ); our_hostname[HOST_NAME_MAX] = '\0'; size1 = 150 + strlen( username ) + strlen( our_hostname ); char stanza1[ size1 ]; snprintf( stanza1, sizeof(stanza1), "<stream:stream version='1.0' xmlns:stream='http://etherx.jabber.org/streams' " "xmlns='jabber:component:accept' to='%s' from='%s' xml:lang='en'>", username, our_hostname ); /* send the first stanze */ session->state_machine->connecting = CONNECTING_1; if( socket_send( session->sock_id, stanza1 ) ) { osrfLogWarning(OSRF_LOG_MARK, "error sending"); socket_disconnect( session->sock_mgr, session->sock_id ); session->sock_id = 0; return 0; } /* wait for reply */ socket_wait(session->sock_mgr, connect_timeout, session->sock_id); /* server acknowledges our existence, now see if we can login */ if( session->state_machine->connecting == CONNECTING_2 ) { int ss = buffer_length( session->session_id ) + strlen( password ) + 5; char hashstuff[ss]; snprintf( hashstuff, sizeof(hashstuff), "%s%s", OSRF_BUFFER_C_STR( session->session_id ), password ); char* hash = shahash( hashstuff ); size2 = 100 + strlen( hash ); char stanza2[ size2 ]; snprintf( stanza2, sizeof(stanza2), "<handshake>%s</handshake>", hash ); if( socket_send( session->sock_id, stanza2 ) ) { osrfLogWarning(OSRF_LOG_MARK, "error sending"); socket_disconnect( session->sock_mgr, session->sock_id ); session->sock_id = 0; return 0; } } } else { /* we're not a component */ /* the first Jabber connect stanza */ size1 = 100 + strlen( server ); char stanza1[ size1 ]; snprintf( stanza1, sizeof(stanza1), "<stream:stream to='%s' xmlns='jabber:client' " "xmlns:stream='http://etherx.jabber.org/streams'>", server ); /* send the first stanze */ session->state_machine->connecting = CONNECTING_1; if( socket_send( session->sock_id, stanza1 ) ) { osrfLogWarning(OSRF_LOG_MARK, "error sending"); socket_disconnect( session->sock_mgr, session->sock_id ); session->sock_id = 0; return 0; } /* wait for reply */ socket_wait( session->sock_mgr, connect_timeout, session->sock_id ); /* make the timeout smarter XXX */ if( auth_type == AUTH_PLAIN ) { /* the second jabber connect stanza including login info*/ size2 = 150 + strlen( username ) + strlen( password ) + strlen( resource ); char stanza2[ size2 ]; snprintf( stanza2, sizeof(stanza2), "<iq id='123456789' type='set'><query xmlns='jabber:iq:auth'>" "<username>%s</username><password>%s</password><resource>%s</resource></query></iq>", username, password, resource ); /* server acknowledges our existence, now see if we can login */ if( session->state_machine->connecting == CONNECTING_2 ) { if( socket_send( session->sock_id, stanza2 ) ) { osrfLogWarning(OSRF_LOG_MARK, "error sending"); socket_disconnect( session->sock_mgr, session->sock_id ); session->sock_id = 0; return 0; } } } else if( auth_type == AUTH_DIGEST ) { int ss = buffer_length( session->session_id ) + strlen( password ) + 5; char hashstuff[ss]; snprintf( hashstuff, sizeof(hashstuff), "%s%s", OSRF_BUFFER_C_STR( session->session_id ), password ); char* hash = shahash( hashstuff ); /* the second jabber connect stanza including login info */ size2 = 150 + strlen( username ) + strlen( hash ) + strlen(resource); char stanza2[ size2 ]; snprintf( stanza2, sizeof(stanza2), "<iq id='123456789' type='set'><query xmlns='jabber:iq:auth'>" "<username>%s</username><digest>%s</digest><resource>%s</resource></query></iq>", username, hash, resource ); /* server acknowledges our existence, now see if we can login */ if( session->state_machine->connecting == CONNECTING_2 ) { if( socket_send( session->sock_id, stanza2 ) ) { osrfLogWarning(OSRF_LOG_MARK, "error sending"); socket_disconnect( session->sock_mgr, session->sock_id ); session->sock_id = 0; return 0; } } } else { osrfLogWarning(OSRF_LOG_MARK, "Invalid auth_type parameter: %d", (int) auth_type ); socket_disconnect( session->sock_mgr, session->sock_id ); session->sock_id = 0; return 0; } } // not component /* wait for reply to login request */ socket_wait( session->sock_mgr, connect_timeout, session->sock_id ); if( session->state_machine->connected ) { /* yar! */ return 1; } else { socket_disconnect( session->sock_mgr, session->sock_id ); session->sock_id = 0; return 0; } }
int main(int argc, char **argv) { /* Run main garbage collector when quiting the daemon */ gc_attach(main_gc); /* Catch all exit signals for gc */ gc_catch(); loglevel = LOG_INFO; log_file_disable(); log_shell_enable(); char *logfile = malloc(strlen(LOG_FILE)+1); strcpy(logfile, LOG_FILE); log_file_set(logfile); sfree((void *)&logfile); prevMessage = malloc(4); memset(prevMessage, '\0', 4); progname = malloc(14); strcpy(progname, "splash-daemon"); struct socket_callback_t socket_callback; struct options_t *options = NULL; char *args = NULL; char buffer[BUFFER_SIZE]; int f; options_add(&options, 'H', "help", no_value, 0, NULL); options_add(&options, 'V', "version", no_value, 0, NULL); options_add(&options, 'D', "nodaemon", no_value, 0, NULL); while (1) { int c; c = options_parse(&options, argc, argv, 1, &args); if (c == -1) break; switch(c) { case 'H': printf("Usage: %s [options]\n", progname); printf("\t -H --help\t\tdisplay usage summary\n"); printf("\t -V --version\t\tdisplay version\n"); printf("\t -S --settings\t\tsettings file\n"); printf("\t -D --nodaemon\t\tdo not daemonize and\n"); printf("\t\t\t\tshow debug information\n"); return (EXIT_SUCCESS); break; case 'V': printf("%s %s\n", progname, "1.0"); return (EXIT_SUCCESS); break; case 'D': nodaemon=1; break; default: printf("Usage: %s [options]\n", progname); return (EXIT_FAILURE); break; } } options_delete(options); pid_file = malloc(sizeof(PID_FILE)+1); strcpy(pid_file, PID_FILE); template_file = malloc(14); strcpy(template_file, "template.json"); if((f = open(pid_file, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) != -1) { if(read(f, buffer, BUFFER_SIZE) != -1) { //If the file is empty, create a new process if(!atoi(buffer)) { running = 0; } else { //Check if the process is running kill(atoi(buffer), 0); //If not, create a new process if(errno == ESRCH) { running = 0; } } } } else { logprintf(LOG_ERR, "could not open / create pid_file %s", pid_file); return EXIT_FAILURE; } close(f); if(nodaemon == 1 || running == 1) { log_level_set(LOG_DEBUG); } if(running == 1) { nodaemon=1; logprintf(LOG_NOTICE, "already active (pid %d)", atoi(buffer)); return EXIT_FAILURE; } if(nodaemon == 0) { deamonize(); socket_start(PORT); fb_init(); } else { socket_start(PORT); } if(template_read(template_file) == EXIT_FAILURE) { logprintf(LOG_NOTICE, "failed to read template file %s", template_file); main_gc(); return EXIT_FAILURE; } if(nodaemon == 1) { //template_print(); } //initialise all socket_clients and handshakes to 0 so not checked memset(socket_clients, 0, sizeof(socket_clients)); socket_callback.client_disconnected_callback = NULL; socket_callback.client_connected_callback = NULL; socket_callback.client_data_callback = &socket_parse_data; main_draw(); /* Make sure the server part is non-blocking by creating a new thread */ pthread_create(&pth, NULL, &update_progress, (void *)NULL); socket_wait((void *)&socket_callback); while(main_loop) { sleep(1); } return EXIT_FAILURE; }
/* * HttpGet - issue a GET command and write received data to output * * return 1 if successful, 0 otherwise */ GLOBALREF int HttpGet(const char *host, const char *outputfile, const char *path, int *size, netbuf *nControl, unsigned int offset, const struct tm *mtime1, struct tm *mtime2) { char buf[512]; sprintf(buf, "GET %s HTTP/1.1\r\nHost: %s\r\n", path, host); if (offset > 0) sprintf(buf, "%sRange: bytes=%d-\r\n", buf, offset); if (mtime1 && mtime1->tm_year) { char mtime[30]; /* Format: * "If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT\r\n" */ strftime(mtime, sizeof(mtime), "%a, %d %b %Y %H:%M:%S GMT", mtime1); sprintf(buf, "%sIf-Modified-Since: %s\r\n", buf, mtime); } sprintf(buf, "%s\r\n", buf); if (!HttpSendCmd(buf,'2',nControl)) { if (nControl->response[9] == '3') { /* If the answer from the server is 304, the requested file * hasn't been modified: no need to retrieve it */ if (mtime1 && mtime1->tm_year && nControl->response[11] == '4') return 0; /* otherwise, it is a redirection */ printf("redirection not supported\n"); } return 0; } while (1) { int ret = 0; char *buf = nControl->response; while (ret < 256) { if (socket_wait(nControl) != 1) return 0; if (net_read(nControl->handle,buf,1) != 1) break; ret++; if (*buf == '\r') continue; if (*buf == '\n') break; buf++; } *buf = 0; if (strstr(nControl->response,"Content-Length")) { sscanf(nControl->response,"Content-Length: %d",size); if (offset > 0) *size += offset; } else if (mtime2 && strstr(nControl->response,"Last-Modified")) { /* Format: * "Last-Modified: Sat, 29 Oct 1994 19:43:31 GMT\r\n" */ char *c = nControl->response+20; int mint, j; static const int months[12] = { ('J'<<16)|('a'<<8)|'n', ('F'<<16)|('e'<<8)|'b', ('M'<<16)|('a'<<8)|'r', ('A'<<16)|('p'<<8)|'r', ('M'<<16)|('a'<<8)|'y', ('J'<<16)|('u'<<8)|'n', ('J'<<16)|('u'<<8)|'l', ('A'<<16)|('u'<<8)|'g', ('S'<<16)|('e'<<8)|'p', ('O'<<16)|('c'<<8)|'t', ('N'<<16)|('o'<<8)|'v', ('D'<<16)|('e'<<8)|'c' }; mtime2->tm_mday = (c[0]-'0')*10+c[1]-'0'; mint = (c[3]<<16)|(c[4]<<8)|c[5]; mtime2->tm_mon = 0; for(j = 0; j < 12; j++) { if (mint == months[j]) { mtime2->tm_mon = j; break; } } mtime2->tm_year = ((c[7]-'0')*10+(c[8]-'0')-19)*100; mtime2->tm_year += (c[9]-'0')*10+c[10]-'0'; mtime2->tm_hour = (c[12]-'0')*10+c[13]-'0'; mtime2->tm_min = (c[15]-'0')*10+c[16]-'0'; mtime2->tm_sec = (c[18]-'0')*10+c[19]-'0'; } if (strlen(nControl->response) == 0) break; } return HttpXfer(outputfile, path, size, nControl, FTPLIB_FILE_READ, FTPLIB_IMAGE); }