summaryrefslogtreecommitdiff
path: root/lib/dotsh.pl.art
blob: 4f0f188e3c651b240535642795984f518bbf9639 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
Article 19995 of comp.lang.perl:
Newsgroups: comp.lang.perl
Path: netlabs!news.cerf.net!mvb.saic.com!MathWorks.Com!europa.eng.gtefsd.com!howland.reston.ans.net!news.ans.net!malgudi.oar.net!chemabs!skf26
From: skf26@cas.org (Scott Frost)
Subject: HOW TO source shell scripts into Perl
Message-ID: <1994Mar21.191518.11636@chemabs.uucp>
Followup-To: scott.frost@cas.org
Keywords: Shell, Source, Dot
Sender: usenet@chemabs.uucp
Organization: Chemical Abstracts Service
Date: Mon, 21 Mar 1994 19:15:18 GMT
Lines: 139

A few days ago I posted a request for information on how to source
a shell script into a perl script.  In general, the responses indicated that
it could not be done (although one came pretty close to the actual solution).

A fellow staff member (who I was posting the request for) wasn't satisfied with
the response and came up with a way.

Before I indicate how he solved the problem, let me suggest some alternative
methods of resolving this issue,

   1.  Hard code the environment variables directly in your PERL script.  This
       is easy but unreliable.  System administrators could change the
       production shell script environment variables and your PERL script would
       be hosed.

   2.  Create a shell wrapper that dots the shell script into your current
       environment and then invoke your perl script.  This approach is easy
       to do, fairly full proof, but an affront to serious PERL programmers
       who believe PERL is God's gift to man (or at least Larry's :-) ).

Chuck's solution involves running the script in the appropriate shell
environment, dumping the shell's environment variables to a file, and then
reading the environment variables into PERL's environment.

It supports ksh, sh, csh, and zsh shells.  It'll look at the first line of
the file to be executed to determine the shell to run it under, if not found,
it'll look at the SHELL environment variable.  If the shell is not one of the
four listed, it'll warn you and attempt to run the shell script under /bin/sh.

      A typical usage might look like this,
      #!/usr/bin/perl

      # Make sure dotsh.pl is placed in your /usr/perl/lib
      require "dotsh.pl";

      print "SHELL_ENV_VAR = $SHELL_ENV_VAR\n" ;
      &dotsh('/tmp/foo') ;                      # script to run
      print "SHELL_ENV_VAR = $SHELL_ENV_VAR\n" ;

      /tmp/foo looks like this:
      #!/bin/ksh
      export SHELL_ENV_VAR="hi mom"

The actual dotsh.pl script follows (BTW, this is now public domain):
#
#   @(#)dotsh.pl                                               03/19/94
#
#   Author: Charles Collins
#
#   Description:
#      This routine takes a shell script and 'dots' it into the current perl
#      environment. This makes it possible to use existing system scripts
#      to alter environment variables on the fly.
#
#   Usage:
#      &dotsh ('ShellScript', 'DependentVariable(s)');
#
#         where
#
#      'ShellScript' is the full name of the shell script to be dotted
#
#      'DependentVariable(s)' is an optional list of shell variables in the
#         form VARIABLE=VALUE,VARIABLE=VALUE,... that 'ShellScript' is
#         dependent upon. These variables MUST be defined using shell syntax.
#
#   Example:
#      &dotsh ('/tmp/foo', 'arg1');
#      &dotsh ('/tmp/foo');
#      &dotsh ('/tmp/foo arg1 ... argN');
#
sub dotsh {
   local(@sh) = @_;
   local($tmp,$key,$shell,*dotsh,$command,$args,$vars) = '';
   $dotsh = shift(@sh);
   @dotsh = split (/\s/, $dotsh);
   $command = shift (@dotsh);
   $args = join (" ", @dotsh);
   $vars = join ("\n", @sh);
   open (_SH_ENV, "$command") || die "Could not open $dotsh!\n";
   chop($_ = <_SH_ENV>);
   $shell = "$1 -c" if ($_ =~ /^\#\!\s*(\S+(\/sh|\/ksh|\/zsh|\/csh))\s*$/);
   close (_SH_ENV);
   if (!$shell) {
      if ($ENV{'SHELL'} =~ /\/sh$|\/ksh$|\/zsh$|\/csh$/) {
	 $shell = "$ENV{'SHELL'} -c";
      } else {
	 print "SHELL not recognized!\nUsing /bin/sh...\n";
	 $shell = "/bin/sh -c";
      }
   }
   if (length($vars) > 0) {
      system "$shell \"$vars;. $command $args; set > /tmp/_sh_env$$\"";
   } else {
      system "$shell \". $command $args; set > /tmp/_sh_env$$\"";
   }

   open (_SH_ENV, "/tmp/_sh_env$$") || die "Could not open /tmp/_sh_env$$!\n";
   while (<_SH_ENV>) {
       chop;
       /=/;
       $ENV{$`} = $';
   }
   close (_SH_ENV);
   system "rm -f /tmp/_sh_env$$";

   foreach $key (keys(ENV)) {
       $tmp .= "\$$key = \$ENV{'$key'};" if $key =~ /^[A-Za-z]\w*$/;
   }
   eval $tmp;
}
1;


























--
Scott K. Frost                                    INET: scott.frost@cas.org