53637e174e031eaa3b4bb5fcef9e870f4ccbd6dd
[gnupg.git] / tools / shmtest.c
1 /* shmtest.c
2  *
3  */
4
5 #include <config.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <errno.h>
10 #include <signal.h>
11 #include <unistd.h>
12 #ifdef HAVE_SYS_IPC_H
13   #include <sys/ipc.h>
14 #endif
15 #ifdef HAVE_SYS_SHM_H
16   #include <sys/shm.h>
17 #endif
18 #include "util.h"
19 #include "ttyio.h"
20 #include "i18n.h"
21
22 #ifdef __MINGW32__
23 int main( int argc, char **argv )
24 {
25     fprintf(stderr, "Sorry, not yet available for Windoze\n");
26     exit(1);
27 }
28 #else
29
30 static int serverpid = -1;
31
32 static void
33 my_usage(void)
34 {
35     fprintf(stderr, "usage: shmtest gpg-command-line\n");
36     exit(1);
37 }
38
39 const char *
40 strusage( int level )
41 {
42     return default_strusage(level);
43 }
44
45 static void
46 i18n_init(void)
47 {
48   #ifdef ENABLE_NLS
49     #ifdef HAVE_LC_MESSAGES
50        setlocale( LC_MESSAGES, "" );
51     #else
52        setlocale( LC_ALL, "" );
53     #endif
54     bindtextdomain( PACKAGE, G10_LOCALEDIR );
55     textdomain( PACKAGE );
56   #endif
57 }
58
59
60 static void
61 do_get_string( int mode, const char *keyword, byte *area, size_t areasize )
62 {
63     size_t n, len;
64     char *p=NULL;
65     int yes=0;
66
67     n = area[0] << 8 | area[1];
68     /* fixme: do some sanity checks here */
69     if( mode == 1 )
70         p = tty_get( keyword );
71     else if( mode == 3 )
72         p = tty_get_hidden( keyword );
73     else
74         yes = tty_get_answer_is_yes( keyword );
75     if( p ) {
76         len = strlen(p);
77         memcpy( area+n+2, p, len );
78         area[n] = len >> 8;
79         area[n+1] = len;
80         m_free(p);
81     }
82     else { /* bool */
83         area[n] = 0;
84         area[n+1] = 1;
85         area[n+2] = yes;
86     }
87     area[3] = 1; /* we should better use a semaphore */
88     kill( serverpid, SIGUSR1 );
89 }
90
91
92
93 int
94 main(int argc, char **argv)
95 {
96     void  *area = NULL;
97     size_t areasize = 4096;
98     int shm_id = -1;
99     FILE *fp;
100     char buf[200];
101     char *p, *p2;
102     size_t n;
103     int i;
104
105     log_set_name("shmtest");
106     i18n_init();
107   #ifndef USE_SHM_COPROCESSING
108     log_info("SHM_COPRPOCESSING is not available\n");
109   #else
110     if( argc < 1 )
111         my_usage();
112
113     for(n=0,i=1; i < argc; i++ )
114         n += strlen(argv[i]) + 1;
115     p = m_alloc( 100 + n );
116     strcpy( p, "../g10/gpg --status-fd 1 --run-as-shm-coprocess 0");
117     for(i=1; i < argc; i++ ) {
118         strcat(p, " " );
119         strcat(p, argv[i] );
120     }
121
122     fp = popen( p, "r" );
123     m_free( p );
124     if( !fp )
125         log_error("popen failed: %s\n", strerror(errno));
126
127     while ( fgets (buf, sizeof (buf) - 1, fp ) != NULL ) {
128         size_t len = strlen(buf);
129         if( len >= 9 && !memcmp( buf, "[GNUPG:] ", 9 ) ) {
130             int word=0;
131             int is_info = 0, is_get = 0;
132
133             for( p = strtok(buf+9, " \n"); p ; p = strtok(NULL, " \n")) {
134                 word++;
135                 if( word==1 && !strcmp(p,"SHM_INFO") ) {
136                     if( !area )
137                         is_info=1;
138                     else
139                         log_error("duplicate SHM_INFO ignored\n" );
140                 }
141                 else if( is_info && (p2 = strchr(p, '=' )) ) {
142                     int val;
143                     *p2++ = 0;
144                     val = atoi(p2); /* should be atou() for some values */
145                     if( !strcmp(p, "pv" ) ) {
146                         if( atoi(p2) != 1 )
147                             log_fatal("invalid protocol version %d\n", val );
148                         is_info = 2;
149                     }
150                     else if( !strcmp(p, "pid" ) )
151                         serverpid = val;
152                     else if( !strcmp(p, "shmid" ) )
153                         shm_id = val;
154                 }
155                 else if( word == 1 && !strcmp(p,"SHM_GET") )
156                     is_get = 1;
157                 else if( word == 1 && !strcmp(p,"SHM_GET_BOOL") )
158                     is_get = 2;
159                 else if( word == 1 && !strcmp(p,"SHM_GET_HIDDEN") )
160                     is_get = 3;
161                 else if( word == 2 && is_get )  {
162                     do_get_string( is_get, p, area, areasize );
163                     break;
164                 }
165                 else if( word == 1 )
166                     log_info("Status: %s\n", p);
167             }
168             if( is_info ) {
169                 if( is_info < 2 )
170                     log_fatal("SHM info without protocol version\n");
171                 if( serverpid == -1 )
172                     log_fatal("SHM info without server's pid\n");
173                 if( shm_id == -1 )
174                     log_fatal("SHM info without id\n");
175                 log_info("Shared memory info: server=%d shm_id=%d\n",
176                                                             serverpid, shm_id);
177                 area = shmat( shm_id, 0, 0 );
178                 if( area == (void*)-1 )
179                     log_fatal("attach to shared memory failed: %s\n",
180                                                             strerror(errno));
181             }
182         }
183         else
184             fputs (buf, stdout);
185     }
186
187
188     if( pclose(fp) )
189         log_error("pclose failed\n");
190
191     return 0;
192   #endif
193 }
194
195
196 #endif /* !__MINGW32__ */