1 |
|
|
/* $OpenBSD: autoexec.c,v 1.17 2015/09/26 21:51:58 jasper 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 |
|
|
/* ARGSUSED */ |
97 |
|
|
int |
98 |
|
|
auto_execute(int f, int n) |
99 |
|
|
{ |
100 |
|
|
char patbuf[128], funcbuf[128], *patp, *funcp; |
101 |
|
|
int s; |
102 |
|
|
|
103 |
|
|
if ((patp = eread("Filename pattern: ", patbuf, sizeof(patbuf), |
104 |
|
|
EFNEW | EFCR)) == NULL) |
105 |
|
|
return (ABORT); |
106 |
|
|
else if (patp[0] == '\0') |
107 |
|
|
return (FALSE); |
108 |
|
|
if ((funcp = eread("Execute: ", funcbuf, sizeof(funcbuf), |
109 |
|
|
EFNEW | EFCR | EFFUNC)) == NULL) |
110 |
|
|
return (ABORT); |
111 |
|
|
else if (funcp[0] == '\0') |
112 |
|
|
return (FALSE); |
113 |
|
|
if ((s = add_autoexec(patp, funcp)) != TRUE) |
114 |
|
|
return (s); |
115 |
|
|
return (TRUE); |
116 |
|
|
} |