Beispiel #1
0
/* PUTLOG -- Format and write a message to the logfile.  This is called by
 * the putlog builtin (clputlog() in builtin.c) and in some places in the
 * CL (e.g., exec.c).
 */
void
putlog (
  struct task  *tp,		/* pointer to task or NULL */
  char	*usermsg 
)
{
	register char	*ip, *op, *otop;
	register int	n;
	char	msg[SZ_LOGBUF], job[5];
	char	*pkg, *tname, *today();
	extern  int  bkgno;			/* job number if bkg job */

	if (!keeplog())
	    return;

	/* If background job, format job number, but only if background
	 * logging is enabled.
	 */
	if (firstask->t_flags & T_BATCH) {
	    if (log_background())
	    	sprintf (job, "[%d] ", bkgno);
	    else
		return;
	} else
	    job[0] = EOS;

	/* If a valid task pointer is given, get the package and task name.
	 * Otherwise, assume it's an internal (cl) logging message.
	 */
	if (tp) {
	    pkg   = tp->t_ltp->lt_pkp->pk_name;
	    tname = tp->t_ltp->lt_lname;
	} else {
	    pkg   = "cl";
	    tname = "";
	}

	/* Format the message.  Only use time, no day and date.  Break long
	 * messages into several lines.
	 */
	sprintf (msg, "# %8.8s %s%s%s %s- ",
		(today() + 4), pkg, (tp ? "." : ""), tname, job);
	otop = &msg[SZ_LOGBUF];
	for (op=msg, n=0;  *op && op < otop;  op++)
	    n++;
	for (ip=usermsg;  (*op++ = *ip++) && op < otop;  n++)
	    if (n + 2 >= MAXCOL) {
		*op++ = '\\';
		*op++ = '\n';
		n = 0;
	    }
	*(op-1) = '\n';
	*op = EOS;
	    
	put_logfile (msg);
}
Beispiel #2
0
/* YY_GETC -- Called by the modified yylex() "input" macro in the lexical
 * analysis stage of the parser to get the next character from the input
 * stream.  When EOF is reached on the stream, add the "bye" command to
 * the logfile.
 */
int 
yy_getc (FILE *fp)
{
	register char ch;

	while ((ch = *ip_cmdblk++) == EOS)
	    if (get_command (fp) == EOF) {
		if (currentask->t_flags & T_INTERACTIVE)
		    if (log_commands())
		        put_logfile ("bye\n");
		return (EOF);
	    }

	return ((int) ch);
}
Beispiel #3
0
/* YY_STARTBLOCK -- Terminate the last command block and start a new one.
 * Save old command block in history (if interactive) and in logfile (if
 * interactive, logging is enabled, and logflag argument is true).  Even
 * if logging is enabled, a command will not be logged which aborts or is
 * interrupted.
 */
void
yy_startblock (
  int	logflag
)
{
	register char *ip;

	if (cldebug)
	    eprintf ("startblock (%d)\n", logflag);

	/* Log cmdblk only if it was filled by an interactive task.  We must
	 * make the test when the new block is initialized since the write is
	 * delayed.
	 */
	if (cmdblk_save) { 
	    /* Do not record commands which consist only of whitespace.
	     */
	    for (ip=cmdblk;  isspace (*ip);  ip++)
		;
	    if (*ip != EOS) {
		/* Use the raw_cmdblk, saved in get_command().
		 */
		put_history (raw_cmdblk);
		if (logflag && log_commands())
		    put_logfile (raw_cmdblk);
	    }
	}

	if (cldebug) 
	    eprintf ("startblock: ifseen=%d\n", ifseen);

	if (!ifseen) {
	    ip_cmdblk = op_cmdblk = cmdblk;
	    *ip_cmdblk = EOS;
	}
	cmdblk_line = 0;
	cmdblk_save = (currentask->t_flags & T_INTERACTIVE);

	/* Mode switching of the lexical analyzer is enabled by this call
	 * if the CL parameter lexmodes is set.  Called between blocks
	 * entered interactively and also during error recovery.
	 */
	lexinit();
}
Beispiel #4
0
/* GET_COMMAND -- Get command line from the input stream.  If not interactive,
 *   all we do is read the line into the cmdblk buffer.  If called when parsing
 *   command input to an interactive task, we must output a prompt before
 *   reading in the command line.  The prompt changes depending on whether or
 *   not the command is the first in a command block (whether or not we have
 *   closure).  After reading the command, we check if it is a history directive
 *   and process it if so.  Otherwise we must still process it to expand any
 *   history macros.  Ignore all blank or comment lines.  These are
 *   any line in which the first non-blank character is a newline or a
 *   '#'.  This will make some things a bit more efficient, but is
 *   actually to allow the if/else parsing to work properly.
 *
 * N.B.: We must directly or indirectly set ip_cmdblk so that yy_getc takes
 *   the next character from the right place.  This is either done directly
 *   or by a call to yy_startblock.
 */
