sync with CUPS changes in SAMBA_3_0
[Samba.git] / source / lib / substitute.c
blob0dbd7be384f01e11ef02d149612aa57415f90fd5
1 /*
2 Unix SMB/Netbios implementation.
3 Version 3.0
4 string substitution functions
5 Copyright (C) Andrew Tridgell 1992-2000
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "includes.h"
25 fstring local_machine="";
26 fstring remote_arch="UNKNOWN";
27 userdom_struct current_user_info;
28 pstring samlogon_user="";
29 BOOL sam_logon_in_ssb = False;
30 fstring remote_proto="UNKNOWN";
31 fstring remote_machine="";
32 static fstring smb_user_name;
36 setup the string used by %U substitution
38 void sub_set_smb_name(const char *name)
40 fstring tmp;
42 /* ignore anonymous settings */
43 if (! *name) return;
45 fstrcpy(tmp,name);
46 trim_string(tmp," "," ");
47 strlower(tmp);
48 alpha_strcpy(smb_user_name,tmp,SAFE_NETBIOS_CHARS,sizeof(smb_user_name)-1);
51 const char* get_remote_machine_name(void)
53 return remote_machine;
57 /*******************************************************************
58 Given a pointer to a %$(NAME) expand it as an environment variable.
59 Return the number of characters by which the pointer should be advanced.
60 Based on code by Branko Cibej <branko.cibej@hermes.si>
61 When this is called p points at the '%' character.
62 ********************************************************************/
64 static size_t expand_env_var(char *p, int len)
66 fstring envname;
67 char *envval;
68 char *q, *r;
69 int copylen;
71 if (p[1] != '$')
72 return 1;
74 if (p[2] != '(')
75 return 2;
78 * Look for the terminating ')'.
81 if ((q = strchr(p,')')) == NULL) {
82 DEBUG(0,("expand_env_var: Unterminated environment variable [%s]\n", p));
83 return 2;
87 * Extract the name from within the %$(NAME) string.
90 r = p+3;
91 copylen = MIN((q-r),(sizeof(envname)-1));
92 strncpy(envname,r,copylen);
93 envname[copylen] = '\0';
95 if ((envval = getenv(envname)) == NULL) {
96 DEBUG(0,("expand_env_var: Environment variable [%s] not set\n", envname));
97 return 2;
101 * Copy the full %$(NAME) into envname so it
102 * can be replaced.
105 copylen = MIN((q+1-p),(sizeof(envname)-1));
106 strncpy(envname,p,copylen);
107 envname[copylen] = '\0';
108 string_sub(p,envname,envval,len);
109 return 0; /* Allow the environment contents to be parsed. */
112 /*******************************************************************
113 Patch from jkf@soton.ac.uk
114 Added this to implement %p (NIS auto-map version of %H)
115 *******************************************************************/
117 static char *automount_path(char *user_name)
119 static pstring server_path;
121 /* use the passwd entry as the default */
122 /* this will be the default if WITH_AUTOMOUNT is not used or fails */
124 pstrcpy(server_path, get_user_home_dir(user_name));
126 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
128 if (lp_nis_home_map()) {
129 char *home_path_start;
130 char *automount_value = automount_lookup(user_name);
132 if(strlen(automount_value) > 0) {
133 home_path_start = strchr(automount_value,':');
134 if (home_path_start != NULL) {
135 DEBUG(5, ("NIS lookup succeeded. Home path is: %s\n",
136 home_path_start?(home_path_start+1):""));
137 pstrcpy(server_path, home_path_start+1);
139 } else {
140 /* NIS key lookup failed: default to user home directory from password file */
141 DEBUG(5, ("NIS lookup failed. Using Home path from passwd file. Home path is: %s\n", server_path ));
144 #endif
146 DEBUG(4,("Home server path: %s\n", server_path));
148 return server_path;
151 /*******************************************************************
152 Patch from jkf@soton.ac.uk
153 This is Luke's original function with the NIS lookup code
154 moved out to a separate function.
155 *******************************************************************/
157 static char *automount_server(char *user_name)
159 extern pstring global_myname;
160 static pstring server_name;
162 /* use the local machine name as the default */
163 /* this will be the default if WITH_AUTOMOUNT is not used or fails */
164 if (*local_machine)
165 pstrcpy(server_name, local_machine);
166 else
167 pstrcpy(server_name, global_myname);
169 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
171 if (lp_nis_home_map()) {
172 int home_server_len;
173 char *automount_value = automount_lookup(user_name);
174 home_server_len = strcspn(automount_value,":");
175 DEBUG(5, ("NIS lookup succeeded. Home server length: %d\n",home_server_len));
176 if (home_server_len > sizeof(pstring))
177 home_server_len = sizeof(pstring);
178 strncpy(server_name, automount_value, home_server_len);
179 server_name[home_server_len] = '\0';
181 #endif
183 DEBUG(4,("Home server: %s\n", server_name));
185 return server_name;
188 /****************************************************************************
189 Do some standard substitutions in a string.
190 ****************************************************************************/
192 void standard_sub_basic(char *str, int len)
194 extern pstring global_myname;
195 char *p, *s;
196 fstring pidstr;
197 struct passwd *pass;
199 for (s=str; (p=strchr(s, '%'));s=p) {
200 fstring tmp_str;
202 int l = len - (int)(p-str);
204 switch (*(p+1)) {
205 case 'U' :
206 fstrcpy(tmp_str, sam_logon_in_ssb?samlogon_user:smb_user_name);
207 strlower(tmp_str);
208 string_sub(p,"%U",tmp_str,l);
209 break;
210 case 'G' :
211 fstrcpy(tmp_str, sam_logon_in_ssb?samlogon_user:smb_user_name);
212 if ((pass = Get_Pwnam(tmp_str, False))!=NULL) {
213 string_sub(p,"%G",gidtoname(pass->pw_gid),l);
214 } else {
215 p += 2;
217 break;
218 case 'D' :
219 fstrcpy(tmp_str, current_user_info.domain);
220 strupper(tmp_str);
221 string_sub(p,"%D", tmp_str,l);
222 break;
223 case 'I' : string_sub(p,"%I", client_addr(),l); break;
224 case 'L' :
225 if (*local_machine)
226 string_sub(p,"%L", local_machine,l);
227 else {
228 pstring temp_name;
230 pstrcpy(temp_name, global_myname);
231 strlower(temp_name);
232 string_sub(p,"%L", temp_name,l);
234 break;
235 case 'M' : string_sub(p,"%M", client_name(),l); break;
236 case 'R' : string_sub(p,"%R", remote_proto,l); break;
237 case 'T' : string_sub(p,"%T", timestring(False),l); break;
238 case 'a' : string_sub(p,"%a", remote_arch,l); break;
239 case 'd' :
240 slprintf(pidstr,sizeof(pidstr)-1, "%d",(int)sys_getpid());
241 string_sub(p,"%d", pidstr,l);
242 break;
243 case 'h' : string_sub(p,"%h", myhostname(),l); break;
244 case 'm' : string_sub(p,"%m", remote_machine,l); break;
245 case 'v' : string_sub(p,"%v", VERSION,l); break;
246 case '$' : p += expand_env_var(p,l); break; /* Expand environment variables */
247 case '\0':
248 p++;
249 break; /* don't run off the end of the string */
251 default: p+=2;
252 break;
257 /****************************************************************************
258 Do some standard substitutions in a string.
259 ****************************************************************************/
261 void standard_sub_advanced(int snum, char *user, char *connectpath, gid_t gid, char *str, int len)
263 char *p, *s, *home;
265 for (s=str; (p=strchr(s, '%'));s=p) {
266 int l = len - (int)(p-str);
268 switch (*(p+1)) {
269 case 'N' : string_sub(p,"%N", automount_server(user),l); break;
270 case 'H':
271 if ((home = get_user_home_dir(user))) {
272 string_sub(p,"%H",home, l);
273 } else {
274 p += 2;
276 break;
277 case 'P':
278 string_sub(p,"%P", connectpath, l);
279 break;
281 case 'S':
282 string_sub(p,"%S", lp_servicename(snum), l);
283 break;
285 case 'g':
286 string_sub(p,"%g", gidtoname(gid), l);
287 break;
288 case 'u':
289 string_sub(p,"%u", user, l);
290 break;
292 /* Patch from jkf@soton.ac.uk Left the %N (NIS
293 * server name) in standard_sub_basic as it is
294 * a feature for logon servers, hence uses the
295 * username. The %p (NIS server path) code is
296 * here as it is used instead of the default
297 * "path =" string in [homes] and so needs the
298 * service name, not the username. */
299 case 'p':
300 string_sub(p,"%p", automount_path(lp_servicename(snum)), l);
301 break;
302 case '\0':
303 p++;
304 break; /* don't run off the end of the string */
306 default: p+=2;
307 break;
311 standard_sub_basic(str,len);
314 /****************************************************************************
315 Do some standard substitutions in a string.
316 ****************************************************************************/
318 void standard_sub_conn(connection_struct *conn, char *str, int len)
320 standard_sub_advanced(SNUM(conn), conn->user, conn->connectpath, conn->gid, str, len);
323 /****************************************************************************
324 Like standard_sub but for a homes share where snum still points to the [homes]
325 share. No user specific snum created yet so servicename should be the username.
326 ****************************************************************************/
328 void standard_sub_home(int snum, char *user, char *str, int len)
330 char *p, *s;
332 for (s=str; (p=strchr(s, '%'));s=p) {
333 int l = len - (int)(p-str);
335 switch (*(p+1)) {
336 case 'S':
337 string_sub(p,"%S", user, l);
338 break;
339 case 'p':
340 string_sub(p,"%p", automount_path(user), l);
341 break;
342 case '\0':
343 p++;
344 break; /* don't run off the end of the string */
346 default: p+=2;
347 break;
351 standard_sub_advanced(snum, user, "", -1, str, len);
354 /****************************************************************************
355 Like standard_sub but by snum.
356 ****************************************************************************/
358 void standard_sub_snum(int snum, char *str, int len)
360 extern struct current_user current_user;
361 static uid_t cached_uid = -1;
362 static fstring cached_user;
363 /* calling uidtoname() on every substitute would be too expensive, so
364 we cache the result here as nearly every call is for the same uid */
366 if (cached_uid != current_user.uid) {
367 fstrcpy(cached_user, uidtoname(current_user.uid));
368 cached_uid = current_user.uid;
371 standard_sub_advanced(snum, cached_user, "", -1, str, len);
374 /*******************************************************************
375 Substitute strings with useful parameters.
376 ********************************************************************/
378 void standard_sub_vuser(char *str, int len, user_struct *vuser)
380 standard_sub_advanced(-1, vuser->user.unix_name, "", -1, str, len);
383 /*******************************************************************
384 Substitute strings with useful parameters.
385 ********************************************************************/
387 void standard_sub_vsnum(char *str, int len, user_struct *vuser, int snum)
389 standard_sub_advanced(snum, vuser->user.unix_name, "", -1, str, len);