Exemple #1
0
int main(int argc, char *argv[])
{
	int rc;

	getopts(argc, argv);
	if(getlognumber()) {
		fprintf(stderr, "Cannot determine actual log number\n");
		exit(4);
	}
	if(run_as_daemon) {
		if((rc = daemonize(outputfile)) != 0) {
			fprintf(stderr, "Error starting daemon process : %s\n", strerror(rc));
			exit(5);
		}
	} else {
		if(redirect(outputfile)) {
			exit(6);
		}
	}
	if(workdir) {
		if(chdir(workdir)) {
			perror("Error changing directory: ");
			exit(7);
		}
	}
	if(verbose) {
		print_config();
	}

	if(cmd != NULL) {
		sighandling();
		if(start_cmd() != 0) exit(9);
	}
	return process();
}
Exemple #2
0
void
event_init(pmID pmid)
{
    char cmd[MAXPATHLEN];
    int	i, fd;

    for (i = 0; i < numlogfiles; i++) {
	size_t pathlen = strlen(logfiles[i].pathname);

	/*
	 * We support 2 kinds of PATHNAMEs:
	 * (1) Regular paths.  These paths are opened normally.
	 * (2) Pipes.  If the path ends in '|', the filename is
	 *     interpreted as a command which pipes input to us.
	 */
	if (logfiles[i].pathname[pathlen - 1] != '|') {
	    fd = open(logfiles[i].pathname, O_RDONLY|O_NONBLOCK);
	    if (fd < 0) {
		if (logfiles[i].fd >= 0)	/* log once only */
		    __pmNotifyErr(LOG_ERR, "open: %s - %s",
				logfiles[i].pathname, strerror(errno));
	    } else {
		if (fstat(fd, &logfiles[i].pathstat) < 0)
		    if (logfiles[i].fd >= 0)	/* log once only */
			__pmNotifyErr(LOG_ERR, "fstat: %s - %s",
				    logfiles[i].pathname, strerror(errno));
		lseek(fd, 0, SEEK_END);
	    }
	}
	else {
	    strncpy(cmd, logfiles[i].pathname, sizeof(cmd));
	    cmd[pathlen - 1] = '\0';	/* get rid of the '|' */
	    rstrip(cmd);	/* Remove all trailing whitespace. */
	    fd = start_cmd(cmd, &logfiles[i].pid);
	    if (fd < 0) {
		if (logfiles[i].fd >= 0)	/* log once only */
		    __pmNotifyErr(LOG_ERR, "pipe: %s - %s",
					logfiles[i].pathname, strerror(errno));
	    } else {
		if (fd > maxfd)
		    maxfd = fd;
		FD_SET(fd, &fds);
	    }
	}

	logfiles[i].fd = fd;		/* keep file descriptor (or error) */
	logfiles[i].pmid = pmid;	/* string param metric identifier */
	logfiles[i].queueid = pmdaEventNewQueue(logfiles[i].pmnsname, maxmem);
    }
}
/*-------------------------------------------------------------------*/
int CallHercCmd ( CMDFUNC_ARGS_PROTO )
{
    CMDTAB* pCmdTab;
    size_t  cmdlen, matchlen;
    int     rc = HERRINVCMD;             /* Default to invalid command   */

    /* Let 'cscript' command run immediately in any context */
    if (argc >= 1 && strcasecmp( argv[0], "cscript" ) == 0)
        return cscript_cmd( CMDFUNC_ARGS );

    HERC_CMD_ENTRY();

    /* [ENTER] key by itself: either start the CPU or ignore
       it altogether when instruction stepping is not active. */
    if (0
            || !argc            /* (no args)    */
            || !argv[0]         /* (no cmd)     */
            || !cmdline         /* (no cmdline) */
            || !cmdline[0]      /* (empty cmd)  */
            || !argv[0][0]      /* (empty cmd)  */
       )
    {
        if (sysblk.inststep)
            rc = start_cmd( 0, NULL, NULL );
        else
            rc = 0;         /* ignore [ENTER] */

        HERC_CMD_EXIT();
        return rc;
    }

    /* (sanity check) */
    ASSERT( argc && cmdline && *cmdline && argv[0] && argv[0][0] );

#if defined( OPTION_DYNAMIC_LOAD )
    /* If a system command hook exists, let it try processing it first. */
    /* Only if it rejects it, will we then try processing it ourselves. */
    if(system_command)
        if((rc = system_command( CMDFUNC_ARGS )) != HERRINVCMD)
        {
            HERC_CMD_EXIT();
            return rc;
        }
#endif /* defined( OPTION_DYNAMIC_LOAD ) */

    /* Check for comment command. We need to test for this separately
       rather than scanning our COMAMND table since the first token
       of the "command" might not be a single '#' or '*'. That is to
       say, the first token might be "#comment" or "*comment" (with
       no blanks following the '#' or '*'), which would thus not match
       either of our "comment_cmd" COMMAND table entries. Note that
       this also means the COMMAND table entries for '*' and '#' are
       redundant since they will never be used (since we're processing
       comments here and not via our table search), but that's okay. */
    if (0
            || argv[0][0] == '#'       /* (comment command?) */
            || argv[0][0] == '*'       /* (comment command?) */
       )
    {
        /* PROGRAMMING NOTE: we ALWAYS call the "comment_cmd" function
           for comments even though today it does nothing. We might decide
           to do additional processing for comments in the future (such
           as simply counting them for example), so we should ALWAYS call
           our comment_cmd function here instead of just returning. */
        rc = comment_cmd( CMDFUNC_ARGS );
        HERC_CMD_EXIT();
        return rc;
    }

    /* Route standard formatted commands from our COMMAND routing table */

    /* PROGRAMMING NOTE: since our table is now sorted, the below could
       be converted to a more efficient binary search algorithm instead */

    for (pCmdTab = cmdtab; pCmdTab->statement; pCmdTab++)
    {
        if (1
                && pCmdTab->function
                && (pCmdTab->type & sysblk.sysgroup)
                /* Commands issues through DIAG8 must NOT be part of the SYSNDIAG8 group */
                && (!(sysblk.diag8cmd & DIAG8CMD_RUNNING) || !(pCmdTab->type & SYSNDIAG8))
           )
        {
            cmdlen = pCmdTab->mincmdlen ? pCmdTab->mincmdlen : strlen( pCmdTab->statement );
            matchlen = MAX( strlen(argv[0]), cmdlen );

            if (!strncasecmp( argv[0], pCmdTab->statement, matchlen ))
            {
                char cmd[256]; /* (copy of command name) */

                /* Make full-length copy of the true command's name */
                strlcpy( cmd, pCmdTab->statement, sizeof(cmd) );
                argv[0] = cmd; /* (since theirs may be abbreviated) */

                /* Run command in background? (last argument == '&') */
                if (strcmp(argv[argc-1],"&") == 0)
                {
                    BGCMD *bgcmd;
                    TID tid;
                    int i,len;

                    /* Calculate length of the command-line (all arguments
                       except the last one), including intervening blanks. */
                    for (len=0, i=0; i < argc-1; i++ )
                        len += (int) strlen( (char*) argv[i] ) + 1;

                    /* Build parameter to pass to background thread */
                    bgcmd = (BGCMD*) malloc( sizeof(BGCMD) + len );
                    bgcmd->func = pCmdTab->function;

                    /* Build private copy of cmdline for bgcmd_thread */
                    strlcpy( bgcmd->cmdline, argv[0], len );
                    for (i=1; i < argc-1; i++)
                    {
                        strlcat( bgcmd->cmdline,  " ",    len );
                        strlcat( bgcmd->cmdline, argv[i], len );
                    }

                    /* Process command asynchronously in the background */
                    rc = create_thread( &tid, DETACHED, bgcmd_thread, bgcmd, "bgcmd_thread" );
                }
                else /* (not a background command) */
                {
                    /* Does last argument start with two ampersands? */
                    if (strncmp( argv[argc-1], "&&", 2 ) == 0)
                        /* Yes, skip past the first one */
                        argv[argc-1]++; /* ("&&&" ==> "&&", "&&" ==> "&", etc) */

                    /* Process the Hercules command */
                    rc = pCmdTab->function( CMDFUNC_ARGS );
                }
                break;
            }
            /* end strncasecmp( table entry match ) */
        }
        /* end if ( valid table entry ) */
    }
    /* end for ( search table ) */

    /* If we didn't find an exact match in our table, check if
       this is maybe a special non-standard formatted command. */
    if (rc == HERRINVCMD && (sysblk.sysgroup & SYSCMDNOPER))
    {
        /* shadow file commands: add/remove/compress/display/check */
        if (0
                || !strncasecmp( cmdline, "sf+", 3 )
                || !strncasecmp( cmdline, "sf-", 3 )
                || !strncasecmp( cmdline, "sfc", 3 )
                || !strncasecmp( cmdline, "sfd", 3 )
                || !strncasecmp( cmdline, "sfk", 3 )
           )
            rc = ShadowFile_cmd( CMDFUNC_ARGS );
        else
            /* "x+" and "x-" commands: turn switch on or off */
            if (0
                    || '+' == cmdline[1]
                    || '-' == cmdline[1]
               )
                rc = OnOffCommand( CMDFUNC_ARGS );
    }

    HERC_CMD_EXIT();
    return rc;
}
Exemple #4
0
/* Client command loop only considers console inputs + controller messages */
void run_client(char *infile_name) {
    if (!start_cmd(infile_name))
	return;
    while (!cmd_done()) {
	/* Select among controller port, and connections to routers */
	FD_ZERO(&cset);
	maxcfd = 0;
	add_cfd(controller_fd);
	cmd_select(maxcfd+1, &cset, NULL, NULL, NULL);
	if (cmd_done())
	    break;
	int fd;
	for (fd = 0; fd <= maxcfd; fd++) {
	    if (!FD_ISSET(fd, &cset))
		continue;
	    bool eof;
	    chunk_ptr msg = chunk_read(fd, &eof);
	    if (eof) {
		/* Unexpected EOF */
		if (fd == controller_fd) {
		    err(true, "Unexpected EOF from controller (fatal)");
		} else {
		    err(false,
"Unexpected EOF from unexpected source. fd %d (ignored)", fd);
		}
		close(fd);
		continue;
	    }
	    if (msg == NULL) {
		err(false, "Could not read chunk from fd %d (ignored)", fd);
		continue;
	    }
	    word_t h = chunk_get_word(msg, 0);
	    unsigned code = msg_get_header_code(h);
	    if (fd == controller_fd) {
		/* Message from controller */
		switch(code) {
		case MSG_DO_FLUSH:
		    chunk_free(msg);
#if RPT >= 5
		    report(5, "Received flush message from controller");
#endif
		    if (flush_helper) {
			flush_helper();
		    }
		    break;
		case MSG_STAT:
#if RPT >= 5
		    report(5, "Received summary statistics from controller");
#endif
		    if (stat_helper) {
			/* Get a copy of the byte usage from mem. allocator */
			stat_helper(msg);
		    }
		    chunk_free(msg);
		    /* Client can proceed with next command */
		    unblock_console();
		    break;
		case MSG_KILL:
		    chunk_free(msg);
#if RPT >= 1
		    report(1, "Received kill message from controller");
#endif
		    finish_cmd();
		    break;
		case MSG_GC_START:
		    chunk_free(msg);
		    gc_start(code);
		    break;
		case MSG_GC_FINISH:
		    chunk_free(msg);
		    gc_finish(code);
		    break;
		default:
		    chunk_free(msg);
		    err(false,
			"Unknown message code %u from controller (ignored)",
			code);
		}
	    } else {
		err(false,
		    "Received message from unknown source.  fd %d (ignored)",
		    fd);
		close(fd);
		continue;
	    }
	}
    }
}
Exemple #5
0
static void run_controller(char *infile_name) {
    if (!start_cmd(infile_name))
	return;
    while (!cmd_done()) {
	FD_ZERO(&set);
	int fd;
	word_t w;
	unsigned ip;
	unsigned port;
	add_fd(listen_fd);
	keyvalue_iterstart(new_conn_map);
	/* Check for messages from newly connected clients, workers, and routers */
	while (keyvalue_iternext(new_conn_map, &w, NULL)) {
	    fd = w;
	    add_fd(fd);
	}
	if (need_routers == 0) {
	    /* Accept messages from workers */
	    set_iterstart(worker_fd_set);
	    while (set_iternext(worker_fd_set, &w)) {
		fd = w;
		add_fd(fd);
	    }
	    /* Accept messages from clients */
	    set_iterstart(client_fd_set);
	    while (set_iternext(client_fd_set, &w)) {
		fd = w;
		add_fd(fd);
	    }
	}

	cmd_select(maxfd+1, &set, NULL, NULL, NULL);

	for (fd = 0; fd <= maxfd; fd++) {
	    if (!FD_ISSET(fd, &set))
		continue;
	    if (fd == listen_fd) {
		unsigned ip;
		int connfd = accept_connection(fd, &ip);
		keyvalue_insert(new_conn_map, (word_t) connfd, (word_t) ip);
#if RPT >= 4
		report(4, "Accepted new connection.  Connfd = %d, IP = 0x%x",
		       connfd, ip);
#endif
		continue;
	    }
	    bool eof;
	    chunk_ptr msg = chunk_read(fd, &eof);
	    if (eof) {
		/* Unexpected EOF */
		if (keyvalue_remove(new_conn_map, (word_t) fd, NULL, NULL)) {
		    err(false, "Unexpected EOF from new connection, fd %d", fd);
		} else if (set_member(worker_fd_set, (word_t) fd, true)) {
		    err(false, "Unexpected EOF from connected worker, fd %d.  Shutting down", fd);
		    /* Shut down system */
		    finish_cmd();
		} else if (set_member(client_fd_set, (word_t) fd, true)) {
#if RPT >= 3
		    report(3, "Disconnection from client (fd %d)", fd);
#endif
		    if (need_client_fd_set && set_member(need_client_fd_set,
							 (word_t) fd, false)) {
#if RPT >= 3
			report(3, "Removing client from GC activities");
#endif
			handle_gc_msg(MSG_GC_FINISH, 0, fd, true);
		    }
		} else {
		    err(false, "Unexpected EOF from unknown source, fd %d", fd);
		}
		close(fd);
		continue;
	    }
	    if (msg == NULL) {
		err(false, "Could not read chunk from fd %d (ignored)", fd);
		continue;
	    }
	    word_t h = chunk_get_word(msg, 0);
	    unsigned code = msg_get_header_code(h);
#if RPT >= 5
	    report(5, "Received message with code %d from fd %d", code, fd);
#endif
	    if (keyvalue_remove(new_conn_map, (word_t) fd, NULL, &w)) {
		ip = w;
		chunk_free(msg);
		/* Should be a registration message */
		switch (code) {
		case MSG_REGISTER_ROUTER:
		    if (need_routers == 0) {
			err(false, "Unexpected router registration.  (Ignored)");
			close(fd);
			break;
		    }
		    port = msg_get_header_port(h);
		    word_t node_id = msg_build_node_id(port, ip);
		    set_insert(router_addr_set, node_id);
		    set_insert(router_fd_set, (word_t) fd);
#if RPT >= 4
		    report(4, "Added router with fd %d.  IP 0x%x.  Port %u",
			   fd, ip, port);
#endif
		    need_routers --;
		    if (need_routers == 0) {
#if RPT >= 2
			report(2, "All routers connected");
#endif
			/* Have gotten all of the necessary routers.
			   Notify any registered workers */
			set_iterstart(worker_fd_set);
			int wfd;
			while (set_iternext(worker_fd_set, &w)) {
			    wfd = w;
			    add_agent(wfd, false);
			}
		    }
		    break;
		case MSG_REGISTER_WORKER:
		    if (worker_fd_set->nelements >= worker_cnt) {
			err(false, "Unexpected worker registration.  (Ignored)");
			close(fd);
			break;
		    }
		    set_insert(worker_fd_set, (word_t) fd);
#if RPT >= 4
		    report(4, "Added worker with fd %d", fd);
#endif
		    if (need_routers == 0)
			add_agent(fd, false);
		    break;
		case MSG_REGISTER_CLIENT:
		    if (gc_state == GC_READY) {
			set_insert(client_fd_set, (word_t) fd);
#if RPT >= 4
			report(4, "Added client with fd %d", fd);
#endif
			if (need_workers == 0)
			    add_agent(fd, true);
		    } else {
			if (!defer_client_fd_set) {
			    defer_client_fd_set = word_set_new();
			}
			set_insert(defer_client_fd_set, (word_t) fd);
#if RPT >= 3
			report(3, "Deferring client with fd %d until GC completed",
			       fd);
#endif
		    }
		    break;
		default:
		    err(false, "Unexpected message code %u from new connection",
			code);
		    break;
		}
	    } else if (set_member(worker_fd_set, (word_t) fd, false)) {
		/* Message from worker */
		switch (code) {
		    unsigned agent;
		    unsigned gen;
		case MSG_READY_WORKER:
		    chunk_free(msg);
		    if (need_workers == 0) {
			err(false, "Unexpected worker ready.  (Ignored)");
			close(fd);
			break;
		    }
		    need_workers--;
		    if (need_workers == 0) {
#if RPT >= 2
			report(2, "All workers connected");
#endif			
			/* Notify any pending clients */
			set_iterstart(client_fd_set);
			int cfd;
			while (set_iternext(client_fd_set, &w)) {
			    cfd = w;
			    add_agent(cfd, true);
			}
		    }
		    break;
		case MSG_STAT:
		    /* Message gets stashed away.  Don't free it */
		    add_stat_message(msg);
		    break;
		case MSG_CLIOP_ACK:
		    /* Worker acknowledging receipt of global operation info */
		    agent = msg_get_header_agent(h);
		    int client_fd = receive_global_op_worker_ack(agent);
		    if (client_fd >= 0) {
			/* Have received complete set of acknowledgements. */
			/* Send ack to client */
			if (chunk_write(client_fd, msg)) {
#if RPT >= 6
			    report(6,
"Sent ack to client for global operation with id %u", agent);
#endif
			} else {
			    err(false,
"Failed to send ack to client for global operation with id %u.  Fd %d",
				agent, client_fd);
			}
		    }
		    chunk_free(msg);
		    break;
		case MSG_GC_START:
		case MSG_GC_FINISH:
		    handle_gc_msg(code, 0, fd, false);
		    chunk_free(msg);
		    break;
		case MSG_GC_REQUEST:
		    gen = msg_get_header_generation(h);
		    chunk_free(msg);
		    handle_gc_msg(code, gen, fd, false);
		    break;
		default:
		    chunk_free(msg);
		    err(false, "Unexpected message code %u from worker", code);
		}
	    } else if (set_member(client_fd_set, (word_t) fd, false)) {
		/* Message from client */
		switch(code){
		    unsigned agent;
		    word_t w;
		case MSG_KILL:
		    /* Shutdown entire system */
		    chunk_free(msg);
#if RPT >= 2
		    report(2, "Remote request to kill system");
#endif
		    finish_cmd();
		    return;
		case MSG_DO_FLUSH:
		    /* Initiate a flush operation */
		    chunk_free(msg);
		    flush_requestor_fd = fd;
		    do_controller_flush_cmd(0, NULL);
		    break;
		case MSG_CLIOP_DATA:
		    /* Request for global operation from client */
		    agent = msg_get_header_agent(h);
		    add_global_op(agent, fd);
		    /* Send message to all workers */
		    set_iterstart(worker_fd_set);
		    while (set_iternext(worker_fd_set, &w)) {
			int worker_fd = (int) w;
			if (chunk_write(worker_fd, msg)) {
#if RPT >= 6
			    report(6,
"Sent global operation information with id %u to worker with fd %d",
				   agent, worker_fd);
#endif
			} else {
			    err(false,
"Failed to send global operation information with id %u to worker with fd %d",
				agent, worker_fd);
			}
		    }
		    chunk_free(msg);
		    break;
		case MSG_CLIOP_ACK:
		    /* Completion of global operation by client */
		    agent = msg_get_header_agent(h);
		    /* Send message to all workers */
		    set_iterstart(worker_fd_set);
		    while (set_iternext(worker_fd_set, &w)) {
			int worker_fd = (int) w;
			if (chunk_write(worker_fd, msg)) {
#if RPT >= 6
			    report(6,
"Sent global operation acknowledgement with id %u to worker with fd %d",
				   agent, worker_fd);
#endif
			} else {
			    err(false,
"Failed to send global operation acknowledgement with id %u to worker with fd %d",
				agent, worker_fd);
			}
		    }
		    chunk_free(msg);
		    break;
		case MSG_GC_START:
		case MSG_GC_FINISH:
		    handle_gc_msg(code, 0, fd, true);
		    chunk_free(msg);
		    break;
		default:
		    err(false, "Unexpected message code %u from client", code);
		}

	    } else {
		chunk_free(msg);
		err(false, "Unexpected message on fd %d (Ignored)", fd);
	    }
	}
    }
}
Exemple #6
0
int process()
{
#define BUFSIZE 2048

	FILE *outf;
	char filename[PATH_MAX + 1];
	char analyzeline[PATH_MAX*3 + 1];
	int lineno;
	static char buf[BUFSIZE+1];

	if(open_pipe()) {
		if(childpid)
			kill(childpid, SIGTERM);
		exit(8);
	}
	while(terminate != 2) {

		while(last_logno - first_logno > no_of_segments) {
			snprintf(filename, PATH_MAX, "%s.%d", logbasename, first_logno);
			if (analyzer != NULL) {
				snprintf(analyzeline, PATH_MAX*3, "%s %s", analyzer, filename);
				system(analyzeline);
			}
			unlink(filename);
			first_logno++;
		}

		last_logno++;
		snprintf(filename, PATH_MAX, "%s.%d", logbasename, last_logno);
		outf = fopen(filename, "w");
		if(outf == NULL) {
			fprintf(stderr, "Error opening file %s : %s\n", filename, strerror(errno));
			if(childpid) {
				kill(childpid, SIGTERM);
				sleep(10);
			}
			return 9;
		}
		fnout = fileno(outf);
		lineno = 0;
		while((lineno < no_of_lines) && (terminate != 2)) {
			if(fgets(buf, BUFSIZE, paip) == NULL) {
				fclose(paip);
				fflush(outf);
				if (childpid) {
					fprintf(outf, "[scrolllog] Waiting for child (%d) to terminate\n", (int) childpid);
					fflush(outf);
					do {
						switch ((int)waitpid((pid_t) -1, &status, 0)) {
						case -1:
							if(errno == ECHILD) {

								fprintf(outf, "[scrolllog] WARNING, childpid != 0 && ECHILD !\n");
								fflush(outf);

								restart   = 1;
							}
							break;
						default:
							if (WIFEXITED(status)) {
								status = WEXITSTATUS(status);
							} else if (WIFSIGNALED(status)) {
								status = 128 + WTERMSIG(status);
							} else
								continue;
							fprintf(outf, "[scrolllog] Child exited with state %d\n", status);
							fflush(outf);
							if (status == 0) restart = 0;
							else restart = 1;
						}

						childpid  = 0;
						terminate = 1;
					} while(childpid != 0);
				}
				if(terminate == 1) {
					if(restart && (cmd != NULL)) {
						fprintf(outf, "[scrolllog] Try to restart child (child terminated with exit code <> 0)\n");
						fflush(outf);
						if(start_cmd() != 0) {
							fprintf(outf, "[scrolllog] restart of child failed\n");
							fflush(outf);
							exit(9);
						}
						terminate = 0;
					} else {
						terminate = 2;
						fprintf(outf, "[scrolllog] I terminate (after cleaning up)\n");
						fflush(outf);
						break;
					}
				}
				if(open_pipe()) {
					terminate = 2;
					fprintf(outf, "\n");
					fprintf(outf, "\n[scrolllog] ****************************************");
					fprintf(outf, "\n[scrolllog] **                                    **");
					fprintf(outf, "\n[scrolllog] ** Couldn't open/lock pipe            **");
					if(childpid) {
						fprintf(outf, "\n[scrolllog] ** scrolllog terminates and sends a   **");
						fprintf(outf, "\n[scrolllog] ** SIGTERM to its child               **");
						kill(childpid, SIGTERM);
						sleep(10);
					}
					fprintf(outf, "\n[scrolllog] **                                    **");
					fprintf(outf, "\n[scrolllog] ****************************************\n");
					fflush(outf);
					return 10;
				}

				continue;
			}
			fputs(buf, outf);
			fflush(outf);
			lineno++;
		}
		fclose(outf);

	}

	return status;
}