static void init_outbuf(void) { outbuf_total = 1; outbuf_base = malloc(BUFSIZ); clear_outbuf(); }
/* pass_on() * Is the work loop of the logger. Selects on the pipe to the to_erl * program erlang. If input arrives from to_erl it is passed on to * erlang. */ static void pass_on(pid_t childpid) { int len; fd_set readfds; fd_set writefds; fd_set* writefds_ptr; struct timeval timeout; time_t last_activity; char buf[BUFSIZ]; char log_alive_buffer[ALIVE_BUFFSIZ+1]; int lognum; int rfd, wfd=0, lfd=0; int maxfd; int ready; int got_some = 0; /* from to_erl */ /* Open the to_erl pipe for reading. * We can't open the writing side because nobody is reading and * we'd either hang or get an error. */ if ((rfd = sf_open(fifo2, O_RDONLY|DONT_BLOCK_PLEASE, 0)) < 0) { ERRNO_ERR1(LOG_ERR,"Could not open FIFO '%s' for reading.", fifo2); exit(1); } #ifdef DEBUG status("run_erl: %s opened for reading\n", fifo2); #endif /* Open the log file */ lognum = find_next_log_num(); lfd = open_log(lognum, O_RDWR|O_APPEND|O_CREAT|O_SYNC); /* Enter the work loop */ while (1) { int exit_status; maxfd = MAX(rfd, mfd); maxfd = MAX(wfd, maxfd); FD_ZERO(&readfds); FD_SET(rfd, &readfds); FD_SET(mfd, &readfds); FD_ZERO(&writefds); if (outbuf_size() == 0) { writefds_ptr = NULL; } else { FD_SET(wfd, &writefds); writefds_ptr = &writefds; } time(&last_activity); timeout.tv_sec = log_alive_minutes*60; /* don't assume old BSD bug */ timeout.tv_usec = 0; ready = select(maxfd + 1, &readfds, writefds_ptr, NULL, &timeout); if (ready < 0) { if (errno == EINTR) { if (waitpid(childpid, &exit_status, WNOHANG) == childpid) { /* * The Erlang emulator has terminated. Give us some more * time to write out any pending data before we terminate too. */ alarm(5); } FD_ZERO(&readfds); FD_ZERO(&writefds); } else { /* Some error occured */ ERRNO_ERR0(LOG_ERR,"Error in select."); exit(1); } } else { time_t now; if (waitpid(childpid, &exit_status, WNOHANG) == childpid) { alarm(5); FD_ZERO(&readfds); FD_ZERO(&writefds); } /* Check how long time we've been inactive */ time(&now); if(!ready || now - last_activity > log_activity_minutes*60) { /* Either a time out: 15 minutes without action, */ /* or something is coming in right now, but it's a long time */ /* since last time, so let's write a time stamp this message */ struct tm *tmptr; if (log_alive_in_gmt) { tmptr = gmtime(&now); } else { tmptr = localtime(&now); } if (!strftime(log_alive_buffer, ALIVE_BUFFSIZ, log_alive_format, tmptr)) { strn_cpy(log_alive_buffer, sizeof(log_alive_buffer), "(could not format time in 256 positions " "with current format string.)"); } log_alive_buffer[ALIVE_BUFFSIZ] = '\0'; sn_printf(buf, sizeof(buf), "\n===== %s%s\n", ready?"":"ALIVE ", log_alive_buffer); write_to_log(&lfd, &lognum, buf, strlen(buf)); } } /* * Write any pending output first. */ if (FD_ISSET(wfd, &writefds)) { int written; char* buf = outbuf_first(); len = outbuf_size(); written = sf_write(wfd, buf, len); if (written < 0 && errno == EAGAIN) { /* * Nothing was written - this is really strange because * select() told us we could write. Ignore. */ } else if (written < 0) { /* * A write error. Assume that to_erl has terminated. */ clear_outbuf(); sf_close(wfd); wfd = 0; } else { /* Delete the written part (or all) from the buffer. */ outbuf_delete(written); } } /* * Read master pty and write to FIFO. */ if (FD_ISSET(mfd, &readfds)) { #ifdef DEBUG status("Pty master read; "); #endif if ((len = sf_read(mfd, buf, BUFSIZ)) <= 0) { sf_close(rfd); if(wfd) sf_close(wfd); sf_close(mfd); unlink(fifo1); unlink(fifo2); if (len < 0) { if(errno == EIO) ERROR0(LOG_ERR,"Erlang closed the connection."); else ERRNO_ERR0(LOG_ERR,"Error in reading from terminal"); exit(1); } exit(0); } write_to_log(&lfd, &lognum, buf, len); /* * Save in the output queue. */ if (wfd) { outbuf_append(buf, len); } } /* * Read from FIFO, write to master pty */ if (FD_ISSET(rfd, &readfds)) { #ifdef DEBUG status("FIFO read; "); #endif if ((len = sf_read(rfd, buf, BUFSIZ)) < 0) { sf_close(rfd); if(wfd) sf_close(wfd); sf_close(mfd); unlink(fifo1); unlink(fifo2); ERRNO_ERR0(LOG_ERR,"Error in reading from FIFO."); exit(1); } if(!len) { /* to_erl closed its end of the pipe */ sf_close(rfd); rfd = sf_open(fifo2, O_RDONLY|DONT_BLOCK_PLEASE, 0); if (rfd < 0) { ERRNO_ERR1(LOG_ERR,"Could not open FIFO '%s' for reading.", fifo2); exit(1); } got_some = 0; /* reset for next session */ } else { if(!wfd) { /* Try to open the write pipe to to_erl. Now that we got some data * from to_erl, to_erl should already be reading this pipe - open * should succeed. But in case of error, we just ignore it. */ if ((wfd = sf_open(fifo1, O_WRONLY|DONT_BLOCK_PLEASE, 0)) < 0) { status("Client expected on FIFO %s, but can't open (len=%d)\n", fifo1, len); sf_close(rfd); rfd = sf_open(fifo2, O_RDONLY|DONT_BLOCK_PLEASE, 0); if (rfd < 0) { ERRNO_ERR1(LOG_ERR,"Could not open FIFO '%s' for reading.", fifo2); exit(1); } wfd = 0; } else { #ifdef DEBUG status("run_erl: %s opened for writing\n", fifo1); #endif } } if (!got_some && wfd && buf[0] == '\014') { char wbuf[30]; int wlen = sn_printf(wbuf,sizeof(wbuf),"[run_erl v%u-%u]\n", RUN_ERL_HI_VER, RUN_ERL_LO_VER); outbuf_append(wbuf,wlen); } got_some = 1; /* Write the message */ #ifdef DEBUG status("Pty master write; "); #endif len = extract_ctrl_seq(buf, len); if(len==1 && buf[0] == '\003') { kill(childpid,SIGINT); } else if (len>0 && write_all(mfd, buf, len) != len) { ERRNO_ERR0(LOG_ERR,"Error in writing to terminal."); sf_close(rfd); if(wfd) sf_close(wfd); sf_close(mfd); exit(1); } } #ifdef DEBUG status("OK\n"); #endif } } } /* pass_on() */
/* *---------- * main proc *---------- */ static int file_parse(int fd, PGconn *conn, const char *abs_path) { int ret = 0; int size = 0; int wlen = 0; char *buf = (char*)NULL; char *realcmd = (char *)NULL; char *rdlinecmd = (char *)NULL; #define TM_LEN 25 //char timebf[TM_LEN]; char *timebf = NULL; //struct timeval stamp; struct rpldsk_packet packet; struct timeval stamp; enum CMD_STATUS cmd_s = CMD_UNKNOWN; if ((timebf = malloc(TM_LEN)) == NULL) { fprintf(stderr, "malloc failed.\n"); return -1; } memset(timebf, 0, TM_LEN); while ((ret = read(fd, &packet, sizeof(struct rpldsk_packet))) == sizeof(struct rpldsk_packet)) { //dbg("<-packet->\nsize: %x\nevent: %x\nmagic: %x\n", packet.size, packet.event, packet.magic); if (packet.magic != MAGIC_SIG) { fprintf(stderr, "\n<Packet inconsistency>\n"); return -1; } size = packet.size; if (size <= 0) { fprintf(stderr, ("\n" "<Packet inconsistency>" ": bad size" "\n")); return -1; } switch (packet.event) { case EVT_WRITE: dbg("case EVT_WRITE\n"); /* read packet.size and store in outbuf */ if ((buf = malloc(size+1)) == NULL) { fprintf(stderr, "malloc error\n"); close(fd); return -1; } read(fd, buf, size); buf[size] = '\0'; #ifdef WALK_LOG dbg("\n[TTY_OUT]\n............\n%s\n............\n\n", buf); //break; #endif last_outlen = strlen(buf); // size-1 : remove '\0' in packet.data if (s_cmd == CMD_BEGIN) { outlen += last_outlen; } else { outlen = last_outlen+1; outbuf[0] = '\0'; } if (outlen >= OUT_BFMAX) { fprintf(stderr, "BUG: OUT_BFMAX to small\n"); exit(1); } strncat(outbuf, buf, size); outbuf[outlen-1] = '\0'; free(buf); buf = (char *)NULL; break; case EVT_READ: dbg("case EVT_RD: start\n"); if (PS == NULL) { if (outbuf[0] == '\0') { fprintf(stderr, "BUG: No PS but outbuf is null.\n"); //lseek(fd, size, SEEK_CUR); //break; } } char *tmp = find_ps(outbuf); if (tmp && *tmp) { //update_ps if (PS != NULL) { free(PS); PS = NULL; } PS = tmp; dbg("\nps found\n--\n%s\n--\n", PS); clear_inbuf(); stamp = packet.time; s_cmd = CMD_BEGIN; dbg("\nCMD_BEGIN...\n"); } if (s_cmd != CMD_BEGIN) { lseek(fd, size, SEEK_CUR); clear_inbuf(); clear_outbuf(); break; } //add_completion if last_inbuf is 'tab' buf = last_ttyio(inbuf, last_inlen); dbg("\n\n-inbuf-\n%s\n-lastin(%d)-\n%s\n-outbuf-\n%s\n\n", inbuf, last_inlen, buf, outbuf); if (is_last_tab(buf) == 0) { str_rm_char(outbuf, CHR_BELL); add_completion(inbuf, outbuf); dbg("**inbuf-updated:%s\n", inbuf); } myfree((void *)&buf); clear_outbuf(); //read new tty_in if ((buf = malloc(size+1)) == NULL) { fprintf(stderr, "malloc error\n"); close(fd); return -1; } read(fd, buf, size); buf[size] = '\0'; #ifdef WALK_LOG dbg("\n[TTY_IN]\n............\n%s\n............\n\n", buf); //break; #endif last_inlen = strlen(buf); // size-1 : remove '\0' in packet.data inlen += last_inlen; if (inlen >= OUT_BFMAX) { fprintf(stderr, "BUG: OUT_BFMAX to small\n"); exit(1); } strncat(inbuf, buf, size); inbuf[inlen-1] = '\0'; if (is_cmdend(inbuf) == 0) { dbg("\n...CMD_END.\n"); //get rdlinecmd from rd-pkt.data getcmd(inbuf, &rdlinecmd, rl_name); format_time(&timebf, &(stamp.tv_sec)); dbg("\n\nrdlinecmd(%s)\n-inbuf-\n%s\n--\n\n", rdlinecmd, inbuf); //output dumped log logdump(timebf, PS, rdlinecmd, abs_path, User); //fprintf(stdout, "[%s]%s%s\n", timebf, PS, rdlinecmd); if (rdlinecmd && *rdlinecmd) { if (!(PS[0] == '>')) add_history(rdlinecmd); } free(rdlinecmd); rdlinecmd = NULL; clear_inbuf(); s_cmd = CMD_END; } free(buf); buf = (char *)NULL; //get rdlinecmd from rd-pkt.data //parse_rd_pkt(fd, &rdlinecmd, &packet, rl_name, &timebf); break; case EVT_ID_USER: if ((User = malloc(size)) == NULL) { fprintf(stderr, "malloc(User) error.\n"); close(fd); exit(1); } read(fd, User, size); //fprintf(stdout, "User: %s\n", User); break; case EVT_ID_TIME: if ((Time = malloc(size)) == NULL) { fprintf(stderr, "malloc(User) error.\n"); close(fd); exit(1); } read(fd, Time, size); //fprintf(stdout, "Time: %s\n", Time); break; case EVT_LCLOSE: dbg("EVT_LCLOSE\n"); fflush(stdout); clear_inbuf(); clear_outbuf(); return 0; default: dbg("EVT: %x, lseek\n", packet.event); lseek(fd, size, SEEK_CUR); break; } } free(timebf); return 0; }