1 /* CWirc - X-Chat plugin for sending and receiving raw morse code over IRC
2    (c) Pierre-Philippe Coupard - 18/06/2003
3 
4    CWirc extensions routines
5 
6    This program is distributed under the terms of the GNU General Public License
7    See the COPYING file for details
8 */
9 #include <stdio.h>
10 #include <string.h>
11 #include <unistd.h>
12 #include <dirent.h>
13 #include <sys/stat.h>
14 #include <sys/types.h>
15 
16 #include "types.h"
17 #include "cwirc.h"
18 #include "extension.h"
19 #include "ipc.h"
20 #include "common.h"
21 
22 
23 
24 /* Variables */
25 char cwirc_extensions[MAX_CWIRC_EXTENSIONS][FILENAME_MAX];
26 
27 
28 
29 /* Browse the CWirc extensions directory and store filenames present there */
get_available_cwirc_extensions(void)30 void get_available_cwirc_extensions(void)
31 {
32   DIR *extdir;
33   struct dirent *dirent;
34   struct stat statbuf;
35   char fullpathname[FILENAME_MAX];
36   int i;
37 
38   /* Initialize the extensions table */
39   for(i=0;i<MAX_CWIRC_EXTENSIONS;i++)
40     cwirc_extensions[i][0]=0;
41 
42   /* Open the extensions directory */
43   if((extdir=opendir(EXTENSIONS_DIR))==NULL)
44     return;
45 
46   /* Browse the content of the directory */
47   for(i=0;i<MAX_CWIRC_EXTENSIONS && (dirent=readdir(extdir))!=NULL;)
48   {
49     /* Is the directory entry an executable file ? */
50     sprintf(fullpathname,"%s/%s",EXTENSIONS_DIR,dirent->d_name);
51     if(stat(fullpathname,&statbuf)!=-1 && S_ISREG(statbuf.st_mode) &&
52 	!access(fullpathname,X_OK))
53     {
54       strncpy(cwirc_extensions[i],dirent->d_name,FILENAME_MAX-1);
55       cwirc_extensions[i][FILENAME_MAX-1]=0;
56       i++;
57     }
58   }
59 
60   /* Close the directory */
61   closedir(extdir);
62 }
63 
64 
65 
66 /* Execute an extension program, passing it "--cwirc" as first argument, and
67    the extension API's shared memory id as second argument. Return NULL or
68    an error message. */
exec_extension_program(char * fname,int ext_shmid)69 char *exec_extension_program(char *fname,int ext_shmid)
70 {
71   static char errmsg[64];
72   struct cwirc_extension_api *ext_sharedmem;
73   char fullpathname[FILENAME_MAX];
74   int pid;
75 
76   /* Attach to the extension API's shared memory block */
77   if((ext_sharedmem=(struct cwirc_extension_api *)cwirc_shm_attach(ext_shmid))
78 	==(struct cwirc_extension_api *)-1)
79   {
80     strcpy(errmsg,"Error : can't attach to the extension API's shared memory.");
81     return(errmsg);
82   }
83 
84   /* If an extension process is already running, abort */
85   if(ext_sharedmem->pid!=-1)
86   {
87     cwirc_shm_detach(ext_sharedmem);
88     strcpy(errmsg,"An extension program is already running.");
89     return(errmsg);
90   }
91 
92   /* Spawn the extension program */
93   switch((pid=fork()))
94   {
95   case -1:
96     strcpy(errmsg,"Error : fork() : Cannot spawn the extension process.");
97     return(errmsg);
98     break;
99 
100   case 0:		/* I'm the child */
101     /* Close the extension program's stdout so it doesn't trickle down to the
102        X-Chat window */
103     close(1);
104 
105     /* Detach from the extension API's shared memory block */
106     cwirc_shm_detach(ext_sharedmem);
107 
108     /* Execute the extension program */
109     sprintf(errmsg,"0x%0x",ext_shmid);	/* Reuse errmsg to store the shm id */
110     sprintf(fullpathname,"%s/%s",EXTENSIONS_DIR,fname);
111     execl(fullpathname,fname,"--cwirc",errmsg,NULL);
112     fprintf(stderr,"Error : cannot execute \"%s\".\n",fullpathname);
113     fflush(stderr);
114     sleep(1);	/* Give the parent a change to catch us dying prematurely */
115     _exit(0);
116     break;
117   }
118 
119   ext_sharedmem->pid=pid;
120 
121   /* Detach from the extension API's shared memory block */
122   cwirc_shm_detach(ext_sharedmem);
123 
124   return(NULL);
125 }
126