/* cfengine for GNU
 
        Copyright (C) 1995
        Free Software Foundation, Inc.
 
   This file is part of GNU cfengine - written and maintained 
   by Mark Burgess, Dept of Computing and Engineering, Oslo College,
   Dept. of Theoretical physics, University of Oslo
 
   This program is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the
   Free Software Foundation; either version 2, or (at your option) any
   later version.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
 
  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA

*/
 

/*******************************************************************/
/*                                                                 */
/*  Parse Zone for cfengine                                        */
/*                                                                 */
/*  This is wide screen entertainment. Resize                      */
/*  your window before viewing!                                    */
/*                                                                 */
/*  The routines here are called by the lexer and the yacc parser  */
/*                                                                 */
/*******************************************************************/

 /*
    The parser uses the classification of strings into id's items
    paths, varpaths etc. Each complete action is gradually assembled
    by setting flags based on what action, class etc is being
    parsed. e.g. HAVEPATH, FROM_LINK etc.. these are typed as
    "flag" in the variables file. When all the necessary critera
    are met, or the beginning of a new definition is found
    the action gets completed and installed in the actions lists.

  */

#define INET

#include <stdio.h>
#include "cf.defs.h"
#include "cf.extern.h"

extern FILE *yyin;

/*******************************************************************/

ParseInputFiles()

{ struct Item *ptr;
  char filename[bufsize], *sp;

if (strcmp(VINPUTFILE,".") == 0) /* read from standard input */
   {
   yyin = stdin;

   if (!feof(yyin))
      {
      yyparse();
      }

   InstallPending(ACTION);
   }
else
   {
   filename[0] = '\0';

   if ((sp=getenv(CFINPUTSVAR)) != NULL)
      {
      if (! IsAbsoluteFileName(VINPUTFILE))     /* Don't prepend to absolute names */
	 { 
	 strcpy(filename,sp);
	 if (filename[strlen(filename)-1] != '/')
	    {
	    strcat(filename,"/");
	    }
	 }
      }
   
   strcat(filename,VINPUTFILE);

   if ((yyin = fopen(filename,"r")) == NULL)      /* Open root file */
      {
      if (sp == NULL)
	 {
	 printf("cfengine:%s: (%s is set to <nothing>)\n",VPREFIX,CFINPUTSVAR);
	 }
      else
	 {
	 printf("cfengine:%s: (%s is set to %s)\n",VPREFIX,CFINPUTSVAR,sp);
	 }
      
      printf("cfengine:%s: Can't open file %s\n",VPREFIX,VINPUTFILE);
      exit (1);
      }

   strcpy(VCURRENTFILE,VINPUTFILE);

   Debug("BEGIN PARSING %s\n",VCURRENTFILE);

   LINENUMBER=1;

   while (!feof(yyin))
      { 
      yyparse();
      }

   fclose (yyin);

   InstallPending(ACTION);
   }
   
for (ptr = VIMPORT; ptr != NULL; ptr=ptr->next)
   {
   if (IsExcluded(ptr->classes))
      {
      continue;
      }
   
   filename[0] = '\0';

   if ((sp=getenv(CFINPUTSVAR)) != NULL)
      {
      if (! IsAbsoluteFileName(ptr->name))   
         { 
         strcpy(filename,sp);
         if (filename[strlen(filename)-1] != '/')
            {
            strcat(filename,"/");
            }
         }
      }

   strcat(filename,ptr->name);

   if ((yyin = fopen(filename,"r")) == NULL) 
      {
      if (sp == NULL)
         {
         printf("cfengine:%s: (%s is set to <nothing>)\n",VPREFIX,CFINPUTSVAR);
         }
      else
         {
         printf("cfengine:%s: (%s is set to %s)\n",VPREFIX,CFINPUTSVAR,sp);
         }
      
      sprintf(VBUFF,"Can't open file %s\n",filename);
      FatalError(VBUFF);
      }

   LINENUMBER = 1;
   strcpy(VCURRENTFILE,ptr->name);

   Debug("PARSING FILE (%s)\n\n",ptr->name);

   while (!feof(yyin))
      { 
      yyparse();
      }

   fclose (yyin);
   InstallPending(ACTION);
   }

VCURRENTFILE[0]='\0';       /* Zero filename for subsequent errors */

Debug("(END OF PARSING)\n");
}

