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