/[cvs]/lpr-agent/lpr-agent
ViewVC logotype

Contents of /lpr-agent/lpr-agent

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.3 - (show annotations)
Tue Aug 19 20:45:28 2003 UTC (20 years, 8 months ago) by teddy
Branch: MAIN
CVS Tags: HEAD
Changes since 1.2: +3 -3 lines
Updated default values to conform to information from <URL:http://www.helpdesk.bth.se/Www/Lang_com/Faq/List.asp?TypeID=1141>.

1 #!/usr/bin/python
2 #
3 # lpr-agent - keep a password in memory and use it to print stuff
4 # Copyright (C) 2000 Teddy Hogeborn
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #
20 # Author: Teddy Hogeborn <teddy@fukt.bth.se>
21 # Folkparksv. 22
22 # 372 38 Ronneby
23 # SWEDEN
24
25 import os, errno, tempfile, sys, getopt, SocketServer, rfc822, string
26 from socket import *
27 from signal import *
28
29 # Parse the command line options and set the "c_flag" accordingly
30 optlist, args = getopt.getopt(sys.argv[1:], 'bck', ['sh', 'bourne-shell',\
31 'csh', 'c-shell',\
32 'debug', 'kill', \
33 'version', 'help'])
34
35 if ('--version', '') in optlist:
36 print """lpr-agent (lpr-agent) 1.0
37 Copyright (C) 2000 Teddy Hogeborn
38 lpr-agent comes with ABSOLUTELY NO WARRANTY.
39 You may redistribute copies of lpr-agent under the terms of the GNU
40 General Public License. For more information about these matters, see
41 the file named COPYING."""
42 sys.exit(0)
43
44 if ('--help', '') in optlist:
45 print """lpr-agent prints some shell commands to be evaluated and also forks
46 off and stays in memory, receiving commands and data on a Unix file
47 system socket. It can then be accessed with the program "lpr-client".
48
49 Usage: lpr-agent [options]
50
51 Examples of common usage:
52 Start a server and evaluate commands
53 eval `lpr-agent`
54 Start a server and evaluate commands suitable for C-shells
55 eval `lpr-agent --c-shell`
56 Kill the agent (when logging out or when not printing anymore):
57 lpr-agent --kill
58
59 Normal options:
60 -k, --kill kill the agent
61 -b, --sh, --bourne-shell print commands suitable for
62 bourne shells
63 -c, --csh, --c-shell print commands suitable for
64 c-shells
65 --version show version number
66 --help show this help
67
68 Obscure or debugging options:
69 --debug do not close stdout and stderr,
70 show debugging information on
71 stdout and lets any Python
72 errors show up on stderr
73
74 Report bugs to <teddy@fukt.bth.se>.
75 """
76 sys.exit(0)
77
78 debug_flag = ('--debug', '') in optlist
79
80 c_flag = (('-c', '') in optlist) or (('--csh', '') in optlist)\
81 or (('--c-shell', '') in optlist)
82
83 if (('-k', '') in optlist or ('--kill', '') in optlist):
84 if os.environ.has_key('LPR_AGENT_PID'):
85 try:
86 os.kill(string.atoi(os.environ['LPR_AGENT_PID']), SIGTERM)
87 except os.error, the_error:
88 if the_error[0] != errno.ESRCH:
89 raise os.error, the_error
90 else:
91 print "The agent is not running."
92 sys.exit(1)
93 else:
94 print "No agent is running."
95 sys.exit(1)
96 sys.exit(0)
97
98 # Make up a name for the directory.
99 if os.environ.has_key('TMPDIR'):
100 tempfile.template=os.environ['TMPDIR']
101 else:
102 tempfile.tempdir="/tmp"
103 tempfile.template="lpr-" + `os.getpid()` + "-"
104 socket_dir=tempfile.mktemp()
105
106 # Try to create the directory, but don't fail if it already exists.
107 try:
108 os.mkdir(socket_dir, 0700)
109 except os.error, the_error:
110 if the_error[0] != errno.EEXIST:
111 raise os.error, the_error
112 else:
113 # If the directory alread exists we should be able to change
114 # the permissions on it. If we can't, the directory is owned
115 # by someone else who is trying to fool us into using it.
116 os.chmod(socket_dir, 0700)
117
118 # Make up a name for the file/socket.
119 tempfile.tempdir=socket_dir
120 tempfile.template="agent." + `os.getpid()` + "-"
121 socket_name=tempfile.mktemp()
122
123 def cleanup_socket():
124 "Close socket, remove file and directory; called on exit."
125 try:
126 sock.shutdown(2)
127 except os.error, the_error:
128 pass
129 try:
130 os.remove(socket_name)
131 except os.error, the_error:
132 pass
133 try:
134 os.rmdir(socket_dir)
135 except os.error, the_error:
136 pass
137
138 # Try to create an unnamed socket. If we fail we call the cleanup
139 # function to remove the directory and then call the default error
140 # handler, which should abort. (The file/socket hasn't been created
141 # yet.)
142 try:
143 sock = socket(AF_UNIX, SOCK_STREAM)
144 except os.error, the_error:
145 cleanup_socket()
146 raise os.error, the_error
147
148 # Fork off a child daemon process; In the parent, just print some
149 # commands to be eval'ed by a shell and then exit.
150 pid=os.fork()
151 if pid != 0:
152 if c_flag:
153 print "setenv LPR_AUTH_SOCK " + socket_name + ";"
154 print "setenv LPR_AGENT_PID " + `pid` + ";"
155 print "echo Agent pid " + `pid` + ";"
156 else:
157 print "LPR_AUTH_SOCK=" + socket_name + "; export LPR_AUTH_SOCK;"
158 print "LPR_AGENT_PID=" + `pid` + "; export LPR_AGENT_PID;"
159 print "echo Agent pid " + `pid` + ";"
160 sys.exit(0)
161
162 # We want to become a daemon now.
163
164 # Close all standard open file descriptors
165 #sys.stdin.close()
166 null=os.open("/dev/null", os.O_NOCTTY | os.O_RDONLY)
167 os.dup2(null, sys.stdin.fileno())
168 os.close(null)
169 if not debug_flag:
170 # sys.stdout.close()
171 # sys.stderr.close()
172 null=os.open("/dev/null", os.O_NOCTTY | os.O_WRONLY)
173 os.dup2(null, sys.stdout.fileno())
174 os.dup2(null, sys.stderr.fileno())
175 os.close(null)
176
177 # Create a new process group for this process
178 os.setsid()
179
180 # On exit remove the socket and the directory
181 sys.exitfunc=cleanup_socket
182
183 signal(SIGINT, SIG_IGN)
184
185 signal(SIGHUP, lambda signum, frame: sys.exit(0))
186 signal(SIGTERM, lambda signum, frame: sys.exit(0))
187
188 # OK, we're a real daemon now.
189
190 BUFSIZE=8192
191
192 def stripcrnl(string):
193 "Return STRING with any CR or NL stripped off the end."
194 result = ""
195 if string[-1:] == '\n' or string[-1:] == '\r':
196 result = string[:-1]
197 if result[-1:] == '\n' or result[-1:] == '\r':
198 return result[:-1]
199 else:
200 return result
201
202 # Inherit a handler class to handle every connection.
203 class connectionhandler(SocketServer.BaseRequestHandler):
204 def handle(self):
205 if debug_flag:
206 print sys.argv[0] + ": server handling connection"
207 clientdata = os.fdopen(self.request.fileno(), "rb")
208 # Read first line; it has the command on it.
209 command = clientdata.readline()
210 command = stripcrnl(command)
211 if debug_flag:
212 print sys.argv[0] + ": ServerCommand: " + command
213 # Read headers, if any.
214 message = rfc822.Message(clientdata, 0)
215 if debug_flag:
216 print sys.argv[0] + ": Server EOH"
217 # Do stuff depending on command.
218 if command == "debug":
219 # Debug command, just print all the input to stdout.
220 # This is only of any use if the agent is running with
221 # --debug, i.e., has not closed stdout.
222 if debug_flag:
223 print sys.argv[0] + ": Server command: debug"
224 if debug_flag:
225 # print "password: " + agent.password
226 while 1:
227 data = clientdata.read(BUFSIZE)
228 if not data: break
229 if debug_flag:
230 sys.stdout.write(data)
231 elif command == "print":
232 # Print command, pipe the input to smbclient.
233 if debug_flag:
234 print sys.argv[0] + ": server command: print"
235 smbclientformat = "smbclient \"%s\" \"%s\" -N -P %s %s -c \"%s\""
236 # service, passwd, ip, options, command
237 smbserver = "slade"
238 smbprinter = "rby_expen"
239 smbservice = None
240 smbserverip = "-I slade.student.bth.se"
241 smbclientoptions = ""
242 smbclientcommand = "printmode graphics;print -"
243 if message.getheader('SmbClientFormat'):
244 smbclientformat = message.getheader('SmbClientFormat')
245 if message.getheader('SmbServer'):
246 smbserverip = ""
247 smbserver = message.getheader('SmbServer')
248 if message.getheader('SmbPrinter'):
249 smbprinter = message.getheader('SmbPrinter')
250 if message.getheader('SmbService'):
251 smbserver = None
252 smbprinter = None
253 smbclientip = ""
254 smbservice = message.getheader('SmbService')
255 if message.getheader('SmbServerIP'):
256 smbserverip = "-I \"" \
257 + message.getheader('SmbServerIP')\
258 + "\""
259 if message.getheader('SmbClientOptions'):
260 smbclientoptions = message.getheader('SmbClientOptions')
261 if message.getheader('SmbClientCommand'):
262 smbclientcommand = message.getheader('SmbClientCommand')
263 # If it wasn't explicitly set, set the service from the
264 # components, default or otherwise.
265 if not smbservice:
266 smbservice = "//%s/%s" % (smbserver, smbprinter)
267 pipecmd = smbclientformat % (smbservice,\
268 agent.password, \
269 smbserverip, \
270 smbclientoptions, \
271 smbclientcommand)
272 pipe = None
273 pipe = os.popen(pipecmd, "w")
274 if debug_flag:
275 print sys.argv[0] + ": Pipecmd: " + pipecmd
276 while 1:
277 data = clientdata.read(BUFSIZE)
278 if not data: break
279 if debug_flag:
280 sys.stdout.write(data)
281 else:
282 pipe.write(data)
283 #if not debug_flag:
284 pipe.close()
285 elif command == "write":
286 # Write command, write input to file specified in header.
287 # Used for testing.
288 if debug_flag:
289 print sys.argv[0] + ": server command: write"
290 outfile = open(message.getheader('Filename'), "wb")
291 while 1:
292 data = clientdata.read(BUFSIZE)
293 if not data: break
294 outfile.write(data)
295 outfile.close()
296 elif command == "password":
297 # Set password variable.
298 if debug_flag:
299 print sys.argv[0] + ": server command: password"
300 password = clientdata.readline(80)
301 agent.password = stripcrnl(password)
302 del password
303 elif command == "eval":
304 # Eval all input. May be used for extension and
305 # modification of already running agents.
306 if debug_flag:
307 print sys.argv[0] + ": server command: eval"
308 while 1:
309 line = clientdata.readline()
310 if not line: break
311 eval(line)
312 elif command == "quit":
313 clientdata.close()
314 self.request.close()
315 cleanup_socket()
316 os._exit(0)
317 else:
318 if debug_flag:
319 print sys.argv[0] + ": Unknown command '" + command + "'"
320 clientdata.close()
321 self.request.close()
322
323 ## Inherit a server agent class.
324 # class LPRAgent(ForkingMixIn, SocketServer.UnixStreamServer): pass
325 class LPRAgent(SocketServer.UnixStreamServer):
326 password = ""
327
328 # Instantiate an agent to listen on the socket and call the handler.
329 agent = LPRAgent(socket_name, connectionhandler)
330
331 if debug_flag:
332 print sys.argv[0] + ": Server starting..."
333
334 # Go go go!
335 agent.serve_forever()

root@recompile.se
ViewVC Help
Powered by ViewVC 1.1.26