commit - 257add310e4b16ae43b467b91f66b773da39f470
commit + cc8dff2ee1ef0ddea980fd71c953692343f8c94b
blob - 985c5323d767ed6d605af104b0c49c6272599d77 (mode 644)
blob + /dev/null
--- got/got.h
+++ /dev/null
-/*
- * Copyright (c) 2020 Tracey Emery <tracey@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-struct gotconfig_remote_repo {
- TAILQ_ENTRY(gotconfig_remote_repo) entry;
- char *name;
- char *repository;
- char *server;
- char *protocol;
- char *user;
-};
-TAILQ_HEAD(gotconfig_remote_repo_list, gotconfig_remote_repo);
-
-struct gotconfig {
- struct gotconfig_remote_repo_list remotes;
- int nremotes;
-};
-
-/*
- * Parse individual gotconfig repository files
- */
-const struct got_error* gotconfig_parse(struct gotconfig **,
- const char *filename);
-
-void gotconfig_free(struct gotconfig *);
blob - 2f21cabf60a5f58a82e88cc68ac7102a6ee66f11 (mode 644)
blob + /dev/null
--- got/parse.y
+++ /dev/null
-/*
- * Copyright (c) 2020 Tracey Emery <tracey@openbsd.org>
- * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
- * Copyright (c) 2004 Ryan McBride <mcbride@openbsd.org>
- * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
- * Copyright (c) 2001 Markus Friedl. All rights reserved.
- * Copyright (c) 2001 Daniel Hartmeier. All rights reserved.
- * Copyright (c) 2001 Theo de Raadt. All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-%{
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-
-#include <netinet/in.h>
-
-#include <arpa/inet.h>
-
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <event.h>
-#include <ifaddrs.h>
-#include <imsg.h>
-#include <limits.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <syslog.h>
-#include <unistd.h>
-
-#include "got_error.h"
-#include "got.h"
-
-static struct file {
- FILE *stream;
- char *name;
- size_t ungetpos;
- size_t ungetsize;
- u_char *ungetbuf;
- int eof_reached;
- int lineno;
-} *file;
-static const struct got_error* newfile(struct file**, const char *);
-static void closefile(struct file *);
-int yyparse(void);
-int yylex(void);
-int yyerror(const char *, ...)
- __attribute__((__format__ (printf, 1, 2)))
- __attribute__((__nonnull__ (1)));
-int kw_cmp(const void *, const void *);
-int lookup(char *);
-int igetc(void);
-int lgetc(int);
-void lungetc(int);
-int findeol(void);
-
-TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead);
-struct sym {
- TAILQ_ENTRY(sym) entry;
- int used;
- int persist;
- char *nam;
- char *val;
-};
-
-int symset(const char *, const char *, int);
-char *symget(const char *);
-
-const struct got_error* gerror = NULL;
-struct gotconfig_remote_repo *remote;
-struct gotconfig gotconfig;
-static const struct got_error* new_remote(struct gotconfig_remote_repo **);
-
-typedef struct {
- union {
- int64_t number;
- char *string;
- } v;
- int lineno;
-} YYSTYPE;
-
-%}
-
-%token ERROR
-%token REMOTE REPOSITORY SERVER PROTOCOL USER
-%token <v.string> STRING
-%token <v.number> NUMBER
-
-%%
-
-grammar : /* empty */
- | grammar '\n'
- | grammar remote '\n'
- ;
-remoteopts2 : remoteopts2 remoteopts1 nl
- | remoteopts1 optnl
- ;
-remoteopts1 : REPOSITORY STRING {
- remote->repository = strdup($2);
- if (remote->repository == NULL) {
- free($2);
- yyerror("strdup");
- YYERROR;
- }
- free($2);
- }
- | SERVER STRING {
- remote->server = strdup($2);
- if (remote->server == NULL) {
- free($2);
- yyerror("strdup");
- YYERROR;
- }
- free($2);
- }
- | PROTOCOL STRING {
- remote->protocol = strdup($2);
- if (remote->protocol == NULL) {
- free($2);
- yyerror("strdup");
- YYERROR;
- }
- free($2);
- }
- | USER STRING {
- remote->user = strdup($2);
- if (remote->user == NULL) {
- free($2);
- yyerror("strdup");
- YYERROR;
- }
- free($2);
- }
- ;
-remote : REMOTE STRING {
- static const struct got_error* error;
-
- error = new_remote(&remote);
- if (error) {
- free($2);
- yyerror("%s", error->msg);
- YYERROR;
- }
- remote->name = strdup($2);
- if (remote->name == NULL) {
- free($2);
- yyerror("strdup");
- YYERROR;
- }
- free($2);
- } '{' optnl remoteopts2 '}' {
- TAILQ_INSERT_TAIL(&gotconfig.remotes, remote, entry);
- gotconfig.nremotes++;
- }
- ;
-optnl : '\n' optnl
- | /* empty */
- ;
-nl : '\n' optnl
- ;
-%%
-
-struct keywords {
- const char *k_name;
- int k_val;
-};
-
-int
-yyerror(const char *fmt, ...)
-{
- va_list ap;
- char *msg;
- char *err = NULL;
-
- va_start(ap, fmt);
- if (vasprintf(&msg, fmt, ap) == -1) {
- gerror = got_error_from_errno("vasprintf");
- return 0;
- }
- va_end(ap);
- if (asprintf(&err, "%s:%d: %s", file->name, yylval.lineno, msg) == -1) {
- gerror = got_error_from_errno("asprintf");
- return(0);
- }
- gerror = got_error_msg(GOT_ERR_PARSE_Y_YY, strdup(err));
- free(msg);
- free(err);
- return(0);
-}
-
-int
-kw_cmp(const void *k, const void *e)
-{
- return (strcmp(k, ((const struct keywords *)e)->k_name));
-}
-
-int
-lookup(char *s)
-{
- /* This has to be sorted always. */
- static const struct keywords keywords[] = {
- {"protocol", PROTOCOL},
- {"remote", REMOTE},
- {"repository", REPOSITORY},
- {"server", SERVER},
- {"user", USER},
- };
- const struct keywords *p;
-
- p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
- sizeof(keywords[0]), kw_cmp);
-
- if (p)
- return (p->k_val);
- else
- return (STRING);
-}
-
-#define START_EXPAND 1
-#define DONE_EXPAND 2
-
-static int expanding;
-
-int
-igetc(void)
-{
- int c;
-
- while (1) {
- if (file->ungetpos > 0)
- c = file->ungetbuf[--file->ungetpos];
- else
- c = getc(file->stream);
-
- if (c == START_EXPAND)
- expanding = 1;
- else if (c == DONE_EXPAND)
- expanding = 0;
- else
- break;
- }
- return (c);
-}
-
-int
-lgetc(int quotec)
-{
- int c, next;
-
- if (quotec) {
- c = igetc();
- if (c == EOF) {
- yyerror("reached end of file while parsing "
- "quoted string");
- }
- return (c);
- }
-
- c = igetc();
- while (c == '\\') {
- next = igetc();
- if (next != '\n') {
- c = next;
- break;
- }
- yylval.lineno = file->lineno;
- file->lineno++;
- }
-
- return (c);
-}
-
-void
-lungetc(int c)
-{
- if (c == EOF)
- return;
-
- if (file->ungetpos >= file->ungetsize) {
- void *p = reallocarray(file->ungetbuf, file->ungetsize, 2);
- if (p == NULL)
- err(1, "%s", __func__);
- file->ungetbuf = p;
- file->ungetsize *= 2;
- }
- file->ungetbuf[file->ungetpos++] = c;
-}
-
-int
-findeol(void)
-{
- int c;
-
- /* Skip to either EOF or the first real EOL. */
- while (1) {
- c = lgetc(0);
- if (c == '\n') {
- file->lineno++;
- break;
- }
- if (c == EOF)
- break;
- }
- return (ERROR);
-}
-
-int
-yylex(void)
-{
- unsigned char buf[8096];
- unsigned char *p, *val;
- int quotec, next, c;
- int token;
-
-top:
- p = buf;
- c = lgetc(0);
- while (c == ' ' || c == '\t')
- c = lgetc(0); /* nothing */
-
- yylval.lineno = file->lineno;
- if (c == '#') {
- c = lgetc(0);
- while (c != '\n' && c != EOF)
- c = lgetc(0); /* nothing */
- }
- if (c == '$' && !expanding) {
- while (1) {
- c = lgetc(0);
- if (c == EOF)
- return (0);
-
- if (p + 1 >= buf + sizeof(buf) - 1) {
- yyerror("string too long");
- return (findeol());
- }
- if (isalnum(c) || c == '_') {
- *p++ = c;
- continue;
- }
- *p = '\0';
- lungetc(c);
- break;
- }
- val = symget(buf);
- if (val == NULL) {
- yyerror("macro '%s' not defined", buf);
- return (findeol());
- }
- p = val + strlen(val) - 1;
- lungetc(DONE_EXPAND);
- while (p >= val) {
- lungetc(*p);
- p--;
- }
- lungetc(START_EXPAND);
- goto top;
- }
-
- switch (c) {
- case '\'':
- case '"':
- quotec = c;
- while (1) {
- c = lgetc(quotec);
- if (c == EOF)
- return (0);
- if (c == '\n') {
- file->lineno++;
- continue;
- } else if (c == '\\') {
- next = lgetc(quotec);
- if (next == EOF)
- return (0);
- if (next == quotec || c == ' ' || c == '\t')
- c = next;
- else if (next == '\n') {
- file->lineno++;
- continue;
- } else
- lungetc(next);
- } else if (c == quotec) {
- *p = '\0';
- break;
- } else if (c == '\0') {
- yyerror("syntax error");
- return (findeol());
- }
- if (p + 1 >= buf + sizeof(buf) - 1) {
- yyerror("string too long");
- return (findeol());
- }
- *p++ = c;
- }
- yylval.v.string = strdup(buf);
- if (yylval.v.string == NULL)
- err(1, "%s", __func__);
- return (STRING);
- }
-
-#define allowed_to_end_number(x) \
- (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
-
- if (c == '-' || isdigit(c)) {
- do {
- *p++ = c;
- if ((unsigned)(p-buf) >= sizeof(buf)) {
- yyerror("string too long");
- return (findeol());
- }
- c = lgetc(0);
- } while (c != EOF && isdigit(c));
- lungetc(c);
- if (p == buf + 1 && buf[0] == '-')
- goto nodigits;
- if (c == EOF || allowed_to_end_number(c)) {
- const char *errstr = NULL;
-
- *p = '\0';
- yylval.v.number = strtonum(buf, LLONG_MIN,
- LLONG_MAX, &errstr);
- if (errstr) {
- yyerror("\"%s\" invalid number: %s",
- buf, errstr);
- return (findeol());
- }
- return (NUMBER);
- } else {
-nodigits:
- while (p > buf + 1)
- lungetc(*--p);
- c = *--p;
- if (c == '-')
- return (c);
- }
- }
-
-#define allowed_in_string(x) \
- (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
- x != '{' && x != '}' && \
- x != '!' && x != '=' && x != '#' && \
- x != ','))
-
- if (isalnum(c) || c == ':' || c == '_') {
- do {
- *p++ = c;
- if ((unsigned)(p-buf) >= sizeof(buf)) {
- yyerror("string too long");
- return (findeol());
- }
- c = lgetc(0);
- } while (c != EOF && (allowed_in_string(c)));
- lungetc(c);
- *p = '\0';
- token = lookup(buf);
- if (token == STRING) {
- yylval.v.string = strdup(buf);
- if (yylval.v.string == NULL)
- err(1, "%s", __func__);
- }
- return (token);
- }
- if (c == '\n') {
- yylval.lineno = file->lineno;
- file->lineno++;
- }
- if (c == EOF)
- return (0);
- return (c);
-}
-
-static const struct got_error*
-newfile(struct file **nfile, const char *name)
-{
- const struct got_error* error = NULL;
-
- (*nfile) = calloc(1, sizeof(struct file));
- if ((*nfile) == NULL)
- return got_error_from_errno2(__func__, "calloc");
- (*nfile)->name = strdup(name);
- if ((*nfile)->name == NULL) {
- free(nfile);
- return got_error_from_errno2(__func__, "strdup");
- }
- (*nfile)->stream = fopen((*nfile)->name, "r");
- if ((*nfile)->stream == NULL) {
- char *msg = NULL;
- if (asprintf(&msg, "%s", (*nfile)->name) == -1)
- return got_error_from_errno("asprintf");
- error = got_error_msg(GOT_ERR_NO_CONFIG_FILE, msg);
- free((*nfile)->name);
- free((*nfile));
- free(msg);
- return error;
- }
- (*nfile)->lineno = 1;
- (*nfile)->ungetsize = 16;
- (*nfile)->ungetbuf = malloc((*nfile)->ungetsize);
- if ((*nfile)->ungetbuf == NULL) {
- fclose((*nfile)->stream);
- free((*nfile)->name);
- free((*nfile));
- return got_error_from_errno2(__func__, "malloc");
- }
- return error;
-}
-
-static const struct got_error*
-new_remote(struct gotconfig_remote_repo **remote)
-{
- const struct got_error *error = NULL;
-
- *remote = calloc(1, sizeof(**remote));
- if (*remote == NULL)
- error = got_error_from_errno("calloc");
- return error;
-}
-
-static void
-closefile(struct file *file)
-{
- fclose(file->stream);
- free(file->name);
- free(file->ungetbuf);
- free(file);
-}
-
-const struct got_error*
-gotconfig_parse(struct gotconfig **conf, const char *filename)
-{
- struct sym *sym, *next;
-
- *conf = NULL;
-
- /*
- * We don't require that gotconfig exists
- * So, null gerror and goto done
- */
- gerror = newfile(&file, filename);
- if (gerror && gerror->code == GOT_ERR_NO_CONFIG_FILE) {
- gerror = NULL;
- goto done;
- } else if (gerror)
- return gerror;
-
- TAILQ_INIT(&gotconfig.remotes);
-
- yyparse();
- closefile(file);
-
- /* Free macros and check which have not been used. */
- TAILQ_FOREACH_SAFE(sym, &symhead, entry, next) {
- if (!sym->persist) {
- free(sym->nam);
- free(sym->val);
- TAILQ_REMOVE(&symhead, sym, entry);
- free(sym);
- }
- }
-done:
- *conf = &gotconfig;
- return gerror;
-}
-
-void
-gotconfig_free(struct gotconfig *conf)
-{
- struct gotconfig_remote_repo *remote;
-
- while (!TAILQ_EMPTY(&conf->remotes)) {
- remote = TAILQ_FIRST(&conf->remotes);
- TAILQ_REMOVE(&conf->remotes, remote, entry);
- free(remote->name);
- free(remote->repository);
- free(remote->server);
- free(remote->protocol);
- free(remote->user);
- free(remote);
- }
-}
-
-int
-symset(const char *nam, const char *val, int persist)
-{
- struct sym *sym;
-
- TAILQ_FOREACH(sym, &symhead, entry) {
- if (strcmp(nam, sym->nam) == 0)
- break;
- }
-
- if (sym != NULL) {
- if (sym->persist == 1)
- return (0);
- else {
- free(sym->nam);
- free(sym->val);
- TAILQ_REMOVE(&symhead, sym, entry);
- free(sym);
- }
- }
- sym = calloc(1, sizeof(*sym));
- if (sym == NULL)
- return (-1);
-
- sym->nam = strdup(nam);
- if (sym->nam == NULL) {
- free(sym);
- return (-1);
- }
- sym->val = strdup(val);
- if (sym->val == NULL) {
- free(sym->nam);
- free(sym);
- return (-1);
- }
- sym->used = 0;
- sym->persist = persist;
- TAILQ_INSERT_TAIL(&symhead, sym, entry);
- return (0);
-}
-
-int
-cmdline_symset(char *s)
-{
- char *sym, *val;
- int ret;
- size_t len;
-
- val = strrchr(s, '=');
- if (val == NULL)
- return (-1);
-
- len = strlen(s) - strlen(val) + 1;
- sym = malloc(len);
- if (sym == NULL)
- errx(1, "cmdline_symset: malloc");
-
- strlcpy(sym, s, len);
-
- ret = symset(sym, val + 1, 1);
- free(sym);
-
- return (ret);
-}
-
-char *
-symget(const char *nam)
-{
- struct sym *sym;
-
- TAILQ_FOREACH(sym, &symhead, entry) {
- if (strcmp(nam, sym->nam) == 0) {
- sym->used = 1;
- return (sym->val);
- }
- }
- return (NULL);
-}