1/* cmdarg.c
2   Look up a command with arguments in a command table.
3
4   Copyright (C) 1992 Ian Lance Taylor
5
6   This file is part of the Taylor UUCP uuconf library.
7
8   This library is free software; you can redistribute it and/or
9   modify it under the terms of the GNU Library General Public License
10   as published by the Free Software Foundation; either version 2 of
11   the License, or (at your option) any later version.
12
13   This library is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16   Library General Public License for more details.
17
18   You should have received a copy of the GNU Library General Public
19   License along with this library; if not, write to the Free Software
20   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
21
22   The author of the program may be contacted at ian@airs.com.
23   */
24
25#include "uucnfi.h"
26
27#if USE_RCS_ID
28const char _uuconf_cmdarg_rcsid[] = "$Id: cmdarg.c,v 1.7 2002/03/05 19:10:42 ian Rel $";
29#endif
30
31#include <ctype.h>
32
33#undef strcmp
34#if HAVE_STRCASECMP
35#undef strcasecmp
36#endif
37extern int strcmp (), strcasecmp ();
38
39/* Look up a command with arguments in a table and execute it.  */
40
41int
42uuconf_cmd_args (pglobal, cargs, pzargs, qtab, pinfo, pfiunknown, iflags,
43		 pblock)
44     pointer pglobal;
45     int cargs;
46     char **pzargs;
47     const struct uuconf_cmdtab *qtab;
48     pointer pinfo;
49     int (*pfiunknown) P((pointer, int, char **, pointer, pointer));
50     int iflags;
51     pointer pblock;
52{
53  struct sglobal *qglobal = (struct sglobal *) pglobal;
54  int bfirstu, bfirstl;
55  int (*pficmp) P((const char *, const char *));
56  register const struct uuconf_cmdtab *q;
57  int itype;
58  int callowed;
59
60  bfirstu = bfirstl = pzargs[0][0];
61  if ((iflags & UUCONF_CMDTABFLAG_CASE) != 0)
62    pficmp = strcmp;
63  else
64    {
65      if (islower (bfirstu))
66	bfirstu = toupper (bfirstu);
67      if (isupper (bfirstl))
68	bfirstl = tolower (bfirstl);
69      pficmp = strcasecmp;
70    }
71
72  itype = 0;
73
74  for (q = qtab; q->uuconf_zcmd != NULL; q++)
75    {
76      int bfirst;
77
78      bfirst = q->uuconf_zcmd[0];
79      if (bfirst != bfirstu && bfirst != bfirstl)
80	continue;
81
82      itype = UUCONF_TTYPE_CMDTABTYPE (q->uuconf_itype);
83      if (itype != UUCONF_CMDTABTYPE_PREFIX)
84	{
85	  if ((*pficmp) (q->uuconf_zcmd, pzargs[0]) == 0)
86	    break;
87	}
88      else
89	{
90	  size_t clen;
91
92	  clen = strlen (q->uuconf_zcmd);
93	  if ((iflags & UUCONF_CMDTABFLAG_CASE) != 0)
94	    {
95	      if (strncmp (q->uuconf_zcmd, pzargs[0], clen) == 0)
96		break;
97	    }
98	  else
99	    {
100	      if (strncasecmp (q->uuconf_zcmd, pzargs[0], clen) == 0)
101		break;
102	    }
103	}
104    }
105
106  if (q->uuconf_zcmd == NULL)
107    {
108      if (pfiunknown == NULL)
109	return UUCONF_CMDTABRET_CONTINUE;
110      return (*pfiunknown) (pglobal, cargs, pzargs, (pointer) NULL, pinfo);
111    }
112
113  callowed = UUCONF_CARGS_CMDTABTYPE (q->uuconf_itype);
114  if (callowed != 0 && callowed != cargs)
115    return UUCONF_SYNTAX_ERROR | UUCONF_CMDTABRET_EXIT;
116
117  switch (itype)
118    {
119    case UUCONF_TTYPE_CMDTABTYPE (UUCONF_CMDTABTYPE_STRING):
120      if (cargs == 1)
121	*(char **) q->uuconf_pvar = (char *) "";
122      else if (cargs == 2)
123	*(char **) q->uuconf_pvar = pzargs[1];
124      else
125	return UUCONF_SYNTAX_ERROR | UUCONF_CMDTABRET_EXIT;
126
127      return UUCONF_CMDTABRET_KEEP;
128
129    case UUCONF_TTYPE_CMDTABTYPE (UUCONF_CMDTABTYPE_INT):
130      return _uuconf_iint (qglobal, pzargs[1], q->uuconf_pvar, TRUE);
131
132    case UUCONF_TTYPE_CMDTABTYPE (UUCONF_CMDTABTYPE_LONG):
133      return _uuconf_iint (qglobal, pzargs[1], q->uuconf_pvar, FALSE);
134
135    case UUCONF_TTYPE_CMDTABTYPE (UUCONF_CMDTABTYPE_BOOLEAN):
136      return _uuconf_iboolean (qglobal, pzargs[1], (int *) q->uuconf_pvar);
137
138    case UUCONF_TTYPE_CMDTABTYPE (UUCONF_CMDTABTYPE_FULLSTRING):
139      if (cargs == 1)
140	{
141	  char ***ppz = (char ***) q->uuconf_pvar;
142	  int iret;
143
144	  *ppz = NULL;
145	  iret = _uuconf_iadd_string (qglobal, (char *) NULL, FALSE, FALSE,
146				      ppz, pblock);
147	  if (iret != UUCONF_SUCCESS)
148	    return iret | UUCONF_CMDTABRET_EXIT;
149
150	  return UUCONF_CMDTABRET_CONTINUE;
151	}
152      else
153	{
154	  char ***ppz = (char ***) q->uuconf_pvar;
155	  int i;
156
157	  *ppz = NULL;
158	  for (i = 1; i < cargs; i++)
159	    {
160	      int iret;
161
162	      iret = _uuconf_iadd_string (qglobal, pzargs[i], FALSE, FALSE,
163					  ppz, pblock);
164	      if (iret != UUCONF_SUCCESS)
165		{
166		  *ppz = NULL;
167		  return iret | UUCONF_CMDTABRET_EXIT;
168		}
169	    }
170
171	  return UUCONF_CMDTABRET_KEEP;
172	}
173
174    case UUCONF_TTYPE_CMDTABTYPE (UUCONF_CMDTABTYPE_FN):
175    case UUCONF_TTYPE_CMDTABTYPE (UUCONF_CMDTABTYPE_PREFIX):
176      return (*q->uuconf_pifn) (pglobal, cargs, pzargs, q->uuconf_pvar,
177				pinfo);
178
179    default:
180      return UUCONF_SYNTAX_ERROR | UUCONF_CMDTABRET_EXIT;
181    }
182
183  /*NOTREACHED*/
184}
185