/* WARNING: This file was generated by dkct. Changes you make here will be lost if dkct is run again! Original source: pqdrun.ctr */ /* Copyright (C) 2012, Dirk Krause Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above opyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the author nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file pqdrun.c The pqdrun module. */ #line 39 "pqdrun.ctr" #include "dk3all.h" #include "printqd.h" #line 45 "pqdrun.ctr" /** Job structure for a session. */ typedef struct { printqd_job *job; /**< Service job structure. */ printqd_session *sess; /**< Current session. */ dk3_sto_t *s_s; /**< Session storage. */ printqd_socket_conf *sc; /**< Listener socket configuration. */ char const *ibuf; /**< Input buffer. */ char *obuf; /**< Output buffer. */ size_t szobuf; /**< Size of output buffer. */ int plev; /**< Protocol level. */ int reaction; /**< Reaction. */ int dbsync; /**< Flag: Database sync recommended. */ int rqt; /**< Request type. */ } pqd_run_session_job; /** Request keywords at the beginning of the request line. */ static char const * const pqdrun_request_types[] = { /* 0 */ "jobstart", /* 1 */ "filestart", /* 2 */ "fileend", /* 3 */ "jobend", /* 4 */ "info", /* 5 */ "control", NULL #line 76 "pqdrun.ctr" }; /** Process an input line. The line to process is available in @a ibuf. The function has to set @a reaction. If @a reaction is set to PQD_RUN_REACTION_RESPONSE, the response must be written to obuf as string containing a trailing newline and finished by 0x00 byte. @param prsj Session job structure. */ static void pqdrun_process_input(pqd_run_session_job *prsj) { char cbuf[PRINTQD_LINE_SIZE]; /* Private copy. */ char *p1; /* Start of line. */ char *p2; /* Arguments. */ #line 96 "pqdrun.ctr" strcpy(cbuf, prsj->ibuf); p1 = dk3str_c8_start(cbuf, NULL); if(p1) { p2 = dk3str_c8_next(p1, NULL); if(p2) { switch(prsj->rqt = dk3str_c8_array_index(pqdrun_request_types, p1, 0)) { case 0: { #line 103 "pqdrun.ctr" if(prsj->plev >= 1) { dk3app_log_3(job->app, DK3_LL_INFO, job->msg, 5, 6, ibuf); prsj->reaction = PQDRUN_REACTION_NONE; } } break; case 1: { #line 109 "pqdrun.ctr" if(prsj->plev >= 1) { dk3app_log_3(job->app, DK3_LL_INFO, job->msg, 5, 6, ibuf); prsj->reaction = PQDRUN_REACTION_NONE; } } break; case 2: { #line 115 "pqdrun.ctr" if(prsj->plev >= 1) { dk3app_log_3(job->app, DK3_LL_INFO, job->msg, 5, 6, ibuf); prsj->reaction = PQDRUN_REACTION_NONE; } } break; case 3: { #line 121 "pqdrun.ctr" if(prsj->plev >= 1) { dk3app_log_3(job->app, DK3_LL_INFO, job->msg, 5, 6, ibuf); prsj->reaction = PQDRUN_REACTION_NONE; } break; case 4: { #line 126 "pqdrun.ctr" prsj->reaction = PQDRUN_REACTION_NONE; } break; case 5: { #line 129 "pqdrun.ctr" if(prsj->plev >= 2) { dk3app_log_3(job->app, DK3_LL_INFO, job->msg, 5, 6, ibuf); prsj->reaction = PQDRUN_REACTION_NONE; } } break; } } } #line 138 "pqdrun.ctr" } static void pqdrun_log_response( dk3_app_t *app, dkChar const * const *msg, size_t i1, size_t i2, char const *txt ) { char obuf[PRINTQD_LINE_SIZE]; /* Output buffer. */ strcpy(obuf, txt); dk3str_delnl(obuf); dk3app_log_msg(app, DK3_LL_INFO, msg, i1, i2, obuf); } void printqd_run_one_session( printqd_job *job, printqd_session *sess, dk3_sto_t *storage, printqd_socket_conf *sc, int plevel ) { char ibuf[PRINTQD_LINE_SIZE]; /* Input line buffer. */ char obuf[PRINTQD_LINE_SIZE]; /* Output buffer. */ pqd_run_session_job prsj; /* Session job. */ size_t rsl; /* Response length. */ ssize_t rdbytes; /* Bytes read. */ ssize_t wrbytes; /* Bytes written. */ int oldmode; /* Old socket mode. */ int ec; /* Error code. */ #line 179 "pqdrun.ctr" /* Initialize job structure. */ prsj.job = job; prsj.sess = sess; prsj.s_s = storage; prsj.sc = sc; prsj.plev = plevel; prsj.ibuf = ibuf; prsj.obuf = obuf; prsj.szobuf = sizeof(obuf); obuf[0] = '\0'; prsj.reaction = PQDRUN_REACTION_CLOSE; prsj.dbsync = 0; prsj.rqt = -1; /* Read in non-blocking mode, after reading switch back to blocking. */ oldmode = fcntl(sess->ss, F_GETFL); fcntl(sess->ss, F_SETFL, (oldmode | O_NONBLOCK); rdbytes = recv(sess->ss, ibuf, sizeof(ibuf), 0); ec = errno; fcntl(sess->ss, F_SETFL, oldmode); /* Process input if any. */ if(rdbytes >= 0) { if(rdbytes > 0) { /* Only process input if the socket was not yet shut down for writing. */ if(!((sess->flags) & PRINTQD_SESSION_FLAG_SHUTDOWN_WRITE)) { ibuf[(rdbytes < (sizeof(ibuf)-1)) ? rdbytes : (sizeof(ibuf)-1)] = '\0'; dk3str_c8_delnl(ibuf); pqdrun_process_input(&prsj); switch(prsj.reaction) { case PQDRUN_REACTION_RESPONSE: { if(prsj->rqt != 4) { pqdrun_log_response(job->app, job->msg, 7, 8, obuf); } rsl = strlen(obuf); wrbytes = send(sess->ss, obuf, rsl, 0); if(wrbytes < ((ssize_t)rsl)) { dk3sto_remove(storage, (void *)sess); close(sess->ss); dk3_delete(sess) } else { #ifdef SHUT_WR shutdown(sess->ss, SHUT_WR); #else shutdown(sess->ss, 1); #endif sess->flags |= PRINTQD_SESSION_FLAG_SHUTDOWN_WRITE; } } break; case PQDRUN_REACTION_NONE: { #ifdef SHUT_WR shutdown(sess->ss, SHUT_WR); #else shutdown(sess->ss, 1); #endif sess->flags |= PRINTQD_SESSION_FLAG_SHUTDOWN_WRITE; } break; default: { dk3sto_remove(storage, (void *)sess); close(sess->ss); dk3_delete(sess) } break; } if(prsj.dbsync) { dk3dbi_sync(job->db); } } } else { /* The peer initiated an orderly shutdown, so we can close the socket. */ dk3sto_remove(storage, (void *)sess); close(sess->ss); dk3_delete(sess) } } else { /* If we failed to receive data we can close the socket unless the receive operation would block or a signal occured. */ switch(ec) { #if defined(EWOULDBLOCK) && defined(EAGAIN) #if EWOULDBLOCK == EAGAIN case EAGAIN: { } break; #else case EWOULDBLOCK: { } break; case EAGAIN: { } break; #endif #else #ifdef EWOULDBLOCK case EWOULDBLOCK: { } break; #else #ifdef EAGAIN case EAGAIN: { } break; #endif #endif #endif #ifdef EINTR case EINTR: { #line 289 "pqdrun.ctr" } break; #endif default: { #line 292 "pqdrun.ctr" dk3sto_remove(storage, (void *)sess); close(sess->ss); dk3_delete(sess) } break; } } #line 299 "pqdrun.ctr" }