/*******************************************************************/

SetAction (action)

enum actions action;

{
InstallPending(ACTION);   /* Flush any existing actions */

Debug1("\nBEGIN NEW ACTION %s\n",ACTIONTEXT[action]);

ACTION = action;
strcpy(ACTIONBUFF,ACTIONTEXT[action]);

switch (ACTION)
   {
   case files:
   case makepath:
   case tidy:
   case disable:
   case image:
   case links:
   case required:
   case shellcommands:
   case processes:  InitializeAction();
   }

CURRENTAUTHPATH[0] = '\0';

strcpy(CLASSBUFF,"any");    /* default class */
CLASS=soft;
}

/*******************************************************************/

HandleId(id)

char *id;

{
Debug1("HandleId(%s)\n",id);

if (ACTION == control)
   {
   switch(ScanVariable(id))
      {
      case fac:    
      case sit:       CLASS = faculty;
                      return;

      case sysad:     CLASS = sysadm;
                      return;

      case dom:       CLASS = domain;
                      return;

      case timez:     CLASS = timezon;
                      return;

      case netmsk:    CLASS = netmask;
                      return;

      case nfstp:     CLASS = nfstypec;
                      return;

      case ssize:     CLASS = sensiblesize;
                      return;

      case scount:    CLASS = sensiblecount; 
                      return;

      case esize:     CLASS = editfilesize;
                      return;

      case actseq:    CLASS = actionsequence;
                      return;

      case acess:     CLASS = accesss;
                      return;

      case mpat:      CLASS = mountpath;
                      return;

      case hpat:      CLASS = homepat;
                      return;

      case adclass:   CLASS = addclasses;
                      return;

      case excludecp: CLASS = excludecopy;
		      return;

      case excludeln: CLASS = excludelink;
	              return;

      case cplinks:   CLASS = copylinks;
	              return;
		      
      case lncopies:  CLASS = linkcopies;
	              return;

      case repos:     CLASS = repository;
	              return;

      case repchar:   CLASS = reposchar;
		      return;

      case listsep:   CLASS = listseparator;
	              return;

      case underscore:
	              CLASS = underscoreclasses;
		      return;

      case ifname:    CLASS = interfacename;
	              return;

      case expafter:  CLASS = expireafter;
	              return;
		      
      case ifelap:    CLASS = ifelapsed;
	              return;

      default:        RecordMacroId(id);
                      CLASS = soft;
                      return;
      }
   }

if (ACTION == groups)
   { int count = 1;
     char *cid = id;

   while (*cid != '\0')
      {
      if (*cid++ == '.')
         {
         count++;
         }
      }

   if (strcmp(id,"any") == 0)
      {
      yyerror("Reserved class <any>");
      }

   if (count > 1)                              /* compound class */
      {
      yyerror("Group with compound identifier");
      FatalError("Dots [.] not allowed in group identifiers");
      }

   if (IsHardClass(id))
      {
      yyerror("Reserved class name (choose a different name)");
      }

   strcpy(GROUPBUFF,id);
   }


switch(ACTION)   /* Check for IP names in cfd */
   {
   case admit:
                 InstallAuthItem(CURRENTAUTHPATH,id,&VADMIT,&VADMITTOP,CLASSBUFF);
		 break;
   case deny:
                 InstallAuthItem(CURRENTAUTHPATH,id,&VDENY,&VDENYTOP,CLASSBUFF);
		 break;		    
   }



strcpy(CLASSBUFF,"any");    /* default class */
CLASS=soft;
}

/*******************************************************************/

HandleClass (id)

char *id;

{ int members;

InstallPending(ACTION);

Debug1("HandleClass(%s)\n",id);

if ((members = CompoundId(id)) > 1)             /* Parse compound id */
   {
   Debug1("Compound identifier-class = (%s) with %d members\n",id,members);
   }
else
   {
   Debug1("simple identifier-class = (%s)\n",CLASSTEXT[CLASS]);
   }

Debug1("HandleClass(end)\n");
}

