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
23static int shared_fd;
24static char *variables;
25static int shared_size;
26
27/*****************************************************
28setup the shared area
29*******************************************************/
30void 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
64static int locked;
65
66/*****************************************************
67lock the shared variable area
68*******************************************************/
69static 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/*****************************************************
88unlock the shared variable area
89*******************************************************/
90static 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/*****************************************************
100get a variable from the shared area
101*******************************************************/
102char *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/*****************************************************
155set a variable in the shared area
156*******************************************************/
157void 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	safe_strcpy(&variables[shared_size] + 4, name, l1-1);
183	safe_strcpy(&variables[shared_size] + 4 + l1, val, l2-1);
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/*****************************************************************
198return true if the passed fd is the SMBW_HANDLE
199*****************************************************************/
200int smbw_shared_fd(int fd)
201{
202	return (shared_fd && shared_fd == fd);
203}
204