Esempio n. 1
0
static void init_outbuf(void)
{
    outbuf_total = 1;
    outbuf_base = malloc(BUFSIZ);
    clear_outbuf();
}
Esempio n. 2
0
/* 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() */
Esempio n. 3
0
/*
 *----------
 * 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;
}