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