BUG 417: fix %UuGg variables expansion in include lines setging the current_user_info...
[ira/wip.git] / source / lib / substitute.c
1 /* 
2    Unix SMB/CIFS implementation.
3    string substitution functions
4    Copyright (C) Andrew Tridgell 1992-2000
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
22 #include "includes.h"
23
24 fstring local_machine="";
25 fstring remote_arch="UNKNOWN";
26 userdom_struct current_user_info;
27 fstring remote_proto="UNKNOWN";
28
29 static fstring remote_machine;
30 static fstring smb_user_name;
31
32 /** 
33  * Set the 'local' machine name
34  * @param local_name the name we are being called
35  * @param if this is the 'final' name for us, not be be changed again
36  */
37
38 void set_local_machine_name(const char* local_name, BOOL perm)
39 {
40         static BOOL already_perm = False;
41         fstring tmp_local_machine;
42
43         /*
44          * Windows NT/2k uses "*SMBSERVER" and XP uses "*SMBSERV"
45          * arrggg!!! 
46          */
47
48         if (strequal(local_name, "*SMBSERVER")) 
49                 return;
50
51         if (strequal(local_name, "*SMBSERV")) 
52                 return;
53
54         if (already_perm)
55                 return;
56
57         already_perm = perm;
58
59         fstrcpy(tmp_local_machine,local_name);
60         trim_char(tmp_local_machine,' ',' ');
61         alpha_strcpy(local_machine,tmp_local_machine,SAFE_NETBIOS_CHARS,sizeof(local_machine)-1);
62         strlower_m(local_machine);
63 }
64
65 /** 
66  * Set the 'remote' machine name
67  * @param remote_name the name our client wants to be called by
68  * @param if this is the 'final' name for them, not be be changed again
69  */
70
71 void set_remote_machine_name(const char* remote_name, BOOL perm)
72 {
73         static BOOL already_perm = False;
74         fstring tmp_remote_machine;
75
76         if (already_perm)
77                 return;
78
79         already_perm = perm;
80
81         fstrcpy(tmp_remote_machine,remote_name);
82         trim_char(tmp_remote_machine,' ',' ');
83         alpha_strcpy(remote_machine,tmp_remote_machine,SAFE_NETBIOS_CHARS,sizeof(remote_machine)-1);
84         strlower_m(remote_machine);
85 }
86
87 const char* get_remote_machine_name(void) 
88 {
89         return remote_machine;
90 }
91
92 const char* get_local_machine_name(void) 
93 {
94         if (!*local_machine) {
95                 return global_myname();
96         }
97
98         return local_machine;
99 }
100
101 /*******************************************************************
102  Setup the string used by %U substitution.
103 ********************************************************************/
104
105 void sub_set_smb_name(const char *name)
106 {
107         fstring tmp;
108
109         /* don't let anonymous logins override the name */
110         if (! *name)
111                 return;
112
113         fstrcpy(tmp,name);
114         trim_char(tmp,' ',' ');
115         strlower_m(tmp);
116         alpha_strcpy(smb_user_name,tmp,SAFE_NETBIOS_CHARS,sizeof(smb_user_name)-1);
117 }
118
119 char* sub_get_smb_name( void )
120 {
121         return smb_user_name;
122 }
123
124 /*******************************************************************
125  Setup the strings used by substitutions. Called per packet. Ensure
126  %U name is set correctly also.
127 ********************************************************************/
128
129 void set_current_user_info(const userdom_struct *pcui)
130 {
131         current_user_info = *pcui;
132         /* The following is safe as current_user_info.smb_name
133          * has already been sanitised in register_vuid. */
134         fstrcpy(smb_user_name, current_user_info.smb_name);
135 }
136
137 /*******************************************************************
138  Given a pointer to a %$(NAME) expand it as an environment variable.
139  Return the number of characters by which the pointer should be advanced.
140  Based on code by Branko Cibej <branko.cibej@hermes.si>
141  When this is called p points at the '%' character.
142 ********************************************************************/
143
144 static size_t expand_env_var(char *p, int len)
145 {
146         fstring envname;
147         char *envval;
148         char *q, *r;
149         int copylen;
150
151         if (p[1] != '$')
152                 return 1;
153
154         if (p[2] != '(')
155                 return 2;
156
157         /*
158          * Look for the terminating ')'.
159          */
160
161         if ((q = strchr_m(p,')')) == NULL) {
162                 DEBUG(0,("expand_env_var: Unterminated environment variable [%s]\n", p));
163                 return 2;
164         }
165
166         /*
167          * Extract the name from within the %$(NAME) string.
168          */
169
170         r = p+3;
171         copylen = MIN((q-r),(sizeof(envname)-1));
172         strncpy(envname,r,copylen);
173         envname[copylen] = '\0';
174
175         if ((envval = getenv(envname)) == NULL) {
176                 DEBUG(0,("expand_env_var: Environment variable [%s] not set\n", envname));
177                 return 2;
178         }
179
180         /*
181          * Copy the full %$(NAME) into envname so it
182          * can be replaced.
183          */
184
185         copylen = MIN((q+1-p),(sizeof(envname)-1));
186         strncpy(envname,p,copylen);
187         envname[copylen] = '\0';
188         string_sub(p,envname,envval,len);
189         return 0; /* Allow the environment contents to be parsed. */
190 }
191
192 /*******************************************************************
193  Given a pointer to a %$(NAME) in p and the whole string in str
194  expand it as an environment variable.
195  Return a new allocated and expanded string.
196  Based on code by Branko Cibej <branko.cibej@hermes.si>
197  When this is called p points at the '%' character.
198  May substitute multiple occurrencies of the same env var.
199 ********************************************************************/
200
201
202 static char * realloc_expand_env_var(char *str, char *p)
203 {
204         char *envname;
205         char *envval;
206         char *q, *r;
207         int copylen;
208
209         if (p[0] != '%' || p[1] != '$' || p[2] != '(')
210                 return str;
211
212         /*
213          * Look for the terminating ')'.
214          */
215
216         if ((q = strchr_m(p,')')) == NULL) {
217                 DEBUG(0,("expand_env_var: Unterminated environment variable [%s]\n", p));
218                 return str;
219         }
220
221         /*
222          * Extract the name from within the %$(NAME) string.
223          */
224
225         r = p + 3;
226         copylen = q - r;
227         envname = (char *)malloc(copylen + 1 + 4); /* reserve space for use later add %$() chars */
228         if (envname == NULL) return NULL;
229         strncpy(envname,r,copylen);
230         envname[copylen] = '\0';
231
232         if ((envval = getenv(envname)) == NULL) {
233                 DEBUG(0,("expand_env_var: Environment variable [%s] not set\n", envname));
234                 SAFE_FREE(envname);
235                 return str;
236         }
237
238         /*
239          * Copy the full %$(NAME) into envname so it
240          * can be replaced.
241          */
242
243         copylen = q + 1 - p;
244         strncpy(envname,p,copylen);
245         envname[copylen] = '\0';
246         r = realloc_string_sub(str, envname, envval);
247         SAFE_FREE(envname);
248         if (r == NULL) return NULL;
249         return r;
250 }
251
252 /*******************************************************************
253  Patch from jkf@soton.ac.uk
254  Added this to implement %p (NIS auto-map version of %H)
255 *******************************************************************/
256
257 static char *automount_path(const char *user_name)
258 {
259         static pstring server_path;
260
261         /* use the passwd entry as the default */
262         /* this will be the default if WITH_AUTOMOUNT is not used or fails */
263
264         pstrcpy(server_path, get_user_home_dir(user_name));
265
266 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
267
268         if (lp_nis_home_map()) {
269                 char *home_path_start;
270                 char *automount_value = automount_lookup(user_name);
271
272                 if(strlen(automount_value) > 0) {
273                         home_path_start = strchr_m(automount_value,':');
274                         if (home_path_start != NULL) {
275                                 DEBUG(5, ("NIS lookup succeeded.  Home path is: %s\n",
276                                                 home_path_start?(home_path_start+1):""));
277                                 pstrcpy(server_path, home_path_start+1);
278                         }
279                 } else {
280                         /* NIS key lookup failed: default to user home directory from password file */
281                         DEBUG(5, ("NIS lookup failed. Using Home path from passwd file. Home path is: %s\n", server_path ));
282                 }
283         }
284 #endif
285
286         DEBUG(4,("Home server path: %s\n", server_path));
287
288         return server_path;
289 }
290
291 /*******************************************************************
292  Patch from jkf@soton.ac.uk
293  This is Luke's original function with the NIS lookup code
294  moved out to a separate function.
295 *******************************************************************/
296
297 static const char *automount_server(const char *user_name)
298 {
299         static pstring server_name;
300         const char *local_machine_name = get_local_machine_name(); 
301
302         /* use the local machine name as the default */
303         /* this will be the default if WITH_AUTOMOUNT is not used or fails */
304         if (local_machine_name && *local_machine_name)
305                 pstrcpy(server_name, local_machine_name);
306         else
307                 pstrcpy(server_name, global_myname());
308         
309 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
310
311         if (lp_nis_home_map()) {
312                 int home_server_len;
313                 char *automount_value = automount_lookup(user_name);
314                 home_server_len = strcspn(automount_value,":");
315                 DEBUG(5, ("NIS lookup succeeded.  Home server length: %d\n",home_server_len));
316                 if (home_server_len > sizeof(pstring))
317                         home_server_len = sizeof(pstring);
318                 strncpy(server_name, automount_value, home_server_len);
319                 server_name[home_server_len] = '\0';
320         }
321 #endif
322
323         DEBUG(4,("Home server: %s\n", server_name));
324
325         return server_name;
326 }
327
328 /****************************************************************************
329  Do some standard substitutions in a string.
330  len is the length in bytes of the space allowed in string str. If zero means
331  don't allow expansions.
332 ****************************************************************************/
333
334 void standard_sub_basic(const char *smb_name, char *str,size_t len)
335 {
336         char *p, *s;
337         fstring pidstr;
338         struct passwd *pass;
339         const char *local_machine_name = get_local_machine_name();
340
341         for (s=str; (p=strchr_m(s, '%'));s=p) {
342                 fstring tmp_str;
343
344                 int l = (int)len - (int)(p-str);
345
346                 if (l < 0)
347                         l = 0;
348                 
349                 switch (*(p+1)) {
350                 case 'U' : 
351                         fstrcpy(tmp_str, smb_name);
352                         strlower_m(tmp_str);
353                         string_sub(p,"%U",tmp_str,l);
354                         break;
355                 case 'G' :
356                         fstrcpy(tmp_str, smb_name);
357                         if ((pass = Get_Pwnam(tmp_str))!=NULL) {
358                                 string_sub(p,"%G",gidtoname(pass->pw_gid),l);
359                         } else {
360                                 p += 2;
361                         }
362                         break;
363                 case 'D' :
364                         fstrcpy(tmp_str, current_user_info.domain);
365                         strupper_m(tmp_str);
366                         string_sub(p,"%D", tmp_str,l);
367                         break;
368                 case 'I' :
369                         string_sub(p,"%I", client_addr(),l);
370                         break;
371                 case 'i' :
372                         string_sub(p,"%i", client_socket_addr(),l);
373                         break;
374                 case 'L' : 
375                         if (local_machine_name && *local_machine_name)
376                                 string_sub(p,"%L", local_machine_name,l); 
377                         else {
378                                 pstring temp_name;
379
380                                 pstrcpy(temp_name, global_myname());
381                                 strlower_m(temp_name);
382                                 string_sub(p,"%L", temp_name,l); 
383                         }
384                         break;
385                 case 'M' :
386                         string_sub(p,"%M", client_name(),l);
387                         break;
388                 case 'R' :
389                         string_sub(p,"%R", remote_proto,l);
390                         break;
391                 case 'T' :
392                         string_sub(p,"%T", timestring(False),l);
393                         break;
394                 case 'a' :
395                         string_sub(p,"%a", remote_arch,l);
396                         break;
397                 case 'd' :
398                         slprintf(pidstr,sizeof(pidstr)-1, "%d",(int)sys_getpid());
399                         string_sub(p,"%d", pidstr,l);
400                         break;
401                 case 'h' :
402                         string_sub(p,"%h", myhostname(),l);
403                         break;
404                 case 'm' :
405                         string_sub(p,"%m", get_remote_machine_name(),l);
406                         break;
407                 case 'v' :
408                         string_sub(p,"%v", SAMBA_VERSION_STRING,l);
409                         break;
410                 case '$' :
411                         p += expand_env_var(p,l);
412                         break; /* Expand environment variables */
413                 case '\0': 
414                         p++; 
415                         break; /* don't run off the end of the string */
416                         
417                 default: p+=2; 
418                         break;
419                 }
420         }
421 }
422
423 static void standard_sub_advanced(int snum, const char *user, 
424                                   const char *connectpath, gid_t gid, 
425                                   const char *smb_name, char *str, size_t len)
426 {
427         char *p, *s, *home;
428
429         for (s=str; (p=strchr_m(s, '%'));s=p) {
430                 int l = (int)len - (int)(p-str);
431         
432                 if (l < 0)
433                         l = 0;
434         
435                 switch (*(p+1)) {
436                 case 'N' :
437                         string_sub(p,"%N", automount_server(user),l);
438                         break;
439                 case 'H':
440                         if ((home = get_user_home_dir(user)))
441                                 string_sub(p,"%H",home, l);
442                         else
443                                 p += 2;
444                         break;
445                 case 'P': 
446                         string_sub(p,"%P", connectpath, l); 
447                         break;
448                 case 'S': 
449                         string_sub(p,"%S", lp_servicename(snum), l); 
450                         break;
451                 case 'g': 
452                         string_sub(p,"%g", gidtoname(gid), l); 
453                         break;
454                 case 'u': 
455                         string_sub(p,"%u", user, l); 
456                         break;
457                         
458                         /* Patch from jkf@soton.ac.uk Left the %N (NIS
459                          * server name) in standard_sub_basic as it is
460                          * a feature for logon servers, hence uses the
461                          * username.  The %p (NIS server path) code is
462                          * here as it is used instead of the default
463                          * "path =" string in [homes] and so needs the
464                          * service name, not the username.  */
465                 case 'p': 
466                         string_sub(p,"%p", automount_path(lp_servicename(snum)), l); 
467                         break;
468                 case '\0': 
469                         p++; 
470                         break; /* don't run off the end of the string */
471                         
472                 default: p+=2; 
473                         break;
474                 }
475         }
476
477         standard_sub_basic(smb_name, str, len);
478 }
479
480 /****************************************************************************
481  Do some standard substitutions in a string.
482  This function will return an allocated string that have to be freed.
483 ****************************************************************************/
484
485 char *talloc_sub_basic(TALLOC_CTX *mem_ctx, const char *smb_name, const char *str)
486 {
487         char *a, *t;
488         a = alloc_sub_basic(smb_name, str);
489         if (!a) return NULL;
490         t = talloc_strdup(mem_ctx, a);
491         SAFE_FREE(a);
492         return t;
493 }
494
495 char *alloc_sub_basic(const char *smb_name, const char *str)
496 {
497         char *b, *p, *s, *t, *r, *a_string;
498         fstring pidstr;
499         struct passwd *pass;
500         const char *local_machine_name = get_local_machine_name();
501
502         /* workaround to prevent a crash while lookinf at bug #687 */
503         
504         if ( !str ) {
505                 DEBUG(0,("alloc_sub_basic: NULL source string!  This should not happen\n"));
506                 return NULL;
507         }
508         
509         a_string = strdup(str);
510         if (a_string == NULL) {
511                 DEBUG(0, ("alloc_sub_specified: Out of memory!\n"));
512                 return NULL;
513         }
514         
515         for (b = s = a_string; (p = strchr_m(s, '%')); s = a_string + (p - b)) {
516
517                 r = NULL;
518                 b = t = a_string;
519                 
520                 switch (*(p+1)) {
521                 case 'U' : 
522                         r = strdup_lower(smb_name);
523                         if (r == NULL) goto error;
524                         t = realloc_string_sub(t, "%U", r);
525                         break;
526                 case 'G' :
527                         r = strdup(smb_name);
528                         if (r == NULL) goto error;
529                         if ((pass = Get_Pwnam(r))!=NULL) {
530                                 t = realloc_string_sub(t, "%G", gidtoname(pass->pw_gid));
531                         } 
532                         break;
533                 case 'D' :
534                         r = strdup_upper(current_user_info.domain);
535                         if (r == NULL) goto error;
536                         t = realloc_string_sub(t, "%D", r);
537                         break;
538                 case 'I' :
539                         t = realloc_string_sub(t, "%I", client_addr());
540                         break;
541                 case 'L' : 
542                         if (local_machine_name && *local_machine_name)
543                                 t = realloc_string_sub(t, "%L", local_machine_name); 
544                         else
545                                 t = realloc_string_sub(t, "%L", global_myname()); 
546                         break;
547                 case 'N':
548                         t = realloc_string_sub(t, "%N", automount_server(smb_name));
549                         break;
550                 case 'M' :
551                         t = realloc_string_sub(t, "%M", client_name());
552                         break;
553                 case 'R' :
554                         t = realloc_string_sub(t, "%R", remote_proto);
555                         break;
556                 case 'T' :
557                         t = realloc_string_sub(t, "%T", timestring(False));
558                         break;
559                 case 'a' :
560                         t = realloc_string_sub(t, "%a", remote_arch);
561                         break;
562                 case 'd' :
563                         slprintf(pidstr,sizeof(pidstr)-1, "%d",(int)sys_getpid());
564                         t = realloc_string_sub(t, "%d", pidstr);
565                         break;
566                 case 'h' :
567                         t = realloc_string_sub(t, "%h", myhostname());
568                         break;
569                 case 'm' :
570                         t = realloc_string_sub(t, "%m", remote_machine);
571                         break;
572                 case 'v' :
573                         t = realloc_string_sub(t, "%v", SAMBA_VERSION_STRING);
574                         break;
575                 case '$' :
576                         t = realloc_expand_env_var(t, p); /* Expand environment variables */
577                         break;
578                         
579                 default: 
580                         break;
581                 }
582
583                 p++;
584                 SAFE_FREE(r);
585                 if (t == NULL) goto error;
586                 a_string = t;
587         }
588
589         return a_string;
590 error:
591         SAFE_FREE(a_string);
592         return NULL;
593 }
594
595 /****************************************************************************
596  Do some specific substitutions in a string.
597  This function will return an allocated string that have to be freed.
598 ****************************************************************************/
599
600 char *talloc_sub_specified(TALLOC_CTX *mem_ctx,
601                         const char *input_string,
602                         const char *username,
603                         const char *domain,
604                         uid_t uid,
605                         gid_t gid)
606 {
607         char *a, *t;
608         a = alloc_sub_specified(input_string, username, domain, uid, gid);
609         if (!a) return NULL;
610         t = talloc_strdup(mem_ctx, a);
611         SAFE_FREE(a);
612         return t;
613 }
614
615 char *alloc_sub_specified(const char *input_string,
616                         const char *username,
617                         const char *domain,
618                         uid_t uid,
619                         gid_t gid)
620 {
621         char *a_string, *ret_string;
622         char *b, *p, *s, *t;
623
624         a_string = strdup(input_string);
625         if (a_string == NULL) {
626                 DEBUG(0, ("alloc_sub_specified: Out of memory!\n"));
627                 return NULL;
628         }
629         
630         for (b = s = a_string; (p = strchr_m(s, '%')); s = a_string + (p - b)) {
631                 
632                 b = t = a_string;
633                 
634                 switch (*(p+1)) {
635                 case 'U' : 
636                         t = realloc_string_sub(t, "%U", username);
637                         break;
638                 case 'u' : 
639                         t = realloc_string_sub(t, "%u", username);
640                         break;
641                 case 'G' :
642                         if (gid != -1) {
643                                 t = realloc_string_sub(t, "%G", gidtoname(gid));
644                         } else {
645                                 t = realloc_string_sub(t, "%G", "NO_GROUP");
646                         }
647                         break;
648                 case 'g' :
649                         if (gid != -1) {
650                                 t = realloc_string_sub(t, "%g", gidtoname(gid));
651                         } else {
652                                 t = realloc_string_sub(t, "%g", "NO_GROUP");
653                         }
654                         break;
655                 case 'D' :
656                         t = realloc_string_sub(t, "%D", domain);
657                         break;
658                 case 'N' : 
659                         t = realloc_string_sub(t, "%N", automount_server(username)); 
660                         break;
661                 default: 
662                         break;
663                 }
664
665                 p++;
666                 if (t == NULL) {
667                         SAFE_FREE(a_string);
668                         return NULL;
669                 }
670                 a_string = t;
671         }
672
673         ret_string = alloc_sub_basic(username, a_string);
674         SAFE_FREE(a_string);
675         return ret_string;
676 }
677
678 char *talloc_sub_advanced(TALLOC_CTX *mem_ctx,
679                         int snum,
680                         const char *user,
681                         const char *connectpath,
682                         gid_t gid,
683                         const char *smb_name,
684                         const char *str)
685 {
686         char *a, *t;
687         a = alloc_sub_advanced(snum, user, connectpath, gid, smb_name, str);
688         if (!a) return NULL;
689         t = talloc_strdup(mem_ctx, a);
690         SAFE_FREE(a);
691         return t;
692 }
693
694 char *alloc_sub_advanced(int snum, const char *user, 
695                                   const char *connectpath, gid_t gid, 
696                                   const char *smb_name, const char *str)
697 {
698         char *a_string, *ret_string;
699         char *b, *p, *s, *t, *h;
700
701         a_string = strdup(str);
702         if (a_string == NULL) {
703                 DEBUG(0, ("alloc_sub_specified: Out of memory!\n"));
704                 return NULL;
705         }
706         
707         for (b = s = a_string; (p = strchr_m(s, '%')); s = a_string + (p - b)) {
708                 
709                 b = t = a_string;
710                 
711                 switch (*(p+1)) {
712                 case 'N' :
713                         t = realloc_string_sub(t, "%N", automount_server(user));
714                         break;
715                 case 'H':
716                         if ((h = get_user_home_dir(user)))
717                                 t = realloc_string_sub(t, "%H", h);
718                         break;
719                 case 'P': 
720                         t = realloc_string_sub(t, "%P", connectpath); 
721                         break;
722                 case 'S': 
723                         t = realloc_string_sub(t, "%S", lp_servicename(snum)); 
724                         break;
725                 case 'g': 
726                         t = realloc_string_sub(t, "%g", gidtoname(gid)); 
727                         break;
728                 case 'u': 
729                         t = realloc_string_sub(t, "%u", user); 
730                         break;
731                         
732                         /* Patch from jkf@soton.ac.uk Left the %N (NIS
733                          * server name) in standard_sub_basic as it is
734                          * a feature for logon servers, hence uses the
735                          * username.  The %p (NIS server path) code is
736                          * here as it is used instead of the default
737                          * "path =" string in [homes] and so needs the
738                          * service name, not the username.  */
739                 case 'p': 
740                         t = realloc_string_sub(t, "%p", automount_path(lp_servicename(snum))); 
741                         break;
742                         
743                 default: 
744                         break;
745                 }
746
747                 p++;
748                 if (t == NULL) {
749                         SAFE_FREE(a_string);
750                         return NULL;
751                 }
752                 a_string = t;
753         }
754
755         ret_string = alloc_sub_basic(smb_name, a_string);
756         SAFE_FREE(a_string);
757         return ret_string;
758 }
759
760 /****************************************************************************
761  Do some standard substitutions in a string.
762 ****************************************************************************/
763
764 void standard_sub_conn(connection_struct *conn, char *str, size_t len)
765 {
766         standard_sub_advanced(SNUM(conn), conn->user, conn->connectpath,
767                         conn->gid, smb_user_name, str, len);
768 }
769
770 char *talloc_sub_conn(TALLOC_CTX *mem_ctx, connection_struct *conn, const char *str)
771 {
772         return talloc_sub_advanced(mem_ctx, SNUM(conn), conn->user,
773                         conn->connectpath, conn->gid,
774                         smb_user_name, str);
775 }
776
777 char *alloc_sub_conn(connection_struct *conn, const char *str)
778 {
779         return alloc_sub_advanced(SNUM(conn), conn->user, conn->connectpath,
780                         conn->gid, smb_user_name, str);
781 }
782
783 /****************************************************************************
784  Like standard_sub but by snum.
785 ****************************************************************************/
786
787 void standard_sub_snum(int snum, char *str, size_t len)
788 {
789         extern struct current_user current_user;
790         static uid_t cached_uid = -1;
791         static fstring cached_user;
792         /* calling uidtoname() on every substitute would be too expensive, so
793            we cache the result here as nearly every call is for the same uid */
794
795         if (cached_uid != current_user.uid) {
796                 fstrcpy(cached_user, uidtoname(current_user.uid));
797                 cached_uid = current_user.uid;
798         }
799
800         standard_sub_advanced(snum, cached_user, "", -1,
801                               smb_user_name, str, len);
802 }