r13058: Add %w macro for the winbind seperator which allows us for example
[amitay/samba.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 'w' :
452                         string_sub(p,"%w", lp_winbind_separator(),l);
453                         break;
454                 case '$' :
455                         p += expand_env_var(p,l);
456                         break; /* Expand environment variables */
457                 case '\0': 
458                         p++; 
459                         break; /* don't run off the end of the string */
460                         
461                 default: p+=2; 
462                         break;
463                 }
464         }
465 }
466
467 static void standard_sub_advanced(int snum, const char *user, 
468                                   const char *connectpath, gid_t gid, 
469                                   const char *smb_name, char *str, size_t len)
470 {
471         char *p, *s, *home;
472
473         for (s=str; (p=strchr_m(s, '%'));s=p) {
474                 int l = (int)len - (int)(p-str);
475         
476                 if (l < 0)
477                         l = 0;
478         
479                 switch (*(p+1)) {
480                 case 'N' :
481                         string_sub(p,"%N", automount_server(user),l);
482                         break;
483                 case 'H':
484                         if ((home = get_user_home_dir(user)))
485                                 string_sub(p,"%H",home, l);
486                         else
487                                 p += 2;
488                         break;
489                 case 'P': 
490                         string_sub(p,"%P", connectpath, l); 
491                         break;
492                 case 'S': 
493                         if ( snum != -1 )
494                                 string_sub(p,"%S", lp_servicename(snum), l); 
495                         break;
496                 case 'g': 
497                         string_sub(p,"%g", gidtoname(gid), l); 
498                         break;
499                 case 'u': 
500                         string_sub(p,"%u", user, l); 
501                         break;
502                         
503                         /* Patch from jkf@soton.ac.uk Left the %N (NIS
504                          * server name) in standard_sub_basic as it is
505                          * a feature for logon servers, hence uses the
506                          * username.  The %p (NIS server path) code is
507                          * here as it is used instead of the default
508                          * "path =" string in [homes] and so needs the
509                          * service name, not the username.  */
510                 case 'p': 
511                         if ( snum != -1 )
512                                 string_sub(p,"%p", automount_path(lp_servicename(snum)), l); 
513                         break;
514                 case '\0': 
515                         p++; 
516                         break; /* don't run off the end of the string */
517                         
518                 default: p+=2; 
519                         break;
520                 }
521         }
522
523         standard_sub_basic(smb_name, str, len);
524 }
525
526 /****************************************************************************
527  Do some standard substitutions in a string.
528  This function will return an allocated string that have to be freed.
529 ****************************************************************************/
530
531 char *talloc_sub_basic(TALLOC_CTX *mem_ctx, const char *smb_name, const char *str)
532 {
533         char *a, *t;
534         a = alloc_sub_basic(smb_name, str);
535         if (!a) return NULL;
536         t = talloc_strdup(mem_ctx, a);
537         SAFE_FREE(a);
538         return t;
539 }
540
541 char *alloc_sub_basic(const char *smb_name, const char *str)
542 {
543         char *b, *p, *s, *t, *r, *a_string;
544         fstring pidstr;
545         struct passwd *pass;
546         const char *local_machine_name = get_local_machine_name();
547
548         /* workaround to prevent a crash while lookinf at bug #687 */
549         
550         if ( !str ) {
551                 DEBUG(0,("alloc_sub_basic: NULL source string!  This should not happen\n"));
552                 return NULL;
553         }
554         
555         a_string = SMB_STRDUP(str);
556         if (a_string == NULL) {
557                 DEBUG(0, ("alloc_sub_specified: Out of memory!\n"));
558                 return NULL;
559         }
560         
561         for (b = s = a_string; (p = strchr_m(s, '%')); s = a_string + (p - b)) {
562
563                 r = NULL;
564                 b = t = a_string;
565                 
566                 switch (*(p+1)) {
567                 case 'U' : 
568                         r = strdup_lower(smb_name);
569                         if (r == NULL) goto error;
570                         t = realloc_string_sub(t, "%U", r);
571                         break;
572                 case 'G' :
573                         r = SMB_STRDUP(smb_name);
574                         if (r == NULL) goto error;
575                         if ((pass = Get_Pwnam(r))!=NULL) {
576                                 t = realloc_string_sub(t, "%G", gidtoname(pass->pw_gid));
577                         } 
578                         break;
579                 case 'D' :
580                         r = strdup_upper(current_user_info.domain);
581                         if (r == NULL) goto error;
582                         t = realloc_string_sub(t, "%D", r);
583                         break;
584                 case 'I' :
585                         t = realloc_string_sub(t, "%I", client_addr());
586                         break;
587                 case 'L' : 
588                         if (local_machine_name && *local_machine_name)
589                                 t = realloc_string_sub(t, "%L", local_machine_name); 
590                         else
591                                 t = realloc_string_sub(t, "%L", global_myname()); 
592                         break;
593                 case 'N':
594                         t = realloc_string_sub(t, "%N", automount_server(smb_name));
595                         break;
596                 case 'M' :
597                         t = realloc_string_sub(t, "%M", client_name());
598                         break;
599                 case 'R' :
600                         t = realloc_string_sub(t, "%R", remote_proto);
601                         break;
602                 case 'T' :
603                         t = realloc_string_sub(t, "%T", timestring(False));
604                         break;
605                 case 'a' :
606                         t = realloc_string_sub(t, "%a", remote_arch);
607                         break;
608                 case 'd' :
609                         slprintf(pidstr,sizeof(pidstr)-1, "%d",(int)sys_getpid());
610                         t = realloc_string_sub(t, "%d", pidstr);
611                         break;
612                 case 'h' :
613                         t = realloc_string_sub(t, "%h", myhostname());
614                         break;
615                 case 'm' :
616                         t = realloc_string_sub(t, "%m", remote_machine);
617                         break;
618                 case 'v' :
619                         t = realloc_string_sub(t, "%v", SAMBA_VERSION_STRING);
620                         break;
621                 case 'w' :
622                         t = realloc_string_sub(t, "%w", lp_winbind_separator());
623                         break;
624                 case '$' :
625                         t = realloc_expand_env_var(t, p); /* Expand environment variables */
626                         break;
627                         
628                 default: 
629                         break;
630                 }
631
632                 p++;
633                 SAFE_FREE(r);
634                 if (t == NULL) goto error;
635                 a_string = t;
636         }
637
638         return a_string;
639 error:
640         SAFE_FREE(a_string);
641         return NULL;
642 }
643
644 /****************************************************************************
645  Do some specific substitutions in a string.
646  This function will return an allocated string that have to be freed.
647 ****************************************************************************/
648
649 char *talloc_sub_specified(TALLOC_CTX *mem_ctx,
650                         const char *input_string,
651                         const char *username,
652                         const char *domain,
653                         uid_t uid,
654                         gid_t gid)
655 {
656         char *a, *t;
657         a = alloc_sub_specified(input_string, username, domain, uid, gid);
658         if (!a) return NULL;
659         t = talloc_strdup(mem_ctx, a);
660         SAFE_FREE(a);
661         return t;
662 }
663
664 char *alloc_sub_specified(const char *input_string,
665                         const char *username,
666                         const char *domain,
667                         uid_t uid,
668                         gid_t gid)
669 {
670         char *a_string, *ret_string;
671         char *b, *p, *s, *t;
672
673         a_string = SMB_STRDUP(input_string);
674         if (a_string == NULL) {
675                 DEBUG(0, ("alloc_sub_specified: Out of memory!\n"));
676                 return NULL;
677         }
678         
679         for (b = s = a_string; (p = strchr_m(s, '%')); s = a_string + (p - b)) {
680                 
681                 b = t = a_string;
682                 
683                 switch (*(p+1)) {
684                 case 'U' : 
685                         t = realloc_string_sub(t, "%U", username);
686                         break;
687                 case 'u' : 
688                         t = realloc_string_sub(t, "%u", username);
689                         break;
690                 case 'G' :
691                         if (gid != -1) {
692                                 t = realloc_string_sub(t, "%G", gidtoname(gid));
693                         } else {
694                                 t = realloc_string_sub(t, "%G", "NO_GROUP");
695                         }
696                         break;
697                 case 'g' :
698                         if (gid != -1) {
699                                 t = realloc_string_sub(t, "%g", gidtoname(gid));
700                         } else {
701                                 t = realloc_string_sub(t, "%g", "NO_GROUP");
702                         }
703                         break;
704                 case 'D' :
705                         t = realloc_string_sub(t, "%D", domain);
706                         break;
707                 case 'N' : 
708                         t = realloc_string_sub(t, "%N", automount_server(username)); 
709                         break;
710                 default: 
711                         break;
712                 }
713
714                 p++;
715                 if (t == NULL) {
716                         SAFE_FREE(a_string);
717                         return NULL;
718                 }
719                 a_string = t;
720         }
721
722         ret_string = alloc_sub_basic(username, a_string);
723         SAFE_FREE(a_string);
724         return ret_string;
725 }
726
727 char *talloc_sub_advanced(TALLOC_CTX *mem_ctx,
728                         int snum,
729                         const char *user,
730                         const char *connectpath,
731                         gid_t gid,
732                         const char *smb_name,
733                         const char *str)
734 {
735         char *a, *t;
736         a = alloc_sub_advanced(snum, user, connectpath, gid, smb_name, str);
737         if (!a) return NULL;
738         t = talloc_strdup(mem_ctx, a);
739         SAFE_FREE(a);
740         return t;
741 }
742
743 char *alloc_sub_advanced(int snum, const char *user, 
744                                   const char *connectpath, gid_t gid, 
745                                   const char *smb_name, const char *str)
746 {
747         char *a_string, *ret_string;
748         char *b, *p, *s, *t, *h;
749
750         a_string = SMB_STRDUP(str);
751         if (a_string == NULL) {
752                 DEBUG(0, ("alloc_sub_specified: Out of memory!\n"));
753                 return NULL;
754         }
755         
756         for (b = s = a_string; (p = strchr_m(s, '%')); s = a_string + (p - b)) {
757                 
758                 b = t = a_string;
759                 
760                 switch (*(p+1)) {
761                 case 'N' :
762                         t = realloc_string_sub(t, "%N", automount_server(user));
763                         break;
764                 case 'H':
765                         if ((h = get_user_home_dir(user)))
766                                 t = realloc_string_sub(t, "%H", h);
767                         break;
768                 case 'P': 
769                         t = realloc_string_sub(t, "%P", connectpath); 
770                         break;
771                 case 'S': 
772                         t = realloc_string_sub(t, "%S", lp_servicename(snum)); 
773                         break;
774                 case 'g': 
775                         t = realloc_string_sub(t, "%g", gidtoname(gid)); 
776                         break;
777                 case 'u': 
778                         t = realloc_string_sub(t, "%u", user); 
779                         break;
780                         
781                         /* Patch from jkf@soton.ac.uk Left the %N (NIS
782                          * server name) in standard_sub_basic as it is
783                          * a feature for logon servers, hence uses the
784                          * username.  The %p (NIS server path) code is
785                          * here as it is used instead of the default
786                          * "path =" string in [homes] and so needs the
787                          * service name, not the username.  */
788                 case 'p': 
789                         t = realloc_string_sub(t, "%p", automount_path(lp_servicename(snum))); 
790                         break;
791                         
792                 default: 
793                         break;
794                 }
795
796                 p++;
797                 if (t == NULL) {
798                         SAFE_FREE(a_string);
799                         return NULL;
800                 }
801                 a_string = t;
802         }
803
804         ret_string = alloc_sub_basic(smb_name, a_string);
805         SAFE_FREE(a_string);
806         return ret_string;
807 }
808
809 /****************************************************************************
810  Do some standard substitutions in a string.
811 ****************************************************************************/
812
813 void standard_sub_conn(connection_struct *conn, char *str, size_t len)
814 {
815         standard_sub_advanced(SNUM(conn), conn->user, conn->connectpath,
816                         conn->gid, smb_user_name, str, len);
817 }
818
819 char *talloc_sub_conn(TALLOC_CTX *mem_ctx, connection_struct *conn, const char *str)
820 {
821         return talloc_sub_advanced(mem_ctx, SNUM(conn), conn->user,
822                         conn->connectpath, conn->gid,
823                         smb_user_name, str);
824 }
825
826 char *alloc_sub_conn(connection_struct *conn, const char *str)
827 {
828         return alloc_sub_advanced(SNUM(conn), conn->user, conn->connectpath,
829                         conn->gid, smb_user_name, str);
830 }
831
832 /****************************************************************************
833  Like standard_sub but by snum.
834 ****************************************************************************/
835
836 void standard_sub_snum(int snum, char *str, size_t len)
837 {
838         static uid_t cached_uid = -1;
839         static fstring cached_user;
840         /* calling uidtoname() on every substitute would be too expensive, so
841            we cache the result here as nearly every call is for the same uid */
842
843         if (cached_uid != current_user.uid) {
844                 fstrcpy(cached_user, uidtoname(current_user.uid));
845                 cached_uid = current_user.uid;
846         }
847
848         standard_sub_advanced(snum, cached_user, "", current_user.gid,
849                               smb_user_name, str, len);
850 }