b4cfcf71486a3ead71dea398a73d10839378c34b
[abartlet/samba.git/.git] / source3 / smbwrapper / shared.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB wrapper functions - shared variables
4    Copyright (C) Andrew Tridgell 1998
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22
23 static int shared_fd;
24 static char *variables;
25 static int shared_size;
26
27 /***************************************************** 
28 setup the shared area 
29 *******************************************************/
30 void smbw_setup_shared(void)
31 {
32         int fd;
33         pstring name, s;
34
35         slprintf(name,sizeof(name)-1, "%s/smbw.XXXXXX",tmpdir());
36
37         fd = smb_mkstemp(name);
38
39         if (fd == -1) goto failed;
40
41         unlink(name);
42
43         shared_fd = set_maxfiles(SMBW_MAX_OPEN);
44         
45         while (shared_fd && dup2(fd, shared_fd) != shared_fd) shared_fd--;
46
47         if (shared_fd == 0) goto failed;
48
49         close(fd);
50
51         DEBUG(4,("created shared_fd=%d\n", shared_fd));
52
53         slprintf(s,sizeof(s)-1,"%d", shared_fd);
54
55         setenv("SMBW_HANDLE", s, 1);
56
57         return;
58
59  failed:
60         perror("Failed to setup shared variable area ");
61         exit(1);
62 }
63
64 static int locked;
65
66 /***************************************************** 
67 lock the shared variable area
68 *******************************************************/
69 static void lockit(void)
70 {
71         if (shared_fd == 0) {
72                 char *p = getenv("SMBW_HANDLE");
73                 if (!p) {
74                         DEBUG(0,("ERROR: can't get smbw shared handle\n"));
75                         exit(1);
76                 }
77                 shared_fd = atoi(p);
78         }
79         if (locked==0 && 
80             fcntl_lock(shared_fd,SMB_F_SETLKW,0,1,F_WRLCK)==False) {
81                 DEBUG(0,("ERROR: can't get smbw shared lock (%s)\n", strerror(errno)));
82                 exit(1);
83         }
84         locked++;
85 }
86
87 /***************************************************** 
88 unlock the shared variable area
89 *******************************************************/
90 static void unlockit(void)
91 {
92         locked--;
93         if (locked == 0) {
94                 fcntl_lock(shared_fd,SMB_F_SETLK,0,1,F_UNLCK);
95         }
96 }
97
98
99 /***************************************************** 
100 get a variable from the shared area
101 *******************************************************/
102 char *smbw_getshared(const char *name)
103 {
104         int i;
105         struct stat st;
106         char *var;
107
108         lockit();
109
110         /* maybe the area has changed */
111         if (fstat(shared_fd, &st)) goto failed;
112
113         if (st.st_size != shared_size) {
114                 var = (char *)Realloc(variables, st.st_size);
115                 if (!var) goto failed;
116                 else variables = var;
117                 shared_size = st.st_size;
118                 lseek(shared_fd, 0, SEEK_SET);
119                 if (read(shared_fd, variables, shared_size) != shared_size) {
120                         goto failed;
121                 }
122         }
123
124         unlockit();
125
126         i=0;
127         while (i < shared_size) {
128                 char *n, *v;
129                 int l1, l2;
130
131                 l1 = SVAL(&variables[i], 0);
132                 l2 = SVAL(&variables[i], 2);
133
134                 n = &variables[i+4];
135                 v = &variables[i+4+l1];
136                 i += 4+l1+l2;
137
138                 if (strcmp(name,n)) {
139                         continue;
140                 }
141                 return v;
142         }
143
144         return NULL;
145
146  failed:
147         DEBUG(0,("smbw: shared variables corrupt (%s)\n", strerror(errno)));
148         exit(1);
149         return NULL;
150 }
151
152
153
154 /***************************************************** 
155 set a variable in the shared area
156 *******************************************************/
157 void smbw_setshared(const char *name, const char *val)
158 {
159         int l1, l2;
160         char *var;
161
162         /* we don't allow variable overwrite */
163         if (smbw_getshared(name)) return;
164
165         lockit();
166
167         l1 = strlen(name)+1;
168         l2 = strlen(val)+1;
169
170         var = (char *)Realloc(variables, shared_size + l1+l2+4);
171
172         if (!var) {
173                 DEBUG(0,("out of memory in smbw_setshared\n"));
174                 exit(1);
175         }
176         
177         variables = var;
178
179         SSVAL(&variables[shared_size], 0, l1);
180         SSVAL(&variables[shared_size], 2, l2);
181
182         pstrcpy(&variables[shared_size] + 4, name);
183         pstrcpy(&variables[shared_size] + 4 + l1, val);
184
185         shared_size += l1+l2+4;
186
187         lseek(shared_fd, 0, SEEK_SET);
188         if (write(shared_fd, variables, shared_size) != shared_size) {
189                 DEBUG(0,("smbw_setshared failed (%s)\n", strerror(errno)));
190                 exit(1);
191         }
192
193         unlockit();
194 }
195
196
197 /*****************************************************************
198 return true if the passed fd is the SMBW_HANDLE
199 *****************************************************************/  
200 int smbw_shared_fd(int fd)
201 {
202         return (shared_fd && shared_fd == fd);
203 }