/*******************************************************************/

HandleItem (item)

char *item;

{
Debug1("HandleItem(%s)\n",item);

if (strcmp(item,"+") == 0 || strcmp(item,"-") == 0)
   {
   yyerror("+/- not bound to identifier");
   }

if (item[0] == '+')                               /* Lookup in NIS */
   {
   item++;

   if (item[0] == '@')                               /* Irrelevant */
      {
      item++;
      }

   Debug1("Netgroup item, lookup NIS group (%s)\n",item);

   strcpy(CURRENTITEM,item);

   if (ACTION == groups)
      {
      HandleGroupItem(item,netgroup);
      }
   else
      {
      yyerror("Netgroup reference outside group: action or illegal octal number");
      FatalError("Netgroups may only define internal groups or illegal octal file action.");
      }
   }
else if (item[0] == '-') 
   {
   item++;

   if (item[0] == '@')                               /* Irrelevant */
      {
      item++;

      if (ACTION == groups)
         {
         HandleGroupItem(item,groupdeletion);
         }
      else
         {
         yyerror("Netgroup reference outside group: action or illegal octal number");
         FatalError("Netgroups may only define internal groups or illegal octal file action.");
         }
      }
   else
      {
      if (ACTION == groups)
         {
         HandleGroupItem(item,deletion);
         }
      else
         {
         yyerror("Illegal deletion sign or octal number");
         FatalError("The deletion operator may only be in the groups: action");
         }
      }


   }
else if (item[0] == '\"' || item[0] == '\'' || item[0] == '`') 
   {
   *(item+strlen(item)-1) = '\0';

   if (ACTION == groups)                     /* This test should be redundant */
      {
      HandleGroupItem(item,classscript);
      }
   }
else
   {
   Debug1("simple item = (%s)\n",item);
  
   /* CLASS set by CompoundId via HandleId */

   switch(ACTION)
      {
      case control:     InstallLocalInfo(CLASS,item);
                        break;
      case groups:      HandleGroupItem(item,simple);
                        break;
      case resolve:     AppendNameServer(item);
                        break;
      case image:
      case files:       HandleFileItem(item);
                        break;
      case tidy:        strcpy(CURRENTITEM,item);
                        break;
      case homeservers: InstallHomeserverItem(item);
                        break;
      case binservers:  InstallBinserverItem(item);
                        break;
      case mailserver:  yyerror("Give whole rpc path to mailserver");
                        break;
      case required:    yyerror("Required filesystem must be an absolute path");
                        FatalError("Fatal error");
                        break;
      case mountables:  yyerror("Mountables should be specified by an absolute pathname");
                        break;
      case links:       if (ACTION_IS_LINKCHILDREN && strcmp (item,"linkchildren") == 0)
                           {
                           strcpy(LINKTO,item);
                           }
                        else
                           {
                           yyerror("Links requires path or varitem");
                           }
                        break;
      case import:      AppendImport(item);
                        break;
      case shellcommands:
	                InstallPending(ACTION);
			strcpy(CURRENTPATH,item);
			ACTIONPENDING = true;
                        break;
      case makepath:    yyerror("makepath needs an abolute pathname");
                        FatalError("Fatal Error");
      case disable:     yyerror("disable needs an absolute path name");
                        FatalError("Fatal Error");
      case broadcast:   InstallBroadcastItem(item);
                        break;
      case defaultroute:InstallDefaultRouteItem(item);
                        break;
      case misc_mounts: if (MOUNT_FROM && MOUNT_ONTO && (strcmp(item,"rw") == 0 || strcmp(item,"ro") == 0))
                           {
                           AppendMiscMount(MOUNTFROM,MOUNTONTO,item);
                           CURRENTITEM[0] = '\0';
                           MOUNT_FROM = false;
                           MOUNT_ONTO = false;
                           }
                        else
                           {
                           yyerror("misc_mounts: host:/frompath /mounton_path [ro|rw]\n");
                           }
                        break;

      case unmounta:    yyerror("Umount must be in the format machine:directory");
                        break;

      case editfiles:   /* action recorded in CURRENTITEM, installed from qstring in lexer */
                        strcpy(CURRENTITEM,item);
                        break;

      case ignore:      AppendIgnore(item);
                        break;

      case processes:   if (strcmp(item,"restart") == 0)
	                   {
			   HAVE_RESTART = true;
			   ACTIONPENDING = false;
			   return;
			   }

                        if (ACTIONPENDING)
			   {
			   InstallPending(ACTION);          /* Flush any existing actions */
                           InitializeAction();
			   }
      
                        if (strcmp(item,"SetOptionString") == 0)
			   {
                           if (EXPR[0] == '\0')
			      {
   			      strcpy(EXPR,item);
			      ACTIONPENDING = false;
			      HAVE_RESTART = true;    /* save option string in restart */
			      return;
			      }
			   else
			      {
			      yyerror("Inappropriate placement of SetOptionString");
			      return;
			      }
			   }

	                if (EXPR[0] == '\0')
	                   {
			   if (HAVE_RESTART)
			      {
			      yyerror("Missing search expression");
			      }
			   strcpy(EXPR,item);
			   ACTIONPENDING = true;
			   }
                        else
			   {
			   if (HAVE_RESTART)
			      {
			      strcpy(RESTART,item);
			      HAVE_RESTART= false;
			      ACTIONPENDING = true;
			      }
			   }
                        break;

      default:          FatalError("Internal software failure: Unknown action (%s)\n",item);
      }
   }
}

