예제 #1
0
void readcommandDOS(char * const str, int maxlen)
{   union REGPACK r;

    assert(str);
    assert(maxlen);

    iobuf[0] = (maxlen < CMD_SIZE)? maxlen: CMD_SIZE;
    if(iobuf[1] > iobuf[0])
        iobuf[1] = iobuf[0];

    dprintf(("[CMDINPUT characters max:%u in:%u]\n", iobuf[0], iobuf[1]));
    if(echo)
        printprompt();

    r.r_ax = 0xa00;
    r.r_ds = FP_SEG(iobuf);
    r.r_dx = FP_OFF(iobuf);
    intr(0x21, &r);

    dprintf(("[CMDINPUT characters max:%u out:%u]\n", iobuf[0], iobuf[1]));
    if(iobuf[1])            /* could bug if == 0 */
        memcpy(str, &iobuf[2], iobuf[1]);
    str[iobuf[1]] = 0;
    outc('\n');
}
예제 #2
0
파일: myshell.c 프로젝트: rlyspn/os_shell
int main()
{
	char line[MAXLINE];
	path *pth = createpath("");
	while (1) {
		programlist *pgl;
		
		if (printprompt() == -1) {
			fprintf(stderr, "Getting current directory failed.\n");
		}

		fgets(line, MAXLINE, stdin);
		pgl = parseline(line, pth);

		int child;
		if(handleexit(pgl) == 0){
			cleanuppgl(pgl);
			exit(0);
		}
		if (handlechdir(pgl) <= 0){
			cleanuppgl(pgl);
			continue;
		} else if (handlepath(pgl, pth) <= 0) {
			cleanuppgl(pgl);
			continue;
		}
		child = fork();
		if (child == 0) {
			execline(pgl, pth);
			/*printf("executed line\n"); */
			cleanuppgl(pgl);
			exit(0);
		} else {
			int status;
			int waitret;

			while (1) {
				waitret = wait(&status);
				/* printf("wait ret = %d\n", waitret); */
				if (waitret == -1 && errno == ECHILD) {
					break;
				} else if (waitret == -1 && errno != ECHILD) {
					fprintf(stderr, "Wait failed\n");
					break;
				}
			}
			cleanuppgl(pgl);
		}
	}

	return 0;
}
예제 #3
0
void		sh_pk_ctrl_l(t_usent *us)
{
	while (INDEX < us->c_size)
	{
		go_right(us);
		INDEX++;
	}
	while (us->curs_line != 0 || us->curs_col != us->prompt_size)
	{
		go_left(us);
		tputs(tgetstr("dc", NULL), 0, tputchar);
		INDEX--;
	}
	free(us->edit);
	if (!(us->edit = (char*)malloc(sizeof(char) * 255)))
		sh_error_quit("malloc us->edit fail");
	ft_memset(us->edit, '\0', 255);
	tputs(tgetstr("cl", NULL), 0, tputchar);
	printprompt(NULL);
}
예제 #4
0
void childhandler(int signal)
{
	int status,i;
	pid_t pid;
	if (signal==SIGCHLD) 
	{//	sleep(0);
		while((pid=waitpid(-1, &status,WNOHANG))> 0)
		{	//printf("\n");
			
			for(i=0;i<back_index;i++)
			{
				if((back_job[i].pro_id)==pid)
				{
					back_job[i].back_active=0;
				//	printf("zeroed: %d %d\n",back_job[i].pro_id,back_job[i].back_active);
					break;
				}
			}	
			if(WIFEXITED(status))
			{   			
				printf("\n%s with pid %d terminated with exit status: ",back_job[i].processname,pid);
				printf("%d\n",WEXITSTATUS(status));
			}
			else
			{
				if(WIFSIGNALED(status))
				{ 
					if(over_mark!=1)
						printf("\n%s with pid %d exited due to the signal no. %d\n",back_job[i].processname ,pid,WTERMSIG(status));
				}
			}

			printprompt();
		}
	}	
}
예제 #5
0
int main(void)
{
  int res,ret;
  char cmd[MAXCMD];
  struct cmdlist cmds;
	struct rlimit r;
	r.rlim_cur = 50;
	r.rlim_max = 10000;
	setrlimit(RLIMIT_FSIZE,&r);

  /* setting up the initial values of the structure  */
  /* this should be done every time when new object is created */
  setupnewcommand(&cmds);

  /* Setting up file size limit for this process and for the child processes */
  
  /* main loop of the shell */
  /* this loop proceses command wirtten by user in the following steps: */
  /* 1. Displaying command prompt
     2. Reading command from the std input
     3. Parsing this command
     4. Executing parsed commands
     5. Dealocating used memory
   */
  while(1){
    printprompt();
    if(readcmd(cmd, MAXCMD) == RESERROR) continue;
    res = parsecmd(cmd, MAXCMD, &cmds);
    printparsedcmds(&cmds);
    ret = executecmds(&cmds);
    dealocate(&cmds);
		
  }

  return 0;
}
예제 #6
0
int main(int argc, char *argv[])
{
	//struct rusage usage; 
	int status,i,l,j,ii,length,l1,l2,controld,start,end,bpid;
	char *input_str;
	char c;
	int internal=0;
	int job_no;
	char **ncomms;
	char **args_copy;
	char prompt[1000];
	char user[100],host[100];
	pid_t pid;
	controld=0;
	//createsignal();
	shell_pgid=getpid();
	if (setpgid (shell_pgid, shell_pgid) < 0)
    {
        perror ("Couldn't put the shell in its own process group");
        exit (1);
    }

	// handle sigint with hello
	signal(SIGINT, SIG_IGN);

	if(getcwd(home, sizeof(home))!=NULL)
	{	
		while(1)
		{
			position=0;
			backexit=0;
			//		back_index=0;
			flag=0;
			//		printf("<prachi@LenovoG500s");
			if(controld==0)
				printprompt();
			controld=0;
			for(i=0;i<1000;i++)
				prompt[i]='\0';

			if(getcwd(prompt, sizeof(prompt))!=NULL)
			{
				input_str=get_input();
				if(input_str[0]!='\0')
				{i=0;
				ncomms=split_input3(input_str,1);
				position=ind;
				while(position--)
				{
				//	printf("pid: %d\n",shell_pgid);
					internal=0;
					// args contains the "pipe" parsed commands 
					args=split_input3(ncomms[i],2);
					if(args[0]!="\0");
					{
						// check for built in commands
						if(args[0][0]=='c' && args[0][1]=='d')
							internal=1;
						else if(args[0][0]=='e' && args[0][1]=='x' && args[0][2]=='i' && args[0][3]=='t')
							internal=1;
						else if(args[0][0]=='e' && args[0][1]=='c' && args[0][2]=='h' && args[0][3]=='o')
							internal=1;
						else if(args[0][0]=='p' && args[0][1]=='w' && args[0][2]=='d')
							internal=1;
						else if(args[0][0]=='q' && args[0][1]=='u' && args[0][2]=='i' && args[0][3]=='t')
							internal=1;
						else if(args[0][0]=='f' && args[0][1]=='g')
						{
						//	printf("fg\n");
							internal=-1;
						}
						if(internal!=1 && internal!=-1)
						{
							int len;
							len=strlen(args[0]);
							if(args[0][len-1]=='&')
								back_mark=1;
							pid=fork();
							if(pid==0)
								loop_pipe(args);
							else if(pid<0)
								perror("myshell");
							else 
							{
								if(back_mark!=1)
									waitpid(pid,&status, WUNTRACED);
								else
							    {
									signal(SIGCHLD, childhandler);
									strcpy(copy,args[0]);
									len=strlen(copy);
									copy[len-1]='\0';
									strcpy(back_job[back_index].processname,copy);
									//		printf("args: %s",args[0]);
									back_job[back_index].pro_id=pid;
									back_job[back_index].back_active=1;
									back_index++;
									back_mark=0;										
									// storing background processes data(pid , name) into an array
									printf("%d\n",pid);
								}
							}
						}
						else if(internal==1)
						{
							args=split_input2(args[0]);
							// if built-in commands
							execute_internal(flag);
						}  
						else if(internal==-1)
						{
							// execute fg
							pid_t fpid;
							int status;
							args=split_input2(args[0]);
							fpid = execute_fg(atoi(args[1]));
					//		printf("fpid: %d\n",fpid);
							if(fpid>0)
							{
								kill(fpid, SIGCONT);
								waitpid(fpid,&status,WCONTINUED);
							}
						} 
					}	
					i++;
				}
				free(input_str);
				free(args);
			}
			else
				controld=1;
			}
			else
				perror("myshell:");
		}
	}
	else
	{	perror("myshell:");
		return EXIT_SUCCESS;
	}
	return 0;
}
예제 #7
0
파일: command.c 프로젝트: TijmenW/FreeDOS
/*
 * do the prompt/input/process loop
 *
 *  If xflg is true, the function will not go interactive, but returns.
 *  If commandline != NULL, this command is processed first.
 *
 *  Return: 0: on success
 */
