Beispiel #1
0
int main(int _argc, char **_argv) {
  /* clear shell variables and re-assign a minimum set */
	 	  
  clearenv();
  setenv("PATH", ":/bin:/usr/bin", 1);
  setenv("PROMPT", "$ ", 1);
  setenv("SHELL", _argv[0], 1);

  signal(SIGINT, SIG_IGN); /* ignore ^C */

  while(1) {
    printf("%s", getenv("PROMPT"));
    if(!read_command())
      break;
    split_command();
    if(!argc)
      continue;
    expand_args();
    /* process builtin commands */
    if(!strcmp(argv[0],"exit")) {
      break;
    } else if(!strcmp(argv[0],"set")) {
      if(argc!=3) {
        fprintf(stderr, "set: two arguments required\n");
        continue;
      }
      setenv(argv[1], argv[2], 1);
    } else if(!strcmp(argv[0], "cd")) {
      if(argc!=2) {
        fprintf(stderr, "cd: one argument required\n");
        continue;
      }
      if(chdir(argv[1])==-1) {
        perror("cd");
      }
    } else if(!strcmp(argv[0], "pwd")) {
      if(argc!=1) {
        fprintf(stderr, "pwd: no arguments allowed\n");
        continue;
      }
      printf("%s\n", getcwd(command, BUF_LEN));
    }  else {
      /* run external command */
      run_program();
    }
    free_args();
  }
  printf("\n");

  return 0;
}
Beispiel #2
0
static char *
parse_cmd(int type, char *cmd, const char *repo,
    struct file_info_list *file_info)
{
	int expanded = 0;
	char argbuf[2] = { '\0', '\0' };
	char *allowed_args, *default_args, *args, *file, *p, *q = NULL;
	size_t pos;
	BUF *buf;

	switch (type) {
	case CVS_TRIGGER_COMMITINFO:
		allowed_args = "prsS{}";
		default_args = " %p/%r %S";
		file = CVS_PATH_COMMITINFO;
		break;
	case CVS_TRIGGER_LOGINFO:
		allowed_args = "prsSvVt{}";
		default_args = NULL;
		file = CVS_PATH_LOGINFO;
		break;
	case CVS_TRIGGER_VERIFYMSG:
		allowed_args = "l";
		default_args = " %l";
		file = CVS_PATH_VERIFYMSG;
		break;
	case CVS_TRIGGER_TAGINFO:
		allowed_args = "btoprsSvV{}";
		default_args = " %t %o %p/%r %{sv}";
		file = CVS_PATH_TAGINFO;
		break;
	default:
		return (NULL);
	}

	/* before doing any stuff, check if the command starts with % */
	for (p = cmd;
	     *p != '%' && !isspace((unsigned char)*p) && *p != '\0'; p++)
		;
	if (*p == '%')
		return (NULL);

	buf = buf_alloc(1024);

	p = cmd;
again:
	for (; *p != '\0'; p++) {
		if ((pos = strcspn(p, "$%")) != 0) {
			buf_append(buf, p, pos);
			p += pos;
		}

		q = NULL;
		if (*p == '\0')
			break;
		if (*p++ == '$') {
			if (*p == '{') {
				pos = strcspn(++p, "}");
				if (p[pos] == '\0')
					goto bad;
			} else {
				for (pos = 0; isalpha(p[pos]); pos++)
					;
				if (pos == 0) {
					cvs_log(LP_ERR,
					    "unrecognized variable syntax");
					goto bad;
				}
			}
			q = xmalloc(pos + 1);
			memcpy(q, p, pos);
			q[pos] = '\0';
			if (expand_var(buf, q))
				goto bad;
			p += pos - (*(p - 1) == '{' ? 0 : 1);
		} else {
			switch (*p) {
			case '\0':
				goto bad;
			case '{':
				if (strchr(allowed_args, '{') == NULL)
					goto bad;
				pos = strcspn(++p, "}");
				if (p[pos] == '\0')
					goto bad;
				q = xmalloc(pos + 1);
				memcpy(q, p, pos);
				q[pos] = '\0';
				args = q;
				p += pos;
				break;
			default:
				argbuf[0] = *p;
				args = argbuf;
				break;
			}
	
			if (expand_args(buf, file_info, repo, allowed_args,
			    args))
				goto bad;
			expanded = 1;
		}

		free(q);
	}

	if (!expanded && default_args != NULL) {
		p = default_args;
		expanded = 1;
		goto again;
	}