/***************************************************************************/

HandlePath (path)

char *path;

{
if (ACTION == processes && ! ACTIONPENDING)
   {
   }
else
   {
   InstallPending(ACTION);           /* Flush any existing actions */
   InitializeAction();                 /* Clear data for files/dirs  */
   }

Debug1("path = (%s)\n",path);

strcpy(CURRENTPATH,path);                   /* Yes this must be here */

ACTIONPENDING = true;                     /* we're parsing an action */

if (ACTION_IS_LINK || ACTION_IS_LINKCHILDREN)  /* to-link (after ->) */
   {
   strcpy(LINKTO,CURRENTPATH);
   }
else
   {
   switch (ACTION)
      {
      case control:  if (CLASS == mountpath)
                        {
                        SetMountPath(path);
			break;
                        }

                     if (CLASS == repository)
			{
			SetRepository(path);
			break;
			}

		     if (CLASS == reposchar)
			{
			if (strlen(path) > 1)
			   {
			   yyerror("reposchar can only be a single letter");
			   break;
			   }
			if (path[0] == '/')
			   {
			   yyerror("illegal value for reposchar");
			   break;
			   }
			REPOSCHAR = path[0];
			}

		     if (CLASS == listseparator)
			{
			if (strlen(path) > 1)
			   {
			   yyerror("listseparator can only be a single letter");
			   break;
			   }
			if (path[0] == '/')
			   {
			   yyerror("illegal value for listseparator");
			   break;
			   }
			LISTSEPARATOR = path[0];
			}

                     if (CLASS == homepat)
                        {
                        yyerror("Path relative to mountpath required");
                        FatalError("Absolute path was specified\n");
                        }

                    if (CLASS == soft)
                       {
                       AddMacroValue(CURRENTITEM,path);
                       }

                       break;
      case import:     AppendImport(path);
                       break;
      case links:      /* from link (see cf.l) */
                       break;
		       
      case required:   strcpy(CURRENTPATH,path);
                       break;
      case shellcommands:
                       break;
      case mountables: AppendMountable(path);
                       break;
      case mailserver: InstallMailserverPath(path);
                       break;
      case tidy:       strcpy(CURRENTITEM,path);
                       break;
      case disable:    strcpy(CURRENTPATH,path);
                       ACTIONPENDING = true;
                       break;
      case makepath:   strcpy(CURRENTPATH,path);
                       break;
      case ignore:     AppendIgnore(path);
                       break;

      case misc_mounts:if (! MOUNT_FROM)
                          {
                          MOUNT_FROM = true;
                          strcpy(MOUNTFROM,CURRENTPATH);
                          }
                       else
                          {
                          if (MOUNT_ONTO)
			    {
                            yyerror ("Path not expected");
                            FatalError("misc_mount: syntax error");
                            }
                          MOUNT_ONTO = true;
                          strcpy(MOUNTONTO,CURRENTPATH);
                          }
                       break;

      case unmounta:   AppendUmount(path);
                       break;
      case image:
      case files:      
                       break;

      case editfiles:  /* file recorded in CURRENTPATH */
                       break;

      case processes:   if (EXPR[0] == '\0')
	                   {
			   if (HAVE_RESTART)
			      {
			      yyerror("Missing search expression");
			      }
			   strcpy(EXPR,path);
			   }
                        else
			   {
			   if (HAVE_RESTART)
			      {
			      strcpy(RESTART,path);
			      HAVE_RESTART = false;
			      ACTIONPENDING = true;
			      }
			   }
		       break;

      default:         printf ("HandlePath() DEFAULT\n");
                       printf ("Fatal action is %s\n",ACTIONTEXT[ACTION]);
                       FatalError("Internal software error in HandlePath()");
      }
   }
}

