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