	buf_putc(buf, '\0');
	return (buf_release(buf));

bad:
	free(q);
	cvs_log(LP_NOTICE, "%s contains malformed command '%s'", file, cmd);
	buf_free(buf);
	return (NULL);
}
Beispiel #3
0
int 
exec_write(struct exec_info **info,const char *program,
           const char *args_in,const char *name,int writeonly,int binary)
{
  int ret=G10ERR_GENERAL;

  if(opt.exec_disable && !opt.no_perm_warn)
    {
      log_info(_("external program calls are disabled due to unsafe "
		 "options file permissions\n"));

      return ret;
    }

#if defined(HAVE_GETUID) && defined(HAVE_GETEUID)
  /* There should be no way to get to this spot while still carrying
     setuid privs.  Just in case, bomb out if we are. */
  if ( getuid () != geteuid ())
    BUG ();
#endif

  if(program==NULL && args_in==NULL)
    BUG();

  *info=xmalloc_clear(sizeof(struct exec_info));

  if(name)
    (*info)->name=xstrdup(name);
  (*info)->flags.binary=binary;
  (*info)->flags.writeonly=writeonly;

  /* Expand the args, if any */
  if(args_in && expand_args(*info,args_in))
    goto fail;

#ifdef EXEC_TEMPFILE_ONLY
  if(!(*info)->flags.use_temp_files)
    {
      log_error(_("this platform requires temporary files when calling"
		  " external programs\n"));
      goto fail;
    }

#else /* !EXEC_TEMPFILE_ONLY */

  /* If there are no args, or there are args, but no temp files, we
     can use fork/exec/pipe */
  if(args_in==NULL || (*info)->flags.use_temp_files==0)
    {
      int to[2],from[2];

      if(pipe(to)==-1)
	goto fail;

      if(pipe(from)==-1)
	{
	  close(to[0]);
	  close(to[1]);
	  goto fail;
	}

      if(((*info)->child=fork())==-1)
	{
	  close(to[0]);
	  close(to[1]);
	  close(from[0]);
	  close(from[1]);
	  goto fail;
	}

      if((*info)->child==0)
	{
	  char *shell=getenv("SHELL");

	  if(shell==NULL)
	    shell="/bin/sh";

	  /* I'm the child */

	  /* If the program isn't going to respond back, they get to
             keep their stdout/stderr */
	  if(!(*info)->flags.writeonly)
	    {
	      /* implied close of STDERR */
	      if(dup2(STDOUT_FILENO,STDERR_FILENO)==-1)
		_exit(1);

	      /* implied close of STDOUT */
	      close(from[0]);
	      if(dup2(from[1],STDOUT_FILENO)==-1)
		_exit(1);
	    }

	  /* implied close of STDIN */
	  close(to[1]);
	  if(dup2(to[0],STDIN_FILENO)==-1)
	    _exit(1);

	  if(args_in==NULL)
	    {
	      if(DBG_EXTPROG)
		log_debug("execlp: %s\n",program);

	      execlp(program,program,(void *)NULL);
	    }
	  else
	    {
	      if(DBG_EXTPROG)
		log_debug("execlp: %s -c %s\n",shell,(*info)->command);

	      execlp(shell,shell,"-c",(*info)->command,(void *)NULL);
	    }

	  /* If we get this far the exec failed.  Clean up and return. */

	  if(args_in==NULL)
	    log_error(_("unable to execute program `%s': %s\n"),
		      program,strerror(errno));
	  else
	    log_error(_("unable to execute shell `%s': %s\n"),
		      shell,strerror(errno));

	  /* This mimics the POSIX sh behavior - 127 means "not found"
             from the shell. */
	  if(errno==ENOENT)
	    _exit(127);

	  _exit(1);
	}

      /* I'm the parent */

      close(to[0]);

      (*info)->tochild=fdopen(to[1],binary?"wb":"w");
      if((*info)->tochild==NULL)
	{
          ret = gpg_error_from_syserror ();
	  close(to[1]);
	  goto fail;
	}

      close(from[1]);

      (*info)->fromchild=iobuf_fdopen(from[0],"r");
      if((*info)->fromchild==NULL)
	{
          ret = gpg_error_from_syserror ();
	  close(from[0]);
	  goto fail;
	}

      /* fd iobufs are cached?! */
      iobuf_ioctl((*info)->fromchild,3,1,NULL);

      return 0;
    }
#endif /* !EXEC_TEMPFILE_ONLY */

  if(DBG_EXTPROG)
    log_debug("using temp file `%s'\n",(*info)->tempfile_in);

  /* It's not fork/exec/pipe, so create a temp file */
  if( is_secured_filename ((*info)->tempfile_in) )
    {
      (*info)->tochild = NULL;
      errno = EPERM;
    }
  else
    (*info)->tochild=fopen((*info)->tempfile_in,binary?"wb":"w");
  if((*info)->tochild==NULL)
    {
      ret = gpg_error_from_syserror ();
      log_error(_("can't create `%s': %s\n"),
		(*info)->tempfile_in,strerror(errno));
      goto fail;
    }

  ret=0;

 fail:
  if (ret)
    {
      xfree (*info);
      *info = NULL;
    }
  return ret;
}
Beispiel #4
0
/* evaluate a simple command (3.9.1)
 * 
 * this function doesn't put stuff in background, it always wait()s, so
 * it only needs to fork() real programs
 * ----------------------------------------------------------------------- */
