Changeset 2204 for trunk/auto-reply

Show
Ignore:
Timestamp:
08/16/00 08:39:45 (8 years ago)
Author:
graham
Message:

Try sending direct first, if that fails then send through the server.
Added "Arguments" option to allow passing the user alias/uin etc to the
command.
Added "PassMessage?" option to allow passing the actual event text to the
standard input of the command.

Location:
trunk/auto-reply
Files:
5 modified

Legend:

Unmodified
Added
Removed
  • trunk/auto-reply/configure.in

    r2013 r2204  
    66 
    77dnl All versioning is done via the following line 
    8 AM_INIT_AUTOMAKE(Licq-AutoReply, 0.17) 
     8AM_INIT_AUTOMAKE(Licq-AutoReply, 1.0) 
    99AM_CONFIG_HEADER(config.h) 
    1010 
     
    3636dnl Checks for header files. 
    3737AC_HEADER_STDC 
    38 AC_CHECK_HEADERS(errno.h pwd.h sys/time.h) 
     38AC_CHECK_HEADERS(errno.h pwd.h sys/time.h paths.h) 
    3939AC_HEADER_TIME 
    4040LICQ_SYS_ERRLIST 
  • trunk/auto-reply/licq_autoreply.conf

    r794 r2204  
    22# Edit and copy to ~/.licq 
    33 
    4 # the program to run for output to send in the message 
    54[Reply] 
    6 Program=/usr/games/fortune 
     5# The program to run for output to send in the message. 
     6# "talkback" might be any program or script. 
     7Program = talkback 
    78 
     9# This is a string which will be parsed for user % symbols 
     10# and then appended to the above command. 
     11# This example passes the uin and then the alias in quotes 
     12# So the final command might be: 
     13#   talkback -u 3456789 -a 'coolguy' 
     14# WARNING: be careful passing the alias, name etc as they could 
     15#          contain exploits such as "evil_alias; rm -rf ~". 
     16#          Always quote anything that could contain text. 
     17Arguments = -u %u -a '%a' 
     18 
     19# This flag tells the plugin whether or not the command 
     20# expects the incoming message as standard input 
     21# If set to 1 then the program will be fed the incoming 
     22# message to standard input. 
     23PassMessage = 0 
     24 
     25 
     26# Here is a simple example which will bounce the event 
     27# right back to the user: 
     28# 
     29# Program = cat 
     30# Arguments =  
     31# PassMessage = 1 
     32# 
     33# 
     34# Here is an example which simply sends a fortune back to 
     35# the user: 
     36# 
     37# Program = /usr/games/fortune 
     38# Arguments = 
     39# PassMessage = 0 
     40# 
     41 
  • trunk/auto-reply/src/autoreply.cpp

    r2099 r2204  
    77#include <stdio.h> 
    88#include <stdlib.h> 
     9#include <sys/wait.h> 
     10#include <sys/time.h> 
     11#include <signal.h> 
    912#ifdef HAVE_ERRNO_H 
    1013#include <errno.h> 
     
    1215extern int errno; 
    1316#endif 
     17#ifdef HAVE_PATHS_H 
     18#include <paths.h> 
     19#else 
     20#define _PATH_BSHELL "/bin/sh" 
     21#endif 
     22 
    1423 
    1524#include "autoreply.h" 
     
    7483  conf.SetSection("Reply"); 
    7584  conf.ReadStr("Program", m_szProgram); 
     85  conf.ReadStr("Arguments", m_szArguments, ""); 
     86  conf.ReadBool("PassMessage", m_bPassMessage, false); 
    7687  conf.CloseFile(); 
    7788 
     
    194205void CLicqAutoReply::ProcessEvent(ICQEvent *e) 
    195206{ 
     207  CUserEvent *user_event; 
     208 
     209  if (e->Result() != EVENT_ACKED) 
     210  { 
     211    if (e->Command() == ICQ_CMDxTCP_START && 
     212        (e->SubCommand() != ICQ_CMDxSUB_CHAT && 
     213         e->SubCommand() != ICQ_CMDxSUB_FILE)) 
     214    { 
     215        user_event = e->UserEvent(); 
     216      CICQEventTag *tag = licqDaemon->icqSendMessage(e->Uin(), user_event->Text(), false, 
     217        ICQ_TCPxMSG_URGENT); //urgent, because, hey, he asked us, right? 
     218        delete tag; 
     219    } 
     220  } 
     221 
    196222  delete e; 
    197223} 
     
    216242  else 
    217243  { 
    218     bool r = AutoReplyEvent(nUin); 
     244    bool r = AutoReplyEvent(nUin, e); 
    219245    if (m_bDelete && r) 
    220246    { 
     
    227253 
    228254 
    229 bool CLicqAutoReply::AutoReplyEvent(unsigned long nUin) 
    230 { 
    231   FILE *output; 
    232   char m_szMessage[4096]; 
     255bool CLicqAutoReply::AutoReplyEvent(unsigned long nUin, CUserEvent *event) 
     256{ 
     257  char m_szMessage[4096], szCommand[4096]; 
    233258  char c; 
    234259  int pos = 0; 
     
    238263    m_szMessage[i] = '\0'; 
    239264  } 
    240   output = popen (m_szProgram, "r"); 
    241   if (!output) 
    242   { 
    243     gLog.Warn("%sCould not execute %s\n", L_AUTOREPxSTR, m_szProgram); 
     265 
     266  char *buf = szCommand; 
     267  buf += sprintf(buf, "%s ", m_szProgram); 
     268  ICQUser *u = gUserManager.FetchUser(nUin, LOCK_R); 
     269  u->usprintf(buf, m_szArguments); 
     270  gUserManager.DropUser(u); 
     271 
     272  if (!POpen(szCommand)) 
     273  { 
     274    gLog.Warn("%sCould not execute %s\n", L_AUTOREPxSTR, szCommand); 
    244275    return false; 
    245276  } 
    246   while (((c = fgetc(output)) != EOF) && (pos < 4096)) 
     277  if (m_bPassMessage) 
     278  { 
     279    fprintf(fStdIn, "%s\n", event->Text()); 
     280    fclose(fStdIn); 
     281    fStdIn = NULL; 
     282  } 
     283 
     284  while (((c = fgetc(fStdOut)) != EOF) && (pos < 4096)) 
    247285  { 
    248286    m_szMessage[pos++] = c; 
    249287  } 
    250   pclose (output); 
     288  PClose(); 
     289 
    251290  char *szText = new char[4096 + 256]; 
    252291  sprintf(szText, "%s", m_szMessage); 
    253   CICQEventTag *tag = licqDaemon->icqSendMessage(nUin, szText, false, 
    254      ICQ_TCPxMSG_NORMAL); 
     292  CICQEventTag *tag = licqDaemon->icqSendMessage(nUin, szText, true, 
     293     ICQ_TCPxMSG_URGENT); 
    255294  delete []szText; 
    256295 
    257   ICQUser *u = gUserManager.FetchUser(nUin, LOCK_R); 
     296  u = gUserManager.FetchUser(nUin, LOCK_R); 
    258297  if (u == NULL) return false; 
    259298 
     
    274313} 
    275314 
     315 
     316 
     317bool CLicqAutoReply::POpen(const char *cmd) 
     318{ 
     319  int pdes_out[2], pdes_in[2]; 
     320 
     321  if (pipe(pdes_out) < 0) return false; 
     322  if (pipe(pdes_in) < 0) return false; 
     323 
     324  switch (pid = fork()) 
     325  { 
     326    case -1:                        /* Error. */ 
     327    { 
     328      close(pdes_out[0]); 
     329      close(pdes_out[1]); 
     330      close(pdes_in[0]); 
     331      close(pdes_in[1]); 
     332      return false; 
     333      /* NOTREACHED */ 
     334    } 
     335    case 0:                         /* Child. */ 
     336    { 
     337      if (pdes_out[1] != STDOUT_FILENO) 
     338      { 
     339        dup2(pdes_out[1], STDOUT_FILENO); 
     340        close(pdes_out[1]); 
     341      } 
     342      close(pdes_out[0]); 
     343      if (pdes_in[0] != STDIN_FILENO) 
     344      { 
     345        dup2(pdes_in[0], STDIN_FILENO); 
     346        close(pdes_in[0]); 
     347      } 
     348      close(pdes_in[1]); 
     349      execl(_PATH_BSHELL, "sh", "-c", cmd, NULL); 
     350      _exit(127); 
     351      /* NOTREACHED */ 
     352    } 
     353  } 
     354 
     355  /* Parent; assume fdopen can't fail. */ 
     356  fStdOut = fdopen(pdes_out[0], "r"); 
     357  close(pdes_out[1]); 
     358  fStdIn = fdopen(pdes_in[1], "w"); 
     359  close(pdes_in[0]); 
     360 
     361  // Set both streams to line buffered 
     362  setvbuf(fStdOut, (char*)NULL, _IOLBF, 0); 
     363  setvbuf(fStdIn, (char*)NULL, _IOLBF, 0); 
     364 
     365  return true; 
     366} 
     367 
     368 
     369void CLicqAutoReply::PClose() 
     370{ 
     371   int r, pstat; 
     372 
     373   // Close the file descriptors 
     374   if (fStdOut != NULL) fclose(fStdOut); 
     375   if (fStdIn != NULL) fclose(fStdIn); 
     376   fStdOut = fStdIn = NULL; 
     377 
     378   // See if the child is still there 
     379   r = waitpid(pid, &pstat, WNOHANG); 
     380   // Return if child has exited or there was an inor 
     381   if (r == pid || r == -1) return; 
     382 
     383   // Give the process another .2 seconds to die 
     384   struct timeval tv = { 0, 200000 }; 
     385   select(0, NULL, NULL, NULL, &tv); 
     386 
     387   // Still there? 
     388   r = waitpid(pid, &pstat, WNOHANG); 
     389   if (r == pid || r == -1) return; 
     390 
     391   // Try and kill the process 
     392   if (kill(pid, SIGTERM) == -1) return; 
     393 
     394   // Give it 1 more second to die 
     395   tv.tv_sec = 1; 
     396   tv.tv_usec = 0; 
     397   select(0, NULL, NULL, NULL, &tv); 
     398 
     399   // See if the child is still there 
     400   r = waitpid(pid, &pstat, WNOHANG); 
     401   if (r == pid || r == -1) return; 
     402 
     403   // Kill the bastard 
     404   kill(pid, SIGKILL); 
     405   // Now he will die for sure 
     406   waitpid(pid, &pstat, 0); 
     407} 
     408 
     409 
  • trunk/auto-reply/src/autoreply.h

    r2099 r2204  
    2626  bool m_bExit, m_bEnabled, m_bDelete; 
    2727  char *m_szStatus; 
    28   char m_szProgram[512]; 
     28  char m_szProgram[512], m_szArguments[512]; 
     29  bool m_bPassMessage; 
    2930 
    3031  CICQDaemon *licqDaemon; 
     
    3738 
    3839  void ProcessUserEvent(unsigned long, unsigned long); 
    39   bool AutoReplyEvent(unsigned long); 
     40  bool AutoReplyEvent(unsigned long, CUserEvent *); 
     41 
     42  bool POpen(const char *cmd); 
     43  void PClose(); 
     44 
     45protected: 
     46  int pid; 
     47  FILE *fStdOut; 
     48  FILE *fStdIn; 
    4049 
    4150}; 
  • trunk/auto-reply/src/main.cpp

    r2154 r2204  
    4242const char *LP_Version() 
    4343{ 
    44   static const char version[] = "0.17"; 
     44  static const char version[] = "1.00"; 
    4545  return version; 
    4646}