xref: /openbsd/usr.bin/mg/autoexec.c (revision d415bd75)
1 /* $OpenBSD: autoexec.c,v 1.19 2023/03/08 04:43:11 guenther Exp $ */
2 /* this file is in the public domain */
3 /* Author: Vincent Labrecque <vincent@openbsd.org>	April 2002 */
4 
5 #include <sys/queue.h>
6 #include <fnmatch.h>
7 #include <signal.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 
12 #include "def.h"
13 #include "funmap.h"
14 
15 struct autoexec {
16 	SLIST_ENTRY(autoexec) next;	/* link in the linked list */
17 	const char	*pattern;	/* Pattern to match to filenames */
18 	PF		 fp;
19 };
20 
21 static SLIST_HEAD(, autoexec)	 autos;
22 static int			 ready;
23 
24 
25 #define AUTO_GROW 8
26 /*
27  * Return a NULL terminated array of function pointers to be called
28  * when we open a file that matches <fname>.  The list must be free(ed)
29  * after use.
30  */
31 PF *
32 find_autoexec(const char *fname)
33 {
34 	PF		*pfl, *npfl;
35 	int		 have, used;
36 	struct autoexec *ae;
37 
38 	if (!ready)
39 		return (NULL);
40 
41 	pfl = NULL;
42 	have = 0;
43 	used = 0;
44 	SLIST_FOREACH(ae, &autos, next) {
45 		if (fnmatch(ae->pattern, fname, 0) == 0) {
46 			if (used >= have) {
47 				npfl = reallocarray(pfl, have + AUTO_GROW + 1,
48 				    sizeof(PF));
49 				if (npfl == NULL)
50 					panic("out of memory");
51 				pfl = npfl;
52 				have += AUTO_GROW;
53 			}
54 			pfl[used++] = ae->fp;
55 		}
56 	}
57 	if (used)
58 		pfl[used] = NULL;
59 
60 	return (pfl);
61 }
62 
63 int
64 add_autoexec(const char *pattern, const char *func)
65 {
66 	PF		 fp;
67 	struct autoexec *ae;
68 
69 	if (!ready) {
70 		SLIST_INIT(&autos);
71 		ready = 1;
72 	}
73 	fp = name_function(func);
74 	if (fp == NULL)
75 		return (FALSE);
76 	ae = malloc(sizeof(*ae));
77 	if (ae == NULL)
78 		return (FALSE);
79 	ae->fp = fp;
80 	ae->pattern = strdup(pattern);
81 	if (ae->pattern == NULL) {
82 		free(ae);
83 		return (FALSE);
84 	}
85 	SLIST_INSERT_HEAD(&autos, ae, next);
86 
87 	return (TRUE);
88 }
89 
90 /*
91  * Register an auto-execute hook; that is, specify a filename pattern
92  * (conforming to the shell's filename globbing rules) and an associated
93  * function to execute when a file matching the specified pattern
94  * is read into a buffer.
95 */
96 int
97 auto_execute(int f, int n)
98 {
99 	char	patbuf[BUFSIZE], funcbuf[BUFSIZE], *patp, *funcp;
100 	int	s;
101 
102 	if ((patp = eread("Filename pattern: ", patbuf, sizeof(patbuf),
103 	    EFNEW | EFCR)) == NULL)
104 		return (ABORT);
105 	else if (patp[0] == '\0')
106 		return (FALSE);
107 	if ((funcp = eread("Execute: ", funcbuf, sizeof(funcbuf),
108 	    EFNEW | EFCR | EFFUNC)) == NULL)
109 		return (ABORT);
110 	else if (funcp[0] == '\0')
111 		return (FALSE);
112 	if ((s = add_autoexec(patp, funcp)) != TRUE)
113 		return (s);
114 	return (TRUE);
115 }
116