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