int
get_command (
  FILE	*fp
)
{
	register char *ip, *op;
	char	raw_cmd[SZ_LINE+1];	/* buffer for raw command line	*/
	char	new_cmd[SZ_CMDBLK+1];	/* temporary for processed cmd	*/
	int	execute=1, temp, status;


	if (!(currentask->t_flags & T_INTERACTIVE)  ||
	    parse_state == PARSE_PARAMS) {

	    /* Ensure that searches through string terminate. */
	    cmdblk[SZ_LINE] = '\0';
	    ip_cmdblk = cmdblk;

	    while (YES) {
 		currentask->t_scriptln++;	/* noninteractive mode	*/

		status = (fgets (cmdblk, SZ_LINE, fp) == NULL ? EOF : OK);
		if (status == EOF) {
		    cmdblk[0] = '\0';
		    break;
		}

		/* Check if this is a blank line. */
		for (ip = cmdblk;  *ip == ' ' || *ip == '\t';  ip++)
		    ;
		if (*ip == '\n' || *ip == '\0')
		    continue;

		/* Check for the #{ ... #} lexmode toggle sequences.  These
		 * are matched only at the beginning of a line.  #{ sets
		 * command mode on the command input stream and #} clears it.
		 */
		if (*ip == '#') {
		    if (ip == cmdblk) {
			if (*(ip+1) == '{') {
			    lex_setcpumode (fp);
			    lexinit();
			} else if (*(ip+1) == '}') {
			    lex_clrcpumode (fp);
			    lexinit();
			}
		    }
		    continue;
		}

		break;
	    }

	    if (cldebug || echocmds())
		eprintf ("%s", status == EOF ? "bye\n" : cmdblk);

	    return (status);
	}

	raw_cmd[SZ_LINE] = '\0';
	while (YES) {
	    /* Prompt the user for a new command if the input buffer is empty.
	     * The CL prompt clears raw mode in case it is left in effect by a
	     * program abort.
	     */
input_:
	    if (c_fstati (fileno(fp), F_UNREAD) == 0) {
		if (c_fstati ((XINT)STDIN, F_RAW) == YES)
		    c_fseti ((XINT)STDIN, F_RAW, NO);
		if (cmdblk_line == 0)
		    pprompt (curpack->pk_name);
		else
		    pprompt (NOCLOSURE);
	    }

	    /* Read the next command line. */
	    if (fgets (raw_cmd, SZ_LINE, fp) == NULL)
		return (EOF);

	    /* Check for the #{ ... #} lexmode toggle sequences.  These
	     * are matched only at the beginning of a line.  #{ sets
	     * command mode on the command input stream and #} clears it.
	     */
	    if (*(ip=raw_cmd) == '#') {
		if (*(ip+1) == '{') {
		    lex_setcpumode (fp);
		    lexinit();
		} else if (*(ip+1) == '}') {
		    lex_clrcpumode (fp);
		    lexinit();
		}
	    }

	    /* Skip leading whitespace. */
	    for (ip=raw_cmd;  *ip == ' ' || *ip == '\t';  ip++)
		;

	    /* For interactive comments, make sure we store them in the
	     * history and the logfile.  This is so that users can add
	     * comments into the logfile interactively.
	     */
	    if (*ip == '#') {
		put_history (raw_cmd);
	  	if (log_commands())
		    put_logfile (raw_cmd);
	    } else if (*ip != '\n' && *ip != '\0') {
		cmdblk_line++;
		break;
	    }
	}

	/* If history directive, transform the directive into an executable
	 * command block using the history data.  Echo the new command as
	 * if the user had typed it, for verification.
	 */
	if (*raw_cmd == HISTCHAR) {
	    /* Use screen style history editing only if the CL parameter
	     * "ehinit" contains the boolean variable "verify" (or if the 
	     * cmd is "ehistory", below).
	     */
	    if (eh_verify)
		execute = edit_history_directive (raw_cmd+1, new_cmd);
	    else {
		execute = process_history_directive (raw_cmd, new_cmd);
		fputs (new_cmd, currentask->t_stdout);
	    }

	} else if (expand_history_macros (raw_cmd, new_cmd)) {
	    fputs (new_cmd, currentask->t_stdout);

	} else {
	    static  char ehist[] = "ehistory";
	    int     n;

	    for (n=0, ip=raw_cmd, op=ehist;  (*ip == *op);  ip++, op++)
		n++;
	    if (n > 0 && isspace (*ip)) {
		while (isspace (*ip))
		    ip++;
		execute = edit_history_directive (ip, new_cmd);
	    }
	}

	/* If user deletes entire line go back and get another command.  */
	for (ip=new_cmd;  isspace (*ip);  ip++)
	    ;
	if (*ip == EOS) {
	    cmdblk_line = 0;
	    execute = 1;
	    goto input_;
	}

	/* Now move the processed command into the cmdblk buffer.  If there
	 * is not enough storage remaining in the cmdblk buffer, we have to
	 * break the actual (large) command block up, calling yy_startblock to
	 * start a new block, but without changing the line number within the
	 * block.  We must not let the history mechanism limit the size of a
	 * command block.
	 */
	op_cmdblk = ip_cmdblk - 1;		/* back up to EOS	*/
	if (strlen (new_cmd) > (cmdblk + SZ_CMDBLK - op_cmdblk)) {
	    temp = cmdblk_line;
	    yy_startblock (LOG);
	    cmdblk_line = temp;
	}
	ip_cmdblk = op = op_cmdblk;
	for (ip=new_cmd;  (*op++ = *ip++) != EOS;  )
	    ;

	/* Save the "raw command" here for use in yy_startblock.  This is
	 * to handle the problem of procedure script parsing overwriting
	 * the raw command in cmdblk.
	 */
	strcpy (raw_cmdblk, cmdblk);

	if (!execute)
	    yy_startblock (NOLOG);

	fflush (currentask->t_stdout);
	return (OK);
}