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

Annotation of /lpr-agent/lpr-agent

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.3 - (hide 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 teddy 1.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 teddy 1.2 # Author: Teddy Hogeborn <teddy@fukt.bth.se>
21 teddy 1.1 # 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 teddy 1.2 Report bugs to <teddy@fukt.bth.se>.
75 teddy 1.1 """
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 teddy 1.2 # Try to create the directory, but don't fail if it already exists.
107 teddy 1.1 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 teddy 1.2 # Try to create an unnamed socket. If we fail we call the cleanup
139 teddy 1.1 # 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 teddy 1.3 smbserver = "slade"
238     smbprinter = "rby_expen"
239 teddy 1.1 smbservice = None
240 teddy 1.3 smbserverip = "-I slade.student.bth.se"
241 teddy 1.1 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