예제 #1
0
파일: dfu.c 프로젝트: rroart/freevms
main(int argc, char *argv[])

/*	MAIN

	Purpose : 1 Get privilege mask
		  2 Setup SMG environment unless no VT or DFU$NOSMG is set
		  3 Get and Parse command (syntax only)
		  4 Dispatch to correct subroutine

	Inputs  : Command line (if specified through foreign command)

	Outputs : returns last status code to DCL in  case
		  of single command processing. In interactive mode
		  always returns SS$_NORMAL.
*/
{
    const rms_eof=98938,smg$_eof=1213442;
    struct
    {
        short status, count;
        int extra ;
    } iosb;
    static char command_line[255], *e;
    unsigned int out_len,ret_len,prvmask;
    void reset_ctrl(), clean_ctrlc(),
         prev_screen(), next_screen(), dump_screen(), toggle_width() ;
    int smg_flag, x, y, i, ttype;
    int cursor_on = SMG$M_CURSOR_ON;
    $DESCRIPTOR(input_line , command_line);
    $DESCRIPTOR(prompt,"DFU> ");
    $DESCRIPTOR(terminal,"SYS$COMMAND");
    $DESCRIPTOR(top_txt,"< DFU V2.2 (Freeware) >");
    $DESCRIPTOR(status_txt,"Statistics");
    $DESCRIPTOR(do_key,"DO");
    $DESCRIPTOR(pf2,"PF2");
    $DESCRIPTOR(pf4,"PF4");
    $DESCRIPTOR(prev,"PREV_SCREEN");
    $DESCRIPTOR(next,"NEXT_SCREEN");
    $DESCRIPTOR(select,"SELECT");
    $DESCRIPTOR(help,"HELP");

    /* First find out how we got called ( by RUN, or a foreign command */
    ret_len = 0;
#if 0
    status = lib$get_foreign(&input_line,0,&ret_len,0);
#else
    status = 1;
#if 0
    strcpy(command_line,argv[1]);
#endif
#endif
    out_len = ret_len;

    smg$enable = TRUE;
    key_tab = 0;
    disp2_id = 0;
    cip = 0;

    setvbuf(stdout, NULL, _IONBF, 0);      // need this to see i/o at all
#if 0
    smg$enable = FALSE;
    vms_mm = check_vms_mm();
#else
    /* Now create the SMG environment */

    colls=80;
    rows=24;
    SMG$CREATE_PASTEBOARD(&paste_id, 0, &rows,
                          &colls,&SMG$M_KEEP_CONTENTS,&ttype,0);
    if ((e = (char *) getenv("DFU$NOSMG")) && *e) smg$enable = FALSE;
    else
    {
        if (ttype != SMG$K_VTTERMTABLE) smg$enable = FALSE;
        if (ttype != SMG$K_VTTERMTABLE) SMG$DELETE_PASTEBOARD(&paste_id,&i0);
    }

    SMG$CREATE_VIRTUAL_KEYBOARD(&keyb_id,0,0,0,0);
    if (smg$enable)
        /* Setup key table */
    {
        SMG$ERASE_PASTEBOARD(&paste_id, 0, 0, 0, 0, 0, 0);
        SMG$CREATE_KEY_TABLE(&key_tab);
        colls -=2;
        orig_colls = colls;
        smg_flag = SMG$M_KEY_NOECHO + SMG$M_KEY_TERMINATE;
        SMG$ADD_KEY_DEF(&key_tab,&do_key,0, &smg_flag, &do_key,0);
        SMG$ADD_KEY_DEF(&key_tab,&pf4,0, &smg_flag,&pf4,0);
        SMG$ADD_KEY_DEF(&key_tab,&prev,0, &smg_flag, &prev,0);
        SMG$ADD_KEY_DEF(&key_tab,&next,0, &smg_flag, &next,0);
        SMG$ADD_KEY_DEF(&key_tab,&pf2,0, &smg_flag, &help,0);
        SMG$ADD_KEY_DEF(&key_tab,&help,0, &smg_flag, &help,0);
        SMG$ADD_KEY_DEF(&key_tab,&select,0, &smg_flag, &select,0);
        SMG$CREATE_VIRTUAL_DISPLAY(&i500, &colls , &disp1_id, &SMG$M_BORDER,
                                   0, 0);
        x = 508 - rows;
        y = rows - 7;
        SMG$CREATE_VIEWPORT(&disp1_id,&x,&i1,&y,&colls);
        SMG$CREATE_VIRTUAL_DISPLAY(&i2, &colls, &status_id, 0 , 0, 0);
        SMG$CREATE_VIRTUAL_DISPLAY(&i2, &colls, &disp2_id, 0 , 0, 0);
        SMG$SET_BROADCAST_TRAPPING(&paste_id,brdcst_ast,0);
        SMG$LABEL_BORDER(&disp1_id, &top_txt, 0, 0,&SMG$M_BOLD, 0, 0);
        SMG$LABEL_BORDER(&status_id, &status_txt, 0, 0,&SMG$M_BOLD, 0, 0);
        SMG$PASTE_VIRTUAL_DISPLAY(&disp1_id, &paste_id, &i2,&i2,0);
        x = rows - 4;
        SMG$PASTE_VIRTUAL_DISPLAY(&status_id, &paste_id, &x,&i2,0);
        x = rows - 1;
        SMG$PASTE_VIRTUAL_DISPLAY(&disp2_id, &paste_id, &x,&i2,0);
        x = 508 - rows;
        SMG$SET_CURSOR_ABS(&disp1_id,&x,&i1);
        SMG$SET_CURSOR_ABS(&disp2_id,&i1,&i1);
        SMG$BEGIN_PASTEBOARD_UPDATE(&paste_id);
    }
#endif

    sprintf(outbuf,"\n     Disk and File Utilities for OpenVMS DFU V2.2");
    put_disp();
    sprintf(outbuf,"     Freeware version");
    put_disp();
    sprintf(outbuf,"     Copyright © 1995 Digital Equipment Corporation\n");
    put_disp();

    if (smg$enable)
    {
        /* Enter additional info */
        sprintf(outbuf,"     DFU functions are : \n");
        put_disp();
        sprintf(outbuf,"     DEFRAGMENT : Defragment files");
        put_disp();
        sprintf(outbuf,"     DELETE     : Delete files by File-ID; delete directory (trees)");
        put_disp();
        sprintf(outbuf,"     DIRECTORY  : Manipulate directories");
        put_disp();
        sprintf(outbuf,"     REPORT     : Generate a complete disk report");
        put_disp();
        sprintf(outbuf,"     SEARCH     : Fast file search");
        put_disp();
        sprintf(outbuf,"     SET        : Modify file attributes");
        put_disp();
        sprintf(outbuf,"     UNDELETE   : Recover deleted files");
        put_disp();
        sprintf(outbuf,"     VERIFY     : Check and repair disk structure");
        put_disp();
        SMG$END_PASTEBOARD_UPDATE(&paste_id);
    }

    prvmask = 0;
    status = dfu_check_access(&prvmask);  /*Get the privilege mask */

    /* Setup terminal channel for control purposes; get the terminal chars */
    status = SYS$ASSIGN(&terminal, &tchan, 0,0);
    status = SYS$QIOW(0,tchan, IO$_SENSEMODE,0,0,0,&orgttchar,12,0,0,0,0);
    for (i = 0; i < 3; i++) ttchar[i] = orgttchar[i];
    ttchar[2] &= ~TT2$M_EDITING; /* Clear line edit bit */
    clean_ctrlc(); /* Enable CTRL/W if needed */

    if (ret_len==0)
    {
        if (smg$enable)
            status = SMG$READ_COMPOSED_LINE(&keyb_id,&key_tab,&input_line,&prompt,
                                            &out_len,&disp2_id,0,0,0,0,0);
        else
            status = SMG$READ_COMPOSED_LINE(&keyb_id,0,&input_line,&prompt,
                                            &out_len,0,0,0,0,0,0);
    }

    memcpy (command_line, input_line.dsc$a_pointer, input_line.dsc$w_length);
    cip = 1;

    /* Main loop starts here. Get a command and pasre it*/
    for (;;)
    {
        /* loop forever until EXIT is entered */
        if(status==smg$_eof) status = exit_command(prvmask);
        if ((status&1) != 1) goto endfor;
        if (out_len == 0) goto endfor;

        /* First catch special screen commands */
        if (smg$enable)
        {
            status = strncmp(command_line, "PREV_SCREEN", 11);
            if (status == 0)
            {
                prev_screen();
                goto endfor;
            }
            status = strncmp(command_line, "DO",2);
            if (status == 0)
            {
                status = spawn_command(prvmask);
                goto endfor;
            }
            status = strncmp(command_line, "PF4",3);
            if (status == 0)
            {
                dump_screen();
                goto endfor;
            }
            status = strncmp(command_line, "NEXT_SCREEN", 11);
            if (status == 0)
            {
                next_screen();
                goto endfor;
            }
            status = strncmp(command_line, "SELECT", 6);
            if (status == 0)
            {
                toggle_width();
                goto endfor;
            }

            SMG$ERASE_DISPLAY(&disp1_id, 0, 0, 0, 0);
            SMG$ERASE_DISPLAY(&status_id, 0, 0, 0, 0);
            SMG$CHANGE_VIEWPORT(&disp1_id,&x,&i1,&y,&colls);
            SMG$SET_CURSOR_ABS(&disp1_id,&x,&i1);
        }

        /* Catch the CLI errors do avoid disrupting the SMG screen... */
#if 0
        VAXC$ESTABLISH(prim_hand);
#endif
        status = CLI$DCL_PARSE(&input_line,&dfu_tables,0 /* not yet lib$get_input*/,0,&prompt); // check added & before dfu_tables
#if 0
        VAXC$ESTABLISH(NULL);
#endif
        if (status == CLI$_NOCOMD) singlemsg(0,status);
        if ((status & 1 ) != 1) goto endfor;
        else
            /* Now dispatch if no errors */
        {
            reset_ctrl();
            CLI$DISPATCH(prvmask);
            clean_ctrlc();
            cip = 0;
            status = brdcst_ast();
            if (smg$enable) SMG$SET_CURSOR_MODE(&paste_id, &cursor_on);
        }
endfor:
        if (ret_len !=0)
        {
            /* Single command processing , so exit here */
            status += 0x10000000; /* Do not echo the error on DCL level */
            if (smg$enable)
            {
                if (colls != orig_colls) toggle_width();
                SMG$SET_CURSOR_ABS(&disp2_id,&i2,&i1);
            }
            exit(status);
        }
        /* Get next line */
        cip = 0;
#if 1
        if (smg$enable)
        {
            SMG$ERASE_LINE(&disp2_id, &i1, &i1);
            SMG$SET_CURSOR_ABS(&disp2_id,&i1,&i1);
            status = SMG$READ_COMPOSED_LINE(&keyb_id,&key_tab,&input_line,
                                            &prompt,&out_len,&disp2_id,0,0,0,0,0); /*Get next command */
            cip = 1;
        }
        else
            status = SMG$READ_COMPOSED_LINE(&keyb_id,0,&input_line,
                                            &prompt,&out_len,0,0,0,0,0,0); /*Get next command */
#else
        printf("%s",prompt.dsc$a_pointer);
        out_len = read(0,command_line,254);
        out_len--;
        command_line[out_len]=0;
        if (strncmp(command_line,"exit",4)==0)
            return 0;
#endif
    }
}  /* END of MAIN */
예제 #2
0
char *
readpassphrase(const char *prompt, char *pbuf, size_t buflen, int flags)
{

	static unsigned long keyboard_id, keytable_id = 0;
	unsigned long ctrl_mask, saved_ctrl_mask = 0;
	int timeout_secs = 0;
	int *timeout_ptr = NULL;
	unsigned long status = 0;
	unsigned short iosb[4];
	unsigned short ttchan, result_len = 0, stdin_is_tty;

	$DESCRIPTOR(ttdsc, "");
	$DESCRIPTOR(pbuf_dsc, "");
	$DESCRIPTOR(prompt_dsc, "");
	char *retval = NULL;
	char *myprompt = NULL;
	char input_fspec[MY_PASSWORD_LEN + 1];

	if (pbuf == NULL || buflen == 0) {
		errno = EINVAL;
		return NULL;
	}
	bzero(pbuf, buflen);
	pbuf_dsc.dsc$a_pointer = pbuf;
	pbuf_dsc.dsc$w_length = buflen - 1;


	/*
	 * If stdin is not a terminal and only reading from a terminal is allowed, we
	 * stop here.  
	 */
	stdin_is_tty = isatty(fileno(stdin));
	if (stdin_is_tty != 1 && (flags & RPP_REQUIRE_TTY)) {
		errno = ENOTTY;
		return NULL;
	}

	/*
	 * We need the file or device associated with stdin in VMS format.
	 */
	if (fgetname(stdin, input_fspec, 1)) {
		ttdsc.dsc$a_pointer = (char *)&input_fspec;
		ttdsc.dsc$w_length = strlen(input_fspec);
	} else {
		errno = EMFILE;
		return NULL;
	}

	/* 
	 * The prompt is expected to provide its own leading newline.
	 */
	myprompt = malloc(strlen(prompt) + 1);
	if (myprompt == NULL) {
		errno = ENOMEM;
		return NULL;
	}
	sprintf(myprompt, "\n%s", prompt);
	prompt_dsc.dsc$a_pointer = myprompt;
	prompt_dsc.dsc$w_length = strlen(myprompt);

	if (!(flags & RPP_ECHO_ON) && (stdin_is_tty)) {
		/* Disable Ctrl-T and Ctrl-Y */
		ctrl_mask = LIB$M_CLI_CTRLT | LIB$M_CLI_CTRLY;
		status = LIB$DISABLE_CTRL(&ctrl_mask, &saved_ctrl_mask);
		if (!$VMS_STATUS_SUCCESS(status)) {
			errno = EVMSERR;
			vaxc$errno = status;
			free(myprompt);
			return NULL;
		}
	}

	/* 
	 * Unless timeouts are disabled, find out how long should we wait for input
	 * before giving up.
	 */
	if (!(flags & RPP_TIMEOUT_OFF)) {
		unsigned long tmo_item = SYI$_LGI_PWD_TMO;

		status = LIB$GETSYI(&tmo_item, &timeout_secs);
		if (!$VMS_STATUS_SUCCESS(status))
			timeout_secs = DEFAULT_TIMEOUT;
		timeout_ptr = &timeout_secs;
	}

	if (!(flags & RPP_ECHO_ON) && (stdin_is_tty)) {
		/* 
		 * If we are suppressing echoing, get a line of input with $QIOW.  
		 * Non-echoed lines are not stored for recall.  (The same thing
		 * could be done with SMG but would require maintenance of a virtual 
		 * display and pasteboard.)
		 */
		status = SYS$ASSIGN(&ttdsc, &ttchan, 0, 0, 0);
		if ($VMS_STATUS_SUCCESS(status)) {

			unsigned long qio_func = IO$_READPROMPT | IO$M_NOECHO | IO$M_PURGE;

			if (!(flags & RPP_TIMEOUT_OFF))
				qio_func |= IO$M_TIMED;
			bzero(iosb, sizeof(iosb));

			status = SYS$QIOW(0,
					  (unsigned long) ttchan,
					  qio_func, &iosb, 0, 0, pbuf, buflen - 1, timeout_secs, 0, myprompt, strlen(myprompt));

			if ($VMS_STATUS_SUCCESS(status)) {
				status = iosb[0];
				result_len = iosb[1];	/* bytes actually read */
			}
			(void) SYS$DASSGN(ttchan);
		}
	} else {
		/* 
		 * We are not suppressing echoing because echoing has been explicitly 
		 * enabled and/or we are not reading from a terminal.  In this case we 
		 * use SMG, which will store commands for recall.  The virtual keyboard 
		 * and key table are static and will only be created if we haven't been 
		 * here before.
		 */
		status = SS$_NORMAL;
		if (keyboard_id == 0) {
			unsigned char recall_size = RECALL_SIZE;

			status = SMG$CREATE_VIRTUAL_KEYBOARD(&keyboard_id, &ttdsc, 0, 0, &recall_size);
		}
		if ($VMS_STATUS_SUCCESS(status) && keytable_id == 0) {
			status = SMG$CREATE_KEY_TABLE(&keytable_id);
		}

		if ($VMS_STATUS_SUCCESS(status)) {
			status = SMG$READ_COMPOSED_LINE(&keyboard_id,
							&keytable_id, &pbuf_dsc, &prompt_dsc, &result_len, 0, 0, 0, timeout_ptr);
		}
	}

	/* 
	 * Process return value from SYS$QIOW or SMG$READ_COMPOSED_LINE.
	 */
	switch (status) {
	case SS$_TIMEOUT:
		errno = ETIMEDOUT;
		break;
	case SMG$_EOF:
		if (result_len != 0) {
			status = SS$_NORMAL;
		}
		/* fall through */
	default:
		if ($VMS_STATUS_SUCCESS(status)) {
			int i;

			if (flags & RPP_FORCELOWER) {
				for (i = 0; i < result_len; i++)
					pbuf[i] = tolower(pbuf[i]);
			}
			if (flags & RPP_FORCEUPPER) {
				for (i = 0; i < result_len; i++)
					pbuf[i] = toupper(pbuf[i]);
			}
			if (flags & RPP_SEVENBIT) {
				for (i = 0; i < result_len; i++)
					pbuf[i] &= 0x7f;
			}
			pbuf[result_len] = '\0';
			retval = pbuf;
		} else {
			errno = EVMSERR;
			vaxc$errno = status;
		}
	}			/* end switch */

	free(myprompt);

	if (!(flags & RPP_ECHO_ON) && (stdin_is_tty)) {
		/*
		 * Reenable previous control processing.
		 */
		status = LIB$ENABLE_CTRL(&saved_ctrl_mask);

		if (!$VMS_STATUS_SUCCESS(status)) {
			errno = EVMSERR;
			vaxc$errno = status;
			return NULL;
		}
	}

	return retval;

}				/* getpassphrase */