/*******************************************************************/

HandleVarpath(varpath)         

  /* Expand <binserver> and <fac> etc. Note that the right hand  */
  /* side of links etc. gets expanded at runtime. <binserver> is */
  /* only legal on the right hand side.                          */

char *varpath;

{
InstallPending(ACTION);   /* Flush any existing actions */
InitializeAction();

Debug1("HandleVarpath(%s)\n",varpath);

if (IsWildCard(varpath) && ! (ACTION == files || ACTION == tidy || ACTION == admit || ACTION == deny))
   {
   yyerror("Wildcards cannot be used in this context:");
   }

strcpy(CURRENTPATH,varpath);

ACTIONPENDING = true;
 
if (ACTION_IS_LINK || ACTION_IS_LINKCHILDREN)
   {
   strcpy(LINKTO,varpath);
   }
else 
   {
   switch (ACTION)
      {
      case tidy:       strcpy(CURRENTITEM,varpath);
                       break;
		       
      case required:   strcpy(CURRENTPATH,varpath);
                       break;
		       
      case makepath:   strcpy(CURRENTPATH,varpath);
                       break;
		       
      case control:    if (CLASS == mountpath)
                          {
                          SetMountPath(varpath);
			  break;
                          }
      
                        if (CLASS == repository)
			   {
			   SetRepository(varpath);
			   break;
			   }

		     if (CLASS == reposchar)
			{
			if (strlen(varpath) > 1)
			   {
			   yyerror("reposchar can only be a single letter");
			   break;
			   }
			if (varpath[0] == '/')
			   {
			   yyerror("illegal value for reposchar");
			   break;
			   }
			REPOSCHAR = varpath[0];
			}

		     if (CLASS == listseparator)
			{
			if (strlen(varpath) > 1)
			   {
			   yyerror("listseparator can only be a single letter");
			   break;
			   }
			if (varpath[0] == '/')
			   {
			   yyerror("illegal value for listseparator");
			   break;
			   }
			LISTSEPARATOR = varpath[0];
			}			

                        if (CLASS == homepat)
                           {
                           yyerror("Home-pattern should be relative to mount-path, not absolute");
                           }

                        if (CLASS == soft)
                           {
                           yyerror("Nested macros not permitted");
                           }
                        break;

      case ignore:      AppendIgnore(varpath);
                        break;

      case links:       /* FROM LINK */
	                break;
      case image:
      case files:
      case editfiles:
                        break;

      case disable:    strcpy(CURRENTPATH,varpath);
                       ACTIONPENDING = true;
                       break;
		       
      case processes:   if (EXPR[0] == '\0')
	                   {
			   if (HAVE_RESTART)
			      {
			      yyerror("Missing search expression");
			      }
			   strcpy(EXPR,varpath);
			   }
                        else
			   {
			   if (HAVE_RESTART)
			      {
			      strcpy(RESTART,varpath);
			      HAVE_RESTART = false;
			      ACTIONPENDING = true;
			      }
			   }
		        break;

      case deny:
      case admit:       Debug("admit/deny varpath=%s\n",varpath);
	                strcpy(CURRENTAUTHPATH,varpath);
	                break;

      default:          FatalError("software error in HandleVarpath()");
      }
   }
}

