133965Sjdp/*	$NetBSD: type_regex.c,v 1.8 2021/04/13 13:13:04 christos Exp $	*/
278828Sobrien
3130561Sobrien/*-
433965Sjdp * Copyright (c) 1998-1999 Brett Lymn
533965Sjdp *                         (blymn@baea.com.au, brett_lymn@yahoo.com.au)
633965Sjdp * All rights reserved.
733965Sjdp *
833965Sjdp * This code has been donated to The NetBSD Foundation by the Author.
933965Sjdp *
1033965Sjdp * Redistribution and use in source and binary forms, with or without
1133965Sjdp * modification, are permitted provided that the following conditions
1233965Sjdp * are met:
1333965Sjdp * 1. Redistributions of source code must retain the above copyright
1433965Sjdp *    notice, this list of conditions and the following disclaimer.
1533965Sjdp * 2. The name of the author may not be used to endorse or promote products
1633965Sjdp *    derived from this software without specific prior written permission
1733965Sjdp *
1833965Sjdp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1933965Sjdp * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2033965Sjdp * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2133965Sjdp * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2233965Sjdp * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23130561Sobrien * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2433965Sjdp * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2533965Sjdp * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2633965Sjdp * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2733965Sjdp * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2833965Sjdp *
2933965Sjdp *
30130561Sobrien */
3133965Sjdp
3233965Sjdp#include <sys/cdefs.h>
3333965Sjdp__RCSID("$NetBSD: type_regex.c,v 1.8 2021/04/13 13:13:04 christos Exp $");
3433965Sjdp
3533965Sjdp#include <stdlib.h>
3633965Sjdp#include <sys/types.h>
3733965Sjdp#include <regex.h>
3860484Sobrien#include "form.h"
3933965Sjdp#include "internals.h"
4033965Sjdp
4133965Sjdp/*
4233965Sjdp * The regex type handling.
4333965Sjdp */
4433965Sjdp
4533965Sjdptypedef struct
4633965Sjdp{
47104834Sobrien	regex_t compiled;
48104834Sobrien	unsigned references;
49104834Sobrien} regex_args;
5033965Sjdp
5160484Sobrien/*
5277298Sobrien * Create the regex arguments structure from the given args.  Return NULL
5360484Sobrien * if the call fails, otherwise return a pointer to the structure allocated.
5460484Sobrien */
5560484Sobrienstatic char *
5660484Sobriencreate_regex_args(va_list *args)
5760484Sobrien{
5833965Sjdp	regex_args *new;
5933965Sjdp	char *expression;
6033965Sjdp
6133965Sjdp	new = malloc(sizeof(*new));
6233965Sjdp
6333965Sjdp	if (new != NULL) {
6433965Sjdp		new->references = 1;
6533965Sjdp		expression = va_arg(*args, char *);
6633965Sjdp		if ((regcomp(&new->compiled, expression,
6733965Sjdp			     (REG_EXTENDED | REG_NOSUB | REG_NEWLINE))) != 0) {
6833965Sjdp			free(new);
6933965Sjdp			return NULL;
7033965Sjdp		}
7133965Sjdp	}
7238889Sjdp
7338889Sjdp	return (void *) new;
7438889Sjdp}
7538889Sjdp
7660484Sobrien/*
7760484Sobrien * Copy the regex argument structure.
7860484Sobrien */
7938889Sjdpstatic char *
8038889Sjdpcopy_regex_args(char *args)
8189857Sobrien{
8233965Sjdp	((regex_args *) (void *) args)->references++;
8333965Sjdp
8433965Sjdp	return (void *) args;
8589857Sobrien}
8633965Sjdp
8733965Sjdp/*
8833965Sjdp * Free the allocated storage associated with the type arguments.
8933965Sjdp */
90130561Sobrienstatic void
9133965Sjdpfree_regex_args(char *args)
9233965Sjdp{
9333965Sjdp	if (args != NULL) {
9477298Sobrien		((regex_args *) (void *) args)->references--;
9533965Sjdp		if (((regex_args *) (void *) args)->references == 0)
9677298Sobrien			free(args);
97130561Sobrien	}
9833965Sjdp}
9933965Sjdp
10060484Sobrien/*
10133965Sjdp * Check the contents of the field buffer match the regex.
10233965Sjdp */
10333965Sjdpstatic int
10438889Sjdpregex_check_field(FIELD *field, char *args)
10533965Sjdp{
10633965Sjdp	if ((args != NULL) &&
10733965Sjdp	    (regexec(&((regex_args *) (void *) field->args)->compiled,
10860484Sobrien		   args, (size_t) 0, NULL, 0) == 0))
10960484Sobrien		return TRUE;
11060484Sobrien
11133965Sjdp	return FALSE;
11260484Sobrien}
11333965Sjdp
11433965Sjdpstatic FIELDTYPE builtin_regex = {
11533965Sjdp	_TYPE_HAS_ARGS | _TYPE_IS_BUILTIN,  /* flags */
11660484Sobrien	0,                                  /* refcount */
117130561Sobrien	NULL,                               /* link */
11833965Sjdp	create_regex_args,                  /* make_args */
11933965Sjdp	copy_regex_args,                    /* copy_args */
12033965Sjdp	free_regex_args,                    /* free_args */
12133965Sjdp	regex_check_field,                  /* field_check */
12233965Sjdp	NULL,                               /* char_check */
12333965Sjdp	NULL,                               /* next_choice */
12433965Sjdp	NULL                                /* prev_choice */
12533965Sjdp};
12633965Sjdp
12733965SjdpFIELDTYPE *TYPE_REGEXP = &builtin_regex;
12833965Sjdp
12933965Sjdp
13033965Sjdp