1/* result.c - sock backend result reading function */
2/* $OpenLDAP$ */
3/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 *
5 * Copyright 2007-2011 The OpenLDAP Foundation.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted only as authorized by the OpenLDAP
10 * Public License.
11 *
12 * A copy of this license is available in the file LICENSE in the
13 * top-level directory of the distribution or, alternatively, at
14 * <http://www.OpenLDAP.org/license.html>.
15 */
16/* ACKNOWLEDGEMENTS:
17 * This work was initially developed by Brian Candler for inclusion
18 * in OpenLDAP Software.
19 */
20
21#include "portable.h"
22
23#include <stdio.h>
24
25#include <ac/errno.h>
26#include <ac/string.h>
27#include <ac/socket.h>
28#include <ac/unistd.h>
29
30#include "slap.h"
31#include "back-sock.h"
32
33/*
34 * FIXME: make a RESULT section compulsory from the socket response.
35 * Otherwise, a partial/aborted response is treated as 'success'.
36 * This is a divergence from the back-shell protocol, but makes things
37 * more robust.
38 */
39
40int
41sock_read_and_send_results(
42    Operation	*op,
43    SlapReply	*rs,
44    FILE	*fp )
45{
46	int	bsize, len;
47	char	*buf, *bp;
48	char	line[BUFSIZ];
49	char	ebuf[128];
50
51	/* read in the result and send it along */
52	buf = (char *) ch_malloc( BUFSIZ );
53	buf[0] = '\0';
54	bsize = BUFSIZ;
55	bp = buf;
56	while ( !feof(fp) ) {
57		errno = 0;
58		if ( fgets( line, sizeof(line), fp ) == NULL ) {
59			if ( errno == EINTR ) continue;
60
61			Debug( LDAP_DEBUG_ANY, "sock: fgets failed: %s (%d)\n",
62				AC_STRERROR_R(errno, ebuf, sizeof ebuf), errno, 0 );
63			break;
64		}
65
66		Debug( LDAP_DEBUG_SHELL, "sock search reading line (%s)\n",
67		    line, 0, 0 );
68
69		/* ignore lines beginning with # (LDIFv1 comments) */
70		if ( *line == '#' ) {
71			continue;
72		}
73
74		/* ignore lines beginning with DEBUG: */
75		if ( strncasecmp( line, "DEBUG:", 6 ) == 0 ) {
76			continue;
77		}
78
79		len = strlen( line );
80		while ( bp + len + 1 - buf > bsize ) {
81			size_t offset = bp - buf;
82			bsize += BUFSIZ;
83			buf = (char *) ch_realloc( buf, bsize );
84			bp = &buf[offset];
85		}
86		strcpy( bp, line );
87		bp += len;
88
89		/* line marked the end of an entry or result */
90		if ( *line == '\n' ) {
91			if ( strncasecmp( buf, "RESULT", 6 ) == 0 ) {
92				break;
93			}
94			if ( strncasecmp( buf, "CONTINUE", 8 ) == 0 ) {
95				struct sockinfo	*si = (struct sockinfo *) op->o_bd->be_private;
96				/* Only valid when operating as an overlay! */
97				assert( si->si_ops != 0 );
98				rs->sr_err = SLAP_CB_CONTINUE;
99				goto skip;
100			}
101
102			if ( (rs->sr_entry = str2entry( buf )) == NULL ) {
103				Debug( LDAP_DEBUG_ANY, "str2entry(%s) failed\n",
104				    buf, 0, 0 );
105			} else {
106				rs->sr_attrs = op->oq_search.rs_attrs;
107				rs->sr_flags = REP_ENTRY_MODIFIABLE;
108				send_search_entry( op, rs );
109				entry_free( rs->sr_entry );
110				rs->sr_attrs = NULL;
111			}
112
113			bp = buf;
114		}
115	}
116	(void) str2result( buf, &rs->sr_err, (char **)&rs->sr_matched, (char **)&rs->sr_text );
117
118	/* otherwise, front end will send this result */
119	if ( rs->sr_err != 0 || op->o_tag != LDAP_REQ_BIND ) {
120		send_ldap_result( op, rs );
121	}
122
123skip:
124	ch_free( buf );
125
126	return( rs->sr_err );
127}
128
129void
130sock_print_suffixes(
131    FILE	*fp,
132    Backend	*be
133)
134{
135	int	i;
136
137	for ( i = 0; be->be_suffix[i].bv_val != NULL; i++ ) {
138		fprintf( fp, "suffix: %s\n", be->be_suffix[i].bv_val );
139	}
140}
141
142void
143sock_print_conn(
144    FILE	*fp,
145    Connection	*conn,
146    struct sockinfo *si
147)
148{
149	if ( conn == NULL ) return;
150
151	if( si->si_extensions & SOCK_EXT_BINDDN ) {
152		fprintf( fp, "binddn: %s\n",
153			conn->c_dn.bv_len ? conn->c_dn.bv_val : "" );
154	}
155	if( si->si_extensions & SOCK_EXT_PEERNAME ) {
156		fprintf( fp, "peername: %s\n",
157			conn->c_peer_name.bv_len ? conn->c_peer_name.bv_val : "" );
158	}
159	if( si->si_extensions & SOCK_EXT_SSF ) {
160		fprintf( fp, "ssf: %d\n", conn->c_ssf );
161	}
162	if( si->si_extensions & SOCK_EXT_CONNID ) {
163		fprintf( fp, "connid: %lu\n", conn->c_connid );
164	}
165}
166