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