1*397ddb8aSnicm /* $OpenBSD: trigger.c,v 1.23 2015/11/05 09:48:21 nicm Exp $ */
2b034d592Sjoris /*
3b034d592Sjoris * Copyright (c) 2008 Tobias Stoeckmann <tobias@openbsd.org>
4b034d592Sjoris * Copyright (c) 2008 Jonathan Armani <dbd@asystant.net>
5b034d592Sjoris *
6b034d592Sjoris * Permission to use, copy, modify, and distribute this software for any
7b034d592Sjoris * purpose with or without fee is hereby granted, provided that the above
8b034d592Sjoris * copyright notice and this permission notice appear in all copies.
9b034d592Sjoris *
10b034d592Sjoris * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11b034d592Sjoris * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12b034d592Sjoris * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13b034d592Sjoris * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14b034d592Sjoris * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15b034d592Sjoris * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16b034d592Sjoris * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17b034d592Sjoris */
18b034d592Sjoris
19b034d592Sjoris #include <sys/queue.h>
20b034d592Sjoris #include <sys/types.h>
21b034d592Sjoris
22b034d592Sjoris #include <ctype.h>
23b034d592Sjoris #include <errno.h>
24ed09211bSjoris #include <libgen.h>
25d2c6cc25Stobias #include <pwd.h>
26b034d592Sjoris #include <regex.h>
27b034d592Sjoris #include <stdio.h>
28b034d592Sjoris #include <stdlib.h>
29b034d592Sjoris #include <string.h>
30b034d592Sjoris #include <unistd.h>
31b034d592Sjoris
32b034d592Sjoris #include "config.h"
33b034d592Sjoris #include "cvs.h"
34b034d592Sjoris
35b034d592Sjoris static int expand_args(BUF *, struct file_info_list *, const char *,
36b034d592Sjoris const char *, char *);
37d2c6cc25Stobias static int expand_var(BUF *, const char *);
38b034d592Sjoris static char *parse_cmd(int, char *, const char *, struct file_info_list *);
39b034d592Sjoris
40b034d592Sjoris static int
expand_args(BUF * buf,struct file_info_list * file_info,const char * repo,const char * allowed_args,char * format)41b034d592Sjoris expand_args(BUF *buf, struct file_info_list *file_info, const char *repo,
42b034d592Sjoris const char *allowed_args, char *format)
43b034d592Sjoris {
44b034d592Sjoris int oldstyle, quote;
45b034d592Sjoris struct file_info *fi = NULL;
46b034d592Sjoris char *p, valbuf[2] = { '\0', '\0' };
47b034d592Sjoris const char *val;
48b034d592Sjoris
49b034d592Sjoris if (file_info != NULL && !TAILQ_EMPTY(file_info))
50b034d592Sjoris fi = TAILQ_FIRST(file_info);
51b034d592Sjoris
52b034d592Sjoris quote = oldstyle = 0;
53b034d592Sjoris
54b034d592Sjoris /* Why does GNU cvs print something if it encounters %{}? */
55b034d592Sjoris if (*format == '\0')
56b034d592Sjoris oldstyle = 1;
57b034d592Sjoris
58b034d592Sjoris for (p = format; *p != '\0'; p++) {
59b034d592Sjoris if (*p != '%' && strchr(allowed_args, *p) == NULL)
60b034d592Sjoris return 1;
61b034d592Sjoris
62b034d592Sjoris switch (*p) {
63b034d592Sjoris case 's':
64b034d592Sjoris case 'V':
65b034d592Sjoris case 'v':
66b034d592Sjoris quote = 1;
67b034d592Sjoris oldstyle = 1;
68b034d592Sjoris break;
69b034d592Sjoris default:
70b034d592Sjoris break;
71b034d592Sjoris }
72b034d592Sjoris }
73b034d592Sjoris if (quote)
747bb3ddb0Sray buf_putc(buf, '"');
75b034d592Sjoris if (oldstyle) {
767bb3ddb0Sray buf_puts(buf, repo);
777bb3ddb0Sray buf_putc(buf, ' ');
78b034d592Sjoris }
79b034d592Sjoris
80b034d592Sjoris if (*format == '\0')
81b034d592Sjoris return 0;
82b034d592Sjoris
836697560eSjoris /*
846697560eSjoris * check like this, add only uses loginfo for directories anyway
856697560eSjoris */
866697560eSjoris if (cvs_cmdop == CVS_OP_ADD) {
877bb3ddb0Sray buf_puts(buf, "- New directory");
886697560eSjoris if (quote)
897bb3ddb0Sray buf_putc(buf, '"');
906697560eSjoris return (0);
916697560eSjoris }
926697560eSjoris
93cb9f753dSjoris if (cvs_cmdop == CVS_OP_IMPORT) {
947bb3ddb0Sray buf_puts(buf, "- Imported sources");
95cb9f753dSjoris if (quote)
967bb3ddb0Sray buf_putc(buf, '"');
97cb9f753dSjoris return (0);
98cb9f753dSjoris }
99cb9f753dSjoris
100b034d592Sjoris for (;;) {
101b034d592Sjoris for (p = format; *p != '\0';) {
102b034d592Sjoris val = NULL;
103b034d592Sjoris
104b034d592Sjoris switch (*p) {
105b034d592Sjoris case '%':
106b034d592Sjoris val = "%";
107b034d592Sjoris break;
108b034d592Sjoris case 'b':
109b034d592Sjoris if (fi != NULL) {
110b034d592Sjoris valbuf[0] = fi->tag_type;
111b034d592Sjoris val = valbuf;
112b034d592Sjoris }
113b034d592Sjoris break;
114b034d592Sjoris case 'o':
115b034d592Sjoris if (fi != NULL)
116b034d592Sjoris val = fi->tag_op;
117b034d592Sjoris break;
118b034d592Sjoris case 'p':
119b034d592Sjoris val = current_cvsroot->cr_dir;
120b034d592Sjoris break;
121b034d592Sjoris case 'r':
122b034d592Sjoris val = repo;
123b034d592Sjoris break;
124b034d592Sjoris case 'l':
125b034d592Sjoris case 'S':
126b034d592Sjoris case 's':
127c723dd1dSjoris if (fi != NULL)
128c723dd1dSjoris val = fi->file_path;
129b034d592Sjoris break;
130b034d592Sjoris case 't':
131b034d592Sjoris if (fi != NULL)
132b034d592Sjoris val = fi->tag_new;
133b034d592Sjoris break;
134b034d592Sjoris case 'V':
1356a32da42Sjoris if (fi != NULL) {
1366697560eSjoris if (fi->crevstr != NULL &&
1376697560eSjoris !strcmp(fi->crevstr,
1386a32da42Sjoris "Non-existent"))
1396a32da42Sjoris val = "NONE";
1406a32da42Sjoris else
141b034d592Sjoris val = fi->crevstr;
1426a32da42Sjoris }
143b034d592Sjoris break;
144b034d592Sjoris case 'v':
145c723dd1dSjoris if (fi != NULL) {
146c723dd1dSjoris if (fi->nrevstr != NULL &&
147c723dd1dSjoris !strcmp(fi->nrevstr, "Removed"))
148c723dd1dSjoris val = "NONE";
149c723dd1dSjoris else
150b034d592Sjoris val = fi->nrevstr;
151c723dd1dSjoris }
152b034d592Sjoris break;
153b034d592Sjoris default:
154b034d592Sjoris return 1;
155b034d592Sjoris }
156b034d592Sjoris
157b034d592Sjoris if (val != NULL)
1587bb3ddb0Sray buf_puts(buf, val);
159b034d592Sjoris
160b034d592Sjoris if (*(++p) != '\0')
1617bb3ddb0Sray buf_putc(buf, ',');
162b034d592Sjoris }
163b034d592Sjoris
164b034d592Sjoris if (fi != NULL)
165b034d592Sjoris fi = TAILQ_NEXT(fi, flist);
166b034d592Sjoris if (fi == NULL)
167b034d592Sjoris break;
168b034d592Sjoris
169b034d592Sjoris if (strlen(format) == 1 && (*format == '%' || *format == 'o' ||
170b034d592Sjoris *format == 'p' || *format == 'r' || *format == 't'))
171b034d592Sjoris break;
172b034d592Sjoris
1737bb3ddb0Sray buf_putc(buf, ' ');
174b034d592Sjoris }
175b034d592Sjoris
176b034d592Sjoris if (quote)
1777bb3ddb0Sray buf_putc(buf, '"');
178b034d592Sjoris
179b034d592Sjoris return 0;
180b034d592Sjoris }
181b034d592Sjoris
182d2c6cc25Stobias static int
expand_var(BUF * buf,const char * var)183d2c6cc25Stobias expand_var(BUF *buf, const char *var)
184d2c6cc25Stobias {
185d2c6cc25Stobias struct passwd *pw;
186d2c6cc25Stobias const char *val;
187d2c6cc25Stobias
188d2c6cc25Stobias if (*var == '=') {
189d2c6cc25Stobias if ((val = cvs_var_get(++var)) == NULL) {
190d2c6cc25Stobias cvs_log(LP_ERR, "no such user variable ${=%s}", var);
191d2c6cc25Stobias return (1);
192d2c6cc25Stobias }
1937bb3ddb0Sray buf_puts(buf, val);
194d2c6cc25Stobias } else {
195d2c6cc25Stobias if (strcmp(var, "CVSEDITOR") == 0 ||
196d2c6cc25Stobias strcmp(var, "EDITOR") == 0 ||
197d2c6cc25Stobias strcmp(var, "VISUAL") == 0)
1987bb3ddb0Sray buf_puts(buf, cvs_editor);
199d2c6cc25Stobias else if (strcmp(var, "CVSROOT") == 0)
2007bb3ddb0Sray buf_puts(buf, current_cvsroot->cr_dir);
201d2c6cc25Stobias else if (strcmp(var, "USER") == 0) {
202d2c6cc25Stobias pw = getpwuid(geteuid());
203d2c6cc25Stobias if (pw == NULL) {
204d2c6cc25Stobias cvs_log(LP_ERR, "unable to retrieve "
205d2c6cc25Stobias "caller ID");
206d2c6cc25Stobias return (1);
207d2c6cc25Stobias }
2087bb3ddb0Sray buf_puts(buf, pw->pw_name);
209d2c6cc25Stobias } else if (strcmp(var, "RCSBIN") == 0) {
210d2c6cc25Stobias cvs_log(LP_ERR, "RCSBIN internal variable is no "
211d2c6cc25Stobias "longer supported");
212d2c6cc25Stobias return (1);
213d2c6cc25Stobias } else {
214d2c6cc25Stobias cvs_log(LP_ERR, "no such internal variable $%s", var);
215d2c6cc25Stobias return (1);
216d2c6cc25Stobias }
217d2c6cc25Stobias }
218d2c6cc25Stobias
219d2c6cc25Stobias return (0);
220d2c6cc25Stobias }
221d2c6cc25Stobias
222b034d592Sjoris static char *
parse_cmd(int type,char * cmd,const char * repo,struct file_info_list * file_info)223b034d592Sjoris parse_cmd(int type, char *cmd, const char *repo,
224b034d592Sjoris struct file_info_list *file_info)
225b034d592Sjoris {
226b034d592Sjoris int expanded = 0;
227b034d592Sjoris char argbuf[2] = { '\0', '\0' };
228dda68017Stobias char *allowed_args, *default_args, *args, *file, *p, *q = NULL;
229b034d592Sjoris size_t pos;
230b034d592Sjoris BUF *buf;
231b034d592Sjoris
232b034d592Sjoris switch (type) {
233b034d592Sjoris case CVS_TRIGGER_COMMITINFO:
234b034d592Sjoris allowed_args = "prsS{}";
235b034d592Sjoris default_args = " %p/%r %S";
236dda68017Stobias file = CVS_PATH_COMMITINFO;
237b034d592Sjoris break;
238b034d592Sjoris case CVS_TRIGGER_LOGINFO:
239aa3c507cSjoris allowed_args = "prsSvVt{}";
240b034d592Sjoris default_args = NULL;
241dda68017Stobias file = CVS_PATH_LOGINFO;
242b034d592Sjoris break;
243b034d592Sjoris case CVS_TRIGGER_VERIFYMSG:
244b034d592Sjoris allowed_args = "l";
245b034d592Sjoris default_args = " %l";
246dda68017Stobias file = CVS_PATH_VERIFYMSG;
247b034d592Sjoris break;
248b034d592Sjoris case CVS_TRIGGER_TAGINFO:
249b034d592Sjoris allowed_args = "btoprsSvV{}";
250b034d592Sjoris default_args = " %t %o %p/%r %{sv}";
251dda68017Stobias file = CVS_PATH_TAGINFO;
252b034d592Sjoris break;
253b034d592Sjoris default:
254b034d592Sjoris return (NULL);
255b034d592Sjoris }
256b034d592Sjoris
257b034d592Sjoris /* before doing any stuff, check if the command starts with % */
258f6ac027fSokan for (p = cmd;
259f6ac027fSokan *p != '%' && !isspace((unsigned char)*p) && *p != '\0'; p++)
260b034d592Sjoris ;
261b034d592Sjoris if (*p == '%')
262b034d592Sjoris return (NULL);
263b034d592Sjoris
2647bb3ddb0Sray buf = buf_alloc(1024);
265b034d592Sjoris
266b034d592Sjoris p = cmd;
267b034d592Sjoris again:
268b034d592Sjoris for (; *p != '\0'; p++) {
269d2c6cc25Stobias if ((pos = strcspn(p, "$%")) != 0) {
2707bb3ddb0Sray buf_append(buf, p, pos);
271b034d592Sjoris p += pos;
272b034d592Sjoris }
273b034d592Sjoris
274b034d592Sjoris q = NULL;
275d2c6cc25Stobias if (*p == '\0')
276d2c6cc25Stobias break;
277d2c6cc25Stobias if (*p++ == '$') {
278d2c6cc25Stobias if (*p == '{') {
279d2c6cc25Stobias pos = strcspn(++p, "}");
280d2c6cc25Stobias if (p[pos] == '\0')
281d2c6cc25Stobias goto bad;
282d2c6cc25Stobias } else {
283f0ffd1c4Sjoris for (pos = 0; isalpha(p[pos]); pos++)
284f0ffd1c4Sjoris ;
285f0ffd1c4Sjoris if (pos == 0) {
286d2c6cc25Stobias cvs_log(LP_ERR,
287d2c6cc25Stobias "unrecognized variable syntax");
288d2c6cc25Stobias goto bad;
289d2c6cc25Stobias }
290d2c6cc25Stobias }
291d2c6cc25Stobias q = xmalloc(pos + 1);
292d2c6cc25Stobias memcpy(q, p, pos);
293d2c6cc25Stobias q[pos] = '\0';
294d2c6cc25Stobias if (expand_var(buf, q))
295d2c6cc25Stobias goto bad;
296f0ffd1c4Sjoris p += pos - (*(p - 1) == '{' ? 0 : 1);
297d2c6cc25Stobias } else {
298b034d592Sjoris switch (*p) {
299b034d592Sjoris case '\0':
300b034d592Sjoris goto bad;
301b034d592Sjoris case '{':
302b034d592Sjoris if (strchr(allowed_args, '{') == NULL)
303b034d592Sjoris goto bad;
304b034d592Sjoris pos = strcspn(++p, "}");
305b034d592Sjoris if (p[pos] == '\0')
306b034d592Sjoris goto bad;
307b034d592Sjoris q = xmalloc(pos + 1);
308b034d592Sjoris memcpy(q, p, pos);
309b034d592Sjoris q[pos] = '\0';
310b034d592Sjoris args = q;
311b034d592Sjoris p += pos;
312b034d592Sjoris break;
313b034d592Sjoris default:
314b034d592Sjoris argbuf[0] = *p;
315b034d592Sjoris args = argbuf;
316b034d592Sjoris break;
317b034d592Sjoris }
318b034d592Sjoris
319d2c6cc25Stobias if (expand_args(buf, file_info, repo, allowed_args,
320d2c6cc25Stobias args))
321b034d592Sjoris goto bad;
322b034d592Sjoris expanded = 1;
323d2c6cc25Stobias }
324b034d592Sjoris
325*397ddb8aSnicm free(q);
326b034d592Sjoris }
327b034d592Sjoris
328b034d592Sjoris if (!expanded && default_args != NULL) {
329b034d592Sjoris p = default_args;
330b034d592Sjoris expanded = 1;
331b034d592Sjoris goto again;
332b034d592Sjoris }
333b034d592Sjoris
3347bb3ddb0Sray buf_putc(buf, '\0');
3357bb3ddb0Sray return (buf_release(buf));
336b034d592Sjoris
337b034d592Sjoris bad:
338*397ddb8aSnicm free(q);
339dda68017Stobias cvs_log(LP_NOTICE, "%s contains malformed command '%s'", file, cmd);
3407bb3ddb0Sray buf_free(buf);
341b034d592Sjoris return (NULL);
342b034d592Sjoris }
343b034d592Sjoris
344b034d592Sjoris int
cvs_trigger_handle(int type,char * repo,char * in,struct trigger_list * list,struct file_info_list * files)345b034d592Sjoris cvs_trigger_handle(int type, char *repo, char *in, struct trigger_list *list,
346b034d592Sjoris struct file_info_list *files)
347b034d592Sjoris {
348b034d592Sjoris int r;
349b034d592Sjoris char *cmd;
350b034d592Sjoris struct trigger_line *line;
351b034d592Sjoris
352b034d592Sjoris TAILQ_FOREACH(line, list, flist) {
3530fb47b56Stobias if ((cmd = parse_cmd(type, line->line, repo, files)) == NULL)
3540fb47b56Stobias return (1);
355b034d592Sjoris switch(type) {
356b034d592Sjoris case CVS_TRIGGER_COMMITINFO:
357b034d592Sjoris case CVS_TRIGGER_TAGINFO:
358b034d592Sjoris case CVS_TRIGGER_VERIFYMSG:
359b034d592Sjoris if ((r = cvs_exec(cmd, NULL, 1)) != 0) {
360*397ddb8aSnicm free(cmd);
3610fb47b56Stobias return (r);
362b034d592Sjoris }
363b034d592Sjoris break;
364b034d592Sjoris default:
365b034d592Sjoris (void)cvs_exec(cmd, in, 1);
366b034d592Sjoris break;
367b034d592Sjoris }
368*397ddb8aSnicm free(cmd);
369b034d592Sjoris }
370b034d592Sjoris
3710fb47b56Stobias return (0);
372b034d592Sjoris }
373b034d592Sjoris
374b034d592Sjoris struct trigger_list *
cvs_trigger_getlines(char * file,char * repo)375b034d592Sjoris cvs_trigger_getlines(char * file, char * repo)
376b034d592Sjoris {
377b034d592Sjoris FILE *fp;
378b034d592Sjoris int allow_all, lineno, match = 0;
379b034d592Sjoris size_t len;
380b034d592Sjoris regex_t preg;
381b034d592Sjoris struct trigger_list *list;
382b034d592Sjoris struct trigger_line *tline;
383b9fc9a72Sderaadt char fpath[PATH_MAX];
384b034d592Sjoris char *currentline, *defaultline = NULL, *nline, *p, *q, *regex;
385b034d592Sjoris
386b034d592Sjoris if (strcmp(file, CVS_PATH_EDITINFO) == 0 ||
387b034d592Sjoris strcmp(file, CVS_PATH_VERIFYMSG) == 0)
388b034d592Sjoris allow_all = 0;
389b034d592Sjoris else
390b034d592Sjoris allow_all = 1;
391b034d592Sjoris
392b9fc9a72Sderaadt (void)xsnprintf(fpath, PATH_MAX, "%s/%s", current_cvsroot->cr_dir,
393b034d592Sjoris file);
394b034d592Sjoris
395b034d592Sjoris if ((fp = fopen(fpath, "r")) == NULL) {
396b034d592Sjoris if (errno != ENOENT)
397b034d592Sjoris cvs_log(LP_ERRNO, "cvs_trigger_getlines: %s", file);
398b034d592Sjoris return (NULL);
399b034d592Sjoris }
400b034d592Sjoris
4014f43feaaStobias list = xmalloc(sizeof(*list));
4024f43feaaStobias TAILQ_INIT(list);
4034f43feaaStobias
404b034d592Sjoris lineno = 0;
405b034d592Sjoris nline = NULL;
406c7e0e589Sjoris while ((currentline = fgetln(fp, &len)) != NULL) {
407b034d592Sjoris if (currentline[len - 1] == '\n') {
408b034d592Sjoris currentline[len - 1] = '\0';
409b034d592Sjoris } else {
410b034d592Sjoris nline = xmalloc(len + 1);
411b034d592Sjoris memcpy(nline, currentline, len);
412b034d592Sjoris nline[len] = '\0';
413b034d592Sjoris currentline = nline;
414b034d592Sjoris }
415b034d592Sjoris
416b034d592Sjoris lineno++;
417b034d592Sjoris
418f6ac027fSokan for (p = currentline; isspace((unsigned char)*p); p++)
419b034d592Sjoris ;
420b034d592Sjoris
421b034d592Sjoris if (*p == '\0' || *p == '#')
422b034d592Sjoris continue;
423b034d592Sjoris
424f6ac027fSokan for (q = p; !isspace((unsigned char)*q) && *q != '\0'; q++)
425b034d592Sjoris ;
426b034d592Sjoris
427b034d592Sjoris if (*q == '\0')
428b034d592Sjoris goto bad;
429b034d592Sjoris
430b034d592Sjoris *q++ = '\0';
431b034d592Sjoris regex = p;
432b034d592Sjoris
433f6ac027fSokan for (; isspace((unsigned char)*q); q++)
434b034d592Sjoris ;
435b034d592Sjoris
436b034d592Sjoris if (*q == '\0')
437b034d592Sjoris goto bad;
438b034d592Sjoris
439b034d592Sjoris if (strcmp(regex, "ALL") == 0 && allow_all) {
440b034d592Sjoris tline = xmalloc(sizeof(*tline));
441b034d592Sjoris tline->line = xstrdup(q);
442b034d592Sjoris TAILQ_INSERT_TAIL(list, tline, flist);
443b034d592Sjoris } else if (defaultline == NULL && !match &&
444b034d592Sjoris strcmp(regex, "DEFAULT") == 0) {
445b034d592Sjoris defaultline = xstrdup(q);
446b034d592Sjoris } else if (!match) {
447b034d592Sjoris if (regcomp(&preg, regex, REG_NOSUB|REG_EXTENDED))
448b034d592Sjoris goto bad;
449b034d592Sjoris
450b034d592Sjoris if (regexec(&preg, repo, 0, NULL, 0) != REG_NOMATCH) {
451b034d592Sjoris match = 1;
452b034d592Sjoris
453b034d592Sjoris tline = xmalloc(sizeof(*tline));
454b034d592Sjoris tline->line = xstrdup(q);
455b034d592Sjoris TAILQ_INSERT_HEAD(list, tline, flist);
456b034d592Sjoris }
457b034d592Sjoris regfree(&preg);
458b034d592Sjoris }
459b034d592Sjoris }
460c7e0e589Sjoris
461*397ddb8aSnicm free(nline);
462b034d592Sjoris
463b034d592Sjoris if (defaultline != NULL) {
464b034d592Sjoris if (!match) {
465b034d592Sjoris tline = xmalloc(sizeof(*tline));
466b034d592Sjoris tline->line = defaultline;
467b034d592Sjoris TAILQ_INSERT_HEAD(list, tline, flist);
468b034d592Sjoris } else
469*397ddb8aSnicm free(defaultline);
470b034d592Sjoris }
471b034d592Sjoris
4724f43feaaStobias (void)fclose(fp);
4734f43feaaStobias
474b034d592Sjoris if (TAILQ_EMPTY(list)) {
475*397ddb8aSnicm free(list);
476b034d592Sjoris list = NULL;
477b034d592Sjoris }
478b034d592Sjoris
479b034d592Sjoris return (list);
480b034d592Sjoris
481b034d592Sjoris bad:
482b034d592Sjoris cvs_log(LP_NOTICE, "%s: malformed line %d", file, lineno);
483*397ddb8aSnicm free(defaultline);
484b034d592Sjoris cvs_trigger_freelist(list);
485b034d592Sjoris
4864f43feaaStobias (void)fclose(fp);
4874f43feaaStobias
488b034d592Sjoris return (NULL);
489b034d592Sjoris }
490b034d592Sjoris
491b034d592Sjoris void
cvs_trigger_freelist(struct trigger_list * list)492b034d592Sjoris cvs_trigger_freelist(struct trigger_list * list)
493b034d592Sjoris {
494b034d592Sjoris struct trigger_line *line;
495b034d592Sjoris
496b034d592Sjoris while ((line = TAILQ_FIRST(list)) != NULL) {
497b034d592Sjoris TAILQ_REMOVE(list, line, flist);
498*397ddb8aSnicm free(line->line);
499*397ddb8aSnicm free(line);
500b034d592Sjoris }
501b034d592Sjoris
502*397ddb8aSnicm free(list);
503b034d592Sjoris }
504b034d592Sjoris
505b034d592Sjoris void
cvs_trigger_freeinfo(struct file_info_list * list)506b034d592Sjoris cvs_trigger_freeinfo(struct file_info_list * list)
507b034d592Sjoris {
508b034d592Sjoris struct file_info * fi;
509b034d592Sjoris
510b034d592Sjoris while ((fi = TAILQ_FIRST(list)) != NULL) {
511b034d592Sjoris TAILQ_REMOVE(list, fi, flist);
512b034d592Sjoris
513*397ddb8aSnicm free(fi->file_path);
514*397ddb8aSnicm free(fi->file_wd);
515*397ddb8aSnicm free(fi->crevstr);
516*397ddb8aSnicm free(fi->nrevstr);
517*397ddb8aSnicm free(fi->tag_new);
518*397ddb8aSnicm free(fi->tag_old);
519*397ddb8aSnicm free(fi);
520b034d592Sjoris }
521b034d592Sjoris }
522b034d592Sjoris
523b034d592Sjoris void
cvs_trigger_loginfo_header(BUF * buf,char * repo)524b034d592Sjoris cvs_trigger_loginfo_header(BUF *buf, char *repo)
525b034d592Sjoris {
526b9fc9a72Sderaadt char *dir, pwd[PATH_MAX];
527b9fc9a72Sderaadt char hostname[HOST_NAME_MAX+1];
528b034d592Sjoris
529b034d592Sjoris if (gethostname(hostname, sizeof(hostname)) == -1) {
530b034d592Sjoris fatal("cvs_trigger_loginfo_header: gethostname failed %s",
531b034d592Sjoris strerror(errno));
532b034d592Sjoris }
533b034d592Sjoris
534b034d592Sjoris if (getcwd(pwd, sizeof(pwd)) == NULL)
535b034d592Sjoris fatal("cvs_trigger_loginfo_header: Cannot get working "
536b034d592Sjoris "directory");
537b034d592Sjoris
538b034d592Sjoris if ((dir = dirname(pwd)) == NULL) {
539b034d592Sjoris fatal("cvs_trigger_loginfo_header: dirname failed %s",
540b034d592Sjoris strerror(errno));
541b034d592Sjoris }
542b034d592Sjoris
5437bb3ddb0Sray buf_puts(buf, "Update of ");
5447bb3ddb0Sray buf_puts(buf, current_cvsroot->cr_dir);
5457bb3ddb0Sray buf_putc(buf, '/');
5467bb3ddb0Sray buf_puts(buf, repo);
5477bb3ddb0Sray buf_putc(buf, '\n');
548b034d592Sjoris
5497bb3ddb0Sray buf_puts(buf, "In directory ");
5507bb3ddb0Sray buf_puts(buf, hostname);
5517bb3ddb0Sray buf_puts(buf, ":");
55229d9b3a9Snicm buf_puts(buf, dir);
5537bb3ddb0Sray buf_putc(buf, '/');
5547bb3ddb0Sray buf_puts(buf, repo);
5557bb3ddb0Sray buf_putc(buf, '\n');
5567bb3ddb0Sray buf_putc(buf, '\n');
557b034d592Sjoris }
558b034d592Sjoris
559