xref: /openbsd-src/usr.bin/mg/autoexec.c (revision 5b133f3f277e80f096764111e64f3a1284acb179)
1*5b133f3fSguenther /* $OpenBSD: autoexec.c,v 1.19 2023/03/08 04:43:11 guenther Exp $ */
232c49409Svincent /* this file is in the public domain */
332c49409Svincent /* Author: Vincent Labrecque <vincent@openbsd.org>	April 2002 */
432c49409Svincent 
5cc6738c5Sbcallah #include <sys/queue.h>
6cc6738c5Sbcallah #include <fnmatch.h>
7cc6738c5Sbcallah #include <signal.h>
8cc6738c5Sbcallah #include <stdio.h>
9cc6738c5Sbcallah #include <stdlib.h>
10cc6738c5Sbcallah #include <string.h>
11cc6738c5Sbcallah 
1232c49409Svincent #include "def.h"
1332c49409Svincent #include "funmap.h"
1432c49409Svincent 
1532c49409Svincent struct autoexec {
1632c49409Svincent 	SLIST_ENTRY(autoexec) next;	/* link in the linked list */
1732c49409Svincent 	const char	*pattern;	/* Pattern to match to filenames */
1832c49409Svincent 	PF		 fp;
1932c49409Svincent };
2032c49409Svincent 
2132c49409Svincent static SLIST_HEAD(, autoexec)	 autos;
2232c49409Svincent static int			 ready;
2332c49409Svincent 
246f801c0eSkjell 
256f801c0eSkjell #define AUTO_GROW 8
2632c49409Svincent /*
2732c49409Svincent  * Return a NULL terminated array of function pointers to be called
2832c49409Svincent  * when we open a file that matches <fname>.  The list must be free(ed)
2932c49409Svincent  * after use.
3032c49409Svincent  */
3132c49409Svincent PF *
find_autoexec(const char * fname)3232c49409Svincent find_autoexec(const char *fname)
3332c49409Svincent {
340a8956baSvincent 	PF		*pfl, *npfl;
3532c49409Svincent 	int		 have, used;
3632c49409Svincent 	struct autoexec *ae;
3732c49409Svincent 
3832c49409Svincent 	if (!ready)
3932c49409Svincent 		return (NULL);
4032c49409Svincent 
4132c49409Svincent 	pfl = NULL;
4232c49409Svincent 	have = 0;
4332c49409Svincent 	used = 0;
4432c49409Svincent 	SLIST_FOREACH(ae, &autos, next) {
4532c49409Svincent 		if (fnmatch(ae->pattern, fname, 0) == 0) {
4632c49409Svincent 			if (used >= have) {
47887501eaSdoug 				npfl = reallocarray(pfl, have + AUTO_GROW + 1,
486f801c0eSkjell 				    sizeof(PF));
490a8956baSvincent 				if (npfl == NULL)
5032c49409Svincent 					panic("out of memory");
510a8956baSvincent 				pfl = npfl;
526f801c0eSkjell 				have += AUTO_GROW;
5332c49409Svincent 			}
5432c49409Svincent 			pfl[used++] = ae->fp;
5532c49409Svincent 		}
5632c49409Svincent 	}
576f801c0eSkjell 	if (used)
5832c49409Svincent 		pfl[used] = NULL;
596f801c0eSkjell 
6032c49409Svincent 	return (pfl);
6132c49409Svincent }
6232c49409Svincent 
6332c49409Svincent int
add_autoexec(const char * pattern,const char * func)6432c49409Svincent add_autoexec(const char *pattern, const char *func)
6532c49409Svincent {
6632c49409Svincent 	PF		 fp;
6732c49409Svincent 	struct autoexec *ae;
6832c49409Svincent 
6932c49409Svincent 	if (!ready) {
7032c49409Svincent 		SLIST_INIT(&autos);
7132c49409Svincent 		ready = 1;
7232c49409Svincent 	}
7332c49409Svincent 	fp = name_function(func);
7432c49409Svincent 	if (fp == NULL)
7532c49409Svincent 		return (FALSE);
76f66aba3dSdb 	ae = malloc(sizeof(*ae));
7732c49409Svincent 	if (ae == NULL)
7832c49409Svincent 		return (FALSE);
7932c49409Svincent 	ae->fp = fp;
8032c49409Svincent 	ae->pattern = strdup(pattern);
8132c49409Svincent 	if (ae->pattern == NULL) {
8232c49409Svincent 		free(ae);
8332c49409Svincent 		return (FALSE);
8432c49409Svincent 	}
8532c49409Svincent 	SLIST_INSERT_HEAD(&autos, ae, next);
8632c49409Svincent 
8732c49409Svincent 	return (TRUE);
8832c49409Svincent }
8932c49409Svincent 
90893214c4Skjell /*
91893214c4Skjell  * Register an auto-execute hook; that is, specify a filename pattern
92893214c4Skjell  * (conforming to the shell's filename globbing rules) and an associated
93893214c4Skjell  * function to execute when a file matching the specified pattern
94893214c4Skjell  * is read into a buffer.
95893214c4Skjell */
9632c49409Svincent int
auto_execute(int f,int n)9732c49409Svincent auto_execute(int f, int n)
9832c49409Svincent {
998127eec9Slum 	char	patbuf[BUFSIZE], funcbuf[BUFSIZE], *patp, *funcp;
10032c49409Svincent 	int	s;
10132c49409Svincent 
102e4eb8759Skjell 	if ((patp = eread("Filename pattern: ", patbuf, sizeof(patbuf),
103e4eb8759Skjell 	    EFNEW | EFCR)) == NULL)
104f66aba3dSdb 		return (ABORT);
105e54a2abfSvincent 	else if (patp[0] == '\0')
106f66aba3dSdb 		return (FALSE);
107e4eb8759Skjell 	if ((funcp = eread("Execute: ", funcbuf, sizeof(funcbuf),
1087be39135Skjell 	    EFNEW | EFCR | EFFUNC)) == NULL)
109f66aba3dSdb 		return (ABORT);
110e54a2abfSvincent 	else if (funcp[0] == '\0')
111f66aba3dSdb 		return (FALSE);
112e54a2abfSvincent 	if ((s = add_autoexec(patp, funcp)) != TRUE)
11332c49409Svincent 		return (s);
11432c49409Svincent 	return (TRUE);
11532c49409Svincent }
116