int process_input(int xflag, char *commandline)
{
    /* Dimensionate parsedline that no sprintf() can overflow the buffer
     */
  char parsedline[MAX_INTERNAL_COMMAND_SIZE + sizeof(errorlevel) * 8]
    , *readline;
/* Return the maximum pointer into parsedline to add 'numbytes' bytes */
#define parsedMax(numbytes)   \
  (parsedline + MAX_INTERNAL_COMMAND_SIZE - 1 - (numbytes))
  char *evar;
  char *tp;
  char *ip;
  char *cp;
  char forvar;
  int echothisline;
  int tracethisline;

  do
  {
  	interactive_command = 0;		/* not directly entered by user */
  	echothisline = tracethisline = 0;
    if(commandline) {
      ip = commandline;
      readline = commandline = NULL;
    } else {
    if ((readline = malloc(MAX_INTERNAL_COMMAND_SIZE + 1)) == NULL)
    {
      error_out_of_memory();
      return 1;
    }

      if (NULL == (ip = readbatchline(&echothisline, readline,
                      MAX_INTERNAL_COMMAND_SIZE)))
      { /* if no batch input then... */
      if (xflag   /* must not go interactive */
       || (fdattr(0) & 0x84) == 0x84  /* input is NUL device */
       || feof(stdin))    /* no further input */
      {
        free(readline);
        break;
      }

      /* Go Interactive */
		interactive_command = 1;		/* directly entered by user */
      readcommand(ip = readline, MAX_INTERNAL_COMMAND_SIZE);
      tracemode = 0;          /* reset trace mode */
      }
    }

    /* 
     * The question mark '?' has a double meaning:
     *	C:\> ?
     *		==> Display short help
     *
     *	C:\> ? command arguments
     *		==> enable tracemode for just this line
     */
    if(*(ip = trim(ip)) == '?') {
    	 ip = trim(ip + 1);
    	 if(!*ip) {		/* is short help command */
#ifdef INCLUDE_CMD_QUESTION
    	 	showcmds(ip);
#endif
			free(readline);
			continue;
		}
		/* this-line-tracemode */
		echothisline = 0;
		tracethisline = 1;
	}

  /* The FOR hack
    If the line matches /^\s*for\s+\%[a-z]\s/, the FOR hack
    becomes active, because FOR requires the sequence "%<ch>"
    in its input.
    When the percent (%) expansion is made later on, any
    sequence "%<ch>" is retained.
  */
  cp = ip;
  if(matchtok(cp, "for") && *cp == '%' && isalpha(cp[1])
   && isspace(cp[2]))   /* activate FOR hack */
    forvar = toupper(cp[1]);
  else forvar = 0;

  cp = parsedline;
    while (*ip)
    {
      /* Assume that at least one character is added, place the
        test here to simplify the switch() statement */
      if(cp >= parsedMax(1)) {
        cp = NULL;    /* error condition */
        break;
      }
      if (*ip == '%')
      {
        switch (*++ip)
        {
          case '\0':    /* FOR hack forvar == 0 if no FOR is active */
            *cp++ = '%';
            break;

          case '%':
            *cp++ = *ip++;
            break;

          case '0':
          case '1':
          case '2':
          case '3':
          case '4':
          case '5':
          case '6':
          case '7':
          case '8':
          case '9':
            if (NULL != (tp = find_arg(*ip - '0')))
            {
              if(cp >= parsedMax(strlen(tp))) {
                cp = NULL;
                goto intBufOver;
              }
              cp = stpcpy(cp, tp);
              ip++;
            }
            else
              *cp++ = '%';
              /* Let the digit be copied in the cycle */

            break;

          case '?':
            /* overflow check: parsedline has that many character
              "on reserve" */
            cp += sprintf(cp, "%u", errorlevel);
            ip++;
            break;

          default:
            if(forvar == toupper(*ip)) {    /* FOR hack */
              *cp++ = '%';			/* let the var be copied in next cycle */
              break;
            }
            if ((tp = strchr(ip, '%')) != NULL)
            {
              *tp = '\0';

              if ((evar = getEnv(ip)) != NULL) {
                if(cp >= parsedMax(strlen(evar))) {
                  cp = NULL;
                  goto intBufOver;
                }
                cp = stpcpy(cp, evar);
               }

              ip = tp + 1;
            }
            break;
        }
        continue;
      }

      if (iscntrl(*ip))
        *cp = ' ';
      else 
      	*cp++ = *ip++;
    }

intBufOver:
    free(readline);

  if(!cp) {     /* internal buffer overflow */
    error_line_too_long();
    continue;
  }

    *cp = '\0';   /* terminate copied string */

    if (echothisline)           /* Echo batch file line */
    {
      printprompt();
      puts(parsedline);
    }

    if (*parsedline)
    {
      if(tracethisline)
      	++tracemode;
      parsecommandline(parsedline);
      if(tracethisline)
      	--tracemode;
      if (echothisline || echo)
        putchar('\n');
    }
  }
  while (!canexit || !exitflag);

  return 0;
}
예제 #8
0
/* read in a command line */
void readcommandEnhanced(char * const str, const int maxlen)
{
        unsigned char insert = 1;
        unsigned ch;
#ifdef FEATURE_FILENAME_COMPLETION
        unsigned lastch = 0;
#endif
#ifdef FEATURE_HISTORY
        int histLevel = 0;
        char prvLine[MAX_INTERNAL_COMMAND_SIZE];
#endif
        unsigned curx;
        unsigned cury;
        int count;
        unsigned current = 0;
        unsigned charcount = 0;

        assert(str);
        assert(maxlen <= MAX_INTERNAL_COMMAND_SIZE);

        /* if echo off, don't print prompt */
        if(echo)
                printprompt();

        orgx = wherex();
        orgy = wherey();
        memset(str, 0, maxlen);

        _setcursortype(_NORMALCURSOR);

#ifdef FEATURE_HISTORY
        histGet(histLevel - 1, prvLine, sizeof(prvLine));
#endif

        do {
                ch = cgetchar();

                if(cbreak)
                        ch = KEY_CTL_C;

                switch(ch) {
                case KEY_BS:               /* delete character to left of cursor */

                        if(current > 0 && charcount > 0) {
                          if(current == charcount) {     /* if at end of line */
                                str[current - 1] = 0;
                                if (wherex() != 1)
                                  outs("\b \b");
                                else
                                {
                                  goxy(MAX_X, wherey() - 1);
                                  outblank();
                                  goxy(MAX_X, wherey() - 1);
                                }
                          }
                          else
                          {
                                for (count = current - 1; count < charcount; count++)
                                  str[count] = str[count + 1];
                                if (wherex() != 1)
                                  goxy(wherex() - 1, wherey());
                                else
                                  goxy(MAX_X, wherey() - 1);
                                curx = wherex();
                                cury = wherey();
                                outsblank(&str[current - 1]);
                                goxy(curx, cury);
                          }
                          charcount--;
                          current--;
                        }
                        break;

                case KEY_INSERT:           /* toggle insert/overstrike mode */
                        insert ^= 1;
                        if (insert)
                          _setcursortype(_NORMALCURSOR);
                        else
                          _setcursortype(_SOLIDCURSOR);
                        break;

                case KEY_DELETE:           /* delete character under cursor */

                        if (current != charcount && charcount > 0)
                        {
                          for (count = current; count < charcount; count++)
                                str[count] = str[count + 1];
                          charcount--;
                          curx = wherex();
                          cury = wherey();
                          outsblank(&str[current]);
                          goxy(curx, cury);
                        }
                        break;

                case KEY_HOME:             /* goto beginning of string */

                        if (current != 0)
                        {
                          goxy(orgx, orgy);
                          current = 0;
                        }
                        break;

                case KEY_END:              /* goto end of string */

                        if (current != charcount)
                        {
                          goxy(orgx, orgy);
                          outs(str);
                          current = charcount;
                        }
                        break;

#ifdef FEATURE_FILENAME_COMPLETION
                case KEY_TAB:            /* expand current file name */
                        if(current == charcount) {      /* only works at end of line */
                          if(lastch != KEY_TAB) { /* if first TAB, complete filename */
                                complete_filename(str, charcount);
                                charcount = strlen(str);
                                current = charcount;

                                goxy(orgx, orgy);
                                outs(str);
                                if ((strlen(str) > (MAX_X - orgx)) && (orgy == MAX_Y + 1))
                                  orgy--;
                          } else {                 /* if second TAB, list matches */
                                if (show_completion_matches(str, charcount))
                                {
                                  printprompt();
                                  orgx = wherex();
                                  orgy = wherey();
                                  outs(str);
                                }
                          }
                        }
                        else
                          beep();
                        break;
#endif

                case KEY_ENTER:            /* end input, return to main */

#ifdef FEATURE_HISTORY
                        if(str[0])
                          histSet(0, str);      /* add to the history */
#endif

                        outc('\n');
                        break;

                case KEY_CTL_C:                 /* ^C */
                case KEY_ESC:              /* clear str  Make this callable! */

                        clrcmdline(str, maxlen, orgx, orgy);
                        current = charcount = 0;

                        if(ch == KEY_CTL_C && !echo) {
                          /* enable echo to let user know that's this
                                is the command line */
                          echo = 1;
                          printprompt();
                        }
                        break;

                case KEY_RIGHT:            /* move cursor right */

                        if (current != charcount)
                        {
                          current++;
                          if (wherex() == MAX_X)
                                goxy(1, wherey() + 1);
                          else
                                goxy(wherex() + 1, wherey());
                                break;
                        }
                        /* cursor-right at end of string grabs the next character
                                from the previous line */
                        /* FALL THROUGH */

#ifndef FEATURE_HISTORY
                        break;
#else
                case KEY_F1:       /* get character from last command buffer */
                          if (current < strlen(prvLine)) {
                                 outc(str[current] = prvLine[current]);
                                 charcount = ++current;
                          }
                          break;

                case KEY_F3:               /* get previous command from buffer */
                        if(charcount < strlen(prvLine)) {
                                outs(strcpy(&str[charcount], &prvLine[charcount]));
                           current = charcount = strlen(str);
                   }
                   break;

                case KEY_UP:               /* get previous command from buffer */
                        if(!histGet(--histLevel, prvLine, sizeof(prvLine)))
                                ++histLevel;            /* failed -> keep current command line */
                        else {
                                clrcmdline(str, maxlen, orgx, orgy);
                                strcpy(str, prvLine);
                                current = charcount = strlen(str);
                                outs(str);
                                histGet(histLevel - 1, prvLine, sizeof(prvLine));
                        }
                        break;

                case KEY_DOWN:             /* get next command from buffer */
                        if(histLevel) {
                                clrcmdline(str, maxlen, orgx, orgy);
                                strcpy(prvLine, str);
                                histGet(++histLevel, str, maxlen);
                                current = charcount = strlen(str);
                                outs(str);
                        }
                        break;

                case KEY_F5: /* keep cmdline in F3/UP buffer and move to next line */
                        strcpy(prvLine, str);
                        clrcmdline(str, maxlen, orgx, orgy);
                        outc('@');
                        if(orgy >= MAX_Y) {
                                outc('\n');                     /* Force scroll */
                                orgy = MAX_Y;
                        } else {
                                ++orgy;
                        }
                        goxy(orgx, orgy);
                        current = charcount = 0;

                        break;

#endif

                case KEY_LEFT:             /* move cursor left */
                        if(current > 0) {
                          current--;
                          if (wherex() == 1)
                                goxy(MAX_X, wherey() - 1);
                          else
                                goxy(wherex() - 1, wherey());
                        }
                        break;


                case KEY_CTRL_LEFT:     /* move cursor left to begin of word */
                        while(current > 0) {
                          current--;
                          if (wherex() == 1)
                                goxy(MAX_X, wherey() - 1);
                          else
                                goxy(wherex() - 1, wherey());

                          if(isworddelimiter(str[current-1])    /* ignore current == 0 */
                           && !isworddelimiter(str[current]))
                             break;
                        }
                        break;

                case KEY_CTRL_RIGHT:    /* move cursor right to begin of word */
                        while(current < charcount) {
                          current++;
                          if (wherex() == MAX_X)
                                goxy(1, wherey() + 1);
                          else
                                goxy(wherex() + 1, wherey());

                          if(isworddelimiter(str[current-1])
                           && !isworddelimiter(str[current]))
                             break;
                        }
                        break;

                default:                 /* insert character into string... */

                        if ((ch >= 32 && ch <= 255) && (charcount != (maxlen - 2)))
                        {
                          if (insert && current != charcount)
                          {
                                for (count = charcount; count > current; count--)
                                  str[count] = str[count - 1];
                                str[current++] = ch;
                                curx = wherex() + 1;
                                cury = wherey();
                                outs(&str[current - 1]);
                                if ((strlen(str) > (MAX_X - orgx)) && (orgy == MAX_Y + 1))
                                  cury--;
                                goxy(curx, cury);
                                charcount++;
                          }
                          else
                          {
                                if (current == charcount)
                                  charcount++;
                                str[current++] = ch;
                                outc(ch);
                          }
                          if ((strlen(str) > (MAX_X - orgx)) && (orgy == MAX_Y + 1))
                                orgy--;
                        }
                        else
                          beep();
                        break;
                }
#ifdef FEATURE_FILENAME_COMPLETION
                lastch = ch;
#endif
        } while(ch != KEY_ENTER);

        _setcursortype(_NORMALCURSOR);
}
예제 #9
0
파일: command.c 프로젝트: FDOS/freecom
/*
 * do the prompt/input/process loop
 *
 *  If xflg is true, the function will not go interactive, but returns.
 *  If commandline != NULL, this command is processed first.
 *
 *  Return: 0: on success
 */
