summaryrefslogtreecommitdiff
path: root/usr.bin/mg/autoexec.c
blob: 020b1b6d8d03c4ad382ec1e65a58a57fd42bf3b0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/* $OpenBSD: autoexec.c,v 1.2 2002/08/22 23:28:19 deraadt Exp $ */
/* this file is in the public domain */
/* Author: Vincent Labrecque <vincent@openbsd.org>	April 2002 */

#include "def.h"
#include "funmap.h"

#include <sys/queue.h>

#include <fnmatch.h>

struct autoexec {
	SLIST_ENTRY(autoexec) next;	/* link in the linked list */
	const char	*pattern;	/* Pattern to match to filenames */
	PF		 fp;
};

static SLIST_HEAD(, autoexec)	 autos;
static int			 ready;

/*
 * Return a NULL terminated array of function pointers to be called
 * when we open a file that matches <fname>.  The list must be free(ed)
 * after use.
 */
PF *
find_autoexec(const char *fname)
{
	PF *pfl;
	int have, used;
	struct autoexec *ae;

	if (!ready)
		return (NULL);

	pfl = NULL;
	have = 0;
	used = 0;
	SLIST_FOREACH(ae, &autos, next) {
		if (fnmatch(ae->pattern, fname, 0) == 0) {
			if (used >= have) {
				have += 8;
				/*
				 * XXX - realloc(NULL, ...) is not really
				 *       portable
				 */
				pfl = realloc(pfl, (have + 1) * sizeof(PF));
				if (pfl == NULL)
					panic("out of memory");
			}
			pfl[used++] = ae->fp;
		}
	}
	if (used) {
		pfl[used] = NULL;
		pfl = realloc(pfl, (used + 1) * sizeof(PF));
	}
	return (pfl);
}

int
add_autoexec(const char *pattern, const char *func)
{
	PF fp;
	struct autoexec *ae;

	if (!ready) {
		SLIST_INIT(&autos);
		ready = 1;
	}
	fp = name_function(func);
	if (fp == NULL)
		return (FALSE);
	ae = malloc(sizeof *ae);
	if (ae == NULL)
		return (FALSE);
	ae->fp = fp;
	ae->pattern = strdup(pattern);
	if (ae->pattern == NULL) {
		free(ae);
		return (FALSE);
	}
	SLIST_INSERT_HEAD(&autos, ae, next);

	return (TRUE);
}

int
auto_execute(int f, int n)
{
	char patbuf[128], funcbuf[128];
	int s;

	if ((s = ereply("Filename pattern: ", patbuf, sizeof patbuf)) != TRUE)
		return (s);
	if ((s = ereply("Execute: ", funcbuf, sizeof funcbuf)) != TRUE)
		return (s);
	if ((s = add_autoexec(patbuf, funcbuf)) != TRUE)
		return (s);
	return (TRUE);
}