/*******************************************************************/

HandleWildcard(wildcard)

char *wildcard;

{
Debug1("wildcard = (%s)\n",wildcard);

ACTIONPENDING = true;

switch (ACTION)

   {
   case ignore: AppendIgnore(wildcard);
                break;

   case control:  if (CLASS == homepat)
                     {
                     if (*wildcard == '/')
                        {
                        yyerror("Home pattern was specified as absolute path (should be relative to mountpath)");
                        }


                     Debug1(">>Installing wildcard %s as a home pattern\n",wildcard);
                     HandleHomePattern(wildcard);
		     }
                 else if (CLASS == soft)
                     {
                     AddMacroValue(CURRENTITEM,wildcard);
                     }
                 else if ( CLASS == excludecopy || CLASS == excludelink
 		       || CLASS == copylinks || CLASS == linkcopies
		       || CLASS == reposchar || CLASS == listseparator)
		    {
                    if (*wildcard == '/')
                       {
                       yyerror("Pattern should be a relative name, not an absolute path");
                       }
                    InstallLocalInfo(CLASS,wildcard);
                    }
                 else
                    {
                    RecordMacroId(wildcard);
                    }
                 break;
		 
   case files:
                 HandleOptionalFileAttribute(wildcard);
		 break;
   case image:
                 HandleOptionalImageAttribute(wildcard);
		 break;
   case tidy:
                 HandleOptionalTidyAttribute(wildcard);
                 break;
		 
   case makepath:
                 HandleOptionalDirAttribute(wildcard);
		 break;

   case disable:
                 HandleOptionalDisableAttribute(wildcard);
                 break;
   case links:
                 HandleOptionalLinkAttribute(wildcard);
                 break;
   case processes:
                 HandleOptionalProcessAttribute(wildcard);
                 break;

   case shellcommands:
                 HandleOptionalScriptAttribute(wildcard);
		 break;

   case required:
                 HandleOptionalRequired(wildcard);
		 break;

   case admit:
                 InstallAuthItem(CURRENTAUTHPATH,wildcard,&VADMIT,&VADMITTOP,CLASSBUFF);
		 break;
   case deny:
                 InstallAuthItem(CURRENTAUTHPATH,wildcard,&VDENY,&VDENYTOP,CLASSBUFF);
		 break;
   default:
                 yyerror("Wildcards cannot be used in this context:");
   }
}


/*******************************************************************/
/* Level 2                                                         */
/*******************************************************************/

CompoundId(id)                       /* check for dots in the name */

char *id;

{ int count = 1;
  char *cid = id;

for (cid = id; *cid != '\0'; cid++)
   {
   if (*cid == '.' || *cid == '|')
      {
      count++;
      }
   }

bzero(CLASSBUFF,bufsize);
strcpy(CLASSBUFF,id);

switch (count)
   {
   case 1: 
           if (IsHardClass(id))
              {
              CLASS = ClassStringToCode(id);
              }
           else
              {                              /* <soft> class is a group */
              CLASS = soft;
              }

           break;

   default: CLASS = soft;
            break;
   }

return(count);
}

/*******************************************************************/

ShellCommandReturnsZero(comm)

char *comm;