int process_input(int xflag, char *commandline)
{
    /* Dimensionate parsedline that no sprintf() can overflow the buffer
     */
  char parsedline[MAX_INTERNAL_COMMAND_SIZE + sizeof(errorlevel) * 8]
    , *readline;
#if 0
/* Return the maximum pointer into parsedline to add 'numbytes' bytes */
#define parsedMax(numbytes)   \
  (parsedline + MAX_INTERNAL_COMMAND_SIZE - 1 - (numbytes))
  char *evar;
  char *tp;
  char *cp;
#endif
  char *ip;
#if 0
  char forvar;
#endif
  int echothisline;
  int tracethisline;

  do
  {
#ifdef FEATURE_LONG_FILENAMES
    if( toupper( *getEnv( "LFN" ) ) == 'N' )
         __supportlfns = 0;
    else __supportlfns = 1;
#endif
  	interactive_command = 0;		/* not directly entered by user */
  	echothisline = tracethisline = 0;
    if(commandline) {
      ip = commandline;
      readline = commandline = 0;
    } else {
    if ((readline = malloc(MAX_INTERNAL_COMMAND_SIZE + 1)) == 0)
    {
      error_out_of_memory();
      return 1;
    }

      if (0 == (ip = readbatchline(&echothisline, readline,
                      MAX_INTERNAL_COMMAND_SIZE)))
      { /* if no batch input then... */
      if (xflag   /* must not go interactive */
       || (fdattr(0) & 0x84) == 0x84  /* input is NUL device */
       || feof(stdin))    /* no further input */
      {
        free(readline);
        break;
      }

      /* Go Interactive */
		interactive_command = 1;		/* directly entered by user */
		/* Ensure the prompt starts at column #0 */
		if(echo && (mywherex()>1))
			outc('\n');
      readcommand(ip = readline, MAX_INTERNAL_COMMAND_SIZE);
      tracemode = 0;          /* reset trace mode */
      }
    }

    	/* Make sure there is no left-over from last run */
    currCmdHelpScreen = 0;

    /* 
     * The question mark '?' has a double meaning:
     *	C:\> ?
     *		==> Display short help
     *
     *	C:\> ? command arguments
     *		==> enable tracemode for just this line
     */
    if(*(ip = ltrimcl(ip)) == '?') {
    	 ip = ltrimcl(ip + 1);
    	 if(!*ip) {		/* is short help command */
#ifdef INCLUDE_CMD_QUESTION
    	 	showcmds(ip);
#endif
			free(readline);
			continue;
		}
		/* this-line-tracemode */
		echothisline = 0;
		tracethisline = 1;
	}

#if 0
  /* The FOR hack
    If the line matches /^\s*for\s+\%[a-z]\s/, the FOR hack
    becomes active, because FOR requires the sequence "%<ch>"
    in its input.
    When the percent (%) expansion is made later on, any
    sequence "%<ch>" is retained.
  */
  cp = ip;
  if(matchtok(cp, "for") && *cp == '%' && isalpha(cp[1])
   && isargdelim(cp[2]))   /* activate FOR hack */
    forvar = toupper(cp[1]);
  else forvar = 0;

#else
	if(cmd_for_hackery(ip)) {
		free(readline);
		continue;
	}
#endif

	{	int rc = expandEnvVars(ip, parsedline);
		free(readline);
		if(!rc) {
			error_line_too_long();
			continue;
		}
	}
  
    if (echothisline)           /* Echo batch file line */
    {
      printprompt();
      puts(parsedline);
    }

    if (*parsedline)
    {
      if(swapOnExec != ERROR)
      	swapOnExec = defaultToSwap;
      if(tracethisline)
      	++tracemode;
      parsecommandline(parsedline, TRUE);
      if(tracethisline)
      	--tracemode;
    }
  }
  while (!canexit || !exitflag);

  return 0;
}
예제 #10
0
파일: command.c 프로젝트: FDOS/freecom
/*
 * process the command line and execute the appropriate functions
 * full input/output redirection and piping are supported
 */
