/* * srif.c -- Create flags or run external programs on mail events * * srif.c is a part of binkd project * * Copyright (C) 1996-2002 Dima Maloff, 5047/13 and others * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. See COPYING. */ /* * $Id: srif.c,v 2.9.2.2 2004/02/29 08:54:41 gul Exp $ * * $Log: srif.c,v $ * Revision 2.9.2.2 2004/02/29 08:54:41 gul * Fix *A@ macro on call events * (patch by Victor Levenets). * * Revision 2.9.2.1 2003/09/11 17:04:00 stream * Memory leak in evt_queue() * * Revision 2.9 2003/05/28 14:32:57 gul * new function q_add_last_file() - add file to the end of queue * * Revision 2.8 2003/05/27 16:11:17 gul * Improve logging * * Revision 2.7 2003/03/10 17:32:38 gul * Use socklen_t * * Revision 2.6 2003/03/05 13:21:51 gul * Fix warnings * * Revision 2.5 2003/02/23 12:49:00 gul * Added *A* and *A@ macros * * Revision 2.4 2002/03/14 12:26:24 gul * Creating flags bugfix * * Revision 2.3 2002/02/22 00:18:34 gul * Run by-file events with the same command-line once after session * * Revision 2.2 2001/10/27 08:07:19 gul * run and run_args returns exit code of calling process * * Revision 2.1 2001/10/27 07:53:46 gul * Unlink req-file after run freq-processor * * Revision 2.0 2001/01/10 12:12:39 gul * Binkd is under CVS again * * Revision 1.4 1997/06/16 05:40:33 mff * Binkd will not complain about missing .rsp files when running * programms with "exec" statement without using of *S macro. * * Revision 1.3 1997/03/28 06:12:48 mff * Changes to support SRIF: + evt_run(), etc. * * Revision 1.2 1997/02/09 04:17:30 mff * Removed error msgs * * Revision 1.1 1997/01/08 03:57:54 mff * Initial revision * */ #include #include #include #include #include "Config.h" #include "ftnaddr.h" #include "ftnq.h" #include "tools.h" #include "srif.h" #include "run.h" #include "tools.h" EVT_FLAG *evt_flags = 0; static EVTQ *evt_queue(EVTQ *eq, char evt_type, char *path) { EVTQ *tmp; for (tmp=eq; tmp; tmp=tmp->next) { if (tmp->evt_type == evt_type && strcmp(tmp->path, path) == 0) return eq; /* already exists */ } tmp = xalloc(sizeof(EVTQ)); tmp->evt_type = evt_type; tmp->path = xstrdup(path); tmp->next = eq; return tmp; } /* * Tests if filename matches any of EVT_FLAG's patterns. */ int evt_test (EVTQ **eq, char *filename0) { EVT_FLAG *curr; char filename[MAXPATHLEN + 1]; int rc=0; strnzcpy (filename, filename0, MAXPATHLEN); strlower (filename); for (curr = evt_flags; curr; curr = curr->next) { if (pmatch (curr->pattern, filename)) { if (curr->path) { Log (4, "got %s, %screating %s", curr->pattern, curr->imm ? "" : "delayed ", curr->path); if (curr->imm) create_empty_sem_file (curr->path); else *eq = evt_queue(*eq, 'f', curr->path); } else if (curr->command) { Log (4, "got %s, %sstarting %s", curr->pattern, curr->imm ? "" : "delayed ", curr->command); rc=1; } } } return rc; } /* * Sets flags for all matched with evt_test events */ void evt_set (EVTQ *eq) { EVTQ *curr; while (eq) { if (eq->evt_type == 'e') { Log (4, "Running %s", eq->path); run(eq->path); } else { Log (4, "Creating %s", eq->path); create_empty_sem_file(eq->path); } curr = eq->next; free(eq->path); free(eq); eq = curr; } } /* Makes SRIF request and SRIF response names from FTN address of a node */ static int mksrifpaths (FTN_ADDR *fa, char *srf, char *rsp) { ftnaddress_to_filename (srf, fa); if (*srf) { strnzcpy (rsp, srf, MAXPATHLEN); strnzcat (srf, ".srf", MAXPATHLEN); strnzcat (rsp, ".rsp", MAXPATHLEN); return 1; } else return 0; } static int srif_fill (char *path, FTN_ADDR *fa, int nfa, char *req, char *rsp, int prot, int listed, char *peer_name) { FILE *out; int i; if ((out = fopen (path, "w")) != 0) { fprintf (out, "Sysop sysop\n"); for (i = 0; i < nfa; ++i) { char adr[FTN_ADDR_SZ + 1]; ftnaddress_to_str (adr, fa + i); fprintf (out, "AKA %s\n", adr); } fprintf (out, "Baud 115200\n"); fprintf (out, "Time -1\n"); fprintf (out, "RequestList %s\n", req); fprintf (out, "ResponseList %s\n", rsp); fprintf (out, "RemoteStatus %s\n", prot ? "PROTECTED" : "UNPROTECTED"); fprintf (out, "SystemStatus %s\n", listed ? "LISTED" : "UNLISTED"); fprintf (out, "CallerID %s\n", peer_name); fprintf (out, "SessionType OTHER\n"); fclose (out); return 1; } return 0; } static FTNQ *parse_response (FTNQ *q, char *rsp, FTN_ADDR *fa) { FILE *in = fopen (rsp, "r"); if (in) { char buf[MAXPATHLEN + 1]; int i; while (!feof (in)) { if (!fgets (buf, MAXPATHLEN, in)) break; for (i = 0; i < sizeof (buf) - 1 && !isspace (buf[i]); ++i); buf[i] = 0; Log (4, "parse_response: add file `%s' to queue", buf + 1); switch (*buf) { case '=': q = q_add_last_file (q, buf + 1, fa, 'h', 'd', 0); break; case '+': q = q_add_last_file (q, buf + 1, fa, 'h', 0, 0); break; case '-': q = q_add_last_file (q, buf + 1, fa, 'h', 'a', 0); break; default: Log (2, "parse_response: unknown predictor `%c', ignored response file `%s'", *buf, buf + 1); break; } } if (ftell (in) == 0) Log (3, "SRIF response file is empty"); fclose (in); } else Log (1, "parse_response: %s: %s", rsp, strerror (errno)); return q; } static char valid_filename_chars[]=".\\-_:/@"; static EVTQ *run_args(EVTQ *eq, char *cmd, char *filename0, FTN_ADDR *fa, int nfa, int prot, int listed, char *peer_name, STATE *st, int imm) { char *sp, *w; char *fn=filename0; char *pn=peer_name?peer_name:""; char ipaddr[16]; char aka[4]; char adr[FTN_ADDR_SZ + 2]; int i; unsigned int l; size_t sw=1024; int use_fn=0; for(i=0;fn[i];i++) if((!isalnum(fn[i])) && (!strchr(valid_filename_chars, fn[i]))) { fn="-"; Log(4, "Invalid filename (%s) received!", filename0); break; } for(i=0;pn[i];i++) if((!isalnum(pn[i])) && (!strchr(valid_filename_chars, pn[i]))) { i=0; break; } if(!i) { struct sockaddr_in sin; socklen_t si = sizeof (struct sockaddr_in); if((!st) || (getpeername (st->s, (struct sockaddr *) &sin, &si) == -1)) strcpy(ipaddr, "-"); else /* We don't like inet_ntoa ;-) */ { sin.sin_addr.s_addr=htonl(sin.sin_addr.s_addr); sprintf(ipaddr, "%d.%d.%d.%d", (int)(sin.sin_addr.s_addr>>24), (int)((sin.sin_addr.s_addr>>16)&0xFF), (int)((sin.sin_addr.s_addr>>8)&0xFF), (int)(sin.sin_addr.s_addr&0xFF)); } pn=ipaddr; } if(sw<=strlen(cmd)) sw=strlen(cmd)+1; w=(char*)xalloc(sw); strcpy(w, cmd); strcpy(aka, "*A0"); for(l=0; (lMAXPATHLEN)) { Log(2, "GetShortPathName() fails %d", GetLastError()); use_fn=1; strcpy(ts, fn); } w = ed (w, "*N", ts, &sw); break; } #endif use_fn=1; w = ed (w, "*N", fn, &sw); break; case 'F': /* filename */ use_fn=1; w = ed (w, "*F", fn, &sw); break; case 'A': /* AKA */ if (sp[2] == '@' || sp[2] == '*') { char *pa, *addrlist; pa = addrlist = malloc(nfa*(FTN_ADDR_SZ+1l)); if (addrlist == NULL) { Log(1, "Not enough memory, %ld bytes needed", nfa*(FTN_ADDR_SZ+1l)); break; } for (i=0; inext) { if (curr->command && pmatch (curr->pattern, filename)) { if (strstr (curr->command, "*S") || strstr (curr->command, "*s")) { if (!st) { char srf[MAXPATHLEN + 1], rsp[MAXPATHLEN + 1]; if (mksrifpaths (fa, srf, rsp)) { char *w = ed (curr->command, "*S", srf, NULL); if (srif_fill (srf, fa, nfa, filename0, rsp, prot, listed, peer_name)) { if (!run_args (NULL, w, filename0, fa, nfa, prot, listed, peer_name, st, 1)) delete(filename0); } else Log (1, "srif_fill: error"); free (w); q = parse_response (q, rsp, fa); delete (srf); delete (rsp); } else Log (1, "mksrifpaths: error"); } } else *eq = run_args(*eq, curr->command, filename0, fa, nfa, prot, listed, peer_name, st, curr->imm); } } return q; }