{ int status, i, argc;
  pid_t pid;
  char arg[maxshellargs][bufsize];
  char **argv;

/* Build argument array */

for (i = 0; i < maxshellargs; i++)
   {
   bzero (arg[i],bufsize);
   }

argc = SplitCommand(comm,arg);

if ((pid = fork()) < 0)
   {
   FatalError("Failed to fork new process");
   }
else if (pid == 0)                     /* child */
   {
   argv = (char **) malloc((argc+1)*sizeof(char *));

   for (i = 0; i < argc; i++)
      {
      argv[i] = arg[i];
      }

   argv[i] = (char *) NULL;

   if (execv(arg[0],argv) == -1)
      {
      yyerror("script failed");
      perror("execvp");
      exit(1);
      }
   }
else                                    /* parent */
   {
   if (wait(&status) != pid)
      {
      printf("cfengine:%s: Wait for child failed\n",VPREFIX);
      perror("wait");
      return false;
      }
   else
      {
      if (WIFSIGNALED(status))
         {
         Debug("cfengine:%s: script %s returned: %s\n",VPREFIX,comm,WTERMSIG(status));
         return false;
         }

      if (! WIFEXITED(status))
         {
         return false;
         }

      if (WEXITSTATUS(status) == 0)
         {
         return true;
         }
      else
         {
         return false;
         }
      }
   }

}


/*******************************************************************/

SplitCommand(comm,arg)

char *comm, arg[maxshellargs][bufsize];

{ char *sp;
  int i = 0, j;
  char buff[bufsize];

for (sp = comm; *sp != '\0'; sp++)
   {
   bzero(buff,bufsize);

   if (i >= maxshellargs-1)
      {
      yyerror("Too many arguments in embedded script");
      FatalError("Use a wrapper");
      }

   while (*sp == ' ' || *sp == '\t')
      {
      sp++;
      }

   switch (*sp)
      {
      case '\"': sscanf (++sp,"%[^\"]",buff);
                 break;
      case '\'': sscanf (++sp,"%[^\']",buff);
                 break;
      case '`':  sscanf (++sp,"%[^`]",buff);
	         break;
      default:   sscanf (sp,"%s",buff);
                 break;
      }

   for (j = 0; j < bufsize; j++)
      {
      arg[i][j] = buff[j];
      }

   sp += strlen(arg[i]);
   i++;
   }
return (i);
}


/*******************************************************************/
/* Toolkits Misc                                                   */
/*******************************************************************/

InitializeAction()                                   /* Set defaults */

{
Debug1("InitializeAction()\n");

PLUSMASK = 0;
MINUSMASK = 0;
VRECURSE = 0;
VAGE = 99999;
VUIDNAME[0] = '*';
VUIDNAME[1] = '\0';
VGIDNAME[0] = '*';
VGIDNAME[1] = '\0';
HAVE_RESTART = 0;
FILEACTION=warnall;
CURRENTPATH[0] = '\0';
CURRENTITEM[0] = '\0';
ACTIONPENDING = false;
DESTINATION[0] = '\0';
IMAGEACTION[0] = '\0';
PTRAVLINKS = (short) '?';
FORCECOPY = false;
IMAGEBACKUP = true;
ROTATE=0;
TIDYSIZE=0;
PROMATCHES=-1;
AGETYPE='a';
COPYTYPE = 't';
LINKDIRS = 'k';
TIDYDIRS = false;
VEXCLUDEPARSE = NULL;
VINCLUDEPARSE = NULL;
VCPLNPARSE = NULL;
VTIMEOUT=0;
strcpy(ALLCLASSBUFFER,"");
strcpy(CFSERVER,"localhost");
DISCOMP='>';
DISABLESIZE=cfnosize;

 /* Make sure we don't clean the buffer in the middle of a link! */

if ( ! ACTION_IS_LINK && ! ACTION_IS_LINKCHILDREN)
   {
   LINKFROM[0] = '\0';
   LINKTO[0] = '\0';
   LINKSILENT = false;
   LINKTYPE = 's';
   }
}

/*********************************************************************/

SetMountPath (value)

char *value;

{ char buff[bufsize];

bzero(buff,bufsize);

ExpandVarstring(value,buff,"");

Debug("Appending [%s] to mountlist\n",value);

AppendItem(&VMOUNTLIST,buff,CLASSBUFF);
}

/*********************************************************************/

SetRepository (value)

char *value;

{
if (*value != '/')
   {
   yyerror("File repository must be an absolute directory name");
   }

if (VREPOSITORY[0] != '\0')
   {
   yyerror("Redefinition of system variable repository");
   }

ExpandVarstring(value,VREPOSITORY,"");
}

/* EOF */
