1/* $OpenLDAP$ */
2/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3 *
4 * Copyright 1998-2011 The OpenLDAP Foundation.
5 * Portions Copyright 1998-2003 Kurt D. Zeilenga.
6 * Portions Copyright 2003 IBM Corporation.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted only as authorized by the OpenLDAP
11 * Public License.
12 *
13 * A copy of this license is available in file LICENSE in the
14 * top-level directory of the distribution or, alternatively, at
15 * <http://www.OpenLDAP.org/license.html>.
16 */
17/* ACKNOWLEDGEMENTS:
18 * This work was initially developed by Kurt Zeilenga for inclusion
19 * in OpenLDAP Software.  Additional signficant contributors include
20 *    Jong Hyuk Choi
21 */
22
23#include "portable.h"
24
25#include <stdio.h>
26
27#include <ac/stdlib.h>
28#include <ac/ctype.h>
29#include <ac/socket.h>
30#include <ac/string.h>
31
32#include "slapcommon.h"
33#include "ldif.h"
34
35static volatile sig_atomic_t gotsig;
36
37static RETSIGTYPE
38slapcat_sig( int sig )
39{
40	gotsig=1;
41}
42
43int
44slapcat( int argc, char **argv )
45{
46	ID id;
47	int rc = EXIT_SUCCESS;
48	Operation op = {0};
49	const char *progname = "slapcat";
50	int requestBSF;
51	int doBSF = 0;
52
53	slap_tool_init( progname, SLAPCAT, argc, argv );
54
55	requestBSF = ( sub_ndn.bv_len || filter );
56
57#ifdef SIGPIPE
58	(void) SIGNAL( SIGPIPE, slapcat_sig );
59#endif
60#ifdef SIGHUP
61	(void) SIGNAL( SIGHUP, slapcat_sig );
62#endif
63	(void) SIGNAL( SIGINT, slapcat_sig );
64	(void) SIGNAL( SIGTERM, slapcat_sig );
65
66	if( !be->be_entry_open ||
67		!be->be_entry_close ||
68		!( be->be_entry_first_x || be->be_entry_first ) ||
69		!be->be_entry_next ||
70		!be->be_entry_get )
71	{
72		fprintf( stderr, "%s: database doesn't support necessary operations.\n",
73			progname );
74		exit( EXIT_FAILURE );
75	}
76
77	if( be->be_entry_open( be, 0 ) != 0 ) {
78		fprintf( stderr, "%s: could not open database.\n",
79			progname );
80		exit( EXIT_FAILURE );
81	}
82
83	op.o_bd = be;
84	if ( !requestBSF && be->be_entry_first ) {
85		id = be->be_entry_first( be );
86
87	} else {
88		if ( be->be_entry_first_x ) {
89			id = be->be_entry_first_x( be,
90				sub_ndn.bv_len ? &sub_ndn : NULL, scope, filter );
91
92		} else {
93			assert( be->be_entry_first != NULL );
94			doBSF = 1;
95			id = be->be_entry_first( be );
96		}
97	}
98
99	for ( ; id != NOID; id = be->be_entry_next( be ) )
100	{
101		char *data;
102		int len;
103		Entry* e;
104
105		if ( gotsig )
106			break;
107
108		e = be->be_entry_get( be, id );
109		if ( e == NULL ) {
110			printf("# no data for entry id=%08lx\n\n", (long) id );
111			rc = EXIT_FAILURE;
112			if ( continuemode == 0 ) {
113				break;
114
115			} else if ( continuemode == 1 ) {
116				continue;
117			}
118
119			/* this is a last resort: linearly scan all ids
120			 * trying to recover as much as possible (ITS#6482) */
121			while ( ++id != NOID ) {
122				e = be->be_entry_get( be, id );
123				if ( e != NULL ) break;
124				printf("# no data for entry id=%08lx\n\n", (long) id );
125			}
126
127			if ( e == NULL ) break;
128		}
129
130		if ( doBSF ) {
131			if ( sub_ndn.bv_len && !dnIsSuffixScope( &e->e_nname, &sub_ndn, scope ) )
132			{
133				be_entry_release_r( &op, e );
134				continue;
135			}
136
137
138			if ( filter != NULL ) {
139				int rc = test_filter( NULL, e, filter );
140				if ( rc != LDAP_COMPARE_TRUE ) {
141					be_entry_release_r( &op, e );
142					continue;
143				}
144			}
145		}
146
147		if ( verbose ) {
148			printf( "# id=%08lx\n", (long) id );
149		}
150
151		data = entry2str_wrap( e, &len, ldif_wrap );
152		be_entry_release_r( &op, e );
153
154		if ( data == NULL ) {
155			printf("# bad data for entry id=%08lx\n\n", (long) id );
156			rc = EXIT_FAILURE;
157			if( continuemode ) continue;
158			break;
159		}
160
161		if ( fputs( data, ldiffp->fp ) == EOF ||
162			fputs( "\n", ldiffp->fp ) == EOF ) {
163			fprintf(stderr, "%s: error writing output.\n",
164				progname);
165			rc = EXIT_FAILURE;
166			break;
167		}
168	}
169
170	be->be_entry_close( be );
171
172	if ( slap_tool_destroy())
173		rc = EXIT_FAILURE;
174	return rc;
175}
176