]> git.sur5r.net Git - openldap/blob - servers/slapd/back-tcl/tcl_modify.c
569ee2ea91fee3f8b744efbfd0eb32725d662734
[openldap] / servers / slapd / back-tcl / tcl_modify.c
1 /* modify.c - tcl modify routines
2  *
3  * $Id: tcl_modify.c,v 1.7 1999/08/02 23:38:43 hallvard Exp $
4  *
5  * Copyright 1999, Ben Collins <bcollins@debian.org>, All rights reserved.
6  *
7  * Redistribution and use in source and binary forms are permitted only
8  * as authorized by the OpenLDAP Public License.  A copy of this
9  * license is available at http://www.OpenLDAP.org/license.html or
10  * in file LICENSE in the top-level directory of the distribution.
11  */
12
13 #include "portable.h"
14
15 #include <stdio.h>
16
17 #include "slap.h"
18 #include "tcl_back.h"
19
20 int
21 tcl_back_modify (
22         Backend * be,
23         Connection * conn,
24         Operation * op,
25         char *dn,
26         LDAPModList * modlist
27 )
28 {
29         char *command, *suf_tcl, *bp, *tcl_mods, *results;
30         int i, code, err = 0, len, bsize;
31         struct tclinfo *ti = (struct tclinfo *) be->be_private;
32
33         if (ti->ti_modify == NULL) {
34                 send_ldap_result (conn, op, LDAP_UNWILLING_TO_PERFORM, NULL,
35                         "modify not implemented", NULL, NULL );
36                 return (-1);
37         }
38
39         for (i = 0; be->be_suffix[i] != NULL; i++);
40         suf_tcl = Tcl_Merge (i, be->be_suffix);
41
42         tcl_mods = (char *) ch_malloc (BUFSIZ);
43         tcl_mods[0] = '\0';
44         bsize = BUFSIZ;
45         bp = tcl_mods;
46
47         for (; modlist != NULL; modlist = modlist->ml_next) {
48                 LDAPMod *mods = &modlist->ml_mod;
49                 char *op = NULL;
50
51                 switch (mods->mod_op & ~LDAP_MOD_BVALUES) {
52                 case LDAP_MOD_ADD:
53                         op = "add";
54                         break;
55                 case LDAP_MOD_DELETE:
56                         op = "delete";
57                         break;
58                 case LDAP_MOD_REPLACE:
59                         op = "replace";
60                         break;
61                 }
62
63                 len = strlen (mods->mod_type) + strlen (op) + 7;
64                 while (bp + len - tcl_mods > bsize) {
65                         bsize += BUFSIZ;
66                         tcl_mods = (char *) ch_realloc (tcl_mods, bsize);
67                 }
68                 sprintf (bp, "{ {%s: %s} ", op, mods->mod_type);
69                 bp += len;
70                 for (i = 0;
71                         mods->mod_bvalues != NULL && mods->mod_bvalues[i]
72                         != NULL;
73                         i++) {
74                         len = strlen (mods->mod_type) + strlen (
75                                 mods->mod_bvalues[i]->bv_val) + 5 +
76                                 (mods->mod_bvalues[i + 1] == NULL ? 2 : 0);
77                         while (bp + len - tcl_mods > bsize) {
78                                 bsize += BUFSIZ;
79                                 tcl_mods = (char *) ch_realloc (tcl_mods, bsize);
80                         }
81                         sprintf (bp, "{%s: %s} %s", mods->mod_type,
82                                 mods->mod_bvalues[i]->bv_val,
83                                 mods->mod_bvalues[i + 1] ==
84                                 NULL ? "} " : "");
85                         bp += len;
86                 }
87         }
88
89         command = (char *) ch_malloc (strlen (ti->ti_modify) + strlen (suf_tcl)
90                 + strlen (dn) + strlen (tcl_mods) + 64);
91         /* This space is simply for aesthetics--\  */
92         sprintf (command, "%s MODIFY {%ld} {%s} {%s} { %s}",
93                 ti->ti_modify, op->o_msgid, suf_tcl, dn, tcl_mods);
94         Tcl_Free (suf_tcl);
95         free (tcl_mods);
96
97         ldap_pvt_thread_mutex_lock (&tcl_interpreter_mutex);
98         code = Tcl_GlobalEval (ti->ti_ii->interp, command);
99         results = (char *) ch_strdup (ti->ti_ii->interp->result);
100         ldap_pvt_thread_mutex_unlock (&tcl_interpreter_mutex);
101         free (command);
102
103         if (code != TCL_OK) {
104                 err = LDAP_OPERATIONS_ERROR;
105                 Debug (LDAP_DEBUG_SHELL, "tcl_modify_error: %s\n", results,
106                         0, 0);
107         } else {
108                 interp_send_results (be, conn, op, results, NULL, 0);
109         }
110
111         if (err != LDAP_SUCCESS)
112                 send_ldap_result (conn, op, err, NULL,
113                         "internal backend error", NULL, NULL );
114
115         free (results);
116         return (err);
117 }