@@ -108,3 +108,107 @@ int subprocess_start(struct hashmap *hashmap, struct subprocess_entry *entry, co
108108 hashmap_add (hashmap , entry );
109109 return 0 ;
110110}
111+
112+ static int handshake_version (struct child_process * process ,
113+ const char * welcome_prefix , int * versions ,
114+ int * chosen_version )
115+ {
116+ int version_scratch ;
117+ int i ;
118+ char * line ;
119+ const char * p ;
120+
121+ if (!chosen_version )
122+ chosen_version = & version_scratch ;
123+
124+ if (packet_write_fmt_gently (process -> in , "%s-client\n" ,
125+ welcome_prefix ))
126+ return error ("Could not write client identification" );
127+ for (i = 0 ; versions [i ]; i ++ ) {
128+ if (packet_write_fmt_gently (process -> in , "version=%d\n" ,
129+ versions [i ]))
130+ return error ("Could not write requested version" );
131+ }
132+ if (packet_flush_gently (process -> in ))
133+ return error ("Could not write flush packet" );
134+
135+ if (!(line = packet_read_line (process -> out , NULL )) ||
136+ !skip_prefix (line , welcome_prefix , & p ) ||
137+ strcmp (p , "-server" ))
138+ return error ("Unexpected line '%s', expected %s-server" ,
139+ line ? line : "<flush packet>" , welcome_prefix );
140+ if (!(line = packet_read_line (process -> out , NULL )) ||
141+ !skip_prefix (line , "version=" , & p ) ||
142+ strtol_i (p , 10 , chosen_version ))
143+ return error ("Unexpected line '%s', expected version" ,
144+ line ? line : "<flush packet>" );
145+ if ((line = packet_read_line (process -> out , NULL )))
146+ return error ("Unexpected line '%s', expected flush" , line );
147+
148+ /* Check to make sure that the version received is supported */
149+ for (i = 0 ; versions [i ]; i ++ ) {
150+ if (versions [i ] == * chosen_version )
151+ break ;
152+ }
153+ if (!versions [i ])
154+ return error ("Version %d not supported" , * chosen_version );
155+
156+ return 0 ;
157+ }
158+
159+ static int handshake_capabilities (struct child_process * process ,
160+ struct subprocess_capability * capabilities ,
161+ unsigned int * supported_capabilities )
162+ {
163+ int i ;
164+ char * line ;
165+
166+ for (i = 0 ; capabilities [i ].name ; i ++ ) {
167+ if (packet_write_fmt_gently (process -> in , "capability=%s\n" ,
168+ capabilities [i ].name ))
169+ return error ("Could not write requested capability" );
170+ }
171+ if (packet_flush_gently (process -> in ))
172+ return error ("Could not write flush packet" );
173+
174+ while ((line = packet_read_line (process -> out , NULL ))) {
175+ const char * p ;
176+ if (!skip_prefix (line , "capability=" , & p ))
177+ continue ;
178+
179+ for (i = 0 ;
180+ capabilities [i ].name && strcmp (p , capabilities [i ].name );
181+ i ++ )
182+ ;
183+ if (capabilities [i ].name ) {
184+ if (supported_capabilities )
185+ * supported_capabilities |= capabilities [i ].flag ;
186+ } else {
187+ warning ("external filter requested unsupported filter capability '%s'" ,
188+ p );
189+ }
190+ }
191+
192+ return 0 ;
193+ }
194+
195+ int subprocess_handshake (struct subprocess_entry * entry ,
196+ const char * welcome_prefix ,
197+ int * versions ,
198+ int * chosen_version ,
199+ struct subprocess_capability * capabilities ,
200+ unsigned int * supported_capabilities )
201+ {
202+ int retval ;
203+ struct child_process * process = & entry -> process ;
204+
205+ sigchain_push (SIGPIPE , SIG_IGN );
206+
207+ retval = handshake_version (process , welcome_prefix , versions ,
208+ chosen_version ) ||
209+ handshake_capabilities (process , capabilities ,
210+ supported_capabilities );
211+
212+ sigchain_pop (SIGPIPE );
213+ return retval ;
214+ }
0 commit comments