void parsecommandline(char *s, int redirect)
{
  char *in = 0;
  char *out = 0;
  char *fname0 = 0;
  char *fname1 = 0;
  char *nextcmd;

  int of_attrib = O_CREAT | O_TRUNC | O_WRONLY;
  int num;

  assert(s);

  dprintf(("[parsecommandline (%s)]\n", s));

#ifdef FEATURE_ALIASES
  aliasexpand(s, MAX_INTERNAL_COMMAND_SIZE);
  dprintf(("[alias expanded to (%s)]\n", s));
#endif

  if (tracemode)
  {                             /* Question after the variables expansion
                                   and make sure _all_ executed commands will
                                   honor the trace mode */
    /* 
     * Commands may be nested ("if errorlevel 1 echo done>test"). To
     * prevent redirecting FreeCOM prompts to user file, temporarily
     * revert redirection.
     */
    int redir_fdin, redir_fdout, answer;

    if (oldinfd != -1) {
        redir_fdin = dup (0);
        dup2 (oldinfd,  0);
    }
    if (oldoutfd != -1) {
        redir_fdout = dup (1);
        dup2 (oldoutfd, 1);
    }

    printprompt();
    outs(s);
    /* If the user hits ^Break, it has the same effect as
       usually: If he is in a batch file, he is asked if
       to abort all the batchfiles or just the current one */
    answer = userprompt(PROMPT_YES_NO);

    if (oldinfd  != -1) {
        dup2 (redir_fdin,  0);
        dos_close (redir_fdin);
    }
    if (oldoutfd != -1) {
        dup2 (redir_fdout, 1);
        dos_close (redir_fdout);
    }

    if (answer != 1) return;              /* "No" or ^Break   */
  }

  if(!redirect) {
  	docommand(s);
  	return;
  }

  assert(oldinfd == -1);  /* if fails something is wrong; should NEVER */
  assert(oldoutfd == -1); /* happen! -- 2000/01/13 ska*/

  num = get_redirection(s, &in, &out, &of_attrib);
  if (num < 0)                  /* error */
    goto abort;

  /* Set up the initial conditions ... */

  if (in || (num > 1))          /* Need to preserve stdin */
    oldinfd = dup(0);

  if (in)                       /* redirect input from this file name */
  {
    dos_close(0);
    if (0 != devopen(in, O_RDONLY))
    {
		error_redirect_from_file(in);
      goto abort;
    }
  }

  if (out || (num > 1))         /* Need to preserve stdout */
    oldoutfd = dup(1);

  /* Now do all but the last pipe command */
  while (num-- > 1)
  {
    dos_close(1);               /* Close current output file */
    if ((fname0 = tmpfn()) == 0)
      goto abort;
    dos_creat(fname0, 0);

    nextcmd = s + strlen(s) + 1;
    docommand(s);

    dos_close(1);
    dup2(oldoutfd, 1);

    dos_close(0);
    killtmpfn(fname1);          /* fname1 can by NULL */
    fname1 = fname0;
    fname0 = 0;
    dos_open(fname1, O_RDONLY);

    s = nextcmd;
  }

  /* Now set up the end conditions... */

  if (out)                      /* Final output to here */
  {
    dos_close(1);
    if (1 != devopen(out, of_attrib))
    {
		error_redirect_to_file(out);
      goto abort;
    }
  }
  else if (oldoutfd != -1)      /* Restore original stdout */
  {
    dos_close(1);
    dup2(oldoutfd, 1);
    dos_close(oldoutfd);
    oldoutfd = -1;
  }

  docommand(s);                 /* process final command */

abort:
  if (oldinfd != -1)            /* Restore original STDIN */
  {
    dos_close(0);
    dup2(oldinfd, 0);
    dos_close(oldinfd);
    oldinfd = -1;
  }

  if (oldoutfd != -1)           /* Restore original STDOUT */
  {
    dos_close(1);
    dup2(oldoutfd, 1);
    dos_close(oldoutfd);
    oldoutfd = -1;
  }

  killtmpfn(fname1);
  killtmpfn(fname0);

  if (out)
    free(out);

  if (in)
    free(in);
}
예제 #11
0
파일: ed.inputl.c 프로젝트: Lance0312/tcsh
/* CCRETVAL */
int
Inputl(void)
{
    CCRETVAL retval;
    KEYCMD  cmdnum = 0;
    unsigned char tch;		/* the place where read() goes */
    Char    ch;
    int     num;		/* how many chars we have read at NL */
    int	    expnum;
    struct varent *crct = inheredoc ? NULL : adrof(STRcorrect);
    struct varent *autol = adrof(STRautolist);
    struct varent *matchbeep = adrof(STRmatchbeep);
    struct varent *imode = adrof(STRinputmode);
    Char   *SaveChar, *CorrChar;
    int     matchval;		/* from tenematch() */
    int     nr_history_exp;     /* number of (attempted) history expansions */
    COMMAND fn;
    int curlen = 0;
    int newlen;
    int idx;
    Char *autoexpand;

    if (!MapsAreInited)		/* double extra just in case */
	ed_InitMaps();

    ClearDisp();		/* reset the display stuff */
    ResetInLine(0);		/* reset the input pointers */
    if (GettingInput)
	MacroLvl = -1;		/* editor was interrupted during input */

    if (imode && imode->vec != NULL) {
	if (!Strcmp(*(imode->vec), STRinsert))
	    inputmode = MODE_INSERT;
	else if (!Strcmp(*(imode->vec), STRoverwrite))
	    inputmode = MODE_REPLACE;
    }

#if defined(FIONREAD) && !defined(OREO)
    if (!Tty_raw_mode && MacroLvl < 0) {
# ifdef SUNOS4
	long chrs = 0;
# else /* !SUNOS4 */
	/* 
	 * *Everyone* else has an int, but SunOS wants long!
	 * This breaks where int != long (alpha)
	 */
	int chrs = 0;
# endif /* SUNOS4 */

	(void) ioctl(SHIN, FIONREAD, (ioctl_t) & chrs);
	if (chrs == 0) {
	    if (Rawmode() < 0)
		return 0;
	}
    }
#endif /* FIONREAD && !OREO */

    GettingInput = 1;
    NeedsRedraw = 0;
    tellwhat = 0;

    if (RestoreSaved) {
	copyn(InputBuf, SavedBuf.s, INBUFSIZE);/*FIXBUF*/
	LastChar = InputBuf + LastSaved;
	Cursor = InputBuf + CursSaved;
	Hist_num = HistSaved;
	HistSaved = 0;
	RestoreSaved = 0;
    }
    if (HistSaved) {
	Hist_num = HistSaved;
	GetHistLine();
	HistSaved = 0;
    }
    if (Expand) {
	(void) e_up_hist(0);
	Expand = 0;
    }
    Refresh();			/* print the prompt */

    for (num = OKCMD; num == OKCMD;) {	/* while still editing this line */
#ifdef DEBUG_EDIT
	if (Cursor > LastChar)
	    xprintf("Cursor > LastChar\r\n");
	if (Cursor < InputBuf)
	    xprintf("Cursor < InputBuf\r\n");
	if (Cursor > InputLim)
	    xprintf("Cursor > InputLim\r\n");
	if (LastChar > InputLim)
	    xprintf("LastChar > InputLim\r\n");
	if (InputLim != &InputBuf[INBUFSIZE - 2])/*FIXBUF*/
	    xprintf("InputLim != &InputBuf[INBUFSIZE-2]\r\n");
	if ((!DoingArg) && (Argument != 1))
	    xprintf("(!DoingArg) && (Argument != 1)\r\n");
	if (CcKeyMap[0] == 0)
	    xprintf("CcKeyMap[0] == 0 (maybe not inited)\r\n");
#endif

	/* if EOF or error */
	if ((num = GetNextCommand(&cmdnum, &ch)) != OKCMD) {
	    break;
	}

	if (cmdnum >= NumFuns) {/* BUG CHECK command */
#ifdef DEBUG_EDIT
	    xprintf(CGETS(6, 1, "ERROR: illegal command from key 0%o\r\n"), ch);
#endif
	    continue;		/* try again */
	}

	/* now do the real command */
	retval = (*CcFuncTbl[cmdnum]) (ch);

	/* save the last command here */
	LastCmd = cmdnum;

	/* make sure fn is initialized */
	fn = (retval == CC_COMPLETE_ALL) ? LIST_ALL : LIST;

	/* use any return value */
	switch (retval) {

	case CC_REFRESH:
	    Refresh();
	    /*FALLTHROUGH*/
	case CC_NORM:		/* normal char */
	    Argument = 1;
	    DoingArg = 0;
	    /*FALLTHROUGH*/
	case CC_ARGHACK:	/* Suggested by Rich Salz */
	    /* <*****@*****.**> */
	    curchoice = -1;
	    curlen = (int) (LastChar - InputBuf);
	    break;		/* keep going... */

	case CC_EOF:		/* end of file typed */
	    curchoice = -1;
	    curlen = (int) (LastChar - InputBuf);
	    num = 0;
	    break;

	case CC_WHICH:		/* tell what this command does */
	    tellwhat = 1;
	    *LastChar++ = '\n';	/* for the benifit of CSH */
	    num = (int) (LastChar - InputBuf);	/* number characters read */
	    break;

	case CC_NEWLINE:	/* normal end of line */
	    curlen = 0;
	    curchoice = -1;
	    matchval = 1;
	    if (crct && crct->vec != NULL && (!Strcmp(*(crct->vec), STRcmd) ||
			 !Strcmp(*(crct->vec), STRall))) {
		Char *Origin;

                PastBottom();
		Origin = Strsave(InputBuf);
		cleanup_push(Origin, xfree);
		SaveChar = LastChar;
		if (SpellLine(!Strcmp(*(crct->vec), STRcmd)) == 1) {
		    Char *Change;

                    PastBottom();
		    Change = Strsave(InputBuf);
		    cleanup_push(Change, xfree);
		    *Strchr(Change, '\n') = '\0';
		    CorrChar = LastChar;	/* Save the corrected end */
		    LastChar = InputBuf;	/* Null the current line */
		    SoundBeep();
		    printprompt(2, short2str(Change));
		    cleanup_until(Change);
		    Refresh();
		    if (xread(SHIN, &tch, 1) < 0) {
#ifdef convex
		        /*
			 * need to print error message in case file
			 * is migrated
			 */
                        if (errno)
                            stderror(ERR_SYSTEM, progname, strerror(errno));
#else
			cleanup_until(Origin);
			break;
#endif
		    }
		    ch = tch;
		    if (ch == 'y' || ch == ' ') {
			LastChar = CorrChar;	/* Restore the corrected end */
			xprintf("%s", CGETS(6, 2, "yes\n"));
		    }
		    else {
			Strcpy(InputBuf, Origin);
			LastChar = SaveChar;
			if (ch == 'e') {
			    xprintf("%s", CGETS(6, 3, "edit\n"));
			    *LastChar-- = '\0';
			    Cursor = LastChar;
			    printprompt(3, NULL);
			    ClearLines();
			    ClearDisp();
			    Refresh();
			    cleanup_until(Origin);
			    break;
			}
			else if (ch == 'a') {
			    xprintf("%s", CGETS(6, 4, "abort\n"));
		            LastChar = InputBuf;   /* Null the current line */
			    Cursor = LastChar;
			    printprompt(0, NULL);
			    Refresh();
			    cleanup_until(Origin);
			    break;
			}
			xprintf("%s", CGETS(6, 5, "no\n"));
		    }
		    flush();
		}
		cleanup_until(Origin);
	    } else if (crct && crct->vec != NULL &&
		!Strcmp(*(crct->vec), STRcomplete)) {
                if (LastChar > InputBuf && LastChar[-1] == '\n') {
                    LastChar[-1] = '\0';
                    LastChar--;
                    Cursor = LastChar;
                }
                match_unique_match = 1;  /* match unique matches */
		matchval = CompleteLine();
                match_unique_match = 0;
        	curlen = (int) (LastChar - InputBuf);
		if (matchval != 1) {
                    PastBottom();
		}
		if (matchval == 0) {
		    xprintf("%s", CGETS(6, 6, "No matching command\n"));
		} else if (matchval == 2) {
		    xprintf("%s", CGETS(6, 7, "Ambiguous command\n"));
		}
	        if (NeedsRedraw) {
		    ClearLines();
		    ClearDisp();
		    NeedsRedraw = 0;
	        }
	        Refresh();
	        Argument = 1;
	        DoingArg = 0;
		if (matchval == 1) {
                    PastBottom();
                    *LastChar++ = '\n';
                    *LastChar = '\0';
		}
        	curlen = (int) (LastChar - InputBuf);
            }
	    else
		PastBottom();

	    if (matchval == 1) {
	        tellwhat = 0;	/* just in case */
	        Hist_num = 0;	/* for the history commands */
		/* return the number of chars read */
	        num = (int) (LastChar - InputBuf);
	        /*
	         * For continuation lines, we set the prompt to prompt 2
	         */
	        printprompt(1, NULL);
	    }
	    break;

	case CC_CORRECT:
	    if (tenematch(InputBuf, Cursor - InputBuf, SPELL) < 0)
		SoundBeep();		/* Beep = No match/ambiguous */
	    curlen = Repair();
	    break;

	case CC_CORRECT_L:
	    if (SpellLine(FALSE) < 0)
		SoundBeep();		/* Beep = No match/ambiguous */
	    curlen = Repair();
	    break;


	case CC_COMPLETE:
	case CC_COMPLETE_ALL:
	case CC_COMPLETE_FWD:
	case CC_COMPLETE_BACK:
	    switch (retval) {
	    case CC_COMPLETE:
		fn = RECOGNIZE;
		curlen = (int) (LastChar - InputBuf);
		curchoice = -1;
		rotate = 0;
		break;
	    case CC_COMPLETE_ALL:
		fn = RECOGNIZE_ALL;
		curlen = (int) (LastChar - InputBuf);
		curchoice = -1;
		rotate = 0;
		break;
	    case CC_COMPLETE_FWD:
		fn = RECOGNIZE_SCROLL;
		curchoice++;
		rotate = 1;
		break;
	    case CC_COMPLETE_BACK:
		fn = RECOGNIZE_SCROLL;
		curchoice--;
		rotate = 1;
		break;
	    default:
		abort();
	    }
	    if (InputBuf[curlen] && rotate) {
		newlen = (int) (LastChar - InputBuf);
		for (idx = (int) (Cursor - InputBuf); 
		     idx <= newlen; idx++)
			InputBuf[idx - newlen + curlen] =
			InputBuf[idx];
		LastChar = InputBuf + curlen;
		Cursor = Cursor - newlen + curlen;
	    }
	    curlen = (int) (LastChar - InputBuf);


	    nr_history_exp = 0;
	    autoexpand = varval(STRautoexpand);
	    if (autoexpand != STRNULL)
		nr_history_exp += ExpandHistory();

	    /* try normal expansion only if no history references were found */
	    if (nr_history_exp == 0 ||
		Strcmp(autoexpand, STRonlyhistory) != 0) {
		/*
		 * Modified by Martin Boyer ([email protected]):
		 * A separate variable now controls beeping after
		 * completion, independently of autolisting.
		 */
		expnum = (int) (Cursor - InputBuf);
		switch (matchval = tenematch(InputBuf, Cursor-InputBuf, fn)){
		case 1:
		    if (non_unique_match && matchbeep &&
			matchbeep->vec != NULL &&
			(Strcmp(*(matchbeep->vec), STRnotunique) == 0))
			SoundBeep();
		    break;
		case 0:
		    if (matchbeep && matchbeep->vec != NULL) {
			if (Strcmp(*(matchbeep->vec), STRnomatch) == 0 ||
			    Strcmp(*(matchbeep->vec), STRambiguous) == 0 ||
			    Strcmp(*(matchbeep->vec), STRnotunique) == 0)
			    SoundBeep();
		    }
		    else
			SoundBeep();
		    break;
		default:
		    if (matchval < 0) {	/* Error from tenematch */
			curchoice = -1;
			SoundBeep();
			break;
		    }
		    if (matchbeep && matchbeep->vec != NULL) {
			if ((Strcmp(*(matchbeep->vec), STRambiguous) == 0 ||
			     Strcmp(*(matchbeep->vec), STRnotunique) == 0))
			    SoundBeep();
		    }
		    else
			SoundBeep();
		    /*
		     * Addition by David C Lawrence <*****@*****.**>: If an 
		     * attempted completion is ambiguous, list the choices.  
		     * (PWP: this is the best feature addition to tcsh I have 
		     * seen in many months.)
		     */
		    if (autol && autol->vec != NULL && 
			(Strcmp(*(autol->vec), STRambiguous) != 0 || 
					 expnum == Cursor - InputBuf)) {
			if (adrof(STRhighlight) && MarkIsSet) {
			    /* clear highlighting before showing completions */
			    MarkIsSet = 0;
			    ClearLines();
			    ClearDisp();
			    Refresh();
			    MarkIsSet = 1;
			}
			PastBottom();
			fn = (retval == CC_COMPLETE_ALL) ? LIST_ALL : LIST;
			(void) tenematch(InputBuf, Cursor-InputBuf, fn);
		    }
		    break;
		}
	    }
	    if (NeedsRedraw) {
		PastBottom();
		ClearLines();
		ClearDisp();
		NeedsRedraw = 0;
	    }
	    Refresh();
	    Argument = 1;
	    DoingArg = 0;
	    break;

	case CC_LIST_CHOICES:
	case CC_LIST_ALL:
	    if (InputBuf[curlen] && rotate) {
		newlen = (int) (LastChar - InputBuf);
		for (idx = (int) (Cursor - InputBuf); 
		     idx <= newlen; idx++)
			InputBuf[idx - newlen + curlen] =
			InputBuf[idx];
		LastChar = InputBuf + curlen;
		Cursor = Cursor - newlen + curlen;
	    }
	    curlen = (int) (LastChar - InputBuf);
	    if (curchoice >= 0)
		curchoice--;

	    fn = (retval == CC_LIST_ALL) ? LIST_ALL : LIST;
	    /* should catch ^C here... */
	    if (tenematch(InputBuf, Cursor - InputBuf, fn) < 0)
		SoundBeep();
	    Refresh();
	    Argument = 1;
	    DoingArg = 0;
	    break;


	case CC_LIST_GLOB:
	    if (tenematch(InputBuf, Cursor - InputBuf, GLOB) < 0)
		SoundBeep();
	    curlen = Repair();
	    break;

	case CC_EXPAND_GLOB:
	    if (tenematch(InputBuf, Cursor - InputBuf, GLOB_EXPAND) <= 0)
		SoundBeep();		/* Beep = No match */
	    curlen = Repair();
	    break;

	case CC_NORMALIZE_PATH:
	    if (tenematch(InputBuf, Cursor - InputBuf, PATH_NORMALIZE) <= 0)
		SoundBeep();		/* Beep = No match */
	    curlen = Repair();
	    break;

	case CC_EXPAND_VARS:
	    if (tenematch(InputBuf, Cursor - InputBuf, VARS_EXPAND) <= 0)
		SoundBeep();		/* Beep = No match */
	    curlen = Repair();
	    break;

	case CC_NORMALIZE_COMMAND:
	    if (tenematch(InputBuf, Cursor - InputBuf, COMMAND_NORMALIZE) <= 0)
		SoundBeep();		/* Beep = No match */
	    curlen = Repair();
	    break;

	case CC_HELPME:
	    xputchar('\n');
	    /* should catch ^C here... */
	    (void) tenematch(InputBuf, LastChar - InputBuf, PRINT_HELP);
	    Refresh();
	    Argument = 1;
	    DoingArg = 0;
	    curchoice = -1;
	    curlen = (int) (LastChar - InputBuf);
	    break;

	case CC_FATAL:		/* fatal error, reset to known state */
#ifdef DEBUG_EDIT
	    xprintf(CGETS(7, 8, "*** editor fatal ERROR ***\r\n\n"));
#endif				/* DEBUG_EDIT */
	    /* put (real) cursor in a known place */
	    ClearDisp();	/* reset the display stuff */
	    ResetInLine(1);	/* reset the input pointers */
	    Refresh();		/* print the prompt again */
	    Argument = 1;
	    DoingArg = 0;
	    curchoice = -1;
	    curlen = (int) (LastChar - InputBuf);
	    break;

	case CC_ERROR:
	default:		/* functions we don't know about */
	    if (adrof(STRhighlight)) {
		ClearLines();
		ClearDisp();
		Refresh();
	    }
	    DoingArg = 0;
	    Argument = 1;
	    SoundBeep();
	    flush();
	    curchoice = -1;
	    curlen = (int) (LastChar - InputBuf);
	    break;
	}
    }
    (void) Cookedmode();	/* make sure the tty is set up correctly */
    GettingInput = 0;
    flush();			/* flush any buffered output */
    return num;
}
예제 #12
0
파일: noice.c 프로젝트: PaulBatchelor/Noice
void
browse(const char *ipath, const char *ifilter)
{
	int r, fd;
	regex_t re;
	char *newpath;
	struct stat sb;
	char *name, *bin, *dir, *tmp, *run, *env;
	int nowtyping = 0;
    FILE *fp;

	oldpath = NULL;
	path = xstrdup(ipath);
	fltr = xstrdup(ifilter);
begin:
	/* Path and filter should be malloc(3)-ed strings at all times */
	r = populate();
	if (r == -1) {
		if (!nowtyping) {
			printwarn();
			goto nochange;
		}
	}

	for (;;) {
		redraw();

		/* Handle filter-as-you-type mode */
		if (nowtyping)
			goto moretyping;
nochange:
		switch (nextsel(&run, &env)) {
		case SEL_QUIT:
			free(path);
			free(fltr);
			dentfree(dents, n);
			return;
		case SEL_BACK:
			/* There is no going back */
			if (strcmp(path, "/") == 0 ||
			    strcmp(path, ".") == 0 ||
			    strchr(path, '/') == NULL)
				goto nochange;
			dir = xdirname(path);
			if (canopendir(dir) == 0) {
				free(dir);
				printwarn();
				goto nochange;
			}
			/* Save history */
			oldpath = path;
			path = dir;
			/* Reset filter */
			free(fltr);
			fltr = xstrdup(ifilter);
			goto begin;
		case SEL_GOIN:
			/* Cannot descend in empty directories */
			if (n == 0)
				goto nochange;

			name = dents[cur].name;
			newpath = mkpath(path, name);
			DPRINTF_S(newpath);

			/* Get path info */
			fd = open(newpath, O_RDONLY | O_NONBLOCK);
			if (fd == -1) {
				printwarn();
				free(newpath);
				goto nochange;
			}
			r = fstat(fd, &sb);
			if (r == -1) {
				printwarn();
				close(fd);
				free(newpath);
				goto nochange;
			}
			close(fd);
			DPRINTF_U(sb.st_mode);

			switch (sb.st_mode & S_IFMT) {
			case S_IFDIR:
				if (canopendir(newpath) == 0) {
					printwarn();
					free(newpath);
					goto nochange;
				}
				free(path);
				path = newpath;
				/* Reset filter */
				free(fltr);
				fltr = xstrdup(ifilter);
				goto begin;
			case S_IFREG:
				bin = openwith(newpath);
				if (bin == NULL) {
					printmsg("No association");
					free(newpath);
					goto nochange;
				}
				exitcurses();
				spawn(bin, newpath, NULL);
				initcurses();
				free(newpath);
				continue;
			default:
				printmsg("Unsupported file");
				goto nochange;
			}
		case SEL_FLTR:
			/* Read filter */
			printprompt("filter: ");
			tmp = readln();
			if (tmp == NULL)
				tmp = xstrdup(ifilter);
			/* Check and report regex errors */
			r = setfilter(&re, tmp);
			if (r != 0) {
				free(tmp);
				goto nochange;
			}
			free(fltr);
			fltr = tmp;
			DPRINTF_S(fltr);
			/* Save current */
			if (n > 0)
				oldpath = mkpath(path, dents[cur].name);
			goto begin;
		case SEL_TYPE:
			nowtyping = 1;
			tmp = NULL;
moretyping:
			printprompt("type: ");
			if (tmp != NULL)
				printw("%s", tmp);
			r = readmore(&tmp);
			DPRINTF_D(r);
			DPRINTF_S(tmp);
			if (r == 1)
				nowtyping = 0;
			/* Check regex errors */
			if (tmp != NULL) {
				r = setfilter(&re, tmp);
				if (r != 0)
					if (nowtyping) {
						goto moretyping;
					} else {
						free(tmp);
						goto nochange;
					}
			}
			/* Copy or reset filter */
			free(fltr);
			if (tmp != NULL)
				fltr = xstrdup(tmp);
			else
				fltr = xstrdup(ifilter);
			/* Save current */
			if (n > 0)
				oldpath = mkpath(path, dents[cur].name);
			if (!nowtyping)
				free(tmp);
			goto begin;
		case SEL_NEXT:
			if (cur < n - 1)
				cur++;
			break;
		case SEL_PREV:
			if (cur > 0)
				cur--;
			break;
		case SEL_PGDN:
			if (cur < n - 1)
				cur += MIN((LINES - 4) / 2, n - 1 - cur);
			break;
		case SEL_PGUP:
			if (cur > 0)
				cur -= MIN((LINES - 4) / 2, cur);
			break;
		case SEL_HOME:
			cur = 0;
			break;
		case SEL_END:
			cur = n - 1;
			break;
		case SEL_CD:
			/* Read target dir */
			printprompt("chdir: ");
			tmp = readln();
			if (tmp == NULL) {
				clearprompt();
				goto nochange;
			}
			newpath = mkpath(path, tmp);
			free(tmp);
			if (canopendir(newpath) == 0) {
				free(newpath);
				printwarn();
				goto nochange;
			}
			free(path);
			path = newpath;
			free(fltr);
			fltr = xstrdup(ifilter); /* Reset filter */
			DPRINTF_S(path);
			goto begin;
		case SEL_MTIME:
			mtimeorder = !mtimeorder;
			/* Save current */
			if (n > 0)
				oldpath = mkpath(path, dents[cur].name);
			goto begin;
		case SEL_REDRAW:
			/* Save current */
			if (n > 0)
				oldpath = mkpath(path, dents[cur].name);
			goto begin;
		case SEL_RUN:
			run = xgetenv(env, run);
			exitcurses();
			spawn(run, NULL, path);
			initcurses();
			break;
		case SEL_RUNARG:
			name = dents[cur].name;
			run = xgetenv(env, run);
			exitcurses();
			spawn(run, name, path);
			initcurses();
			break;
        case SEL_PRINT:
			name = dents[cur].name;
            fp = fopen("savelist.txt", "a");
            fprintf(fp, "%s/%s\n", path, name);
            fclose(fp);
            break;
		}
		/* Screensaver */
		if (idletimeout != 0 && idle == idletimeout) {
			idle = 0;
			exitcurses();
			spawn(idlecmd, NULL, NULL);
			initcurses();
		}
	}
}