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