aboutsummaryrefslogtreecommitdiffstats
path: root/tests/asschk.c
diff options
context:
space:
mode:
authorRepo Admin <[email protected]>2002-10-19 07:55:27 +0000
committerRepo Admin <[email protected]>2002-10-19 07:55:27 +0000
commit82a17c9fb3d64ccdd474c3bedf564368f77e84a4 (patch)
tree0c01ee8cea5f6f77e830955c6b97024752740a2b /tests/asschk.c
parentBumped version number for cvs version (diff)
downloadgnupg-82a17c9fb3d64ccdd474c3bedf564368f77e84a4.tar.gz
gnupg-82a17c9fb3d64ccdd474c3bedf564368f77e84a4.zip
This commit was manufactured by cvs2svn to create branch
'GNUPG-1-9-BRANCH'.
Diffstat (limited to 'tests/asschk.c')
-rw-r--r--tests/asschk.c1046
1 files changed, 0 insertions, 1046 deletions
diff --git a/tests/asschk.c b/tests/asschk.c
deleted file mode 100644
index 1a11ead33..000000000
--- a/tests/asschk.c
+++ /dev/null
@@ -1,1046 +0,0 @@
-/* asschk.c - Assuan Server Checker
- * Copyright (C) 2002 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG 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 of the License, or
- * (at your option) any later version.
- *
- * GnuPG 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
- */
-
-/* This is a simple stand-alone Assuan server test program. We don't
- want to use the assuan library because we don't want to hide errors
- in that library.
-
- The script language is line based. Empty lines or lines containing
- only white spaces are ignored, line with a hash sign as first non
- white space character are treated as comments.
-
- A simple macro mechanism is implemnted. Macros are expanded before
- a line is processed but after comment processing. Macros are only
- expanded once and non existing macros expand to the empty string.
- A macro is dereferenced by prefixing its name with a dollar sign;
- the end of the name is currently indicated by a white space, a
- dollar sign or a slash. To use a dollor sign verbatim, double it.
-
- A macro is assigned by prefixing a statement with the macro name
- and an equal sign. The value is assigned verbatim if it does not
- resemble a command, otherwise the return value of the command will
- get assigned. The command "let" may be used to assign values
- unambigiously and it should be used if the value starts with a
- letter.
-
- Conditions are not yes implemented except for a simple evaluation
- which yields false for an empty string or the string "0". The
- result may be negated by prefixing with a '!'.
-
- The general syntax of a command is:
-
- [<name> =] <statement> [<args>]
-
- If NAME is not specifed but the statement returns a value it is
- assigned to the name "?" so that it can be referenced using "$?".
- The following commands are implemented:
-
- let <value>
- Return VALUE.
-
- echo <value>
- Print VALUE.
-
- openfile <filename>
- Open file FILENAME for read access and retrun the file descriptor.
-
- createfile <filename>
- Create file FILENAME, open for write access and retrun the file
- descriptor.
-
- pipeserver <program>
- Connect to the Assuan server PROGRAM.
-
- send <line>
- Send LINE to the server.
-
- expect-ok
- Expect an OK response from the server. Status and data out put
- is ignored.
-
- expect-err
- Expect an ERR response from the server. Status and data out put
- is ignored.
-
- count-status <code>
- Initialize the assigned variable to 0 and assign it as an counter for
- status code CODE. This command must be called with an assignment.
-
- quit
- Terminate the process.
-
- quit-if <condition>
- Terminate the process if CONDITION evaluates to true.
-
- fail-if <condition>
- Terminate the process with an exit code of 1 if CONDITION
- evaluates to true.
-
- cmpfiles <first> <second>
- Returns true when the content of the files FIRST and SECOND match.
-
- getenv <name>
- Return the value of the environment variable NAME.
-
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <assert.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 )
-# define ATTR_PRINTF(f,a) __attribute__ ((format (printf,f,a)))
-#else
-# define ATTR_PRINTF(f,a)
-#endif
-
-#define spacep(p) (*(p) == ' ' || *(p) == '\t')
-
-#define MAX_LINELEN 2048
-
-typedef enum {
- LINE_OK = 0,
- LINE_ERR,
- LINE_STAT,
- LINE_DATA,
- LINE_END,
-} LINETYPE;
-
-typedef enum {
- VARTYPE_SIMPLE = 0,
- VARTYPE_FD,
- VARTYPE_COUNTER
-} VARTYPE;
-
-
-struct variable_s {
- struct variable_s *next;
- VARTYPE type;
- unsigned int count;
- char *value;
- char name[1];
-};
-typedef struct variable_s *VARIABLE;
-
-
-static void die (const char *format, ...) ATTR_PRINTF(1,2);
-
-
-/* Name of this program to be printed in error messages. */
-static const char *invocation_name;
-
-/* Talk a bit about what is going on. */
-static int opt_verbose;
-
-/* Option to ignore the echo command. */
-static int opt_no_echo;
-
-/* File descriptors used to communicate with the current server. */
-static int server_send_fd = -1;
-static int server_recv_fd = -1;
-
-/* The Assuan protocol limits the line length to 1024, so we can
- safely use a (larger) buffer. The buffer is filled using the
- read_assuan(). */
-static char recv_line[MAX_LINELEN];
-/* Tell the status of the current line. */
-static LINETYPE recv_type;
-
-/* This is our variable storage. */
-static VARIABLE variable_list;
-
-
-static void
-die (const char *format, ...)
-{
- va_list arg_ptr;
-
- fflush (stdout);
- fprintf (stderr, "%s: ", invocation_name);
-
- va_start (arg_ptr, format);
- vfprintf (stderr, format, arg_ptr);
- va_end (arg_ptr);
- putc ('\n', stderr);
-
- exit (1);
-}
-
-static void
-err (const char *format, ...)
-{
- va_list arg_ptr;
-
- fflush (stdout);
- fprintf (stderr, "%s: ", invocation_name);
-
- va_start (arg_ptr, format);
- vfprintf (stderr, format, arg_ptr);
- va_end (arg_ptr);
- putc ('\n', stderr);
-}
-
-static void *
-xmalloc (size_t n)
-{
- void *p = malloc (n);
- if (!p)
- die ("out of core");
- return p;
-}
-
-static void *
-xcalloc (size_t n, size_t m)
-{
- void *p = calloc (n, m);
- if (!p)
- die ("out of core");
- return p;
-}
-
-static char *
-xstrdup (const char *s)
-{
- char *p = xmalloc (strlen (s)+1);
- strcpy (p, s);
- return p;
-}
-
-
-/* Write LENGTH bytes from BUFFER to FD. */
-static int
-writen (int fd, const char *buffer, size_t length)
-{
- while (length)
- {
- int nwritten = write (fd, buffer, length);
-
- if (nwritten < 0)
- {
- if (errno == EINTR)
- continue;
- return -1; /* write error */
- }
- length -= nwritten;
- buffer += nwritten;
- }
- return 0; /* okay */
-}
-
-
-
-
-/* Assuan specific stuff. */
-
-/* Read a line from FD, store it in the global recv_line, analyze the
- type and store that in recv_type. The function terminates on a
- communication error. Returns a pointer into the inputline to the
- first byte of the arguments. The parsing is very strict to match
- excalty what we want to send. */
-static char *
-read_assuan (int fd)
-{
- static char pending[MAX_LINELEN];
- static size_t pending_len;
- size_t nleft = sizeof recv_line;
- char *buf = recv_line;
- char *p;
-
- while (nleft > 0)
- {
- int n;
-
- if (pending_len)
- {
- if (pending_len >= nleft)
- die ("received line too large");
- memcpy (buf, pending, pending_len);
- n = pending_len;
- pending_len = 0;
- }
- else
- n = read (fd, buf, nleft);
- if (n < 0)
- {
- if (errno == EINTR)
- continue;
- die ("reading fd %d failed: %s", fd, strerror (errno));
- }
- else if (!n)
- die ("received incomplete line on fd %d", fd);
- p = buf;
- nleft -= n;
- buf += n;
-
- for (; n && *p != '\n'; n--, p++)
- ;
- if (n)
- {
- if (n>1)
- {
- n--;
- memcpy (pending, p + 1, n);
- pending_len = n;
- }
- *p = '\0';
- break;
- }
- }
- if (!nleft)
- die ("received line too large");
-
- p = recv_line;
- if (p[0] == 'O' && p[1] == 'K' && (p[2] == ' ' || !p[2]))
- {
- recv_type = LINE_OK;
- p += 3;
- }
- else if (p[0] == 'E' && p[1] == 'R' && p[2] == 'R'
- && (p[3] == ' ' || !p[3]))
- {
- recv_type = LINE_ERR;
- p += 4;
- }
- else if (p[0] == 'S' && (p[1] == ' ' || !p[1]))
- {
- recv_type = LINE_STAT;
- p += 2;
- }
- else if (p[0] == 'D' && p[1] == ' ')
- {
- recv_type = LINE_DATA;
- p += 2;
- }
- else if (p[0] == 'E' && p[1] == 'N' && p[2] == 'D' && !p[3])
- {
- recv_type = LINE_END;
- p += 3;
- }
- else
- die ("invalid line type (%.5s)", p);
-
- return p;
-}
-
-/* Write LINE to the server using FD. It is expected that the line
- contains the terminating linefeed as last character. */
-static void
-write_assuan (int fd, const char *line)
-{
- char buffer[1026];
- size_t n = strlen (line);
-
- if (n > 1024)
- die ("line too long for Assuan protocol");
- strcpy (buffer, line);
- if (!n || buffer[n-1] != '\n')
- buffer[n++] = '\n';
-
- if (writen (fd, buffer, n))
- die ("sending line to %d failed: %s", fd, strerror (errno));
-}
-
-
-/* Start the server with path PGMNAME and connect its stdout and
- strerr to a newly created pipes; the file descriptors are then
- store in the gloabl variables SERVER_SEND_FD and
- SERVER_RECV_FD. The initial handcheck is performed.*/
-static void
-start_server (const char *pgmname)
-{
- int rp[2];
- int wp[2];
- pid_t pid;
-
- if (pipe (rp) < 0)
- die ("pipe creation failed: %s", strerror (errno));
- if (pipe (wp) < 0)
- die ("pipe creation failed: %s", strerror (errno));
-
- fflush (stdout);
- fflush (stderr);
- pid = fork ();
- if (pid < 0)
- die ("fork failed");
-
- if (!pid)
- {
- const char *arg0;
-
- arg0 = strrchr (pgmname, '/');
- if (arg0)
- arg0++;
- else
- arg0 = pgmname;
-
- if (wp[0] != STDIN_FILENO)
- {
- if (dup2 (wp[0], STDIN_FILENO) == -1)
- die ("dup2 failed in child: %s", strerror (errno));
- close (wp[0]);
- }
- if (rp[1] != STDOUT_FILENO)
- {
- if (dup2 (rp[1], STDOUT_FILENO) == -1)
- die ("dup2 failed in child: %s", strerror (errno));
- close (rp[1]);
- }
- if (!opt_verbose)
- {
- int fd = open ("/dev/null", O_WRONLY);
- if (fd == -1)
- die ("can't open `/dev/null': %s", strerror (errno));
- if (dup2 (fd, STDERR_FILENO) == -1)
- die ("dup2 failed in child: %s", strerror (errno));
- close (fd);
- }
-
- close (wp[1]);
- close (rp[0]);
- execl (pgmname, arg0, "--server", NULL);
- die ("exec failed for `%s': %s", pgmname, strerror (errno));
- }
- close (wp[0]);
- close (rp[1]);
- server_send_fd = wp[1];
- server_recv_fd = rp[0];
-
- read_assuan (server_recv_fd);
- if (recv_type != LINE_OK)
- die ("no greating message");
-}
-
-
-
-
-
-/* Script intepreter. */
-
-static void
-unset_var (const char *name)
-{
- VARIABLE var;
-
- for (var=variable_list; var && strcmp (var->name, name); var = var->next)
- ;
- if (!var)
- return;
-/* fprintf (stderr, "unsetting `%s'\n", name); */
-
- if (var->type == VARTYPE_FD && var->value)
- {
- int fd;
-
- fd = atoi (var->value);
- if (fd != -1 && fd != 0 && fd != 1 && fd != 2)
- close (fd);
- }
-
- free (var->value);
- var->value = NULL;
- var->type = 0;
- var->count = 0;
-}
-
-
-static void
-set_type_var (const char *name, const char *value, VARTYPE type)
-{
- VARIABLE var;
-
- if (!name)
- name = "?";
- for (var=variable_list; var && strcmp (var->name, name); var = var->next)
- ;
- if (!var)
- {
- var = xcalloc (1, sizeof *var + strlen (name));
- strcpy (var->name, name);
- var->next = variable_list;
- variable_list = var;
- }
- else
- free (var->value);
-
- if (var->type == VARTYPE_FD && var->value)
- {
- int fd;
-
- fd = atoi (var->value);
- if (fd != -1 && fd != 0 && fd != 1 && fd != 2)
- close (fd);
- }
-
- var->type = type;
- var->count = 0;
- if (var->type == VARTYPE_COUNTER)
- {
- /* We need some extra sapce as scratch area for get_var. */
- var->value = xmalloc (strlen (value) + 1 + 20);
- strcpy (var->value, value);
- }
- else
- var->value = xstrdup (value);
-}
-
-static void
-set_var (const char *name, const char *value)
-{
- set_type_var (name, value, 0);
-}
-
-
-static const char *
-get_var (const char *name)
-{
- VARIABLE var;
-
- for (var=variable_list; var && strcmp (var->name, name); var = var->next)
- ;
- if (!var)
- return NULL;
- if (var->type == VARTYPE_COUNTER && var->value)
- { /* Use the scratch space allocated by set_var. */
- char *p = var->value + strlen(var->value)+1;
- sprintf (p, "%u", var->count);
- return p;
- }
- else
- return var->value;
-}
-
-
-/* Incremente all counter type variables with NAME in their VALUE. */
-static void
-inc_counter (const char *name)
-{
- VARIABLE var;
-
- if (!*name)
- return;
- for (var=variable_list; var; var = var->next)
- {
- if (var->type == VARTYPE_COUNTER
- && var->value && !strcmp (var->value, name))
- var->count++;
- }
-}
-
-
-/* Expand variables in LINE and return a new allocated buffer if
- required. The function might modify LINE if the expanded version
- fits into it. */
-static char *
-expand_line (char *buffer)
-{
- char *line = buffer;
- char *p, *pend;
- const char *value;
- size_t valuelen, n;
- char *result = NULL;
-
- while (*line)
- {
- p = strchr (line, '$');
- if (!p)
- return result; /* nothing more to expand */
-
- if (p[1] == '$') /* quoted */
- {
- memmove (p, p+1, strlen (p+1)+1);
- line = p + 1;
- continue;
- }
- for (pend=p+1; *pend && !spacep (pend)
- && *pend != '$' && *pend != '/'; pend++)
- ;
- if (*pend)
- {
- int save = *pend;
- *pend = 0;
- value = get_var (p+1);
- *pend = save;
- }
- else
- value = get_var (p+1);
- if (!value)
- value = "";
- valuelen = strlen (value);
- if (valuelen <= pend - p)
- {
- memcpy (p, value, valuelen);
- p += valuelen;
- n = pend - p;
- if (n)
- memmove (p, p+n, strlen (p+n)+1);
- line = p;
- }
- else
- {
- char *src = result? result : buffer;
- char *dst;
-
- dst = xmalloc (strlen (src) + valuelen + 1);
- n = p - src;
- memcpy (dst, src, n);
- memcpy (dst + n, value, valuelen);
- n += valuelen;
- strcpy (dst + n, pend);
- line = dst + n;
- free (result);
- result = dst;
- }
- }
- return result;
-}
-
-
-/* Evaluate COND and return the result. */
-static int
-eval_boolean (const char *cond)
-{
- int true = 1;
-
- for ( ; *cond == '!'; cond++)
- true = !true;
- if (!*cond || (*cond == '0' && !cond[1]))
- return !true;
- return true;
-}
-
-
-
-
-
-static void
-cmd_let (const char *assign_to, char *arg)
-{
- set_var (assign_to, arg);
-}
-
-
-static void
-cmd_echo (const char *assign_to, char *arg)
-{
- if (!opt_no_echo)
- printf ("%s\n", arg);
-}
-
-static void
-cmd_send (const char *assign_to, char *arg)
-{
- if (opt_verbose)
- fprintf (stderr, "sending `%s'\n", arg);
- write_assuan (server_send_fd, arg);
-}
-
-static void
-handle_status_line (char *arg)
-{
- char *p;
-
- for (p=arg; *p && !spacep (p); p++)
- ;
- if (*p)
- {
- int save = *p;
- *p = 0;
- inc_counter (arg);
- *p = save;
- }
- else
- inc_counter (arg);
-}
-
-static void
-cmd_expect_ok (const char *assign_to, char *arg)
-{
- if (opt_verbose)
- fprintf (stderr, "expecting OK\n");
- do
- {
- char *p = read_assuan (server_recv_fd);
- if (opt_verbose > 1)
- fprintf (stderr, "got line `%s'\n", recv_line);
- if (recv_type == LINE_STAT)
- handle_status_line (p);
- }
- while (recv_type != LINE_OK && recv_type != LINE_ERR);
- if (recv_type != LINE_OK)
- die ("expected OK but got `%s'", recv_line);
-}
-
-static void
-cmd_expect_err (const char *assign_to, char *arg)
-{
- if (opt_verbose)
- fprintf (stderr, "expecting ERR\n");
- do
- {
- char *p = read_assuan (server_recv_fd);
- if (opt_verbose > 1)
- fprintf (stderr, "got line `%s'\n", recv_line);
- if (recv_type == LINE_STAT)
- handle_status_line (p);
- }
- while (recv_type != LINE_OK && recv_type != LINE_ERR);
- if (recv_type != LINE_ERR)
- die ("expected ERR but got `%s'", recv_line);
-}
-
-static void
-cmd_count_status (const char *assign_to, char *arg)
-{
- char *p;
-
- if (!*assign_to || !*arg)
- die ("syntax error: count-status requires an argument and a variable");
-
- for (p=arg; *p && !spacep (p); p++)
- ;
- if (*p)
- {
- for (*p++ = 0; spacep (p); p++)
- ;
- if (*p)
- die ("cmpfiles: syntax error");
- }
- set_type_var (assign_to, arg, VARTYPE_COUNTER);
-}
-
-static void
-cmd_openfile (const char *assign_to, char *arg)
-{
- int fd;
- char numbuf[20];
-
- do
- fd = open (arg, O_RDONLY);
- while (fd == -1 && errno == EINTR);
- if (fd == -1)
- die ("error opening `%s': %s", arg, strerror (errno));
-
- sprintf (numbuf, "%d", fd);
- set_type_var (assign_to, numbuf, VARTYPE_FD);
-}
-
-static void
-cmd_createfile (const char *assign_to, char *arg)
-{
- int fd;
- char numbuf[20];
-
- do
- fd = open (arg, O_WRONLY|O_CREAT|O_TRUNC, 0666);
- while (fd == -1 && errno == EINTR);
- if (fd == -1)
- die ("error creating `%s': %s", arg, strerror (errno));
-
- sprintf (numbuf, "%d", fd);
- set_type_var (assign_to, numbuf, VARTYPE_FD);
-}
-
-
-static void
-cmd_pipeserver (const char *assign_to, char *arg)
-{
- if (!*arg)
- die ("syntax error: servername missing");
-
- start_server (arg);
-}
-
-
-static void
-cmd_quit_if(const char *assign_to, char *arg)
-{
- if (eval_boolean (arg))
- exit (0);
-}
-
-static void
-cmd_fail_if(const char *assign_to, char *arg)
-{
- if (eval_boolean (arg))
- exit (1);
-}
-
-
-static void
-cmd_cmpfiles (const char *assign_to, char *arg)
-{
- char *p = arg;
- char *second;
- FILE *fp1, *fp2;
- char buffer1[2048]; /* note: both must be of equal size. */
- char buffer2[2048];
- size_t nread1, nread2;
- int rc = 0;
-
- set_var (assign_to, "0");
- for (p=arg; *p && !spacep (p); p++)
- ;
- if (!*p)
- die ("cmpfiles: syntax error");
- for (*p++ = 0; spacep (p); p++)
- ;
- second = p;
- for (; *p && !spacep (p); p++)
- ;
- if (*p)
- {
- for (*p++ = 0; spacep (p); p++)
- ;
- if (*p)
- die ("cmpfiles: syntax error");
- }
-
- fp1 = fopen (arg, "rb");
- if (!fp1)
- {
- err ("can't open `%s': %s", arg, strerror (errno));
- return;
- }
- fp2 = fopen (second, "rb");
- if (!fp2)
- {
- err ("can't open `%s': %s", second, strerror (errno));
- fclose (fp1);
- return;
- }
- while ( (nread1 = fread (buffer1, 1, sizeof buffer1, fp1)))
- {
- if (ferror (fp1))
- break;
- nread2 = fread (buffer2, 1, sizeof buffer2, fp2);
- if (ferror (fp2))
- break;
- if (nread1 != nread2 || memcmp (buffer1, buffer2, nread1))
- {
- rc = 1;
- break;
- }
- }
- if (feof (fp1) && feof (fp2) && !rc)
- {
- if (opt_verbose)
- err ("files match");
- set_var (assign_to, "1");
- }
- else if (!rc)
- err ("cmpfiles: read error: %s", strerror (errno));
- else
- err ("cmpfiles: mismatch");
- fclose (fp1);
- fclose (fp2);
-}
-
-static void
-cmd_getenv (const char *assign_to, char *arg)
-{
- const char *s;
- s = *arg? getenv (arg):"";
- set_var (assign_to, s? s:"");
-}
-
-
-
-
-/* Process the current script line LINE. */
-static int
-interpreter (char *line)
-{
- static struct {
- const char *name;
- void (*fnc)(const char*, char*);
- } cmdtbl[] = {
- { "let" , cmd_let },
- { "echo" , cmd_echo },
- { "send" , cmd_send },
- { "expect-ok" , cmd_expect_ok },
- { "expect-err", cmd_expect_err },
- { "count-status", cmd_count_status },
- { "openfile" , cmd_openfile },
- { "createfile", cmd_createfile },
- { "pipeserver", cmd_pipeserver },
- { "quit" , NULL },
- { "quit-if" , cmd_quit_if },
- { "fail-if" , cmd_fail_if },
- { "cmpfiles" , cmd_cmpfiles },
- { "getenv" , cmd_getenv },
- { NULL }
- };
- char *p, *save_p;
- int i, save_c;
- char *stmt = NULL;
- char *assign_to = NULL;
- char *must_free = NULL;
-
- for ( ;spacep (line); line++)
- ;
- if (!*line || *line == '#')
- return 0; /* empty or comment */
- p = expand_line (line);
- if (p)
- {
- must_free = p;
- line = p;
- for ( ;spacep (line); line++)
- ;
- if (!*line || *line == '#')
- {
- free (must_free);
- return 0; /* empty or comment */
- }
- }
- for (p=line; *p && !spacep (p) && *p != '='; p++)
- ;
- if (*p == '=')
- {
- *p = 0;
- assign_to = line;
- }
- else if (*p)
- {
- for (*p++ = 0; spacep (p); p++)
- ;
- if (*p == '=')
- assign_to = line;
- }
- if (!*line)
- die ("syntax error");
- stmt = line;
- save_c = 0;
- save_p = NULL;
- if (assign_to)
- { /* this is an assignment */
- for (p++; spacep (p); p++)
- ;
- if (!*p)
- {
- unset_var (assign_to);
- free (must_free);
- return 0;
- }
- stmt = p;
- for (; *p && !spacep (p); p++)
- ;
- if (*p)
- {
- save_p = p;
- save_c = *p;
- for (*p++ = 0; spacep (p); p++)
- ;
- }
- }
- for (i=0; cmdtbl[i].name && strcmp (stmt, cmdtbl[i].name); i++)
- ;
- if (!cmdtbl[i].name)
- {
- if (!assign_to)
- die ("invalid statement `%s'\n", stmt);
- if (save_p)
- *save_p = save_c;
- set_var (assign_to, stmt);
- free (must_free);
- return 0;
- }
-
- if (cmdtbl[i].fnc)
- cmdtbl[i].fnc (assign_to, p);
- free (must_free);
- return cmdtbl[i].fnc? 0:1;
-}
-
-
-
-int
-main (int argc, char **argv)
-{
- char buffer[2048];
- char *p, *pend;
-
- if (!argc)
- invocation_name = "asschk";
- else
- {
- invocation_name = *argv++;
- argc--;
- p = strrchr (invocation_name, '/');
- if (p)
- invocation_name = p+1;
- }
-
-
- set_var ("?","1"); /* defaults to true */
-
- for (; argc; argc--, argv++)
- {
- p = *argv;
- if (*p != '-')
- break;
- if (!strcmp (p, "--verbose"))
- opt_verbose++;
- else if (!strcmp (p, "--no-echo"))
- opt_no_echo++;
- else if (*p == '-' && p[1] == 'D')
- {
- p += 2;
- pend = strchr (p, '=');
- if (pend)
- {
- int tmp = *pend;
- *pend = 0;
- set_var (p, pend+1);
- *pend = tmp;
- }
- else
- set_var (p, "1");
- }
- else if (*p == '-' && p[1] == '-' && !p[2])
- {
- argc--; argv++;
- break;
- }
- else
- break;
- }
- if (argc)
- die ("usage: asschk [--verbose] {-D<name>[=<value>]}");
-
-
- while (fgets (buffer, sizeof buffer, stdin))
- {
- p = strchr (buffer,'\n');
- if (!p)
- die ("incomplete script line");
- *p = 0;
- if (interpreter (buffer))
- break;
- fflush (stdout);
- }
- return 0;
-}
-