27ca5165f9703232db2efacffb912dbf1108e47e
[sfrench/samba-autobuild/.git] / packaging / SGI / sambalp
1 #!/bin/perl
2 #
3 # Hacked by Alan Stebbens <aks@sgi.com> to setuid to the username if 
4 # valid on this system.  Written as a secure Perl script.  To enable,
5 #
6 #       chown root /usr/samba/bin/sambalp
7 #       chmod u+s,+x /usr/samba/bin/sambalp
8 #
9 # If setuidshells is not enabled on your system, you must also do this:
10 #
11 #       systune -i
12 #       nosuidshells = 0
13 #       y
14 #       quit
15 #
16 #       reboot
17 #
18 # This script will still work as a normal user; it will not try
19 # to setuid in this case.
20 #
21 # If the "$PSFIX" variable is set below...
22 #
23 # Workaround Win95 printer driver/Impressario bug by removing
24 # the PS check for available virtual memory.  Note that this
25 # bug appears to be in all Win95 print drivers that generate
26 # PostScript; but is for certain there with a QMS-PS 810 (the
27 # printer type I configure on the Win95-side for printing with
28 # Samba).
29 #
30 # the perl script fixes 3 different bugs. 
31 # 1. remove the JCL statements added by some HP printer drivers to the
32 # beginning of the postscript output. 
33 # 2. Fix a bug in output from word files with long filenames. A non-printing
34 # character added to the end of the title comment by word is 
35 # removed. 
36 # 3. The VM fix described above.
37 #
38 #
39 # Modified for Perl4 compatibility.
40 #
41
42 $PROG = "sambalp";
43
44 $PSFIX = 1;                     # set to 0 if you don't want to run
45                                 # the "psfix" portion
46
47 # Untaint the PATH variable
48 @PATH = split(' ',<<EOF);
49         /usr/sbin /usr/bsd /sbin /usr/bin /bin /usr/lib /usr/local/bin
50 EOF
51 $ENV{'PATH'} = join(':',@PATH);
52
53         print "$#ARGV ".scalar(@ARGV)."\n";
54 if (scalar(@ARGV) < 2) {
55     print STDERR "usage: $PROG printer file [user] [system]\n";
56     exit;
57 }
58
59 $printer = $ARGV[0];
60 $file    = $ARGV[1];
61 $user    = $ARGV[2];
62 $system  = $ARGV[3];
63
64 $user = "nobody" unless($user);
65 $system = `hostname` unless($system);
66
67 open(LPSTAT,"/usr/bin/lpstat -t|") || die("Can't get printer list.\n");
68 @printers = ();
69 while (<LPSTAT>) {
70     next unless /^printer (\w+)/;
71     push(@printers,$1);
72 }
73 close LPSTAT;
74 # Create a hash list
75 @printers{@printers} = @printers;
76     
77 # Untaint the printer name
78 if (defined($prtname = $printers{$printer})) {
79     $printer = $prtname;
80 } else {
81     die("Unknown printer: \"$printer\"\n");
82 }
83
84 if ($> == 0) {          # are we root?
85     # yes -- then perform a taint checks and possibly do a suid check
86
87     # Untaint the file and system names (pretend to filter them)
88     $file   =   $file =~ /^(.*)/ ? $1 : die("Bad file: $file\n");
89     $system = $system =~ /^(.*)/ ? $1 : die("Bad system: $system\n");
90
91     # Get the valid users
92     setpwent;
93     %users = ();
94     while (@pwe = getpwent()) { 
95         $uids{$pwe[0]} = $pwe[2];
96         $users{$pwe[2]} = $pwe[0];
97     }
98     endpwent();
99
100     # Check out the user -- if the user is a real user on this system,
101     # then become that user so that the  printer header page looks right
102     # otherwise, remain as the default user (probably "nobody").
103
104     if (defined($uid = $uids{$user})) {
105
106         # before we change UID, we must ensure that the file is still
107         # readable after the UID change.
108         chown($uid, 9, $file);  # make the file owned by the user
109
110         # Now, go ahead and become the user
111         $name = $users{$uid};
112         $> = $uid;              # become the user
113         $< = $uid;
114     } else {                    # do untaint filtering
115         $name = $user =~ /^(\w+)/ ? $1 : die("Bad user: $user\n");
116     }
117 } else {                        # otherwise, just be me
118     $name = $user;              # whomever that is
119 }
120
121 $lpcommand = "/usr/bin/lp -c -d$printer -t'$name on $system'";
122
123 # This code is from the original "psfix" but it has been completely
124 # rewritten for speed.
125
126 if ($PSFIX) {                   # are we running a "psfix"?
127     open(FILE, $file)           || die("Can't read $file: $!\n");
128     open(LP, "|$lpcommand -")   || die("Can't open pipe to \"lp\": $!\n");
129     select(LP);
130     while (<FILE>) {            # 
131         $_ =~ s/^\004//;                # strip any ctrl-d's
132         if (/^\e%/) {           # get rid of any non-postscript commands
133             while (<FILE>) {    # remove text until next %!PS
134                 s/^\001M//;     # lenmark driver prefixes Ctrl-A M to %!PS
135                 last if /^%!PS/;
136             }
137             last if eof(FILE);
138         } elsif (/^%%Title:/) { # fix bug in long titles from MS Word
139             s/.\r$/\r/;         # remove trailing character on the title
140         } elsif (/^\/VM\?/) {   # remove VM test
141             print "/VM? { pop } bind def\r\n";
142             while (<FILE>) { last if /def\r/; }
143             next;               # don't print
144         }
145         print;
146     }
147     close FILE;
148     close LP;
149 } else {                        # we're not running psfix?
150     system("$lpcommand $file");
151 }
152
153 if ($file =~ m(^/)) {
154         # $file is a fully specified path
155         # Remove the file only if it lives in a directory ending in /tmp.
156         unlink($file) if ($file =~ m(/tmp/[^/]+$));
157 } else {
158         # $file is NOT a fully specified path
159         # Remove the file only if current directory ends in /tmp.
160         unlink($file) if (`pwd` =~ m(/tmp$));
161 }