int eval_simple_command(struct eval *e, struct ncmd *ncmd) {
  union node *nptr;
  int argc;
  char **argv;
  int status;
  union node *args = NULL;
  union node *assigns = NULL;
  union command cmd = { NULL };
  enum hash_id id = H_BUILTIN;
  struct vartab vars;
/*  struct fdstack io;*/
  union node *r;
  union node *redir = ncmd->rdir;

  /* expand arguments,
     if there are arguments we start a hashed search for the command */
  if(expand_args(ncmd->args, &args, 0)) {
    stralloc_nul(&args->narg.stra);
    cmd = exec_hash(args->narg.stra.s, &id);
  }

  /* expand and set the variables,
     mark them for export if we're gonna execute a command */
  if(expand_vars(ncmd->vars, &assigns)) {
    /* if we don't exit after the command, have a command and not a 
       special builtin the variable changes should be temporary */
    if(!(e->flags & E_EXIT) && cmd.ptr && id != H_SBUILTIN)
      vartab_push(&vars);
    
    for(nptr = assigns; nptr; nptr = nptr->list.next)
      var_setsa(&nptr->narg.stra, (cmd.ptr ? V_EXPORT : V_DEFAULT));

    tree_free(assigns);
  }
  
  /* do redirections if present */
/*  if(redir && id != H_SBUILTIN && id != H_EXEC)
    fdstack_push(&io);*/
    
  if(redir/* && id != H_PROGRAM*/) {
    for(r = redir; r; r = r->list.next) {
      struct fd *fd = NULL;
      
      /* if its the exec special builtin the new fd needs to be persistent */
      if(id != H_EXEC) fd_alloca(fd);
      
      /* return if a redirection failed */
      if(redir_eval(&r->nredir, fd, (id == H_EXEC ? R_NOW : 0))) {
        status = 1;
        goto end;
      }
      
      /* check if we need to initialize fd buffers for the new redirection */
      if(fd_needbuf(r->nredir.fd)) {
        /* if its not exec then set up buffers for 
           temporary redirections on the stack */
        if(id != H_EXEC)
          fd_setbuf(r->nredir.fd, alloca(FD_BUFSIZE), FD_BUFSIZE);
        else
          fd_allocbuf(r->nredir.fd, FD_BUFSIZE);
      }
    }
  }
  
  /* if there is no command we can return after 
     setting the vars and doing the redirections */
  if(args == NULL) {
    status = 0;
    goto end;
  }

  /* when the command wasn't found we abort */
  if(cmd.ptr == NULL) {
    sh_error(args->narg.stra.s);
    status = exec_error();
    goto end;
  }

  /* assemble argument list */
  argc = tree_count(args);
  
  argv = alloca((argc + 1) * sizeof(char *));
  expand_argv(args, argv);

  /* execute the command, this may or may not return, depending on E_EXIT */
  status = exec_command(id, cmd, argc, argv, (e->flags & E_EXIT), redir);

end:

  /* restore variable stack */
  if(varstack == &vars)
    vartab_pop(&vars);

  if(args)
    tree_free(args);
  
  /* undo redirections */
  if(id != H_EXEC) {
    for(r = redir; r; r = r->list.next)
      fd_pop(r->nredir.fd);
  }
  
/*  if(fdstack == &io)
    fdstack_pop(&io);*/

  return status;
}
Beispiel #5
0
Datei: main.c Projekt: vidarh/ACE
int main( int argc, char **argv )
{
  int badopt= 0;
  int numfiles= 0;
  char *outfmt;

#ifdef _DCC /* Dice */
  expand_args(argc,argv, &argc,&argv);
#endif /* _DCC */

  infile= outfmt= (char *)0L;
  whoami= *argv;

  fin= stdin;
  fout= stdout;
  ferr= stderr;

  while(--argc>0 && !badopt)
  {
    char *arg= *++argv;

    if(*arg=='-')
    {
      if(arg[1]=='-')
        arg= convert_args(*argv);

      switch(*++arg)
      {

/*-d*/  case 'd':
#ifdef DEBUG
          debuglevel= 1;
#else
          echo("not compiled w/ a symbol DEBUG defined.  No debugging information available -- Sorry.");
#endif
          break;

/*-E*/  case 'E':
          if(arg[1]) ++arg;
          else arg= (--argc > 0) ? *(++argv) : (char *)0L;

          if(arg && *arg)
          {
            if(ferr != stderr)
            {
              warn("warning: option `%s' has already been seen!",*argv);
              fclose(ferr);
            }

            ferr= fopen(arg,"w");

            if(!ferr)
            {
              warn("can't direct error output to `%s' -- will use stderr",arg);
              ferr= stderr;
            }
          }
          else
          { warn("missing filename after `%s' option",*argv);
            ++badopt;
          }
          break;

/*-?*/  case '?':
/*-h*/  case 'h':
          fprintf(stderr,
            "usage: %s [options] [-o|>] [outfile] [<] [infiles..]\n\n",whoami);

          display_args();
          badopt= 1; /* hack: means exit. */
          break;

/*-o*/  case 'o':
          if(arg[1]) ++arg;
          else arg= (--argc > 0) ? *(++argv) : (char *)0L;

          if(arg && *arg)
          {
            if(outfmt)
              warn("option `%s' has already been seen!",*argv);
            outfmt= arg;
          }
          else
          {
            warn("missing output filename after `%s' option",*argv);
            ++badopt;
          }
          break;

/*-s*/  case 's':
          warn("silent option `%s' is not yet implemented -- sorry.",*argv);
          break;

/*-v*/  case 'v':
          display_version_information();
          badopt= 1; /* hack: means exit. */
          break;

/*??*/  default:
          warn("unrecognized option `%s'",*argv);
          ++badopt;
          break;
      }
    }
    else
    {
      if(arg && *arg)
      {
        if( chain_fname(arg) )
        {
          warn("out of memory... aaaiiiiiieeeeeeeee!");
          ++badopt;
        }
        else ++numfiles;
      }
      else
      {
        warn("command line error: can't parse `%s'",arg);
        ++badopt;
      }
    }
  }


  if(numfiles)
  {
    while( !badopt && (infile= unchain_fname()) )
    {
      if( fin= fopen(infile,"rb") )
      {
        if( fout= outfmt ? fmtopen(outfmt, infile) : stdout )
        {
          badopt= dothehardpart();

          if(fout != stdout)
            fclose(fout);
        }
        else ++badopt; /* fmtopen() has already warned */
        fclose(fin);
      }
      else
      {
        warn("can't access your input file `%s'",infile);
        ++badopt;
      }
    }
    purge_flist();
  }

  else if( !badopt )
  {
    if( fout= outfmt ? fmtopen(outfmt, "stdin") : stdout )
    {
      badopt= dothehardpart();

      if(fout != stdout)
         fclose(fout);
    }
    else ++badopt; /* fmtopen() has already warned */
  }

  if(fin  && fin  != stdin)    fclose(fin);
  if(fout && fout != stdout)   fclose(fout);
  if(ferr && ferr != stderr)   fclose(ferr);

  exit( badopt ? 1:0 );
}
Beispiel #6
0
int main(int argc, char *argv[])
{
  int err= 0; /* return code */

  char *outfile    = (char *)0;      /* --output-file       */
  char *errfile    = (char *)0;      /* --error-file        */
  char *headerfile = (char *)0;      /* --texi-header-file  */
  char *yank_type  = "*";            /* --yank-type         */
  char *body_env   = "smallexample"; /* -B<environment>     */

  int page_width         = 80;       /* --page-width        */
  int tabsize            = 8;        /* --tab-size          */
  int tabs_to_spaces     = 0;        /* --tabs-to-spaces    */
  int output_type        = 1;        /* --output-type       */
  int table_of_contents  = 0;        /* --table-of-contents */
  int sort_entries       = 1;        /* --preserve-order    */
  int texi_flags         = TEXI_CREATE_HEADER | TEXI_PARSE_REFERENCES | TEXI_ITEMIZE_REFERENCES;
  int adoc_flags         = ADOC_FORM_FEEDS;
  int warn_mask          = WARN_NORMAL;
  int scanner_flags      = 0;        /* --indented-comments */
                                     /* --unindent-bodytext */
  int minimum_indentation = -1;      /* --reindent-bodytext */

  /* handles for the macro tables */

  int texi_macros = 0;
  int body_macros = 0;

#ifdef _DCC /* Dice */
  expand_args(argc,argv, &argc,&argv);
#endif /* _DCC */

  /* filenames on MS-DOG systems look very ugly: all uppercase and
   * backslashes.  Perform some cosmetics */

#ifdef __MSDOS__
  whoami= "adoc";

#else
  whoami= argv[0];

#endif /*__MSDOS__*/


  /* set the debugging defaults */
  D(bug_init(0,stdout));

  /* initialize the default error stream */
  ferr= stderr;

  if(err == 0)
  {
    /* prepare the texinfo macro table */
    texi_macros= mactab_new( 4+10 );

    if(!texi_macros)
      err= 1;
  }

  if(err == 0)
  {
    /* prepare the body-text macro table */
    body_macros= mactab_new( 2 );

    if(!body_macros)
      err= 2;
  }

  if(err)
    echo("error %d creating macro tables -- not enough memory?", err);

  else

  /* BEGIN scanning command line arguments */

  while( (--argc > 0) && (err <= 0) )
  {
    char *arg= *++argv;

#ifdef DEBUG
    if(argc > 1)  { D(bug("examining command line argument `%s' ( `%s', ... ) [%d]", argv[0], argv[1], argc-1)); }
    else          { D(bug("examining command line argument `%s' ( ) [%d]", argv[0], argc-1)); }
#endif /* DEBUG */

    if(*arg=='-')
    {
      /* remember the original command-line option string */
      char *opt= arg;

      if(arg[1]=='-')
        arg= convert_args(*argv);

      switch(*++arg)
      {

/*-0*/  case '0':
          output_type= 0;
          break;

/*-1*/  case '1':
          output_type= 1;
          break;

/*-2*/  case '2':
          output_type= 2;
          tabs_to_spaces= 1;
          minimum_indentation= 0;
          break;

/*-b*/  case 'b':
          texi_flags |= TEXI_TABLE_FUNCTIONS;
          break;

/*-B*/  case 'B':
          if(arg[1]) ++arg;
          else arg= (--argc > 0) ? *(++argv) : (char *)0;

          if(arg && *arg)
          {
            body_env= arg;
          }
          else
          {
            echo("missing texinfo body text environment after %s option",opt);
            err= 1;
          }
          break;

/*-c*/  case 'c':
          err= mactab_add(body_macros, "\\*", "/*", "*\\", "*/", (char *)0);

          if(err)
            echo("error %d adding comment convertion macros",err);
          break;

/*-d*/  case 'd':

#ifdef DEBUG

          if(arg[1]) { D(bug_level= atoi( &(arg[1]) )); }
          else       { D(bug_level= 1); }

#else /* !DEBUG */
          echo("not compiled w/ -DDEBUG.  No debug information available -- Sorry");
          /* no error */

#endif /* DEBUG */

          break;


/*-D*/  case 'D':
          if(arg[1] && --argc > 0)
          {
            char *lhs= &arg[1];
            char *rhs= *(++argv);

            err= mactab_add(texi_macros, lhs, rhs, (char *)0);

            if(err)
              echo("error adding texinfo macro `%s' = `%s'", lhs, rhs);
          }
          else
          {
            echo("missing macro %s after `%s' option",(arg[1] ? "value":"name"),opt);
            err= 1;
          }
          break;

/*-E*/  case 'E':
          if(arg[1]) ++arg;
          else arg= (--argc > 0) ? *(++argv) : (char *)0;

          if(arg && *arg)
          {
            if(errfile)
            {
              echo("warning: option `%s' has already been seen", opt);
              D(bug("%s \"%s\" superseeds -E \"%s\"", opt, arg, errfile));
            }

            /*errfile= strcmp(arg,"-") ? arg : (char *)0;*/
            errfile= arg;
          }
          else /* !(arg && *arg) */
          {
            echo("missing filename after `%s' option", opt);
            err= 1;
          }
          break;

/*-f*/  case 'f':
          if(arg[1])
          {
            while(*++arg) switch(*arg)
            {
              case 'f':
                adoc_flags |= ADOC_FORM_FEEDS;
                texi_flags |= TEXI_FUNCTION_NEWPAGE;
                break;

              default:
                echo("unknown paging option: `%s'",opt);
                break;
            }
          }
          else /* !arg[1] */
          {
            adoc_flags &= ~ADOC_FORM_FEEDS;
            texi_flags &= ~TEXI_FUNCTION_NEWPAGE;
          }
          break;

/*-g*/  case 'g':
          if(arg[1])
          {
            while(*++arg) switch(*arg)
            {
              case 's':
                texi_flags |= TEXI_GROUP_SECTIONS;
                break;

              default:
                echo("unknown grouping option: `%s'",opt);
                err= 1;
                break;
            }
          }
          else texi_flags &= ~TEXI_GROUP_SECTIONS;
          break;

/*-H*/  case 'H':
          if(arg[1]) ++arg;
          else arg= (--argc > 0) ? *(++argv) : (char *)0;

          if(arg && *arg)
          {
            if(headerfile)
            {
              echo("warning: option `%s' has already been seen", opt);
              D(bug("%s \"%s\" superseeds -H \"%s\"", opt, arg, headerfile));
            }

            headerfile= arg;
          }
          else /* !(arg && *arg) */
          {
            echo("missing texinfo header filename after `%s' option", opt);
            err= 1;
          }
          break;

/*-h*/  case 'h':
          printf("usage: %s [options] [-o outfile] [@ listfile] [infiles...]\n\n", whoami);
          display_args( arg[1] ? atoi(&arg[1]) : 3 );
          err= -1;    /* negative means exit w/o error */
          break;

/*-I*/  case 'I':
          table_of_contents= 1;
          break;

/*-i*/  case 'i':
          yank_type= "i";
          break;

/*-j*/  case 'j':
          if(arg[1]) ++arg;
          else arg= (--argc > 0) ? *(++argv) : (char *)0;

          if(arg && *arg)
          {
            if( (minimum_indentation= atoi(arg)) < 0 )
            {
              echo("illegal indentation: %d  (must be >= 0)", minimum_indentation);
              err= 1;
            }
          }
          else /* !(arg && *arg) */
          {
            echo("missing indentation after `%s' option", opt);
            err= 1;
          }
          break;

/*-l*/  case 'l':
          if(arg[1]) ++arg;
          else arg= (--argc > 0) ? *(++argv) : (char *)0;

          if(arg && *arg)
          {
            page_width= atoi(arg);

            if(page_width < 1)
            {
              echo("illegal page width: `%s'  (must be > 0)", arg);
              err= 1;
            }
          }
          else /* !(arg && *arg) */
          {
            echo("missing page width after `%s' option", opt);
            err= 1;
          }
          break;

/*-M*/  case 'M':
          if(arg[1] && --argc > 0)
          {
            char *lhs= &arg[1];
            char *rhs= *(++argv);

            err= mactab_add(body_macros, lhs, rhs, (char *)0);

            if(err)
              echo("error adding body macro `%s' -> `%s'", lhs, rhs);
          }
          else
          {
            echo("missing macro %s after `%s' option",(arg[1] ? "value":"name"),opt);
            err= 1;
          }
          break;

/*-n*/  case 'n':
          output_type= 0;
          break;

/*-o*/  case 'o':
          if(arg[1]) ++arg;
          else arg= (--argc > 0) ? *(++argv) : (char *)0;

          if(arg && *arg)
          {
            if(outfile)
              echo("warning: option `%s' has already been seen", opt);

            outfile= arg;
          }
          else /* !(arg && *arg) */
          {
            echo("missing filename after `%s' option", opt);
            err= 1;
          }
          break;

/*-p*/  case 'p':
          sort_entries= arg[1] ? 1:0;
          break;

/*-q*/  case 'q':
          break;

/*-T*/  case 'T':
          if(arg[1]) ++arg;
          else arg= (--argc > 0) ? *(++argv) : (char *)0;

          if(arg && *arg)
          {
            tabs_to_spaces= 1;
            tabsize= atoi(arg);

            if(tabsize < 1)
            {
              echo("illegal tab step: `%d'  (must be >= 1)", tabsize);
              err= 1;
            }
          }
          else /* !(arg && *arg) */
          {
            echo("missing tab size after `%s' option", opt);
            err= 1;
          }
          break;

/*-t*/  case 't':
          tabs_to_spaces= arg[1] ? atoi(&arg[1]) : 1;
          break;

/*-U*/  case 'U':
          if(arg[1]) ++arg;
          else arg= (--argc > 0) ? *(++argv) : (char *)0;

          if(arg && *arg)
          {
            mactab_remove(texi_macros, arg, (char *)0);
            mactab_remove(body_macros, arg, (char *)0);
          }

          else /* !(arg && *arg) */
          {
            echo("missing macro after `%s' option", opt);
            err= 1;
          }
          break;

/*-u*/  case 'u':
          if(arg[1])
          {
            scanner_flags &= ~SCANNER_UNINDENT_BODYTEXT;
            minimum_indentation= -1;
          }
          else scanner_flags |= SCANNER_UNINDENT_BODYTEXT;
          break;

/*-v*/  case 'v':
          printf("ADOC Version " VERSION " (compiled " __DATE__ ", " __TIME__ ")\n"
                 "(c)Copyright 1995 by Tobias Ferber,  All Rights Reserved\n" );
          err= -1;
          break;

/*-W*/  case 'W':
          if(arg[1])
          {
            ++arg;

            if( isdigit(*arg) )
              warn_mask |= atoi(arg);

            else switch( strarg(arg, "none",       /* 1 */
                                     "arnings",    /* 2 */
                                     "keywords",   /* 3 */
                                     "absence",    /* 4 */
                                     "untitled",   /* 5 */
                                     "all", "") )  /* 6 */
            {
              case 1:   warn_mask  = WARN_NONE;                 break;
              case 2:   warn_mask |= WARN_NORMAL;               break;
              case 3:   warn_mask |= WARN_UNKNOWN_KEYWORDS;     break;
              case 4:   warn_mask |= WARN_MISSING_KEYWORDS;     break;
              case 5:   warn_mask |= WARN_UNTITLED_SECTION;     break;
              case 6:   warn_mask |= WARN_ALL;                  break;

              default:
                echo("unknown warning method: `%s'",opt);
                err= 1;
                break;
            }
          }
          else warn_mask= WARN_NONE;
          break;

/*-x*/  case 'x':
          if(arg[1])
          {
            switch( strarg(++arg, "off",        /* 1 */
                                  "on",         /* 2 */
                                  "itemize",    /* 3 */
                                  "", "") )     /* 4 */
            {
              case 1:   texi_flags &= ~TEXI_PARSE_REFERENCES;
                        texi_flags &= ~TEXI_ITEMIZE_REFERENCES;   break;

              case 2:   texi_flags |=  TEXI_PARSE_REFERENCES;
                        texi_flags &= ~TEXI_ITEMIZE_REFERENCES;   break;

              case 3:   texi_flags |=  TEXI_PARSE_REFERENCES;
                        texi_flags |=  TEXI_ITEMIZE_REFERENCES;   break;

              default:
                echo("unknown reference handlig option: `%s'",opt);
                err= 1;
                break;
            }
          }
          else texi_flags &= ~(TEXI_PARSE_REFERENCES | TEXI_ITEMIZE_REFERENCES);
          break;


/*-Y*/  case 'Y':
          if(arg[1]) scanner_flags &= ~SCANNER_ALLOW_INDENTED_COMMENTS;
          else       scanner_flags |=  SCANNER_ALLOW_INDENTED_COMMENTS;
          break;

/*-y*/  case 'y':
          if(arg[1]) ++arg;
          else arg= (--argc > 0) ? *(++argv) : (char *)0L;

          if(arg && *arg)
            yank_type= arg;

          else /* !(arg && *arg) */
          {
            echo("missing comment type string after `%s' option", opt);
            err= 1;
          }
          break;

/*-z*/  case 'z':
          texi_flags &= ~TEXI_CREATE_HEADER;
          break;

/*-Z*/  case 'Z':
          if(arg[1]) texi_flags &= ~TEXI_NO_INDEX;
          else       texi_flags |=  TEXI_NO_INDEX;
          break;

          /*
           *  The following options are ignored for compatibility
           *  with Bill Koester's original version `autodoc' which
           *  is part of C=ommodore's Native Developer Kit (NDK).
           */

/*-C*/  case 'C':
/*-F*/  case 'F':
/*-s*/  case 's':
/*-a*/  case 'a':
/*-r*/  case 'r':
/*-w*/  case 'w':
          echo("warning: option `%s' ignored for compatibility", opt);
          break;

/*- */  case '\0':
          if( (err= flist_addfile("")) )
             echo("out of memory... hmmmmmmmmmpf!");
           break;

/*??*/  default:
          echo("unrecognized option `%s'", opt);
          err= 1;
          break;
      }
    }
    else if(*arg=='@')
    {
      if(arg[1]) ++arg;
      else arg= (--argc > 0) ? *(++argv) : (char *)0L;

      if(arg && *arg)
      {
        if( (err= flist_from_file(arg)) )
          echo("out of memory... aaarrrrrrgggggghh!");
      }
      else /* !(arg && *arg) */
      {
        echo("missing filename after `%s'", *argv);
        err= 1;
      }
    }
    else /* *arg != '@' */
    {
      if(arg && *arg)
      {
        if( (err= flist_addfile(arg)) )
          echo("out of memory... aaaiiiiiieeeeeeeee!");
      }
      else echo("internal problem parsing command line arguments: arg is empty");
    }
  }
  /* END scanning command line arguments */
  D(bug("command line argument parsing done"));

  if(err == 0)
  {
    /* prepare the error stream */

    if(errfile && *errfile)
    {
      D(bug("opening error stream `%s'",errfile));

      if( !(ferr= fopen(errfile,"w")) )
      {
        echo("could not write error messages to `%s'",errfile);
        err= __LINE__;
      }
    }
    /*else ferr is initialized to stderr */

    /* if no filename is given then read from stdin */

    if( !flist_getname() )
      flist_addfile("");


    /* read the input files (the scanner takes them from the flist queue) */

    D(bug("reading autodocs of type `%s'", yank_type));

    if(err == 0)
      err= read_source(yank_type, warn_mask, scanner_flags);

    if(err < 0)
      err= -err;  /* I/O error */

    D(bug("disposing file list"));
    flist_dispose();

    /*
     */

    if( (err == 0) && (minimum_indentation >= 0) )
    {
      if( (err= funindent(minimum_indentation, tabsize)) )
        echo("error %d reworking body text indentation -- not enough memory?",err);

      /* funindent() already performed that conversion */
      else tabs_to_spaces= 0;
    }


    if( (err == 0) && (output_type > 0) )
    {
      FILE *fout;

      /* prepare the output file */

      if(outfile && *outfile)
      {
        D(bug("opening output stream `%s'",outfile));

        if(!(fout= fopen(outfile,"w")) )
        {
          echo("could not write to `%s'",outfile);
          err= __LINE__;
        }
      }
      else fout= stdout;


      if( fout && (err==0) )
      {
        if(sort_entries)
        {
          D(bug("sorting entries"));
          funsort();
        }

        switch(output_type)
        {
          case 1: /* --autodoc */

            if(table_of_contents)
            {
              D(bug("writing table of contents"));
              err= gen_autodoc_toc(fout);
            }
            if(err == 0)
            {
              D(bug("writing autodocs"));
              err= gen_autodoc( fout, page_width, tabs_to_spaces ? tabsize : 0, adoc_flags, mactab(body_macros) );
            }
            break;

          case 2: /* --texinfo */
            if(texi_flags & TEXI_CREATE_HEADER)
            {
              D(bug("creating texinfo header"));
              err= gen_texinfo_header( fout, headerfile, mactab(texi_macros) );
            }

            if(err == 0)
            {
              D(bug("adding texinfo body macros"));
              err= mactab_add( body_macros,  "@",        "@@",
                                             "{",        "@{",
                                             "}",        "@}",
                                          /* "...",      "@dots{}", */
                                          /* "TeX",      "@TeX{}",  */
                                             "e.g. ",    "e.g.@: ",
                                             "E.g. ",    "E.g.@: ",
                                             "i.e. ",    "i.e.@: ",
                                             "I.e. ",    "I.e.@: ",   (char *)0 );
            }

            if(err == 0)
            {
              D(bug("creating texinfo output"));
              err+= gen_texinfo( fout, tabs_to_spaces ? tabsize : 0, texi_flags, body_env, mactab(body_macros) );
            }

            if(err)
              echo("error creating texinfo output");
            break;

          default: /* --dry-run */
            break;
        }
      }

      if(fout && (fout != stdout))
        fclose(fout);
    }

    D(bug("disposing libfun entries"));
    funfree();
  }

#ifdef DEBUG
  mactab_debug(bug_stream);
#endif

  D(bug("disposing macro tables"));
  mactab_dispose(body_macros);
  mactab_dispose(texi_macros);

  /*
  */

  if(err > 0)
  {
    echo("[%s] *** Error %d", (outfile && *outfile) ? outfile : "stdout", err);
    fprintf(ferr,"%s terminated abnormally (error %d)\n", whoami, err);
  }

  D(bug("closing I/O streams"));

  if( ferr && (ferr != stderr) && (ferr != stdout) )
    fclose(ferr);

  D(bug("exiting adoc returning %d (%s)", (err>0) ? 1:0, (err>0) ? "error":"success" ));
  D(bug_exit());

#ifdef DEBUG

  if(bug_stream && (bug_stream != stdout))
    fclose(bug_stream);

#endif /*DEBUG*/

  return (err > 0) ? 1:0;
}