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