diff options
author | DongHun Kwak <dh0128.kwak@samsung.com> | 2016-01-27 10:47:25 +0900 |
---|---|---|
committer | DongHun Kwak <dh0128.kwak@samsung.com> | 2016-01-27 10:47:52 +0900 |
commit | ef9b26ed48ff777f0ac2e84e92aa54a382d2b37e (patch) | |
tree | 13a008c6165a5ce4bd06a3b1dd53df91c8b01485 /scheduler | |
parent | 4daab3758f62250691d3994850ddd3a7faf80d5e (diff) | |
download | cups-ef9b26ed48ff777f0ac2e84e92aa54a382d2b37e.tar.gz cups-ef9b26ed48ff777f0ac2e84e92aa54a382d2b37e.tar.bz2 cups-ef9b26ed48ff777f0ac2e84e92aa54a382d2b37e.zip |
Imported Upstream version 2.1.2upstream/2.1.2
Change-Id: Ia36f5862c3fcaa1f053ad69ed961e1fb9043e20b
Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
Diffstat (limited to 'scheduler')
72 files changed, 6856 insertions, 7683 deletions
diff --git a/scheduler/Dependencies b/scheduler/Dependencies index 2035646..e61c288 100644 --- a/scheduler/Dependencies +++ b/scheduler/Dependencies @@ -1,264 +1,270 @@ auth.o: auth.c cupsd.h ../cups/cups-private.h ../cups/string-private.h \ ../config.h ../cups/debug-private.h ../cups/versioning.h \ - ../cups/ipp-private.h ../cups/ipp.h ../cups/http.h ../cups/array.h \ - ../cups/http-private.h ../cups/md5-private.h \ - ../cups/language-private.h ../cups/transcode.h ../cups/language.h \ - ../cups/pwg-private.h ../cups/cups.h ../cups/file.h \ + ../cups/array-private.h ../cups/array.h ../cups/ipp-private.h \ + ../cups/ipp.h ../cups/http.h ../cups/http-private.h ../cups/language.h \ + ../cups/md5-private.h ../cups/language-private.h ../cups/transcode.h \ + ../cups/pwg-private.h ../cups/cups.h ../cups/file.h ../cups/pwg.h \ ../cups/ppd-private.h ../cups/ppd.h ../cups/thread-private.h \ ../cups/file-private.h mime.h sysman.h statbuf.h cert.h auth.h \ - client.h policy.h printers.h classes.h job.h conf.h banners.h dirsvc.h \ - network.h subscriptions.h -avahi.o: avahi.c ../config.h + client.h policy.h printers.h classes.h job.h colorman.h conf.h \ + banners.h dirsvc.h network.h subscriptions.h banners.o: banners.c cupsd.h ../cups/cups-private.h \ ../cups/string-private.h ../config.h ../cups/debug-private.h \ - ../cups/versioning.h ../cups/ipp-private.h ../cups/ipp.h \ - ../cups/http.h ../cups/array.h ../cups/http-private.h \ - ../cups/md5-private.h ../cups/language-private.h ../cups/transcode.h \ - ../cups/language.h ../cups/pwg-private.h ../cups/cups.h ../cups/file.h \ - ../cups/ppd-private.h ../cups/ppd.h ../cups/thread-private.h \ - ../cups/file-private.h mime.h sysman.h statbuf.h cert.h auth.h \ - client.h policy.h printers.h classes.h job.h conf.h banners.h dirsvc.h \ - network.h subscriptions.h ../cups/dir.h + ../cups/versioning.h ../cups/array-private.h ../cups/array.h \ + ../cups/ipp-private.h ../cups/ipp.h ../cups/http.h \ + ../cups/http-private.h ../cups/language.h ../cups/md5-private.h \ + ../cups/language-private.h ../cups/transcode.h ../cups/pwg-private.h \ + ../cups/cups.h ../cups/file.h ../cups/pwg.h ../cups/ppd-private.h \ + ../cups/ppd.h ../cups/thread-private.h ../cups/file-private.h mime.h \ + sysman.h statbuf.h cert.h auth.h client.h policy.h printers.h \ + classes.h job.h colorman.h conf.h banners.h dirsvc.h network.h \ + subscriptions.h ../cups/dir.h cert.o: cert.c cupsd.h ../cups/cups-private.h ../cups/string-private.h \ ../config.h ../cups/debug-private.h ../cups/versioning.h \ - ../cups/ipp-private.h ../cups/ipp.h ../cups/http.h ../cups/array.h \ - ../cups/http-private.h ../cups/md5-private.h \ - ../cups/language-private.h ../cups/transcode.h ../cups/language.h \ - ../cups/pwg-private.h ../cups/cups.h ../cups/file.h \ + ../cups/array-private.h ../cups/array.h ../cups/ipp-private.h \ + ../cups/ipp.h ../cups/http.h ../cups/http-private.h ../cups/language.h \ + ../cups/md5-private.h ../cups/language-private.h ../cups/transcode.h \ + ../cups/pwg-private.h ../cups/cups.h ../cups/file.h ../cups/pwg.h \ ../cups/ppd-private.h ../cups/ppd.h ../cups/thread-private.h \ ../cups/file-private.h mime.h sysman.h statbuf.h cert.h auth.h \ - client.h policy.h printers.h classes.h job.h conf.h banners.h dirsvc.h \ - network.h subscriptions.h + client.h policy.h printers.h classes.h job.h colorman.h conf.h \ + banners.h dirsvc.h network.h subscriptions.h classes.o: classes.c cupsd.h ../cups/cups-private.h \ ../cups/string-private.h ../config.h ../cups/debug-private.h \ - ../cups/versioning.h ../cups/ipp-private.h ../cups/ipp.h \ - ../cups/http.h ../cups/array.h ../cups/http-private.h \ - ../cups/md5-private.h ../cups/language-private.h ../cups/transcode.h \ - ../cups/language.h ../cups/pwg-private.h ../cups/cups.h ../cups/file.h \ - ../cups/ppd-private.h ../cups/ppd.h ../cups/thread-private.h \ - ../cups/file-private.h mime.h sysman.h statbuf.h cert.h auth.h \ - client.h policy.h printers.h classes.h job.h conf.h banners.h dirsvc.h \ - network.h subscriptions.h + ../cups/versioning.h ../cups/array-private.h ../cups/array.h \ + ../cups/ipp-private.h ../cups/ipp.h ../cups/http.h \ + ../cups/http-private.h ../cups/language.h ../cups/md5-private.h \ + ../cups/language-private.h ../cups/transcode.h ../cups/pwg-private.h \ + ../cups/cups.h ../cups/file.h ../cups/pwg.h ../cups/ppd-private.h \ + ../cups/ppd.h ../cups/thread-private.h ../cups/file-private.h mime.h \ + sysman.h statbuf.h cert.h auth.h client.h policy.h printers.h \ + classes.h job.h colorman.h conf.h banners.h dirsvc.h network.h \ + subscriptions.h client.o: client.c cupsd.h ../cups/cups-private.h \ ../cups/string-private.h ../config.h ../cups/debug-private.h \ - ../cups/versioning.h ../cups/ipp-private.h ../cups/ipp.h \ - ../cups/http.h ../cups/array.h ../cups/http-private.h \ - ../cups/md5-private.h ../cups/language-private.h ../cups/transcode.h \ - ../cups/language.h ../cups/pwg-private.h ../cups/cups.h ../cups/file.h \ - ../cups/ppd-private.h ../cups/ppd.h ../cups/thread-private.h \ - ../cups/file-private.h mime.h sysman.h statbuf.h cert.h auth.h \ - client.h policy.h printers.h classes.h job.h conf.h banners.h dirsvc.h \ - network.h subscriptions.h + ../cups/versioning.h ../cups/array-private.h ../cups/array.h \ + ../cups/ipp-private.h ../cups/ipp.h ../cups/http.h \ + ../cups/http-private.h ../cups/language.h ../cups/md5-private.h \ + ../cups/language-private.h ../cups/transcode.h ../cups/pwg-private.h \ + ../cups/cups.h ../cups/file.h ../cups/pwg.h ../cups/ppd-private.h \ + ../cups/ppd.h ../cups/thread-private.h ../cups/file-private.h mime.h \ + sysman.h statbuf.h cert.h auth.h client.h policy.h printers.h \ + classes.h job.h colorman.h conf.h banners.h dirsvc.h network.h \ + subscriptions.h +colorman.o: colorman.c cupsd.h ../cups/cups-private.h \ + ../cups/string-private.h ../config.h ../cups/debug-private.h \ + ../cups/versioning.h ../cups/array-private.h ../cups/array.h \ + ../cups/ipp-private.h ../cups/ipp.h ../cups/http.h \ + ../cups/http-private.h ../cups/language.h ../cups/md5-private.h \ + ../cups/language-private.h ../cups/transcode.h ../cups/pwg-private.h \ + ../cups/cups.h ../cups/file.h ../cups/pwg.h ../cups/ppd-private.h \ + ../cups/ppd.h ../cups/thread-private.h ../cups/file-private.h mime.h \ + sysman.h statbuf.h cert.h auth.h client.h policy.h printers.h \ + classes.h job.h colorman.h conf.h banners.h dirsvc.h network.h \ + subscriptions.h conf.o: conf.c cupsd.h ../cups/cups-private.h ../cups/string-private.h \ ../config.h ../cups/debug-private.h ../cups/versioning.h \ - ../cups/ipp-private.h ../cups/ipp.h ../cups/http.h ../cups/array.h \ - ../cups/http-private.h ../cups/md5-private.h \ - ../cups/language-private.h ../cups/transcode.h ../cups/language.h \ - ../cups/pwg-private.h ../cups/cups.h ../cups/file.h \ + ../cups/array-private.h ../cups/array.h ../cups/ipp-private.h \ + ../cups/ipp.h ../cups/http.h ../cups/http-private.h ../cups/language.h \ + ../cups/md5-private.h ../cups/language-private.h ../cups/transcode.h \ + ../cups/pwg-private.h ../cups/cups.h ../cups/file.h ../cups/pwg.h \ ../cups/ppd-private.h ../cups/ppd.h ../cups/thread-private.h \ ../cups/file-private.h mime.h sysman.h statbuf.h cert.h auth.h \ - client.h policy.h printers.h classes.h job.h conf.h banners.h dirsvc.h \ - network.h subscriptions.h + client.h policy.h printers.h classes.h job.h colorman.h conf.h \ + banners.h dirsvc.h network.h subscriptions.h dirsvc.o: dirsvc.c cupsd.h ../cups/cups-private.h \ ../cups/string-private.h ../config.h ../cups/debug-private.h \ - ../cups/versioning.h ../cups/ipp-private.h ../cups/ipp.h \ - ../cups/http.h ../cups/array.h ../cups/http-private.h \ - ../cups/md5-private.h ../cups/language-private.h ../cups/transcode.h \ - ../cups/language.h ../cups/pwg-private.h ../cups/cups.h ../cups/file.h \ - ../cups/ppd-private.h ../cups/ppd.h ../cups/thread-private.h \ - ../cups/file-private.h mime.h sysman.h statbuf.h cert.h auth.h \ - client.h policy.h printers.h classes.h job.h conf.h banners.h dirsvc.h \ - network.h subscriptions.h + ../cups/versioning.h ../cups/array-private.h ../cups/array.h \ + ../cups/ipp-private.h ../cups/ipp.h ../cups/http.h \ + ../cups/http-private.h ../cups/language.h ../cups/md5-private.h \ + ../cups/language-private.h ../cups/transcode.h ../cups/pwg-private.h \ + ../cups/cups.h ../cups/file.h ../cups/pwg.h ../cups/ppd-private.h \ + ../cups/ppd.h ../cups/thread-private.h ../cups/file-private.h mime.h \ + sysman.h statbuf.h cert.h auth.h client.h policy.h printers.h \ + classes.h job.h colorman.h conf.h banners.h dirsvc.h network.h \ + subscriptions.h env.o: env.c cupsd.h ../cups/cups-private.h ../cups/string-private.h \ ../config.h ../cups/debug-private.h ../cups/versioning.h \ - ../cups/ipp-private.h ../cups/ipp.h ../cups/http.h ../cups/array.h \ - ../cups/http-private.h ../cups/md5-private.h \ - ../cups/language-private.h ../cups/transcode.h ../cups/language.h \ - ../cups/pwg-private.h ../cups/cups.h ../cups/file.h \ + ../cups/array-private.h ../cups/array.h ../cups/ipp-private.h \ + ../cups/ipp.h ../cups/http.h ../cups/http-private.h ../cups/language.h \ + ../cups/md5-private.h ../cups/language-private.h ../cups/transcode.h \ + ../cups/pwg-private.h ../cups/cups.h ../cups/file.h ../cups/pwg.h \ ../cups/ppd-private.h ../cups/ppd.h ../cups/thread-private.h \ ../cups/file-private.h mime.h sysman.h statbuf.h cert.h auth.h \ - client.h policy.h printers.h classes.h job.h conf.h banners.h dirsvc.h \ - network.h subscriptions.h + client.h policy.h printers.h classes.h job.h colorman.h conf.h \ + banners.h dirsvc.h network.h subscriptions.h file.o: file.c cupsd.h ../cups/cups-private.h ../cups/string-private.h \ ../config.h ../cups/debug-private.h ../cups/versioning.h \ - ../cups/ipp-private.h ../cups/ipp.h ../cups/http.h ../cups/array.h \ - ../cups/http-private.h ../cups/md5-private.h \ - ../cups/language-private.h ../cups/transcode.h ../cups/language.h \ - ../cups/pwg-private.h ../cups/cups.h ../cups/file.h \ + ../cups/array-private.h ../cups/array.h ../cups/ipp-private.h \ + ../cups/ipp.h ../cups/http.h ../cups/http-private.h ../cups/language.h \ + ../cups/md5-private.h ../cups/language-private.h ../cups/transcode.h \ + ../cups/pwg-private.h ../cups/cups.h ../cups/file.h ../cups/pwg.h \ ../cups/ppd-private.h ../cups/ppd.h ../cups/thread-private.h \ ../cups/file-private.h mime.h sysman.h statbuf.h cert.h auth.h \ - client.h policy.h printers.h classes.h job.h conf.h banners.h dirsvc.h \ - network.h subscriptions.h ../cups/dir.h + client.h policy.h printers.h classes.h job.h colorman.h conf.h \ + banners.h dirsvc.h network.h subscriptions.h ../cups/dir.h main.o: main.c cupsd.h ../cups/cups-private.h ../cups/string-private.h \ ../config.h ../cups/debug-private.h ../cups/versioning.h \ - ../cups/ipp-private.h ../cups/ipp.h ../cups/http.h ../cups/array.h \ - ../cups/http-private.h ../cups/md5-private.h \ - ../cups/language-private.h ../cups/transcode.h ../cups/language.h \ - ../cups/pwg-private.h ../cups/cups.h ../cups/file.h \ + ../cups/array-private.h ../cups/array.h ../cups/ipp-private.h \ + ../cups/ipp.h ../cups/http.h ../cups/http-private.h ../cups/language.h \ + ../cups/md5-private.h ../cups/language-private.h ../cups/transcode.h \ + ../cups/pwg-private.h ../cups/cups.h ../cups/file.h ../cups/pwg.h \ ../cups/ppd-private.h ../cups/ppd.h ../cups/thread-private.h \ ../cups/file-private.h mime.h sysman.h statbuf.h cert.h auth.h \ - client.h policy.h printers.h classes.h job.h conf.h banners.h dirsvc.h \ - network.h subscriptions.h + client.h policy.h printers.h classes.h job.h colorman.h conf.h \ + banners.h dirsvc.h network.h subscriptions.h ipp.o: ipp.c cupsd.h ../cups/cups-private.h ../cups/string-private.h \ ../config.h ../cups/debug-private.h ../cups/versioning.h \ - ../cups/ipp-private.h ../cups/ipp.h ../cups/http.h ../cups/array.h \ - ../cups/http-private.h ../cups/md5-private.h \ - ../cups/language-private.h ../cups/transcode.h ../cups/language.h \ - ../cups/pwg-private.h ../cups/cups.h ../cups/file.h \ + ../cups/array-private.h ../cups/array.h ../cups/ipp-private.h \ + ../cups/ipp.h ../cups/http.h ../cups/http-private.h ../cups/language.h \ + ../cups/md5-private.h ../cups/language-private.h ../cups/transcode.h \ + ../cups/pwg-private.h ../cups/cups.h ../cups/file.h ../cups/pwg.h \ ../cups/ppd-private.h ../cups/ppd.h ../cups/thread-private.h \ ../cups/file-private.h mime.h sysman.h statbuf.h cert.h auth.h \ - client.h policy.h printers.h classes.h job.h conf.h banners.h dirsvc.h \ - network.h subscriptions.h + client.h policy.h printers.h classes.h job.h colorman.h conf.h \ + banners.h dirsvc.h network.h subscriptions.h listen.o: listen.c cupsd.h ../cups/cups-private.h \ ../cups/string-private.h ../config.h ../cups/debug-private.h \ - ../cups/versioning.h ../cups/ipp-private.h ../cups/ipp.h \ - ../cups/http.h ../cups/array.h ../cups/http-private.h \ - ../cups/md5-private.h ../cups/language-private.h ../cups/transcode.h \ - ../cups/language.h ../cups/pwg-private.h ../cups/cups.h ../cups/file.h \ - ../cups/ppd-private.h ../cups/ppd.h ../cups/thread-private.h \ - ../cups/file-private.h mime.h sysman.h statbuf.h cert.h auth.h \ - client.h policy.h printers.h classes.h job.h conf.h banners.h dirsvc.h \ - network.h subscriptions.h + ../cups/versioning.h ../cups/array-private.h ../cups/array.h \ + ../cups/ipp-private.h ../cups/ipp.h ../cups/http.h \ + ../cups/http-private.h ../cups/language.h ../cups/md5-private.h \ + ../cups/language-private.h ../cups/transcode.h ../cups/pwg-private.h \ + ../cups/cups.h ../cups/file.h ../cups/pwg.h ../cups/ppd-private.h \ + ../cups/ppd.h ../cups/thread-private.h ../cups/file-private.h mime.h \ + sysman.h statbuf.h cert.h auth.h client.h policy.h printers.h \ + classes.h job.h colorman.h conf.h banners.h dirsvc.h network.h \ + subscriptions.h job.o: job.c cupsd.h ../cups/cups-private.h ../cups/string-private.h \ ../config.h ../cups/debug-private.h ../cups/versioning.h \ - ../cups/ipp-private.h ../cups/ipp.h ../cups/http.h ../cups/array.h \ - ../cups/http-private.h ../cups/md5-private.h \ - ../cups/language-private.h ../cups/transcode.h ../cups/language.h \ - ../cups/pwg-private.h ../cups/cups.h ../cups/file.h \ + ../cups/array-private.h ../cups/array.h ../cups/ipp-private.h \ + ../cups/ipp.h ../cups/http.h ../cups/http-private.h ../cups/language.h \ + ../cups/md5-private.h ../cups/language-private.h ../cups/transcode.h \ + ../cups/pwg-private.h ../cups/cups.h ../cups/file.h ../cups/pwg.h \ ../cups/ppd-private.h ../cups/ppd.h ../cups/thread-private.h \ ../cups/file-private.h mime.h sysman.h statbuf.h cert.h auth.h \ - client.h policy.h printers.h classes.h job.h conf.h banners.h dirsvc.h \ - network.h subscriptions.h ../cups/backend.h ../cups/dir.h + client.h policy.h printers.h classes.h job.h colorman.h conf.h \ + banners.h dirsvc.h network.h subscriptions.h ../cups/backend.h \ + ../cups/dir.h log.o: log.c cupsd.h ../cups/cups-private.h ../cups/string-private.h \ ../config.h ../cups/debug-private.h ../cups/versioning.h \ - ../cups/ipp-private.h ../cups/ipp.h ../cups/http.h ../cups/array.h \ - ../cups/http-private.h ../cups/md5-private.h \ - ../cups/language-private.h ../cups/transcode.h ../cups/language.h \ - ../cups/pwg-private.h ../cups/cups.h ../cups/file.h \ - ../cups/ppd-private.h ../cups/ppd.h ../cups/thread-private.h \ - ../cups/file-private.h mime.h sysman.h statbuf.h cert.h auth.h \ - client.h policy.h printers.h classes.h job.h conf.h banners.h dirsvc.h \ - network.h subscriptions.h -network.o: network.c ../cups/http-private.h ../config.h ../cups/http.h \ - ../cups/versioning.h ../cups/array.h ../cups/md5-private.h \ - ../cups/ipp-private.h ../cups/ipp.h cupsd.h ../cups/cups-private.h \ - ../cups/string-private.h ../cups/debug-private.h \ - ../cups/language-private.h ../cups/transcode.h ../cups/language.h \ - ../cups/pwg-private.h ../cups/cups.h ../cups/file.h \ + ../cups/array-private.h ../cups/array.h ../cups/ipp-private.h \ + ../cups/ipp.h ../cups/http.h ../cups/http-private.h ../cups/language.h \ + ../cups/md5-private.h ../cups/language-private.h ../cups/transcode.h \ + ../cups/pwg-private.h ../cups/cups.h ../cups/file.h ../cups/pwg.h \ ../cups/ppd-private.h ../cups/ppd.h ../cups/thread-private.h \ ../cups/file-private.h mime.h sysman.h statbuf.h cert.h auth.h \ - client.h policy.h printers.h classes.h job.h conf.h banners.h dirsvc.h \ - network.h subscriptions.h + client.h policy.h printers.h classes.h job.h colorman.h conf.h \ + banners.h dirsvc.h network.h subscriptions.h +network.o: network.c ../cups/http-private.h ../config.h \ + ../cups/language.h ../cups/array.h ../cups/versioning.h ../cups/http.h \ + ../cups/md5-private.h ../cups/ipp-private.h ../cups/ipp.h cupsd.h \ + ../cups/cups-private.h ../cups/string-private.h \ + ../cups/debug-private.h ../cups/array-private.h \ + ../cups/language-private.h ../cups/transcode.h ../cups/pwg-private.h \ + ../cups/cups.h ../cups/file.h ../cups/pwg.h ../cups/ppd-private.h \ + ../cups/ppd.h ../cups/thread-private.h ../cups/file-private.h mime.h \ + sysman.h statbuf.h cert.h auth.h client.h policy.h printers.h \ + classes.h job.h colorman.h conf.h banners.h dirsvc.h network.h \ + subscriptions.h policy.o: policy.c cupsd.h ../cups/cups-private.h \ ../cups/string-private.h ../config.h ../cups/debug-private.h \ - ../cups/versioning.h ../cups/ipp-private.h ../cups/ipp.h \ - ../cups/http.h ../cups/array.h ../cups/http-private.h \ - ../cups/md5-private.h ../cups/language-private.h ../cups/transcode.h \ - ../cups/language.h ../cups/pwg-private.h ../cups/cups.h ../cups/file.h \ - ../cups/ppd-private.h ../cups/ppd.h ../cups/thread-private.h \ - ../cups/file-private.h mime.h sysman.h statbuf.h cert.h auth.h \ - client.h policy.h printers.h classes.h job.h conf.h banners.h dirsvc.h \ - network.h subscriptions.h + ../cups/versioning.h ../cups/array-private.h ../cups/array.h \ + ../cups/ipp-private.h ../cups/ipp.h ../cups/http.h \ + ../cups/http-private.h ../cups/language.h ../cups/md5-private.h \ + ../cups/language-private.h ../cups/transcode.h ../cups/pwg-private.h \ + ../cups/cups.h ../cups/file.h ../cups/pwg.h ../cups/ppd-private.h \ + ../cups/ppd.h ../cups/thread-private.h ../cups/file-private.h mime.h \ + sysman.h statbuf.h cert.h auth.h client.h policy.h printers.h \ + classes.h job.h colorman.h conf.h banners.h dirsvc.h network.h \ + subscriptions.h printers.o: printers.c cupsd.h ../cups/cups-private.h \ ../cups/string-private.h ../config.h ../cups/debug-private.h \ - ../cups/versioning.h ../cups/ipp-private.h ../cups/ipp.h \ - ../cups/http.h ../cups/array.h ../cups/http-private.h \ - ../cups/md5-private.h ../cups/language-private.h ../cups/transcode.h \ - ../cups/language.h ../cups/pwg-private.h ../cups/cups.h ../cups/file.h \ - ../cups/ppd-private.h ../cups/ppd.h ../cups/thread-private.h \ - ../cups/file-private.h mime.h sysman.h statbuf.h cert.h auth.h \ - client.h policy.h printers.h classes.h job.h conf.h banners.h dirsvc.h \ - network.h subscriptions.h ../cups/dir.h + ../cups/versioning.h ../cups/array-private.h ../cups/array.h \ + ../cups/ipp-private.h ../cups/ipp.h ../cups/http.h \ + ../cups/http-private.h ../cups/language.h ../cups/md5-private.h \ + ../cups/language-private.h ../cups/transcode.h ../cups/pwg-private.h \ + ../cups/cups.h ../cups/file.h ../cups/pwg.h ../cups/ppd-private.h \ + ../cups/ppd.h ../cups/thread-private.h ../cups/file-private.h mime.h \ + sysman.h statbuf.h cert.h auth.h client.h policy.h printers.h \ + classes.h job.h colorman.h conf.h banners.h dirsvc.h network.h \ + subscriptions.h ../cups/dir.h process.o: process.c cupsd.h ../cups/cups-private.h \ ../cups/string-private.h ../config.h ../cups/debug-private.h \ - ../cups/versioning.h ../cups/ipp-private.h ../cups/ipp.h \ - ../cups/http.h ../cups/array.h ../cups/http-private.h \ - ../cups/md5-private.h ../cups/language-private.h ../cups/transcode.h \ - ../cups/language.h ../cups/pwg-private.h ../cups/cups.h ../cups/file.h \ - ../cups/ppd-private.h ../cups/ppd.h ../cups/thread-private.h \ - ../cups/file-private.h mime.h sysman.h statbuf.h cert.h auth.h \ - client.h policy.h printers.h classes.h job.h conf.h banners.h dirsvc.h \ - network.h subscriptions.h + ../cups/versioning.h ../cups/array-private.h ../cups/array.h \ + ../cups/ipp-private.h ../cups/ipp.h ../cups/http.h \ + ../cups/http-private.h ../cups/language.h ../cups/md5-private.h \ + ../cups/language-private.h ../cups/transcode.h ../cups/pwg-private.h \ + ../cups/cups.h ../cups/file.h ../cups/pwg.h ../cups/ppd-private.h \ + ../cups/ppd.h ../cups/thread-private.h ../cups/file-private.h mime.h \ + sysman.h statbuf.h cert.h auth.h client.h policy.h printers.h \ + classes.h job.h colorman.h conf.h banners.h dirsvc.h network.h \ + subscriptions.h quotas.o: quotas.c cupsd.h ../cups/cups-private.h \ ../cups/string-private.h ../config.h ../cups/debug-private.h \ - ../cups/versioning.h ../cups/ipp-private.h ../cups/ipp.h \ - ../cups/http.h ../cups/array.h ../cups/http-private.h \ - ../cups/md5-private.h ../cups/language-private.h ../cups/transcode.h \ - ../cups/language.h ../cups/pwg-private.h ../cups/cups.h ../cups/file.h \ - ../cups/ppd-private.h ../cups/ppd.h ../cups/thread-private.h \ - ../cups/file-private.h mime.h sysman.h statbuf.h cert.h auth.h \ - client.h policy.h printers.h classes.h job.h conf.h banners.h dirsvc.h \ - network.h subscriptions.h + ../cups/versioning.h ../cups/array-private.h ../cups/array.h \ + ../cups/ipp-private.h ../cups/ipp.h ../cups/http.h \ + ../cups/http-private.h ../cups/language.h ../cups/md5-private.h \ + ../cups/language-private.h ../cups/transcode.h ../cups/pwg-private.h \ + ../cups/cups.h ../cups/file.h ../cups/pwg.h ../cups/ppd-private.h \ + ../cups/ppd.h ../cups/thread-private.h ../cups/file-private.h mime.h \ + sysman.h statbuf.h cert.h auth.h client.h policy.h printers.h \ + classes.h job.h colorman.h conf.h banners.h dirsvc.h network.h \ + subscriptions.h select.o: select.c cupsd.h ../cups/cups-private.h \ ../cups/string-private.h ../config.h ../cups/debug-private.h \ - ../cups/versioning.h ../cups/ipp-private.h ../cups/ipp.h \ - ../cups/http.h ../cups/array.h ../cups/http-private.h \ - ../cups/md5-private.h ../cups/language-private.h ../cups/transcode.h \ - ../cups/language.h ../cups/pwg-private.h ../cups/cups.h ../cups/file.h \ - ../cups/ppd-private.h ../cups/ppd.h ../cups/thread-private.h \ - ../cups/file-private.h mime.h sysman.h statbuf.h cert.h auth.h \ - client.h policy.h printers.h classes.h job.h conf.h banners.h dirsvc.h \ - network.h subscriptions.h -server.o: server.c ../cups/http-private.h ../config.h ../cups/http.h \ - ../cups/versioning.h ../cups/array.h ../cups/md5-private.h \ - ../cups/ipp-private.h ../cups/ipp.h cupsd.h ../cups/cups-private.h \ - ../cups/string-private.h ../cups/debug-private.h \ - ../cups/language-private.h ../cups/transcode.h ../cups/language.h \ - ../cups/pwg-private.h ../cups/cups.h ../cups/file.h \ - ../cups/ppd-private.h ../cups/ppd.h ../cups/thread-private.h \ - ../cups/file-private.h mime.h sysman.h statbuf.h cert.h auth.h \ - client.h policy.h printers.h classes.h job.h conf.h banners.h dirsvc.h \ - network.h subscriptions.h + ../cups/versioning.h ../cups/array-private.h ../cups/array.h \ + ../cups/ipp-private.h ../cups/ipp.h ../cups/http.h \ + ../cups/http-private.h ../cups/language.h ../cups/md5-private.h \ + ../cups/language-private.h ../cups/transcode.h ../cups/pwg-private.h \ + ../cups/cups.h ../cups/file.h ../cups/pwg.h ../cups/ppd-private.h \ + ../cups/ppd.h ../cups/thread-private.h ../cups/file-private.h mime.h \ + sysman.h statbuf.h cert.h auth.h client.h policy.h printers.h \ + classes.h job.h colorman.h conf.h banners.h dirsvc.h network.h \ + subscriptions.h +server.o: server.c ../cups/http-private.h ../config.h ../cups/language.h \ + ../cups/array.h ../cups/versioning.h ../cups/http.h \ + ../cups/md5-private.h ../cups/ipp-private.h ../cups/ipp.h cupsd.h \ + ../cups/cups-private.h ../cups/string-private.h \ + ../cups/debug-private.h ../cups/array-private.h \ + ../cups/language-private.h ../cups/transcode.h ../cups/pwg-private.h \ + ../cups/cups.h ../cups/file.h ../cups/pwg.h ../cups/ppd-private.h \ + ../cups/ppd.h ../cups/thread-private.h ../cups/file-private.h mime.h \ + sysman.h statbuf.h cert.h auth.h client.h policy.h printers.h \ + classes.h job.h colorman.h conf.h banners.h dirsvc.h network.h \ + subscriptions.h statbuf.o: statbuf.c cupsd.h ../cups/cups-private.h \ ../cups/string-private.h ../config.h ../cups/debug-private.h \ - ../cups/versioning.h ../cups/ipp-private.h ../cups/ipp.h \ - ../cups/http.h ../cups/array.h ../cups/http-private.h \ - ../cups/md5-private.h ../cups/language-private.h ../cups/transcode.h \ - ../cups/language.h ../cups/pwg-private.h ../cups/cups.h ../cups/file.h \ - ../cups/ppd-private.h ../cups/ppd.h ../cups/thread-private.h \ - ../cups/file-private.h mime.h sysman.h statbuf.h cert.h auth.h \ - client.h policy.h printers.h classes.h job.h conf.h banners.h dirsvc.h \ - network.h subscriptions.h + ../cups/versioning.h ../cups/array-private.h ../cups/array.h \ + ../cups/ipp-private.h ../cups/ipp.h ../cups/http.h \ + ../cups/http-private.h ../cups/language.h ../cups/md5-private.h \ + ../cups/language-private.h ../cups/transcode.h ../cups/pwg-private.h \ + ../cups/cups.h ../cups/file.h ../cups/pwg.h ../cups/ppd-private.h \ + ../cups/ppd.h ../cups/thread-private.h ../cups/file-private.h mime.h \ + sysman.h statbuf.h cert.h auth.h client.h policy.h printers.h \ + classes.h job.h colorman.h conf.h banners.h dirsvc.h network.h \ + subscriptions.h subscriptions.o: subscriptions.c cupsd.h ../cups/cups-private.h \ ../cups/string-private.h ../config.h ../cups/debug-private.h \ - ../cups/versioning.h ../cups/ipp-private.h ../cups/ipp.h \ - ../cups/http.h ../cups/array.h ../cups/http-private.h \ - ../cups/md5-private.h ../cups/language-private.h ../cups/transcode.h \ - ../cups/language.h ../cups/pwg-private.h ../cups/cups.h ../cups/file.h \ - ../cups/ppd-private.h ../cups/ppd.h ../cups/thread-private.h \ - ../cups/file-private.h mime.h sysman.h statbuf.h cert.h auth.h \ - client.h policy.h printers.h classes.h job.h conf.h banners.h dirsvc.h \ - network.h subscriptions.h + ../cups/versioning.h ../cups/array-private.h ../cups/array.h \ + ../cups/ipp-private.h ../cups/ipp.h ../cups/http.h \ + ../cups/http-private.h ../cups/language.h ../cups/md5-private.h \ + ../cups/language-private.h ../cups/transcode.h ../cups/pwg-private.h \ + ../cups/cups.h ../cups/file.h ../cups/pwg.h ../cups/ppd-private.h \ + ../cups/ppd.h ../cups/thread-private.h ../cups/file-private.h mime.h \ + sysman.h statbuf.h cert.h auth.h client.h policy.h printers.h \ + classes.h job.h colorman.h conf.h banners.h dirsvc.h network.h \ + subscriptions.h sysman.o: sysman.c cupsd.h ../cups/cups-private.h \ ../cups/string-private.h ../config.h ../cups/debug-private.h \ - ../cups/versioning.h ../cups/ipp-private.h ../cups/ipp.h \ - ../cups/http.h ../cups/array.h ../cups/http-private.h \ - ../cups/md5-private.h ../cups/language-private.h ../cups/transcode.h \ - ../cups/language.h ../cups/pwg-private.h ../cups/cups.h ../cups/file.h \ - ../cups/ppd-private.h ../cups/ppd.h ../cups/thread-private.h \ - ../cups/file-private.h mime.h sysman.h statbuf.h cert.h auth.h \ - client.h policy.h printers.h classes.h job.h conf.h banners.h dirsvc.h \ - network.h subscriptions.h -timeout.o: timeout.c cupsd.h ../cups/cups-private.h \ - ../cups/string-private.h ../config.h ../cups/debug-private.h \ - ../cups/versioning.h ../cups/ipp-private.h ../cups/ipp.h \ - ../cups/http.h ../cups/array.h ../cups/http-private.h \ - ../cups/md5-private.h ../cups/language-private.h ../cups/transcode.h \ - ../cups/language.h ../cups/pwg-private.h ../cups/cups.h ../cups/file.h \ - ../cups/ppd-private.h ../cups/ppd.h ../cups/thread-private.h \ - ../cups/file-private.h mime.h sysman.h statbuf.h cert.h auth.h \ - client.h policy.h printers.h classes.h job.h conf.h banners.h dirsvc.h \ - network.h subscriptions.h -tls.o: tls.c cupsd.h ../cups/cups-private.h ../cups/string-private.h \ - ../config.h ../cups/debug-private.h ../cups/versioning.h \ - ../cups/ipp-private.h ../cups/ipp.h ../cups/http.h ../cups/array.h \ - ../cups/http-private.h ../cups/md5-private.h \ - ../cups/language-private.h ../cups/transcode.h ../cups/language.h \ - ../cups/pwg-private.h ../cups/cups.h ../cups/file.h \ - ../cups/ppd-private.h ../cups/ppd.h ../cups/thread-private.h \ - ../cups/file-private.h mime.h sysman.h statbuf.h cert.h auth.h \ - client.h policy.h printers.h classes.h job.h conf.h banners.h dirsvc.h \ - network.h subscriptions.h tls-darwin.c + ../cups/versioning.h ../cups/array-private.h ../cups/array.h \ + ../cups/ipp-private.h ../cups/ipp.h ../cups/http.h \ + ../cups/http-private.h ../cups/language.h ../cups/md5-private.h \ + ../cups/language-private.h ../cups/transcode.h ../cups/pwg-private.h \ + ../cups/cups.h ../cups/file.h ../cups/pwg.h ../cups/ppd-private.h \ + ../cups/ppd.h ../cups/thread-private.h ../cups/file-private.h mime.h \ + sysman.h statbuf.h cert.h auth.h client.h policy.h printers.h \ + classes.h job.h colorman.h conf.h banners.h dirsvc.h network.h \ + subscriptions.h filter.o: filter.c ../cups/string-private.h ../config.h \ ../cups/debug-private.h ../cups/versioning.h mime.h ../cups/array.h \ ../cups/ipp.h ../cups/http.h ../cups/file.h @@ -271,59 +277,60 @@ type.o: type.c ../cups/string-private.h ../config.h \ ../cups/ipp.h ../cups/http.h ../cups/file.h cupsfilter.o: cupsfilter.c ../cups/cups-private.h \ ../cups/string-private.h ../config.h ../cups/debug-private.h \ - ../cups/versioning.h ../cups/ipp-private.h ../cups/ipp.h \ - ../cups/http.h ../cups/array.h ../cups/http-private.h \ - ../cups/md5-private.h ../cups/language-private.h ../cups/transcode.h \ - ../cups/language.h ../cups/pwg-private.h ../cups/cups.h ../cups/file.h \ - ../cups/ppd-private.h ../cups/ppd.h ../cups/thread-private.h \ - ../cups/file-private.h mime.h + ../cups/versioning.h ../cups/array-private.h ../cups/array.h \ + ../cups/ipp-private.h ../cups/ipp.h ../cups/http.h \ + ../cups/http-private.h ../cups/language.h ../cups/md5-private.h \ + ../cups/language-private.h ../cups/transcode.h ../cups/pwg-private.h \ + ../cups/cups.h ../cups/file.h ../cups/pwg.h ../cups/ppd-private.h \ + ../cups/ppd.h ../cups/thread-private.h ../cups/file-private.h mime.h cups-deviced.o: cups-deviced.c util.h ../cups/array-private.h \ ../cups/array.h ../cups/versioning.h ../cups/file-private.h \ ../cups/cups-private.h ../cups/string-private.h ../config.h \ ../cups/debug-private.h ../cups/ipp-private.h ../cups/ipp.h \ - ../cups/http.h ../cups/http-private.h ../cups/md5-private.h \ - ../cups/language-private.h ../cups/transcode.h ../cups/language.h \ - ../cups/pwg-private.h ../cups/cups.h ../cups/file.h \ + ../cups/http.h ../cups/http-private.h ../cups/language.h \ + ../cups/md5-private.h ../cups/language-private.h ../cups/transcode.h \ + ../cups/pwg-private.h ../cups/cups.h ../cups/file.h ../cups/pwg.h \ ../cups/ppd-private.h ../cups/ppd.h ../cups/thread-private.h \ ../cups/dir.h -cups-exec.o: cups-exec.c ../cups/string-private.h ../config.h +cups-exec.o: cups-exec.c ../cups/string-private.h ../config.h \ + ../cups/file.h ../cups/versioning.h cups-lpd.o: cups-lpd.c ../cups/cups-private.h ../cups/string-private.h \ ../config.h ../cups/debug-private.h ../cups/versioning.h \ - ../cups/ipp-private.h ../cups/ipp.h ../cups/http.h ../cups/array.h \ - ../cups/http-private.h ../cups/md5-private.h \ - ../cups/language-private.h ../cups/transcode.h ../cups/language.h \ - ../cups/pwg-private.h ../cups/cups.h ../cups/file.h \ + ../cups/array-private.h ../cups/array.h ../cups/ipp-private.h \ + ../cups/ipp.h ../cups/http.h ../cups/http-private.h ../cups/language.h \ + ../cups/md5-private.h ../cups/language-private.h ../cups/transcode.h \ + ../cups/pwg-private.h ../cups/cups.h ../cups/file.h ../cups/pwg.h \ ../cups/ppd-private.h ../cups/ppd.h ../cups/thread-private.h testlpd.o: testlpd.c ../cups/cups.h ../cups/file.h ../cups/versioning.h \ ../cups/ipp.h ../cups/http.h ../cups/array.h ../cups/language.h \ - ../cups/string-private.h ../config.h + ../cups/pwg.h ../cups/string-private.h ../config.h testmime.o: testmime.c ../cups/string-private.h ../config.h ../cups/dir.h \ ../cups/versioning.h ../cups/debug-private.h ../cups/ppd-private.h \ ../cups/cups.h ../cups/file.h ../cups/ipp.h ../cups/http.h \ - ../cups/array.h ../cups/language.h ../cups/ppd.h ../cups/pwg-private.h \ - mime.h + ../cups/array.h ../cups/language.h ../cups/pwg.h ../cups/ppd.h \ + ../cups/pwg-private.h mime.h testspeed.o: testspeed.c ../cups/string-private.h ../config.h \ ../cups/cups.h ../cups/file.h ../cups/versioning.h ../cups/ipp.h \ - ../cups/http.h ../cups/array.h ../cups/language.h \ + ../cups/http.h ../cups/array.h ../cups/language.h ../cups/pwg.h \ ../cups/debug-private.h testsub.o: testsub.c ../cups/cups.h ../cups/file.h ../cups/versioning.h \ ../cups/ipp.h ../cups/http.h ../cups/array.h ../cups/language.h \ - ../cups/debug-private.h ../cups/string-private.h ../config.h \ - ../cups/ipp-private.h + ../cups/pwg.h ../cups/debug-private.h ../cups/string-private.h \ + ../config.h ../cups/ipp-private.h util.o: util.c util.h ../cups/array-private.h ../cups/array.h \ ../cups/versioning.h ../cups/file-private.h ../cups/cups-private.h \ ../cups/string-private.h ../config.h ../cups/debug-private.h \ ../cups/ipp-private.h ../cups/ipp.h ../cups/http.h \ - ../cups/http-private.h ../cups/md5-private.h \ - ../cups/language-private.h ../cups/transcode.h ../cups/language.h \ - ../cups/pwg-private.h ../cups/cups.h ../cups/file.h \ - ../cups/ppd-private.h ../cups/ppd.h ../cups/thread-private.h + ../cups/http-private.h ../cups/language.h ../cups/md5-private.h \ + ../cups/language-private.h ../cups/transcode.h ../cups/pwg-private.h \ + ../cups/cups.h ../cups/file.h ../cups/pwg.h ../cups/ppd-private.h \ + ../cups/ppd.h ../cups/thread-private.h cups-driverd.o: cups-driverd.cxx util.h ../cups/array-private.h \ ../cups/array.h ../cups/versioning.h ../cups/file-private.h \ ../cups/cups-private.h ../cups/string-private.h ../config.h \ ../cups/debug-private.h ../cups/ipp-private.h ../cups/ipp.h \ - ../cups/http.h ../cups/http-private.h ../cups/md5-private.h \ - ../cups/language-private.h ../cups/transcode.h ../cups/language.h \ - ../cups/pwg-private.h ../cups/cups.h ../cups/file.h \ + ../cups/http.h ../cups/http-private.h ../cups/language.h \ + ../cups/md5-private.h ../cups/language-private.h ../cups/transcode.h \ + ../cups/pwg-private.h ../cups/cups.h ../cups/file.h ../cups/pwg.h \ ../cups/ppd-private.h ../cups/ppd.h ../cups/thread-private.h \ ../cups/dir.h ../ppdc/ppdc.h diff --git a/scheduler/Makefile b/scheduler/Makefile index 2790569..c7d244d 100644 --- a/scheduler/Makefile +++ b/scheduler/Makefile @@ -1,16 +1,16 @@ # -# "$Id: Makefile 11173 2013-07-23 12:31:34Z msweet $" +# "$Id: Makefile 12519 2015-02-17 13:10:19Z msweet $" # -# Scheduler Makefile for CUPS. +# Scheduler Makefile for CUPS. # -# Copyright 2007-2012 by Apple Inc. -# Copyright 1997-2007 by Easy Software Products, all rights reserved. +# Copyright 2007-2015 by Apple Inc. +# Copyright 1997-2007 by Easy Software Products, all rights reserved. # -# These coded instructions, statements, and computer programs are the -# property of Apple Inc. and are protected by Federal copyright -# law. Distribution and use rights are outlined in the file "LICENSE.txt" -# which should have been included with this file. If this file is -# file is missing or damaged, see the license at "http://www.cups.org/". +# These coded instructions, statements, and computer programs are the +# property of Apple Inc. and are protected by Federal copyright +# law. Distribution and use rights are outlined in the file "LICENSE.txt" +# which should have been included with this file. If this file is +# file is missing or damaged, see the license at "http://www.cups.org/". # include ../Makedefs @@ -40,8 +40,7 @@ CUPSDOBJS = \ server.o \ statbuf.o \ subscriptions.o \ - sysman.o \ - tls.o + sysman.o LIBOBJS = \ filter.o \ mime.o \ @@ -114,7 +113,7 @@ unittests: $(UNITTARGETS) clean: $(RM) $(OBJS) $(RM) $(TARGETS) $(UNITTARGETS) convert - $(RM) libcupsmime.so libcupsmime.sl libcupsmime.dylib + $(RM) libcupsmime.so libcupsmime.dylib # @@ -172,7 +171,7 @@ install-data: echo Creating $(REQUESTS)/tmp... $(INSTALL_DIR) -m 1770 -g $(CUPS_GROUP) $(REQUESTS)/tmp echo Creating $(CACHEDIR)... - $(INSTALL_DIR) -m 775 -g $(CUPS_GROUP) $(CACHEDIR) + $(INSTALL_DIR) -m 770 -g $(CUPS_GROUP) $(CACHEDIR) if test "x$(INITDIR)" != x; then \ echo Installing init scripts...; \ $(INSTALL_DIR) -m 755 $(BUILDROOT)$(INITDIR)/init.d; \ @@ -180,32 +179,36 @@ install-data: for level in $(RCLEVELS); do \ $(INSTALL_DIR) -m 755 $(BUILDROOT)$(INITDIR)/rc$${level}.d; \ $(LN) ../init.d/cups $(BUILDROOT)$(INITDIR)/rc$${level}.d/S$(RCSTART)cups; \ - if test `uname` = HP-UX; then \ - level=`expr $$level - 1`; \ - $(INSTALL_DIR) -m 755 $(BUILDROOT)$(INITDIR)/rc$${level}.d; \ - fi; \ $(LN) ../init.d/cups $(BUILDROOT)$(INITDIR)/rc$${level}.d/K$(RCSTOP)cups; \ done; \ $(INSTALL_DIR) -m 755 $(BUILDROOT)$(INITDIR)/rc0.d; \ $(LN) ../init.d/cups $(BUILDROOT)$(INITDIR)/rc0.d/K$(RCSTOP)cups; \ fi - if test "x$(INITDIR)" = x -a "x$(INITDDIR)" != x; then \ - $(INSTALL_DIR) $(BUILDROOT)$(INITDDIR); \ - if test "$(INITDDIR)" = "/System/Library/LaunchDaemons"; then \ - echo Installing LaunchDaemons configuration files...; \ - $(INSTALL_DATA) org.cups.cupsd.plist $(BUILDROOT)$(DEFAULT_LAUNCHD_CONF); \ - $(INSTALL_DATA) org.cups.cups-lpd.plist $(BUILDROOT)/System/Library/LaunchDaemons; \ - else \ - echo Installing RC script...; \ - $(INSTALL_SCRIPT) cups.sh $(BUILDROOT)$(INITDDIR)/cups; \ - fi \ + if test "x$(INITDDIR)" != x; then \ + echo Installing init script...; \ + $(INSTALL_DIR) -m 755 $(BUILDROOT)$(INITDDIR); \ + $(INSTALL_SCRIPT) cups.sh $(BUILDROOT)$(INITDDIR); \ + fi + if test "x$(LAUNCHD_DIR)" != x; then \ + echo Installing launchd configuration files...; \ + $(INSTALL_DIR) $(BUILDROOT)$(LAUNCHD_DIR); \ + $(INSTALL_DATA) org.cups.cupsd.plist $(BUILDROOT)$(LAUNCHD_DIR); \ + $(INSTALL_DATA) org.cups.cups-lpd.plist $(BUILDROOT)$(LAUNCHD_DIR); \ fi if test "x$(SMFMANIFESTDIR)" != x; then \ echo Installing SMF manifest in $(SMFMANIFESTDIR)...;\ $(INSTALL_DIR) $(BUILDROOT)/$(SMFMANIFESTDIR); \ $(INSTALL_SCRIPT) cups.xml $(BUILDROOT)$(SMFMANIFESTDIR)/cups.xml; \ fi - if test "x$(XINETD)" != x; then \ + if test "x$(SYSTEMD_DIR)" != x; then \ + echo Installing systemd configuration files...; \ + $(INSTALL_DIR) $(BUILDROOT)$(SYSTEMD_DIR); \ + $(INSTALL_DATA) org.cups.cupsd.path $(BUILDROOT)$(SYSTEMD_DIR); \ + $(INSTALL_DATA) org.cups.cupsd.service $(BUILDROOT)$(SYSTEMD_DIR); \ + $(INSTALL_DATA) org.cups.cupsd.socket $(BUILDROOT)$(SYSTEMD_DIR); \ + $(INSTALL_DATA) org.cups.cups-lpdAT.service $(BUILDROOT)$(SYSTEMD_DIR)/org.cups.cups-lpd@.service; \ + $(INSTALL_DATA) org.cups.cups-lpd.socket $(BUILDROOT)$(SYSTEMD_DIR); \ + elif test "x$(XINETD)" != x; then \ echo Installing xinetd configuration file for cups-lpd...; \ $(INSTALL_DIR) -m 755 $(BUILDROOT)$(XINETD); \ $(INSTALL_DATA) cups-lpd.xinetd $(BUILDROOT)$(XINETD)/cups-lpd; \ @@ -232,6 +235,7 @@ install-exec: $(INSTALL_DIR) $(SYMROOT); \ for file in $(PROGRAMS); do \ cp $$file $(SYMROOT); \ + dsymutil $(SYMROOT)/$$file; \ done \ fi @@ -254,7 +258,7 @@ install-libs: $(INSTALLSTATIC) echo Installing libraries in $(LIBDIR)... $(INSTALL_DIR) -m 755 $(LIBDIR) $(INSTALL_LIB) $(LIBCUPSMIME) $(LIBDIR) - if test $(LIBCUPSMIME) = "libcupsmime.so.1" -o $(LIBCUPSMIME) = "libcupsmime.sl.1"; then \ + if test $(LIBCUPSMIME) = "libcupsmime.so.1"; then \ $(RM) $(LIBDIR)/`basename $(LIBCUPSMIME) .1`; \ $(LN) $(LIBCUPSMIME) $(LIBDIR)/`basename $(LIBCUPSMIME) .1`; \ fi @@ -265,6 +269,7 @@ install-libs: $(INSTALLSTATIC) if test "x$(SYMROOT)" != "x"; then \ $(INSTALL_DIR) $(SYMROOT); \ cp $(LIBCUPSMIME) $(SYMROOT); \ + dsymutil $(SYMROOT)/$(LIBCUPSMIME); \ fi installstatic: @@ -285,7 +290,6 @@ uninstall: $(RM) $(SERVERBIN)/daemon/cups-driverd $(RM) $(SERVERBIN)/daemon/cups-exec $(RM) $(SERVERBIN)/daemon/cups-lpd - $(RM) $(BUILDROOT)/System/Library/Printers/Libraries/convert -$(RMDIR) $(STATEDIR)/certs -$(RMDIR) $(STATEDIR) -$(RMDIR) $(SERVERROOT)/ppd @@ -302,16 +306,13 @@ uninstall: $(RM) $(LIBDIR)/libcupsmime.1.dylib $(RM) $(LIBDIR)/libcupsmime.a $(RM) $(LIBDIR)/libcupsmime.dylib - $(RM) $(LIBDIR)/libcupsmime_s.a - $(RM) $(LIBDIR)/libcupsmime.sl - $(RM) $(LIBDIR)/libcupsmime.sl.1 $(RM) $(LIBDIR)/libcupsmime.so $(RM) $(LIBDIR)/libcupsmime.so.1 -$(RMDIR) $(LIBDIR) $(RM) $(INCLUDEDIR)/cups/mime.h -$(RMDIR) $(INCLUDEDIR)/cups - echo Uninstalling startup script... if test "x$(INITDIR)" != x; then \ + echo Uninstalling init scripts...; \ $(RM) $(BUILDROOT)$(INITDIR)/init.d/cups; \ $(RMDIR) $(BUILDROOT)$(INITDIR)/init.d; \ $(RM) $(BUILDROOT)$(INITDIR)/rc0.d/K00cups; \ @@ -323,23 +324,24 @@ uninstall: $(RM) $(BUILDROOT)$(INITDIR)/rc5.d/S99cups; \ $(RMDIR) $(BUILDROOT)$(INITDIR)/rc5.d; \ fi - if test "x$(INITDIR)" = x -a "x$(INITDDIR)" != x; then \ - if test "$(INITDDIR)" = "/System/Library/StartupItems/PrintingServices"; then \ - $(RM) $(BUILDROOT)$(INITDDIR)/PrintingServices; \ - $(RM) $(BUILDROOT)$(INITDDIR)/StartupParameters.plist; \ - $(RM) $(BUILDROOT)$(INITDDIR)/Resources/English.lproj/Localizable.strings; \ - $(RMDIR) $(BUILDROOT)$(INITDDIR)/Resources/English.lproj; \ - elif test "$(INITDDIR)" = "/System/Library/LaunchDaemons"; then \ - $(RM) $(BUILDROOT)$(INITDDIR)/org.cups.cupsd.plist; \ - $(RM) $(BUILDROOT)$(INITDDIR)/org.cups.cups-lpd.plist; \ - $(RMDIR) $(BUILDROOT)/System/Library/StartupItems/PrintingServices; \ - else \ - $(INSTALL_SCRIPT) init/cups.sh $(BUILDROOT)$(INITDDIR)/cups; \ - fi \ + if test "x$(INITDDIR)" != x; then \ + echo Uninstalling startup script...; \ + $(RM) $(BUILDROOT)$(INITDDIR)/cups.sh; \ $(RMDIR) $(BUILDROOT)$(INITDDIR); \ fi + if test "x$LAUNCHD_DIR" != x; then \ + echo Uninstalling launchd files...; \ + $(RM) $(BUILDROOT)$(LAUNCHD_DIR)/org.cups.cupsd.plist; \ + $(RM) $(BUILDROOT)$(LAUNCHD_DIR)/org.cups.cups-lpd.plist; \ + fi + if test "x$SYSTEMD_DIR" != x; then \ + echo Uninstalling systemd files...; \ + $(RM) $(BUILDROOT)$(SYSTEMD_DIR)/org.cups.cupsd.path; \ + $(RM) $(BUILDROOT)$(SYSTEMD_DIR)/org.cups.cupsd.service; \ + $(RM) $(BUILDROOT)$(SYSTEMD_DIR)/org.cups.cupsd.socket; \ + fi if test "x$(SMFMANIFESTDIR)" != x; then \ - echo Uninstalling SMF manifest in $(SMFMANIFESTDIR)...;\ + echo Uninstalling SMF manifest file...;\ $(RM) $(BUILDROOT)$(SMFMANIFESTDIR)/cups.xml; \ fi if test "x$(XINETD)" != x; then \ @@ -378,18 +380,16 @@ cupsd: $(CUPSDOBJS) $(LIBCUPSMIME) ../cups/$(LIBCUPS) echo Linking $@... $(CC) $(LDFLAGS) -o cupsd $(CUPSDOBJS) -L. -lcupsmime \ $(LIBZ) $(SSLLIBS) $(LIBSLP) $(LIBLDAP) $(PAMLIBS) \ - $(LIBPAPER) $(LIBMALLOC) $(SERVERLIBS) $(DNSSDLIBS) $(LIBS) \ - $(LIBGSSAPI) $(LIBWRAP) + $(LIBPAPER) $(LIBMALLOC) $(SERVERLIBS) $(ONDEMANDLIBS) \ + $(DNSSDLIBS) $(LIBS) $(LIBGSSAPI) $(LIBWRAP) cupsd-static: $(CUPSDOBJS) libcupsmime.a ../cups/$(LIBCUPSSTATIC) echo Linking $@... $(CC) $(LDFLAGS) -o cupsd-static $(CUPSDOBJS) libcupsmime.a \ $(LIBZ) $(SSLLIBS) $(LIBSLP) $(LIBLDAP) $(PAMLIBS) \ ../cups/$(LIBCUPSSTATIC) $(COMMONLIBS) $(LIBZ) $(LIBPAPER) \ - $(LIBMALLOC) $(SERVERLIBS) $(DNSSDLIBS) $(LIBGSSAPI) \ - $(LIBWRAP) - -tls.o: tls-darwin.c tls-gnutls.c tls-openssl.c + $(LIBMALLOC) $(SERVERLIBS) $(ONDEMANDLIBS) $(DNSSDLIBS) \ + $(LIBGSSAPI) $(LIBWRAP) # @@ -402,6 +402,12 @@ cupsfilter: cupsfilter.o $(LIBCUPSMIME) ../cups/$(LIBCUPS) $(RM) convert $(LN) cupsfilter convert +cupsfilter-static: cupsfilter.o libcupsmime.a ../cups/$(LIBCUPSSTATIC) + echo Linking $@... + $(CC) $(LDFLAGS) -o cupsfilter-static cupsfilter.o libcupsmime.a \ + ../cups/$(LIBCUPSSTATIC) $(COMMONLIBS) $(LIBZ) $(SSLLIBS) \ + $(DNSSDLIBS) $(LIBGSSAPI) + # # Make the device daemon, "cups-deviced". @@ -441,10 +447,10 @@ cups-lpd: cups-lpd.o ../cups/$(LIBCUPS) # -# libcupsmime.so.1, libcupsmime.sl.1 +# libcupsmime.so.1 # -libcupsmime.so.1 libcupsmime.sl.1: $(LIBOBJS) +libcupsmime.so.1: $(LIBOBJS) echo Linking $@... $(DSO) $(ARCHFLAGS) $(DSOFLAGS) -o $@ $(LIBOBJS) $(LIBS) $(RM) `basename $@ .1` @@ -468,17 +474,6 @@ libcupsmime.1.dylib: $(LIBOBJS) libcupsmime.exp # -# libcupsmime_s.a -# - -libcupsmime_s.a: $(LIBOBJS) - echo Creating $@... - $(DSO) $(DSOFLAGS) -o libcupsmime_s.o $(LIBOBJS) $(LIBS) - $(RM) $@ - $(AR) $(ARFLAGS) $@ libcupsmime_s.o - - -# # libcupsmime.la # @@ -559,5 +554,5 @@ include Dependencies # -# End of "$Id: Makefile 11173 2013-07-23 12:31:34Z msweet $". +# End of "$Id: Makefile 12519 2015-02-17 13:10:19Z msweet $". # diff --git a/scheduler/auth.c b/scheduler/auth.c index 1169adf..ac9badc 100644 --- a/scheduler/auth.c +++ b/scheduler/auth.c @@ -1,51 +1,19 @@ /* - * "$Id: auth.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: auth.c 12945 2015-10-26 19:46:02Z msweet $" * - * Authorization routines for the CUPS scheduler. + * Authorization routines for the CUPS scheduler. * - * Copyright 2007-2012 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. + * Copyright 2007-2015 by Apple Inc. + * Copyright 1997-2007 by Easy Software Products, all rights reserved. * - * This file contains Kerberos support code, copyright 2006 by - * Jelmer Vernooij. + * This file contains Kerberos support code, copyright 2006 by + * Jelmer Vernooij. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * cupsdAddIPMask() - Add an IP address authorization mask. - * cupsdAddLocation() - Add a location for authorization. - * cupsdAddName() - Add a name to a location... - * cupsdAddNameMask() - Add a host or interface name authorization - * mask. - * cupsdAuthorize() - Validate any authorization credentials. - * cupsdCheckAccess() - Check whether the given address is allowed to - * access a location. - * cupsdCheckAuth() - Check authorization masks. - * cupsdCheckGroup() - Check for a user's group membership. - * cupsdCopyLocation() - Make a copy of a location... - * cupsdDeleteAllLocations() - Free all memory used for location - * authorization. - * cupsdFindBest() - Find the location entry that best matches the - * resource. - * cupsdFindLocation() - Find the named location. - * cupsdFreeLocation() - Free all memory used by a location. - * cupsdIsAuthorized() - Check to see if the user is authorized... - * cupsdNewLocation() - Create a new location for authorization. - * check_authref() - Check if an authorization services reference - * has the supplied right. - * compare_locations() - Compare two locations. - * copy_authmask() - Copy function for auth masks. - * cups_crypt() - Encrypt the password using the DES or MD5 - * algorithms, as needed. - * free_authmask() - Free function for auth masks. - * get_md5_password() - Get an MD5 password. - * pam_func() - PAM conversation function. - * to64() - Base64-encode an integer value... + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -67,9 +35,6 @@ # include <security/pam_appl.h> # endif /* HAVE_PAM_PAM_APPL_H */ #endif /* HAVE_LIBPAM */ -#ifdef HAVE_USERSEC_H -# include <usersec.h> -#endif /* HAVE_USERSEC_H */ #ifdef HAVE_MEMBERSHIP_H # include <membership.h> #endif /* HAVE_MEMBERSHIP_H */ @@ -108,16 +73,14 @@ static int check_authref(cupsd_client_t *con, const char *right); static int compare_locations(cupsd_location_t *a, cupsd_location_t *b); static cupsd_authmask_t *copy_authmask(cupsd_authmask_t *am, void *data); -#if !HAVE_LIBPAM && !defined(HAVE_USERSEC_H) +#if !HAVE_LIBPAM static char *cups_crypt(const char *pw, const char *salt); -#endif /* !HAVE_LIBPAM && !HAVE_USERSEC_H */ +#endif /* !HAVE_LIBPAM */ static void free_authmask(cupsd_authmask_t *am, void *data); -static char *get_md5_password(const char *username, - const char *group, char passwd[33]); #if HAVE_LIBPAM static int pam_func(int, const struct pam_message **, struct pam_response **, void *); -#elif !defined(HAVE_USERSEC_H) +#else static void to64(char *s, unsigned long v, int n); #endif /* HAVE_LIBPAM */ @@ -136,15 +99,6 @@ typedef struct cupsd_authdata_s /**** Authentication data ****/ /* - * Local globals... - */ - -#if defined(__hpux) && HAVE_LIBPAM -static cupsd_authdata_t *auth_data; /* Current client being authenticated */ -#endif /* __hpux && HAVE_LIBPAM */ - - -/* * 'cupsdAddIPMask()' - Add an IP address authorization mask. */ @@ -157,12 +111,7 @@ cupsdAddIPMask( cupsd_authmask_t temp; /* New host/domain mask */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdAddIPMask(masks=%p(%p), address=%x:%x:%x:%x, " - "netmask=%x:%x:%x:%x)", - masks, *masks, - address[0], address[1], address[2], address[3], - netmask[0], netmask[1], netmask[2], netmask[3]); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddIPMask(masks=%p(%p), address=%x:%x:%x:%x, netmask=%x:%x:%x:%x)", masks, *masks, address[0], address[1], address[2], address[3], netmask[0], netmask[1], netmask[2], netmask[3]); temp.type = CUPSD_AUTH_IP; memcpy(temp.mask.ip.address, address, sizeof(temp.mask.ip.address)); @@ -202,8 +151,7 @@ cupsdAddLocation(cupsd_location_t *loc) /* I - Location to add */ { cupsArrayAdd(Locations, loc); - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddLocation: Added location \"%s\"", - loc->location ? loc->location : "(null)"); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddLocation: Added location \"%s\"", loc->location ? loc->location : "(null)"); } } @@ -216,8 +164,7 @@ void cupsdAddName(cupsd_location_t *loc, /* I - Location to add to */ char *name) /* I - Name to add */ { - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddName(loc=%p, name=\"%s\")", - loc, name); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddName(loc=%p, name=\"%s\")", loc, name); if (!loc->names) loc->names = cupsArrayNew3(NULL, NULL, NULL, 0, @@ -247,9 +194,7 @@ cupsdAddNameMask(cups_array_t **masks, /* IO - Masks array (created as needed) * *ifptr; /* Pointer to end of name */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdAddNameMask(masks=%p(%p), name=\"%s\")", - masks, *masks, name); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddNameMask(masks=%p(%p), name=\"%s\")", masks, *masks, name); if (!_cups_strcasecmp(name, "@LOCAL")) { @@ -326,26 +271,6 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ password[HTTP_MAX_VALUE]; /* Password string */ cupsd_cert_t *localuser; /* Certificate username */ - char nonce[HTTP_MAX_VALUE], /* Nonce value from client */ - md5[33], /* MD5 password */ - basicmd5[33]; /* MD5 of Basic password */ - static const char * const states[] = /* HTTP client states... */ - { - "WAITING", - "OPTIONS", - "GET", - "GET", - "HEAD", - "POST", - "POST", - "POST", - "PUT", - "PUT", - "DELETE", - "TRACE", - "CLOSE", - "STATUS" - }; /* @@ -353,13 +278,10 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ * authentication to expect... */ - con->best = cupsdFindBest(con->uri, con->http.state); + con->best = cupsdFindBest(con->uri, httpGetState(con->http)); con->type = CUPSD_AUTH_NONE; - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "[Client %d] con->uri=\"%s\", con->best=%p(%s)", - con->http.fd, con->uri, con->best, - con->best ? con->best->location : ""); + cupsdLogClient(con, CUPSD_LOG_DEBUG2, "con->uri=\"%s\", con->best=%p(%s)", con->uri, con->best, con->best ? con->best->location : ""); if (con->best && con->best->type != CUPSD_AUTH_NONE) { @@ -375,10 +297,7 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ * Decode the Authorization string... */ - authorization = httpGetField(&con->http, HTTP_FIELD_AUTHORIZATION); - - cupsdLogMessage(CUPSD_LOG_DEBUG2, "[Client %d] Authorization=\"%s\"", - con->http.fd, authorization); + authorization = httpGetField(con->http, HTTP_FIELD_AUTHORIZATION); username[0] = '\0'; password[0] = '\0'; @@ -401,16 +320,16 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ * No authorization data provided, return early... */ - cupsdLogMessage(CUPSD_LOG_DEBUG, - "[Client %d] No authentication data provided.", - con->http.fd); + cupsdLogClient(con, CUPSD_LOG_DEBUG, "No authentication data provided."); return; } #ifdef HAVE_AUTHORIZATION_H else if (!strncmp(authorization, "AuthRef ", 8) && - !_cups_strcasecmp(con->http.hostname, "localhost")) + httpAddrLocalhost(httpGetAddress(con->http))) { OSStatus status; /* Status */ + char authdata[HTTP_MAX_VALUE]; + /* Nonce value from client */ int authlen; /* Auth string length */ AuthorizationItemSet *authinfo; /* Authorization item set */ @@ -422,24 +341,18 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ while (isspace(*authorization & 255)) authorization ++; - authlen = sizeof(nonce); - httpDecode64_2(nonce, &authlen, authorization); + authlen = sizeof(authdata); + httpDecode64_2(authdata, &authlen, authorization); if (authlen != kAuthorizationExternalFormLength) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] External Authorization reference size is " - "incorrect.", con->http.fd); + cupsdLogClient(con, CUPSD_LOG_ERROR, "External Authorization reference size is incorrect."); return; } - if ((status = AuthorizationCreateFromExternalForm( - (AuthorizationExternalForm *)nonce, &con->authref)) != 0) + if ((status = AuthorizationCreateFromExternalForm((AuthorizationExternalForm *)authdata, &con->authref)) != 0) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] AuthorizationCreateFromExternalForm " - "returned %d (%s)", con->http.fd, (int)status, - cssmErrorString(status)); + cupsdLogClient(con, CUPSD_LOG_ERROR, "AuthorizationCreateFromExternalForm returned %d (%s)", (int)status, cssmErrorString(status)); return; } @@ -453,9 +366,7 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ { strlcpy(username, authinfo->items[0].value, sizeof(username)); - cupsdLogMessage(CUPSD_LOG_DEBUG, - "[Client %d] Authorized as \"%s\" using AuthRef", - con->http.fd, username); + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Authorized as \"%s\" using AuthRef.", username); } AuthorizationFreeItemSet(authinfo); @@ -473,28 +384,21 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ peersize = sizeof(peercred); - if (getsockopt(con->http.fd, 0, LOCAL_PEERCRED, &peercred, &peersize)) + if (getsockopt(httpGetFd(con->http), 0, LOCAL_PEERCRED, &peercred, &peersize)) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Unable to get peer credentials - %s", - con->http.fd, strerror(errno)); + cupsdLogClient(con, CUPSD_LOG_ERROR, "Unable to get peer credentials - %s", strerror(errno)); return; } if ((pwd = getpwuid(CUPSD_UCRED_UID(peercred))) == NULL) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Unable to find UID %d for peer " - "credentials.", con->http.fd, - (int)CUPSD_UCRED_UID(peercred)); + cupsdLogClient(con, CUPSD_LOG_ERROR, "Unable to find UID %d for peer credentials.", (int)CUPSD_UCRED_UID(peercred)); return; } strlcpy(username, pwd->pw_name, sizeof(username)); - cupsdLogMessage(CUPSD_LOG_DEBUG, - "[Client %d] Authorized as \"%s\" using " - "AuthRef + PeerCred", con->http.fd, username); + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Authorized as \"%s\" using AuthRef + PeerCred.", username); } con->type = CUPSD_AUTH_BASIC; @@ -502,7 +406,7 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ #endif /* HAVE_AUTHORIZATION_H */ #if defined(SO_PEERCRED) && defined(AF_LOCAL) else if (!strncmp(authorization, "PeerCred ", 9) && - con->http.hostaddr->addr.sa_family == AF_LOCAL) + con->http->hostaddr->addr.sa_family == AF_LOCAL && con->best) { /* * Use peer credentials from domain socket connection... @@ -539,50 +443,37 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ if (no_peer) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] PeerCred authentication not allowed for " - "resource per AUTHKEY policy.", con->http.fd); + cupsdLogClient(con, CUPSD_LOG_ERROR, "PeerCred authentication not allowed for resource per AUTHKEY policy."); return; } #endif /* HAVE_AUTHORIZATION_H */ if ((pwd = getpwnam(authorization + 9)) == NULL) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] User \"%s\" does not exist.", con->http.fd, - authorization + 9); + cupsdLogClient(con, CUPSD_LOG_ERROR, "User \"%s\" does not exist.", authorization + 9); return; } peersize = sizeof(peercred); # ifdef __APPLE__ - if (getsockopt(con->http.fd, 0, LOCAL_PEERCRED, &peercred, &peersize)) + if (getsockopt(httpGetFd(con->http), 0, LOCAL_PEERCRED, &peercred, &peersize)) # else - if (getsockopt(con->http.fd, SOL_SOCKET, SO_PEERCRED, &peercred, &peersize)) + if (getsockopt(httpGetFd(con->http), SOL_SOCKET, SO_PEERCRED, &peercred, &peersize)) # endif /* __APPLE__ */ { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Unable to get peer credentials - %s", - con->http.fd, strerror(errno)); + cupsdLogClient(con, CUPSD_LOG_ERROR, "Unable to get peer credentials - %s", strerror(errno)); return; } if (pwd->pw_uid != CUPSD_UCRED_UID(peercred)) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Invalid peer credentials for \"%s\" - got " - "%d, expected %d!", con->http.fd, authorization + 9, - CUPSD_UCRED_UID(peercred), pwd->pw_uid); + cupsdLogClient(con, CUPSD_LOG_ERROR, "Invalid peer credentials for \"%s\" - got %d, expected %d.", authorization + 9, CUPSD_UCRED_UID(peercred), pwd->pw_uid); # ifdef HAVE_SYS_UCRED_H - cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] cr_version=%d", - con->http.fd, peercred.cr_version); - cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] cr_uid=%d", - con->http.fd, peercred.cr_uid); - cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] cr_ngroups=%d", - con->http.fd, peercred.cr_ngroups); - cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] cr_groups[0]=%d", - con->http.fd, peercred.cr_groups[0]); + cupsdLogClient(con, CUPSD_LOG_DEBUG2, "cr_version=%d", peercred.cr_version); + cupsdLogClient(con, CUPSD_LOG_DEBUG2, "cr_uid=%d", peercred.cr_uid); + cupsdLogClient(con, CUPSD_LOG_DEBUG2, "cr_ngroups=%d", peercred.cr_ngroups); + cupsdLogClient(con, CUPSD_LOG_DEBUG2, "cr_groups[0]=%d", peercred.cr_groups[0]); # endif /* HAVE_SYS_UCRED_H */ return; } @@ -593,15 +484,13 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ con->gss_uid = CUPSD_UCRED_UID(peercred); # endif /* HAVE_GSSAPI */ - cupsdLogMessage(CUPSD_LOG_DEBUG, - "[Client %d] Authorized as %s using PeerCred", con->http.fd, - username); + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Authorized as %s using PeerCred.", username); con->type = CUPSD_AUTH_BASIC; } #endif /* SO_PEERCRED && AF_LOCAL */ else if (!strncmp(authorization, "Local", 5) && - !_cups_strcasecmp(con->http.hostname, "localhost")) + httpAddrLocalhost(httpGetAddress(con->http))) { /* * Get Local certificate authentication data... @@ -613,18 +502,14 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ if ((localuser = cupsdFindCert(authorization)) == NULL) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Local authentication certificate not found.", - con->http.fd); + cupsdLogClient(con, CUPSD_LOG_ERROR, "Local authentication certificate not found."); return; } strlcpy(username, localuser->username, sizeof(username)); con->type = localuser->type; - cupsdLogMessage(CUPSD_LOG_DEBUG, - "[Client %d] Authorized as %s using Local", con->http.fd, - username); + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Authorized as %s using Local.", username); } else if (!strncmp(authorization, "Basic", 5)) { @@ -648,8 +533,7 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ if ((ptr = strchr(username, ':')) == NULL) { - cupsdLogMessage(CUPSD_LOG_ERROR, "[Client %d] Missing Basic password.", - con->http.fd); + cupsdLogClient(con, CUPSD_LOG_ERROR, "Missing Basic password."); return; } @@ -661,8 +545,7 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ * Username must not be empty... */ - cupsdLogMessage(CUPSD_LOG_ERROR, "[Client %d] Empty Basic username.", - con->http.fd); + cupsdLogClient(con, CUPSD_LOG_ERROR, "Empty Basic username."); return; } @@ -672,8 +555,7 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ * Password must not be empty... */ - cupsdLogMessage(CUPSD_LOG_ERROR, "[Client %d] Empty Basic password.", - con->http.fd); + cupsdLogClient(con, CUPSD_LOG_ERROR, "Empty Basic password."); return; } @@ -703,59 +585,40 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ strlcpy(data.username, username, sizeof(data.username)); strlcpy(data.password, password, sizeof(data.password)); -# if defined(__sun) || defined(__hpux) +# ifdef __sun pamdata.conv = (int (*)(int, struct pam_message **, struct pam_response **, void *))pam_func; # else pamdata.conv = pam_func; -# endif /* __sun || __hpux */ +# endif /* __sun */ pamdata.appdata_ptr = &data; -# ifdef __hpux - /* - * Workaround for HP-UX bug in pam_unix; see pam_func() below for - * more info... - */ - - auth_data = &data; -# endif /* __hpux */ - pamerr = pam_start("cups", username, &pamdata, &pamh); if (pamerr != PAM_SUCCESS) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] pam_start() returned %d (%s)", - con->http.fd, pamerr, pam_strerror(pamh, pamerr)); + cupsdLogClient(con, CUPSD_LOG_ERROR, "pam_start() returned %d (%s)", pamerr, pam_strerror(pamh, pamerr)); return; } # ifdef HAVE_PAM_SET_ITEM # ifdef PAM_RHOST - pamerr = pam_set_item(pamh, PAM_RHOST, con->http.hostname); + pamerr = pam_set_item(pamh, PAM_RHOST, con->http->hostname); if (pamerr != PAM_SUCCESS) - cupsdLogMessage(CUPSD_LOG_WARN, - "[Client %d] pam_set_item(PAM_RHOST) " - "returned %d (%s)", con->http.fd, pamerr, - pam_strerror(pamh, pamerr)); + cupsdLogClient(con, CUPSD_LOG_WARN, "pam_set_item(PAM_RHOST) returned %d (%s)", pamerr, pam_strerror(pamh, pamerr)); # endif /* PAM_RHOST */ # ifdef PAM_TTY pamerr = pam_set_item(pamh, PAM_TTY, "cups"); if (pamerr != PAM_SUCCESS) - cupsdLogMessage(CUPSD_LOG_WARN, - "[Client %d] pam_set_item(PAM_TTY) " - "returned %d (%s)!", con->http.fd, pamerr, - pam_strerror(pamh, pamerr)); + cupsdLogClient(con, CUPSD_LOG_WARN, "pam_set_item(PAM_TTY) returned %d (%s)", pamerr, pam_strerror(pamh, pamerr)); # endif /* PAM_TTY */ # endif /* HAVE_PAM_SET_ITEM */ pamerr = pam_authenticate(pamh, PAM_SILENT); if (pamerr != PAM_SUCCESS) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] pam_authenticate() returned %d (%s)", - con->http.fd, pamerr, pam_strerror(pamh, pamerr)); + cupsdLogClient(con, CUPSD_LOG_ERROR, "pam_authenticate() returned %d (%s)", pamerr, pam_strerror(pamh, pamerr)); pam_end(pamh, 0); return; } @@ -763,47 +626,19 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ # ifdef HAVE_PAM_SETCRED pamerr = pam_setcred(pamh, PAM_ESTABLISH_CRED | PAM_SILENT); if (pamerr != PAM_SUCCESS) - cupsdLogMessage(CUPSD_LOG_WARN, - "[Client %d] pam_setcred() returned %d (%s)", - con->http.fd, pamerr, - pam_strerror(pamh, pamerr)); + cupsdLogClient(con, CUPSD_LOG_WARN, "pam_setcred() returned %d (%s)", pamerr, pam_strerror(pamh, pamerr)); # endif /* HAVE_PAM_SETCRED */ pamerr = pam_acct_mgmt(pamh, PAM_SILENT); if (pamerr != PAM_SUCCESS) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] pam_acct_mgmt() returned %d (%s)", - con->http.fd, pamerr, pam_strerror(pamh, pamerr)); + cupsdLogClient(con, CUPSD_LOG_ERROR, "pam_acct_mgmt() returned %d (%s)", pamerr, pam_strerror(pamh, pamerr)); pam_end(pamh, 0); return; } pam_end(pamh, PAM_SUCCESS); -#elif defined(HAVE_USERSEC_H) - /* - * Use AIX authentication interface... - */ - - char *authmsg; /* Authentication message */ - int reenter; /* ??? */ - - - cupsdLogMessage(CUPSD_LOG_DEBUG, - "[Client %d] AIX authenticate of username \"%s\"", - con->http.fd, username); - - reenter = 1; - if (authenticate(username, password, &reenter, &authmsg) != 0) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "[Client %d] Unable to authenticate username " - "\"%s\": %s", con->http.fd, username, - strerror(errno)); - return; - } - #else /* * Use normal UNIX password file-based authentication... @@ -825,9 +660,7 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ * No such user... */ - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Unknown username \"%s\".", - con->http.fd, username); + cupsdLogClient(con, CUPSD_LOG_ERROR, "Unknown username \"%s\".", username); return; } @@ -841,9 +674,7 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ * Don't allow blank passwords! */ - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Username \"%s\" has no shadow " - "password.", con->http.fd, username); + cupsdLogClient(con, CUPSD_LOG_ERROR, "Username \"%s\" has no shadow password.", username); return; } @@ -856,9 +687,7 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ * Don't allow blank passwords! */ - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Username \"%s\" has no password.", - con->http.fd, username); + cupsdLogClient(con, CUPSD_LOG_ERROR, "Username \"%s\" has no password.", username); return; } @@ -869,10 +698,6 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ pass = cups_crypt(password, pw->pw_passwd); - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "[Client %d] pw_passwd=\"%s\", crypt=\"%s\"", - con->http.fd, pw->pw_passwd, pass); - if (!pass || strcmp(pw->pw_passwd, pass)) { # ifdef HAVE_SHADOW_H @@ -880,143 +705,28 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ { pass = cups_crypt(password, spw->sp_pwdp); - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "[Client %d] sp_pwdp=\"%s\", crypt=\"%s\"", - con->http.fd, spw->sp_pwdp, pass); - if (pass == NULL || strcmp(spw->sp_pwdp, pass)) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Authentication failed for user " - "\"%s\".", con->http.fd, username); + cupsdLogClient(con, CUPSD_LOG_ERROR, "Authentication failed for user \"%s\".", username); return; } } else # endif /* HAVE_SHADOW_H */ { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Authentication failed for user " - "\"%s\".", con->http.fd, username); + cupsdLogClient(con, CUPSD_LOG_ERROR, "Authentication failed for user \"%s\".", username); return; } } #endif /* HAVE_LIBPAM */ } - cupsdLogMessage(CUPSD_LOG_DEBUG, - "[Client %d] Authorized as %s using Basic", - con->http.fd, username); + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Authorized as \"%s\" using Basic.", username); break; - - case CUPSD_AUTH_BASICDIGEST : - /* - * Do Basic authentication with the Digest password file... - */ - - if (!get_md5_password(username, NULL, md5)) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Unknown MD5 username \"%s\".", - con->http.fd, username); - return; - } - - httpMD5(username, "CUPS", password, basicmd5); - - if (strcmp(md5, basicmd5)) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Authentication failed for \"%s\".", - con->http.fd, username); - return; - } - - cupsdLogMessage(CUPSD_LOG_DEBUG, - "[Client %d] Authorized as %s using BasicDigest", - con->http.fd, username); - break; } con->type = type; } - else if (!strncmp(authorization, "Digest", 6)) - { - /* - * Get the username, password, and nonce from the Digest attributes... - */ - - if (!httpGetSubField2(&(con->http), HTTP_FIELD_AUTHORIZATION, "username", - username, sizeof(username)) || !username[0]) - { - /* - * Username must not be empty... - */ - - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Empty or missing Digest username.", - con->http.fd); - return; - } - - if (!httpGetSubField2(&(con->http), HTTP_FIELD_AUTHORIZATION, "response", - password, sizeof(password)) || !password[0]) - { - /* - * Password must not be empty... - */ - - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Empty or missing Digest password.", - con->http.fd); - return; - } - - if (!httpGetSubField(&(con->http), HTTP_FIELD_AUTHORIZATION, "nonce", - nonce)) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] No nonce value for Digest authentication.", - con->http.fd); - return; - } - - if (strcmp(con->http.hostname, nonce)) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Bad nonce value, expected \"%s\", " - "got \"%s\".", con->http.fd, con->http.hostname, nonce); - return; - } - - /* - * Validate the username and password... - */ - - if (!get_md5_password(username, NULL, md5)) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Unknown MD5 username \"%s\".", - con->http.fd, username); - return; - } - - httpMD5Final(nonce, states[con->http.state], con->uri, md5); - - if (strcmp(md5, password)) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Authentication failed for \"%s\".", - con->http.fd, username); - return; - } - - cupsdLogMessage(CUPSD_LOG_DEBUG, - "[Client %d] Authorized as %s using Digest", con->http.fd, - username); - - con->type = CUPSD_AUTH_DIGEST; - } #ifdef HAVE_GSSAPI else if (!strncmp(authorization, "Negotiate", 9)) { @@ -1037,12 +747,9 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ * to use it... */ - if (gss_init_sec_context == NULL) + if (&gss_init_sec_context == NULL) { - cupsdLogMessage(CUPSD_LOG_WARN, - "[Client %d] GSSAPI/Kerberos authentication failed " - "because the Kerberos framework is not present.", - con->http.fd); + cupsdLogClient(con, CUPSD_LOG_WARN, "GSSAPI/Kerberos authentication failed because the Kerberos framework is not present."); return; } # endif /* __APPLE__ */ @@ -1057,9 +764,7 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ if (!*authorization) { - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "[Client %d] No authentication data specified.", - con->http.fd); + cupsdLogClient(con, CUPSD_LOG_DEBUG2, "No authentication data specified."); return; } @@ -1067,11 +772,11 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ * Decode the authorization string to get the input token... */ - len = strlen(authorization); - input_token.value = malloc(len); + len = (int)strlen(authorization); + input_token.value = malloc((size_t)len); input_token.value = httpDecode64_2(input_token.value, &len, authorization); - input_token.length = len; + input_token.length = (size_t)len; /* * Accept the input token to get the authorization info... @@ -1096,9 +801,7 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ if (GSS_ERROR(major_status)) { - cupsdLogGSSMessage(CUPSD_LOG_DEBUG, major_status, minor_status, - "[Client %d] Error accepting GSSAPI security context", - con->http.fd); + cupsdLogGSSMessage(CUPSD_LOG_DEBUG, major_status, minor_status, "[Client %d] Error accepting GSSAPI security context.", con->number); if (context != GSS_C_NO_CONTEXT) gss_delete_sec_context(&minor_status, &context, GSS_C_NO_BUFFER); @@ -1112,8 +815,7 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ */ if (major_status == GSS_S_CONTINUE_NEEDED) - cupsdLogGSSMessage(CUPSD_LOG_DEBUG, major_status, minor_status, - "[Client %d] Credentials not complete", con->http.fd); + cupsdLogGSSMessage(CUPSD_LOG_DEBUG, major_status, minor_status, "[Client %d] Credentials not complete.", con->number); else if (major_status == GSS_S_COMPLETE) { major_status = gss_display_name(&minor_status, client_name, @@ -1121,8 +823,7 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ if (GSS_ERROR(major_status)) { - cupsdLogGSSMessage(CUPSD_LOG_DEBUG, major_status, minor_status, - "[Client %d] Error getting username", con->http.fd); + cupsdLogGSSMessage(CUPSD_LOG_DEBUG, major_status, minor_status, "[Client %d] Error getting username.", con->number); gss_release_name(&minor_status, &client_name); gss_delete_sec_context(&minor_status, &context, GSS_C_NO_BUFFER); return; @@ -1130,9 +831,7 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ strlcpy(username, output_token.value, sizeof(username)); - cupsdLogMessage(CUPSD_LOG_DEBUG, - "[Client %d] Authorized as %s using Negotiate", - con->http.fd, username); + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Authorized as \"%s\" using Negotiate.", username); gss_release_name(&minor_status, &client_name); gss_release_buffer(&minor_status, &output_token); @@ -1148,7 +847,7 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ * to run as the correct user to get Kerberos credentials of its own. */ - if (_httpAddrFamily(con->http.hostaddr) == AF_LOCAL) + if (httpAddrFamily(con->http->hostaddr) == AF_LOCAL) { cupsd_ucred_t peercred; /* Peer credentials */ socklen_t peersize; /* Size of peer credentials */ @@ -1156,21 +855,17 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ peersize = sizeof(peercred); # ifdef __APPLE__ - if (getsockopt(con->http.fd, 0, LOCAL_PEERCRED, &peercred, &peersize)) + if (getsockopt(httpGetFd(con->http), 0, LOCAL_PEERCRED, &peercred, &peersize)) # else - if (getsockopt(con->http.fd, SOL_SOCKET, SO_PEERCRED, &peercred, + if (getsockopt(httpGetFd(con->http), SOL_SOCKET, SO_PEERCRED, &peercred, &peersize)) # endif /* __APPLE__ */ { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Unable to get peer credentials - %s", - con->http.fd, strerror(errno)); + cupsdLogClient(con, CUPSD_LOG_ERROR, "Unable to get peer credentials - %s", strerror(errno)); } else { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "[Client %d] Using credentials for UID %d.", - con->http.fd, CUPSD_UCRED_UID(peercred)); + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Using credentials for UID %d.", CUPSD_UCRED_UID(peercred)); con->gss_uid = CUPSD_UCRED_UID(peercred); } } @@ -1183,11 +878,9 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ if (sscanf(authorization, "%255s", scheme) != 1) - strcpy(scheme, "UNKNOWN"); + strlcpy(scheme, "UNKNOWN", sizeof(scheme)); - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Bad authentication data \"%s ...\"", - con->http.fd, scheme); + cupsdLogClient(con, CUPSD_LOG_ERROR, "Bad authentication data \"%s ...\".", scheme); return; } @@ -1210,8 +903,8 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ int /* O - 1 if allowed, 0 otherwise */ cupsdCheckAccess( unsigned ip[4], /* I - Client address */ - char *name, /* I - Client hostname */ - int namelen, /* I - Length of hostname */ + const char *name, /* I - Client hostname */ + size_t namelen, /* I - Length of hostname */ cupsd_location_t *loc) /* I - Location to check */ { int allow; /* 1 if allowed, 0 otherwise */ @@ -1269,8 +962,8 @@ cupsdCheckAccess( int /* O - 1 if mask matches, 0 otherwise */ cupsdCheckAuth(unsigned ip[4], /* I - Client address */ - char *name, /* I - Client hostname */ - int name_len, /* I - Length of hostname */ + const char *name, /* I - Client hostname */ + size_t name_len, /* I - Length of hostname */ cups_array_t *masks) /* I - Masks */ { int i; /* Looping var */ @@ -1302,6 +995,8 @@ cupsdCheckAuth(unsigned ip[4], /* I - Client address */ netip6[3] = htonl(ip[3]); #endif /* AF_INET6 */ + cupsdNetIFUpdate(); + if (!strcmp(mask->mask.name.name, "*")) { #ifdef __APPLE__ @@ -1317,8 +1012,6 @@ cupsdCheckAuth(unsigned ip[4], /* I - Client address */ * Check against all local interfaces... */ - cupsdNetIFUpdate(); - for (iface = (cupsd_netif_t *)cupsArrayFirst(NetIFList); iface; iface = (cupsd_netif_t *)cupsArrayNext(NetIFList)) @@ -1456,7 +1149,6 @@ cupsdCheckGroup( { int i; /* Looping var */ struct group *group; /* System group info */ - char junk[33]; /* MD5 password (not used) */ #ifdef HAVE_MBR_UID_TO_UUID uuid_t useruuid, /* UUID for username */ groupuuid; /* UUID for groupname */ @@ -1464,9 +1156,7 @@ cupsdCheckGroup( #endif /* HAVE_MBR_UID_TO_UUID */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdCheckGroup(username=\"%s\", user=%p, groupname=\"%s\")", - username, user, groupname); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCheckGroup(username=\"%s\", user=%p, groupname=\"%s\")", username, user, groupname); /* * Validate input... @@ -1543,15 +1233,6 @@ cupsdCheckGroup( #endif /* HAVE_MBR_UID_TO_UUID */ /* - * Username not found, group not found, or user is not part of the - * system group... Check for a user and group in the MD5 password - * file... - */ - - if (get_md5_password(username, groupname, junk) != NULL) - return (1); - - /* * If we get this far, then the user isn't part of the named group... */ @@ -1587,6 +1268,7 @@ cupsdCopyLocation( if (loc->location) temp->location = _cupsStrAlloc(loc->location); + temp->length = loc->length; temp->limit = loc->limit; temp->order_type = loc->order_type; temp->type = loc->type; @@ -1672,7 +1354,7 @@ cupsdFindBest(const char *path, /* I - Resource path */ *uriptr; /* Pointer into URI */ cupsd_location_t *loc, /* Current location */ *best; /* Best match for location so far */ - int bestlen; /* Length of best match */ + size_t bestlen; /* Length of best match */ int limit; /* Limit field */ static const int limits[] = /* Map http_status_t to CUPSD_AUTH_LIMIT_xyz */ { @@ -1689,6 +1371,8 @@ cupsdFindBest(const char *path, /* I - Resource path */ CUPSD_AUTH_LIMIT_DELETE, CUPSD_AUTH_LIMIT_TRACE, CUPSD_AUTH_LIMIT_ALL, + CUPSD_AUTH_LIMIT_ALL, + CUPSD_AUTH_LIMIT_ALL, CUPSD_AUTH_LIMIT_ALL }; @@ -1701,6 +1385,12 @@ cupsdFindBest(const char *path, /* I - Resource path */ strlcpy(uri, path, sizeof(uri)); + if ((uriptr = strchr(uri, '?')) != NULL) + *uriptr = '\0'; /* Drop trailing query string */ + + if ((uriptr = uri + strlen(uri) - 1) > uri && *uriptr == '/') + *uriptr = '\0'; /* Remove trailing '/' */ + if (!strncmp(uri, "/printers/", 10) || !strncmp(uri, "/classes/", 9)) { @@ -1714,8 +1404,6 @@ cupsdFindBest(const char *path, /* I - Resource path */ *uriptr = '\0'; } - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFindBest: uri = \"%s\"...", uri); - /* * Loop through the list of locations to find a match... */ @@ -1724,12 +1412,14 @@ cupsdFindBest(const char *path, /* I - Resource path */ best = NULL; bestlen = 0; + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFindBest: uri=\"%s\", limit=%x...", uri, limit); + + for (loc = (cupsd_location_t *)cupsArrayFirst(Locations); loc; loc = (cupsd_location_t *)cupsArrayNext(Locations)) { - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFindBest: Location %s Limit %x", - loc->location ? loc->location : "nil", loc->limit); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFindBest: Location %s(%d) Limit %x", loc->location ? loc->location : "(null)", (int)loc->length, loc->limit); if (!strncmp(uri, "/printers/", 10) || !strncmp(uri, "/classes/", 9)) { @@ -1767,8 +1457,7 @@ cupsdFindBest(const char *path, /* I - Resource path */ * Return the match, if any... */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFindBest: best = %s", - best ? best->location : "NONE"); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFindBest: best=%s", best ? best->location : "NONE"); return (best); } @@ -1817,9 +1506,13 @@ cupsdIsAuthorized(cupsd_client_t *con, /* I - Connection */ int i, /* Looping vars */ auth, /* Authorization status */ type; /* Type of authentication */ + http_addr_t *hostaddr = httpGetAddress(con->http); + /* Client address */ + const char *hostname = httpGetHostname(con->http, NULL, 0); + /* Client hostname */ unsigned address[4]; /* Authorization address */ cupsd_location_t *best; /* Best match for location so far */ - int hostlen; /* Length of hostname */ + size_t hostlen; /* Length of hostname */ char *name, /* Current username */ username[256], /* Username to authorize */ ownername[256], /* Owner name to authorize */ @@ -1835,19 +1528,13 @@ cupsdIsAuthorized(cupsd_client_t *con, /* I - Connection */ { "None", "Basic", - "Digest", - "BasicDigest", "Negotiate" }; - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdIsAuthorized: con->uri=\"%s\", con->best=%p(%s)", - con->uri, con->best, con->best ? con->best->location ? - con->best->location : "(null)" : ""); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdIsAuthorized: con->uri=\"%s\", con->best=%p(%s)", con->uri, con->best, con->best ? con->best->location ? con->best->location : "(null)" : ""); if (owner) - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdIsAuthorized: owner=\"%s\"", owner); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdIsAuthorized: owner=\"%s\"", owner); /* * If there is no "best" authentication rule for this request, then @@ -1857,8 +1544,9 @@ cupsdIsAuthorized(cupsd_client_t *con, /* I - Connection */ if (!con->best) { - if (!strcmp(con->http.hostname, "localhost") || - !strcmp(con->http.hostname, ServerName)) + if (httpAddrLocalhost(httpGetAddress(con->http)) || + !strcmp(hostname, ServerName) || + cupsArrayFind(ServerAlias, (void *)hostname)) return (HTTP_OK); else return (HTTP_FORBIDDEN); @@ -1869,35 +1557,30 @@ cupsdIsAuthorized(cupsd_client_t *con, /* I - Connection */ if ((type = best->type) == CUPSD_AUTH_DEFAULT) type = cupsdDefaultAuthType(); - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdIsAuthorized: level=CUPSD_AUTH_%s, type=%s, " - "satisfy=CUPSD_AUTH_SATISFY_%s, num_names=%d", - levels[best->level], types[type], - best->satisfy ? "ANY" : "ALL", cupsArrayCount(best->names)); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdIsAuthorized: level=CUPSD_AUTH_%s, type=%s, satisfy=CUPSD_AUTH_SATISFY_%s, num_names=%d", levels[best->level], types[type], best->satisfy ? "ANY" : "ALL", cupsArrayCount(best->names)); if (best->limit == CUPSD_AUTH_LIMIT_IPP) - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdIsAuthorized: op=%x(%s)", - best->op, ippOpString(best->op)); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdIsAuthorized: op=%x(%s)", best->op, ippOpString(best->op)); /* * Check host/ip-based accesses... */ #ifdef AF_INET6 - if (con->http.hostaddr->addr.sa_family == AF_INET6) + if (httpAddrFamily(hostaddr) == AF_INET6) { /* * Copy IPv6 address... */ - address[0] = ntohl(con->http.hostaddr->ipv6.sin6_addr.s6_addr32[0]); - address[1] = ntohl(con->http.hostaddr->ipv6.sin6_addr.s6_addr32[1]); - address[2] = ntohl(con->http.hostaddr->ipv6.sin6_addr.s6_addr32[2]); - address[3] = ntohl(con->http.hostaddr->ipv6.sin6_addr.s6_addr32[3]); + address[0] = ntohl(hostaddr->ipv6.sin6_addr.s6_addr32[0]); + address[1] = ntohl(hostaddr->ipv6.sin6_addr.s6_addr32[1]); + address[2] = ntohl(hostaddr->ipv6.sin6_addr.s6_addr32[2]); + address[3] = ntohl(hostaddr->ipv6.sin6_addr.s6_addr32[3]); } else #endif /* AF_INET6 */ - if (con->http.hostaddr->addr.sa_family == AF_INET) + if (con->http->hostaddr->addr.sa_family == AF_INET) { /* * Copy IPv4 address... @@ -1906,18 +1589,17 @@ cupsdIsAuthorized(cupsd_client_t *con, /* I - Connection */ address[0] = 0; address[1] = 0; address[2] = 0; - address[3] = ntohl(con->http.hostaddr->ipv4.sin_addr.s_addr); + address[3] = ntohl(hostaddr->ipv4.sin_addr.s_addr); } else memset(address, 0, sizeof(address)); - hostlen = strlen(con->http.hostname); + hostlen = strlen(hostname); - auth = cupsdCheckAccess(address, con->http.hostname, hostlen, best) + auth = cupsdCheckAccess(address, hostname, hostlen, best) ? CUPSD_AUTH_ALLOW : CUPSD_AUTH_DENY; - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdIsAuthorized: auth=CUPSD_AUTH_%s...", - auth ? "DENY" : "ALLOW"); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdIsAuthorized: auth=CUPSD_AUTH_%s...", auth ? "DENY" : "ALLOW"); if (auth == CUPSD_AUTH_DENY && best->satisfy == CUPSD_AUTH_SATISFY_ALL) return (HTTP_FORBIDDEN); @@ -1927,8 +1609,9 @@ cupsdIsAuthorized(cupsd_client_t *con, /* I - Connection */ * See if encryption is required... */ - if ((best->encryption >= HTTP_ENCRYPT_REQUIRED && !con->http.tls && - _cups_strcasecmp(con->http.hostname, "localhost") && + if ((best->encryption >= HTTP_ENCRYPT_REQUIRED && !con->http->tls && + _cups_strcasecmp(hostname, "localhost") && + !httpAddrLocalhost(hostaddr) && best->satisfy == CUPSD_AUTH_SATISFY_ALL) && !(type == CUPSD_AUTH_NEGOTIATE || (type == CUPSD_AUTH_NONE && @@ -1993,9 +1676,9 @@ cupsdIsAuthorized(cupsd_client_t *con, /* I - Connection */ #ifdef HAVE_GSSAPI (type != CUPSD_AUTH_NEGOTIATE || con->gss_uid <= 0) && #endif /* HAVE_GSSAPI */ - (con->type != CUPSD_AUTH_BASIC || type != CUPSD_AUTH_BASICDIGEST)) + con->type != CUPSD_AUTH_BASIC) { - cupsdLogMessage(CUPSD_LOG_ERROR, "Authorized using %s, expected %s!", + cupsdLogMessage(CUPSD_LOG_ERROR, "Authorized using %s, expected %s.", types[con->type], types[type]); return (HTTP_UNAUTHORIZED); @@ -2056,8 +1739,7 @@ cupsdIsAuthorized(cupsd_client_t *con, /* I - Connection */ * allowed... */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdIsAuthorized: Checking user membership..."); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdIsAuthorized: Checking user membership..."); #ifdef HAVE_AUTHORIZATION_H /* @@ -2110,8 +1792,7 @@ cupsdIsAuthorized(cupsd_client_t *con, /* I - Connection */ * Check to see if this user is in any of the named groups... */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdIsAuthorized: Checking group membership..."); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdIsAuthorized: Checking group membership..."); /* * Check to see if this user is in any of the named groups... @@ -2121,9 +1802,7 @@ cupsdIsAuthorized(cupsd_client_t *con, /* I - Connection */ name; name = (char *)cupsArrayNext(best->names)) { - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdIsAuthorized: Checking group \"%s\" membership...", - name); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdIsAuthorized: Checking group \"%s\" membership...", name); if (!_cups_strcasecmp(name, "@SYSTEM")) { @@ -2139,8 +1818,7 @@ cupsdIsAuthorized(cupsd_client_t *con, /* I - Connection */ * The user isn't part of the specified group, so deny access... */ - cupsdLogMessage(CUPSD_LOG_DEBUG, - "cupsdIsAuthorized: User not in group(s)!"); + cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdIsAuthorized: User not in group(s)."); return (con->username[0] ? HTTP_FORBIDDEN : HTTP_UNAUTHORIZED); } @@ -2230,9 +1908,7 @@ check_authref(cupsd_client_t *con, /* I - Connection */ return (0); } - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "AuthorizationCopyRights(\"%s\") succeeded!", - authright.name); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "AuthorizationCopyRights(\"%s\") succeeded.", authright.name); return (1); } @@ -2290,7 +1966,7 @@ copy_authmask(cupsd_authmask_t *mask, /* I - Existing auth mask */ } -#if !HAVE_LIBPAM && !defined(HAVE_USERSEC_H) +#if !HAVE_LIBPAM /* * 'cups_crypt()' - Encrypt the password using the DES or MD5 algorithms, * as needed. @@ -2379,23 +2055,23 @@ cups_crypt(const char *pw, /* I - Password string */ * Copy the final sum to the result string and return... */ - memcpy(result, salt, salt_end - salt); + memcpy(result, salt, (size_t)(salt_end - salt)); ptr = result + (salt_end - salt); *ptr++ = '$'; for (i = 0; i < 5; i ++, ptr += 4) { - n = (((digest[i] << 8) | digest[i + 6]) << 8); + n = ((((unsigned)digest[i] << 8) | (unsigned)digest[i + 6]) << 8); if (i < 4) - n |= digest[i + 12]; + n |= (unsigned)digest[i + 12]; else - n |= digest[5]; + n |= (unsigned)digest[5]; to64(ptr, n, 4); } - to64(ptr, digest[11], 2); + to64(ptr, (unsigned)digest[11], 2); ptr += 2; *ptr = '\0'; @@ -2410,7 +2086,7 @@ cups_crypt(const char *pw, /* I - Password string */ return (crypt(pw, salt)); } } -#endif /* !HAVE_LIBPAM && !HAVE_USERSEC_H */ +#endif /* !HAVE_LIBPAM */ /* @@ -2430,68 +2106,6 @@ free_authmask(cupsd_authmask_t *mask, /* I - Auth mask to free */ } -/* - * 'get_md5_password()' - Get an MD5 password. - */ - -static char * /* O - MD5 password string */ -get_md5_password(const char *username, /* I - Username */ - const char *group, /* I - Group */ - char passwd[33]) /* O - MD5 password string */ -{ - cups_file_t *fp; /* passwd.md5 file */ - char filename[1024], /* passwd.md5 filename */ - line[256], /* Line from file */ - tempuser[33], /* User from file */ - tempgroup[33]; /* Group from file */ - - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "get_md5_password(username=\"%s\", group=\"%s\", passwd=%p)", - username, group ? group : "(null)", passwd); - - snprintf(filename, sizeof(filename), "%s/passwd.md5", ServerRoot); - if ((fp = cupsFileOpen(filename, "r")) == NULL) - { - if (errno != ENOENT) - cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to open %s - %s", filename, - strerror(errno)); - - return (NULL); - } - - while (cupsFileGets(fp, line, sizeof(line)) != NULL) - { - if (sscanf(line, "%32[^:]:%32[^:]:%32s", tempuser, tempgroup, passwd) != 3) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Bad MD5 password line: %s", line); - continue; - } - - if (!strcmp(username, tempuser) && - (group == NULL || !strcmp(group, tempgroup))) - { - /* - * Found the password entry! - */ - - cupsdLogMessage(CUPSD_LOG_DEBUG2, "Found MD5 user %s, group %s...", - username, tempgroup); - - cupsFileClose(fp); - return (passwd); - } - } - - /* - * Didn't find a password entry - return NULL! - */ - - cupsFileClose(fp); - return (NULL); -} - - #if HAVE_LIBPAM /* * 'pam_func()' - PAM conversation function. @@ -2514,7 +2128,7 @@ pam_func( * Allocate memory for the responses... */ - if ((replies = malloc(sizeof(struct pam_response) * num_msg)) == NULL) + if ((replies = malloc(sizeof(struct pam_response) * (size_t)num_msg)) == NULL) return (PAM_CONV_ERR); /* @@ -2523,17 +2137,7 @@ pam_func( DEBUG_printf(("pam_func: appdata_ptr = %p\n", appdata_ptr)); -#ifdef __hpux - /* - * Apparently some versions of HP-UX 11 have a broken pam_unix security - * module. This is a workaround... - */ - - data = auth_data; - (void)appdata_ptr; -#else data = (cupsd_authdata_t *)appdata_ptr; -#endif /* __hpux */ for (i = 0; i < num_msg; i ++) { @@ -2583,7 +2187,7 @@ pam_func( return (PAM_SUCCESS); } -#elif !defined(HAVE_USERSEC_H) +#else /* @@ -2607,5 +2211,5 @@ to64(char *s, /* O - Output string */ /* - * End of "$Id: auth.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: auth.c 12945 2015-10-26 19:46:02Z msweet $". */ diff --git a/scheduler/auth.h b/scheduler/auth.h index 8979023..c42c0a2 100644 --- a/scheduler/auth.h +++ b/scheduler/auth.h @@ -1,16 +1,16 @@ /* - * "$Id: auth.h 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: auth.h 11776 2014-03-28 19:16:05Z msweet $" * - * Authorization definitions for the CUPS scheduler. + * Authorization definitions for the CUPS scheduler. * - * Copyright 2007-2011 by Apple Inc. - * Copyright 1997-2006 by Easy Software Products, all rights reserved. + * Copyright 2007-2014 by Apple Inc. + * Copyright 1997-2006 by Easy Software Products, all rights reserved. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -27,10 +27,8 @@ #define CUPSD_AUTH_DEFAULT -1 /* Use DefaultAuthType */ #define CUPSD_AUTH_NONE 0 /* No authentication */ #define CUPSD_AUTH_BASIC 1 /* Basic authentication */ -#define CUPSD_AUTH_DIGEST 2 /* Digest authentication */ -#define CUPSD_AUTH_BASICDIGEST 3 /* Basic authentication w/passwd.md5 */ -#define CUPSD_AUTH_NEGOTIATE 4 /* Kerberos authentication */ -#define CUPSD_AUTH_AUTO 5 /* Kerberos or Basic, depending on configuration of server */ +#define CUPSD_AUTH_NEGOTIATE 2 /* Kerberos authentication */ +#define CUPSD_AUTH_AUTO 3 /* Kerberos or Basic, depending on configuration of server */ #define CUPSD_AUTH_ANON 0 /* Anonymous access */ #define CUPSD_AUTH_USER 1 /* Must have a valid username/password */ @@ -74,7 +72,7 @@ typedef struct typedef struct { - int length; /* Length of name */ + size_t length; /* Length of name */ char *name; /* Name string */ } cupsd_namemask_t; @@ -91,9 +89,9 @@ typedef struct typedef struct { char *location; /* Location of resource */ + size_t length; /* Length of location string */ ipp_op_t op; /* IPP operation */ int limit, /* Limit for these types of requests */ - length, /* Length of location string */ order_type, /* Allow or Deny */ type, /* Type of authentication */ level, /* Access level required */ @@ -130,10 +128,8 @@ extern void cupsdAddLocation(cupsd_location_t *loc); extern void cupsdAddName(cupsd_location_t *loc, char *name); extern int cupsdAddNameMask(cups_array_t **masks, char *name); extern void cupsdAuthorize(cupsd_client_t *con); -extern int cupsdCheckAccess(unsigned ip[4], char *name, - int namelen, cupsd_location_t *loc); -extern int cupsdCheckAuth(unsigned ip[4], char *name, int namelen, - cups_array_t *masks); +extern int cupsdCheckAccess(unsigned ip[4], const char *name, size_t namelen, cupsd_location_t *loc); +extern int cupsdCheckAuth(unsigned ip[4], const char *name, size_t namelen, cups_array_t *masks); extern int cupsdCheckGroup(const char *username, struct passwd *user, const char *groupname); @@ -147,5 +143,5 @@ extern cupsd_location_t *cupsdNewLocation(const char *location); /* - * End of "$Id: auth.h 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: auth.h 11776 2014-03-28 19:16:05Z msweet $". */ diff --git a/scheduler/banners.c b/scheduler/banners.c index 87a1a68..631a891 100644 --- a/scheduler/banners.c +++ b/scheduler/banners.c @@ -1,5 +1,5 @@ /* - * "$Id: banners.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: banners.c 10996 2013-05-29 11:51:34Z msweet $" * * Banner routines for the CUPS scheduler. * @@ -220,5 +220,5 @@ free_banners(void) /* - * End of "$Id: banners.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: banners.c 10996 2013-05-29 11:51:34Z msweet $". */ diff --git a/scheduler/banners.h b/scheduler/banners.h index 4a91e8a..19ab6f7 100644 --- a/scheduler/banners.h +++ b/scheduler/banners.h @@ -1,5 +1,5 @@ /* - * "$Id: banners.h 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: banners.h 10996 2013-05-29 11:51:34Z msweet $" * * Banner definitions for the CUPS scheduler. * @@ -41,5 +41,5 @@ extern void cupsdLoadBanners(const char *d); /* - * End of "$Id: banners.h 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: banners.h 10996 2013-05-29 11:51:34Z msweet $". */ diff --git a/scheduler/cert.c b/scheduler/cert.c index cd47228..6d93426 100644 --- a/scheduler/cert.c +++ b/scheduler/cert.c @@ -1,25 +1,16 @@ /* - * "$Id: cert.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: cert.c 12972 2015-11-13 20:30:37Z msweet $" * - * Authentication certificate routines for the CUPS scheduler. + * Authentication certificate routines for the CUPS scheduler. * - * Copyright 2007-2012 by Apple Inc. - * Copyright 1997-2006 by Easy Software Products. + * Copyright 2007-2015 by Apple Inc. + * Copyright 1997-2006 by Easy Software Products. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * cupsdAddCert() - Add a certificate. - * cupsdDeleteCert() - Delete a single certificate. - * cupsdDeleteAllCerts() - Delete all certificates... - * cupsdFindCert() - Find a certificate. - * cupsdInitCerts() - Initialize the certificate "system" and root - * certificate. + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -36,6 +27,13 @@ /* + * Local functions... + */ + +static int ctcompare(const char *a, const char *b); + + +/* * 'cupsdAddCert()' - Add a certificate. */ @@ -52,8 +50,7 @@ cupsdAddCert(int pid, /* I - Process ID */ /* Hex constants... */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdAddCert: Adding certificate for PID %d", pid); + cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdAddCert: Adding certificate for PID %d", pid); /* * Allocate memory for the certificate... @@ -111,8 +108,7 @@ cupsdAddCert(int pid, /* I - Process ID */ fchmod(fd, 0440); fchown(fd, RunUser, SystemGroupIDs[0]); - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddCert: NumSystemGroups=%d", - NumSystemGroups); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddCert: NumSystemGroups=%d", NumSystemGroups); #ifdef HAVE_ACL_INIT if (NumSystemGroups > 1) @@ -288,8 +284,7 @@ cupsdDeleteCert(int pid) /* I - Process ID */ * Remove this certificate from the list... */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdDeleteCert: Removing certificate for PID %d", pid); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDeleteCert: Removing certificate for PID %d.", pid); DEBUG_printf(("DELETE pid=%d, username=%s, cert=%s\n", cert->pid, cert->username, cert->certificate)); @@ -363,17 +358,15 @@ cupsdFindCert(const char *certificate) /* I - Certificate */ cupsd_cert_t *cert; /* Current certificate */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFindCert(certificate=%s)", - certificate); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFindCert(certificate=%s)", certificate); for (cert = Certs; cert != NULL; cert = cert->next) - if (!_cups_strcasecmp(certificate, cert->certificate)) + if (!ctcompare(certificate, cert->certificate)) { - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFindCert: Returning %s...", - cert->username); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFindCert: Returning \"%s\".", cert->username); return (cert); } - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFindCert: Certificate not found!"); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFindCert: Certificate not found."); return (NULL); } @@ -417,10 +410,10 @@ cupsdInitCerts(void) * them as the seed... */ - seed = cupsFileGetChar(fp); - seed = (seed << 8) | cupsFileGetChar(fp); - seed = (seed << 8) | cupsFileGetChar(fp); - CUPS_SRAND((seed << 8) | cupsFileGetChar(fp)); + seed = (unsigned)cupsFileGetChar(fp); + seed = (seed << 8) | (unsigned)cupsFileGetChar(fp); + seed = (seed << 8) | (unsigned)cupsFileGetChar(fp); + CUPS_SRAND((seed << 8) | (unsigned)cupsFileGetChar(fp)); cupsFileClose(fp); } @@ -436,5 +429,27 @@ cupsdInitCerts(void) /* - * End of "$Id: cert.c 11173 2013-07-23 12:31:34Z msweet $". + * 'ctcompare()' - Compare two strings in constant time. + */ + +static int /* O - 0 on match, non-zero on non-match */ +ctcompare(const char *a, /* I - First string */ + const char *b) /* I - Second string */ +{ + int result = 0; /* Result */ + + + while (*a && *b) + { + result |= *a ^ *b; + a ++; + b ++; + } + + return (result); +} + + +/* + * End of "$Id: cert.c 12972 2015-11-13 20:30:37Z msweet $". */ diff --git a/scheduler/cert.h b/scheduler/cert.h index 26eaa9f..063c5de 100644 --- a/scheduler/cert.h +++ b/scheduler/cert.h @@ -1,5 +1,5 @@ /* - * "$Id: cert.h 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: cert.h 10996 2013-05-29 11:51:34Z msweet $" * * Authentication certificate definitions for the CUPS scheduler. * @@ -49,5 +49,5 @@ extern void cupsdInitCerts(void); /* - * End of "$Id: cert.h 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: cert.h 10996 2013-05-29 11:51:34Z msweet $". */ diff --git a/scheduler/classes.c b/scheduler/classes.c index 1aed92c..17add06 100644 --- a/scheduler/classes.c +++ b/scheduler/classes.c @@ -1,27 +1,16 @@ /* - * "$Id: classes.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: classes.c 11781 2014-03-28 20:57:22Z msweet $" * - * Printer class routines for the CUPS scheduler. + * Printer class routines for the CUPS scheduler. * - * Copyright 2007-2011 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. + * Copyright 2007-2014 by Apple Inc. + * Copyright 1997-2007 by Easy Software Products, all rights reserved. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * cupsdAddClass() - Add a class to the system. - * cupsdAddPrinterToClass() - Add a printer to a class... - * cupsdDeletePrinterFromClass() - Delete a printer from a class. - * cupsdDeletePrinterFromClasses() - Delete a printer from all classes. - * cupsdFindAvailablePrinter() - Find an available printer in a class. - * cupsdFindClass() - Find the named class. - * cupsdLoadAllClasses() - Load classes from the classes.conf file. - * cupsdSaveAllClasses() - Save classes to the classes.conf file. + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -93,7 +82,7 @@ cupsdAddPrinterToClass( if (c->num_printers == 0) temp = malloc(sizeof(cupsd_printer_t *)); else - temp = realloc(c->printers, sizeof(cupsd_printer_t *) * (c->num_printers + 1)); + temp = realloc(c->printers, sizeof(cupsd_printer_t *) * (size_t)(c->num_printers + 1)); if (temp == NULL) { @@ -147,7 +136,7 @@ cupsdDeletePrinterFromClass( c->num_printers --; if (i < c->num_printers) memmove(c->printers + i, c->printers + i + 1, - (c->num_printers - i) * sizeof(cupsd_printer_t *)); + (size_t)(c->num_printers - i) * sizeof(cupsd_printer_t *)); } else return (0); @@ -343,7 +332,7 @@ cupsdLoadAllClasses(void) cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of classes.conf.", linenum); } - else if (!_cups_strcasecmp(line, "</Class>")) + else if (!_cups_strcasecmp(line, "</Class>") || !_cups_strcasecmp(line, "</DefaultClass>")) { if (p != NULL) { @@ -806,7 +795,10 @@ cupsdSaveAllClasses(void) cupsFilePutConf(fp, "Option", value); } - cupsFilePuts(fp, "</Class>\n"); + if (pclass == DefaultPrinter) + cupsFilePuts(fp, "</DefaultClass>\n"); + else + cupsFilePuts(fp, "</Class>\n"); } cupsdCloseCreatedConfFile(fp, filename); @@ -814,5 +806,5 @@ cupsdSaveAllClasses(void) /* - * End of "$Id: classes.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: classes.c 11781 2014-03-28 20:57:22Z msweet $". */ diff --git a/scheduler/classes.h b/scheduler/classes.h index 6d94de2..bc0196e 100644 --- a/scheduler/classes.h +++ b/scheduler/classes.h @@ -1,5 +1,5 @@ /* - * "$Id: classes.h 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: classes.h 10996 2013-05-29 11:51:34Z msweet $" * * Printer class definitions for the CUPS scheduler. * @@ -31,5 +31,5 @@ extern void cupsdSaveAllClasses(void); /* - * End of "$Id: classes.h 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: classes.h 10996 2013-05-29 11:51:34Z msweet $". */ diff --git a/scheduler/client.c b/scheduler/client.c index b341e9d..3ec3b5c 100644 --- a/scheduler/client.c +++ b/scheduler/client.c @@ -1,90 +1,38 @@ /* - * "$Id: client.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: client.c 12978 2015-11-17 19:29:52Z msweet $" * - * Client routines for the CUPS scheduler. + * Client routines for the CUPS scheduler. * - * Copyright 2007-2012 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. + * Copyright 2007-2015 by Apple Inc. + * Copyright 1997-2007 by Easy Software Products, all rights reserved. * - * This file contains Kerberos support code, copyright 2006 by - * Jelmer Vernooij. + * This file contains Kerberos support code, copyright 2006 by + * Jelmer Vernooij. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * cupsdAcceptClient() - Accept a new client. - * cupsdCloseAllClients() - Close all remote clients immediately. - * cupsdCloseClient() - Close a remote client. - * cupsdFlushHeader() - Flush the header fields to the client. - * cupsdReadClient() - Read data from a client. - * cupsdSendCommand() - Send output from a command via HTTP. - * cupsdSendError() - Send an error message via HTTP. - * cupsdSendHeader() - Send an HTTP request. - * cupsdUpdateCGI() - Read status messages from CGI scripts and - * programs. - * cupsdWriteClient() - Write data to a client as needed. - * check_if_modified() - Decode an "If-Modified-Since" line. - * compare_clients() - Compare two client connections. - * data_ready() - Check whether data is available from a client. - * get_file() - Get a filename and state info. - * install_cupsd_conf() - Install a configuration file. - * is_cgi() - Is the resource a CGI script/program? - * is_path_absolute() - Is a path absolute and free of relative elements - * (i.e. ".."). - * pipe_command() - Pipe the output of a command to the remote - * client. - * valid_host() - Is the Host: field valid? - * write_file() - Send a file via HTTP. - * write_pipe() - Flag that data is available on the CGI pipe. + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* * Include necessary headers... */ +#define _CUPS_NO_DEPRECATED +#define _HTTP_NO_PRIVATE #include "cupsd.h" +#ifdef __APPLE__ +# include <libproc.h> +#endif /* __APPLE__ */ #ifdef HAVE_TCPD_H # include <tcpd.h> #endif /* HAVE_TCPD_H */ /* - * Local globals... - */ - -static const char * const http_states[] = - { /* HTTP state strings */ - "HTTP_WAITING", - "HTTP_OPTIONS", - "HTTP_GET", - "HTTP_GET_SEND", - "HTTP_HEAD", - "HTTP_POST", - "HTTP_POST_RECV", - "HTTP_POST_SEND", - "HTTP_PUT", - "HTTP_PUT_RECV", - "HTTP_DELETE", - "HTTP_TRACE", - "HTTP_CLOSE", - "HTTP_STATUS" - }; -static const char * const ipp_states[] = - { /* IPP state strings */ - "IPP_IDLE", - "IPP_HEADER", - "IPP_ATTRIBUTE", - "IPP_DATA" - }; - - -/* * Local functions... */ @@ -92,9 +40,11 @@ static int check_if_modified(cupsd_client_t *con, struct stat *filestats); static int compare_clients(cupsd_client_t *a, cupsd_client_t *b, void *data); -static int data_ready(cupsd_client_t *con); +#ifdef HAVE_SSL +static int cupsd_start_tls(cupsd_client_t *con, http_encryption_t e); +#endif /* HAVE_SSL */ static char *get_file(cupsd_client_t *con, struct stat *filestats, - char *filename, int len); + char *filename, size_t len); static http_status_t install_cupsd_conf(cupsd_client_t *con); static int is_cgi(cupsd_client_t *con, const char *filename, struct stat *filestats, mime_type_t *type); @@ -115,14 +65,12 @@ static void write_pipe(cupsd_client_t *con); void cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */ { + const char *hostname; /* Hostname of client */ + char name[256]; /* Hostname of client */ int count; /* Count of connections on a host */ - int val; /* Parameter value */ cupsd_client_t *con, /* New client pointer */ *tempcon; /* Temporary client pointer */ - http_addrlist_t *addrlist, /* List of adddresses for host */ - *addr; /* Current address */ socklen_t addrlen; /* Length of address */ - char *hostname; /* Hostname for address */ http_addr_t temp; /* Temporary address variable */ static time_t last_dos = 0; /* Time of last DoS attack */ #ifdef HAVE_TCPD_H @@ -130,9 +78,7 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */ #endif /* HAVE_TCPD_H */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdAcceptClient(lis=%p(%d)) Clients=%d", - lis, lis->fd, cupsArrayCount(Clients)); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAcceptClient(lis=%p(%d)) Clients=%d", lis, lis->fd, cupsArrayCount(Clients)); /* * Make sure we don't have a full set of clients already... @@ -174,19 +120,14 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */ return; } - con->file = -1; - con->http.activity = time(NULL); - con->http.hostaddr = &(con->clientaddr); - con->http.wait_value = 10000; - /* * Accept the client and get the remote address... */ - addrlen = sizeof(http_addr_t); + con->number = ++ LastClientNumber; + con->file = -1; - if ((con->http.fd = accept(lis->fd, (struct sockaddr *)con->http.hostaddr, - &addrlen)) < 0) + if ((con->http = httpAcceptConnection(lis->fd, 0)) == NULL) { if (errno == ENFILE || errno == EMFILE) cupsdPauseListening(); @@ -199,23 +140,10 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */ } /* - * Save the connected port number... - */ - - _httpAddrSetPort(con->http.hostaddr, _httpAddrPort(&(lis->address))); - -#ifdef AF_INET6 - /* - * Convert IPv4 over IPv6 addresses (::ffff:n.n.n.n) to IPv4 forms we - * can more easily use... + * Save the connected address and port number... */ - if (lis->address.addr.sa_family == AF_INET6 && - con->http.hostaddr->ipv6.sin6_addr.s6_addr32[0] == 0 && - con->http.hostaddr->ipv6.sin6_addr.s6_addr32[1] == 0 && - ntohl(con->http.hostaddr->ipv6.sin6_addr.s6_addr32[2]) == 0xffff) - con->http.hostaddr->ipv6.sin6_addr.s6_addr32[2] = 0; -#endif /* AF_INET6 */ + con->clientaddr = lis->address; /* * Check the number of clients on the same address... @@ -224,7 +152,7 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */ for (count = 0, tempcon = (cupsd_client_t *)cupsArrayFirst(Clients); tempcon; tempcon = (cupsd_client_t *)cupsArrayNext(Clients)) - if (httpAddrEqual(tempcon->http.hostaddr, con->http.hostaddr)) + if (httpAddrEqual(httpGetAddress(tempcon->http), httpGetAddress(con->http))) { count ++; if (count >= MaxClientsPerHost) @@ -238,18 +166,12 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */ last_dos = time(NULL); cupsdLogMessage(CUPSD_LOG_WARN, "Possible DoS attack - more than %d clients connecting " - "from %s!", + "from %s.", MaxClientsPerHost, - httpAddrString(con->http.hostaddr, con->http.hostname, - sizeof(con->http.hostname))); + httpGetHostname(con->http, name, sizeof(name))); } -#ifdef WIN32 - closesocket(con->http.fd); -#else - close(con->http.fd); -#endif /* WIN32 */ - + httpClose(con->http); free(con); return; } @@ -258,31 +180,10 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */ * Get the hostname or format the IP address as needed... */ - if (httpAddrLocalhost(con->http.hostaddr)) - { - /* - * Map accesses from the loopback interface to "localhost"... - */ - - strlcpy(con->http.hostname, "localhost", sizeof(con->http.hostname)); - hostname = con->http.hostname; - } + if (HostNameLookups) + hostname = httpResolveHostname(con->http, NULL, 0); else - { - /* - * Map accesses from the same host to the server name. - */ - - if (HostNameLookups) - hostname = httpAddrLookup(con->http.hostaddr, con->http.hostname, - sizeof(con->http.hostname)); - else - { - hostname = NULL; - httpAddrString(con->http.hostaddr, con->http.hostname, - sizeof(con->http.hostname)); - } - } + hostname = httpGetHostname(con->http, NULL, 0); if (hostname == NULL && HostNameLookups == 2) { @@ -290,15 +191,11 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */ * Can't have an unresolved IP address with double-lookups enabled... */ -#ifdef WIN32 - closesocket(con->http.fd); -#else - close(con->http.fd); -#endif /* WIN32 */ + httpClose(con->http); - cupsdLogMessage(CUPSD_LOG_WARN, + cupsdLogClient(con, CUPSD_LOG_WARN, "Name lookup failed - connection from %s closed!", - con->http.hostname); + httpGetHostname(con->http, NULL, 0)); free(con); return; @@ -310,15 +207,17 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */ * Do double lookups as needed... */ - if ((addrlist = httpAddrGetList(con->http.hostname, AF_UNSPEC, NULL)) - != NULL) + http_addrlist_t *addrlist, /* List of addresses */ + *addr; /* Current address */ + + if ((addrlist = httpAddrGetList(hostname, AF_UNSPEC, NULL)) != NULL) { /* * See if the hostname maps to the same IP address... */ for (addr = addrlist; addr; addr = addr->next) - if (httpAddrEqual(con->http.hostaddr, &(addr->addr))) + if (httpAddrEqual(httpGetAddress(con->http), &(addr->addr))) break; } else @@ -333,15 +232,11 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */ * with double-lookups enabled... */ -#ifdef WIN32 - closesocket(con->http.fd); -#else - close(con->http.fd); -#endif /* WIN32 */ + httpClose(con->http); - cupsdLogMessage(CUPSD_LOG_WARN, + cupsdLogClient(con, CUPSD_LOG_WARN, "IP lookup failed - connection from %s closed!", - con->http.hostname); + httpGetHostname(con->http, NULL, 0)); free(con); return; } @@ -352,53 +247,73 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */ * See if the connection is denied by TCP wrappers... */ - request_init(&wrap_req, RQ_DAEMON, "cupsd", RQ_FILE, con->http.fd, NULL); + request_init(&wrap_req, RQ_DAEMON, "cupsd", RQ_FILE, httpGetFd(con->http), + NULL); fromhost(&wrap_req); if (!hosts_access(&wrap_req)) { -#ifdef WIN32 - closesocket(con->http.fd); -#else - close(con->http.fd); -#endif /* WIN32 */ + httpClose(con->http); - cupsdLogMessage(CUPSD_LOG_WARN, + cupsdLogClient(con, CUPSD_LOG_WARN, "Connection from %s refused by /etc/hosts.allow and " - "/etc/hosts.deny rules.", con->http.hostname); + "/etc/hosts.deny rules.", httpGetHostname(con->http, NULL, 0)); free(con); return; } #endif /* HAVE_TCPD_H */ #ifdef AF_LOCAL - if (con->http.hostaddr->addr.sa_family == AF_LOCAL) - cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] Accepted from %s (Domain)", - con->http.fd, con->http.hostname); + if (httpAddrFamily(httpGetAddress(con->http)) == AF_LOCAL) + { +# ifdef __APPLE__ + socklen_t peersize; /* Size of peer credentials */ + pid_t peerpid; /* Peer process ID */ + char peername[256]; /* Name of process */ + + peersize = sizeof(peerpid); + if (!getsockopt(httpGetFd(con->http), SOL_LOCAL, LOCAL_PEERPID, &peerpid, + &peersize)) + { + if (!proc_name((int)peerpid, peername, sizeof(peername))) + cupsdLogClient(con, CUPSD_LOG_DEBUG, + "Accepted from %s (Domain ???[%d])", + httpGetHostname(con->http, NULL, 0), (int)peerpid); + else + cupsdLogClient(con, CUPSD_LOG_DEBUG, + "Accepted from %s (Domain %s[%d])", + httpGetHostname(con->http, NULL, 0), peername, (int)peerpid); + } + else +# endif /* __APPLE__ */ + + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Accepted from %s (Domain)", + httpGetHostname(con->http, NULL, 0)); + } else #endif /* AF_LOCAL */ - cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] Accepted from %s:%d (IPv%d)", - con->http.fd, con->http.hostname, - _httpAddrPort(con->http.hostaddr), - _httpAddrFamily(con->http.hostaddr) == AF_INET ? 4 : 6); + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Accepted from %s:%d (IPv%d)", + httpGetHostname(con->http, NULL, 0), + httpAddrPort(httpGetAddress(con->http)), + httpAddrFamily(httpGetAddress(con->http)) == AF_INET ? 4 : 6); /* * Get the local address the client connected to... */ addrlen = sizeof(temp); - if (getsockname(con->http.fd, (struct sockaddr *)&temp, &addrlen)) + if (getsockname(httpGetFd(con->http), (struct sockaddr *)&temp, &addrlen)) { - cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to get local address - %s", - strerror(errno)); + cupsdLogClient(con, CUPSD_LOG_ERROR, "Unable to get local address - %s", + strerror(errno)); - strcpy(con->servername, "localhost"); + strlcpy(con->servername, "localhost", sizeof(con->servername)); con->serverport = LocalPort; } #ifdef AF_LOCAL - else if (_httpAddrFamily(&temp) == AF_LOCAL) + else if (httpAddrFamily(&temp) == AF_LOCAL) { - strcpy(con->servername, "localhost"); + strlcpy(con->servername, "localhost", sizeof(con->servername)); con->serverport = LocalPort; } #endif /* AF_LOCAL */ @@ -411,7 +326,7 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */ else httpAddrString(&temp, con->servername, sizeof(con->servername)); - con->serverport = _httpAddrPort(&(lis->address)); + con->serverport = httpAddrPort(&(lis->address)); } /* @@ -421,25 +336,13 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */ cupsArrayAdd(Clients, con); /* - * Using TCP_NODELAY improves responsiveness, especially on systems with a slow - * loopback interface. Since we write large buffers when sending print files - * and requests there shouldn't be any performance penalty for this... - */ - - val = 1; - setsockopt(con->http.fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)); - - /* - * Close this file on all execs... - */ - - fcntl(con->http.fd, F_SETFD, fcntl(con->http.fd, F_GETFD) | FD_CLOEXEC); - - /* * Add the socket to the server select. */ - cupsdAddSelect(con->http.fd, (cupsd_selfunc_t)cupsdReadClient, NULL, con); + cupsdAddSelect(httpGetFd(con->http), (cupsd_selfunc_t)cupsdReadClient, NULL, + con); + + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Waiting for request."); /* * Temporarily suspend accept()'s until we lose a client... @@ -453,15 +356,13 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */ * See if we are connecting on a secure port... */ - if (lis->encryption == HTTP_ENCRYPT_ALWAYS) + if (lis->encryption == HTTP_ENCRYPTION_ALWAYS) { /* * https connection; go secure... */ - con->http.encryption = HTTP_ENCRYPT_ALWAYS; - - if (!cupsdStartTLS(con)) + if (cupsd_start_tls(con, HTTP_ENCRYPTION_ALWAYS)) cupsdCloseClient(con); } else @@ -480,8 +381,7 @@ cupsdCloseAllClients(void) cupsd_client_t *con; /* Current client */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCloseAllClients() Clients=%d", - cupsArrayCount(Clients)); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCloseAllClients() Clients=%d", cupsArrayCount(Clients)); for (con = (cupsd_client_t *)cupsArrayFirst(Clients); con; @@ -499,36 +399,18 @@ int /* O - 1 if partial close, 0 if fully closed */ cupsdCloseClient(cupsd_client_t *con) /* I - Client to close */ { int partial; /* Do partial close for SSL? */ -#ifdef HAVE_LIBSSL -#elif defined(HAVE_GNUTLS) -# elif defined(HAVE_CDSASSL) -#endif /* HAVE_LIBSSL */ - cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] Closing connection.", - con->http.fd); + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Closing connection."); /* * Flush pending writes before closing... */ - httpFlushWrite(HTTP(con)); + httpFlushWrite(con->http); partial = 0; -#ifdef HAVE_SSL - /* - * Shutdown encryption as needed... - */ - - if (con->http.tls) - { - partial = 1; - - cupsdEndTLS(con); - } -#endif /* HAVE_SSL */ - if (con->pipe_pid != 0) { /* @@ -551,19 +433,31 @@ cupsdCloseClient(cupsd_client_t *con) /* I - Client to close */ * Close the socket and clear the file from the input set for select()... */ - if (con->http.fd >= 0) + if (httpGetFd(con->http) >= 0) { cupsArrayRemove(ActiveClients, con); cupsdSetBusyState(); +#ifdef HAVE_SSL + /* + * Shutdown encryption as needed... + */ + + if (httpIsEncrypted(con->http)) + partial = 1; +#endif /* HAVE_SSL */ + if (partial) { /* * Only do a partial close so that the encrypted client gets everything. */ - shutdown(con->http.fd, 0); - cupsdAddSelect(con->http.fd, (cupsd_selfunc_t)cupsdReadClient, NULL, con); + httpShutdown(con->http); + cupsdAddSelect(httpGetFd(con->http), (cupsd_selfunc_t)cupsdReadClient, + NULL, con); + + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Waiting for socket close."); } else { @@ -571,9 +465,9 @@ cupsdCloseClient(cupsd_client_t *con) /* I - Client to close */ * Shut the socket down fully... */ - cupsdRemoveSelect(con->http.fd); - close(con->http.fd); - con->http.fd = -1; + cupsdRemoveSelect(httpGetFd(con->http)); + httpClose(con->http); + con->http = NULL; } } @@ -583,13 +477,16 @@ cupsdCloseClient(cupsd_client_t *con) /* I - Client to close */ * Free memory... */ - if (con->http.input_set) - free(con->http.input_set); + cupsdRemoveSelect(httpGetFd(con->http)); + + httpClose(con->http); - httpClearCookie(HTTP(con)); - httpClearFields(HTTP(con)); + if (con->filename) + { + unlink(con->filename); + cupsdClearString(&con->filename); + } - cupsdClearString(&con->filename); cupsdClearString(&con->command); cupsdClearString(&con->options); cupsdClearString(&con->query_string); @@ -642,21 +539,6 @@ cupsdCloseClient(cupsd_client_t *con) /* I - Client to close */ /* - * 'cupsdFlushHeader()' - Flush the header fields to the client. - */ - -int /* I - Bytes written or -1 on error */ -cupsdFlushHeader(cupsd_client_t *con) /* I - Client to flush to */ -{ - int bytes = httpFlushWrite(HTTP(con)); - - con->http.data_encoding = HTTP_ENCODE_LENGTH; - - return (bytes); -} - - -/* * 'cupsdReadClient()' - Read data from a client. */ @@ -664,11 +546,8 @@ void cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ { char line[32768], /* Line from client... */ - operation[64], /* Operation code from socket */ - version[64], /* HTTP version number string */ locale[64], /* Locale */ *ptr; /* Pointer into strings */ - int major, minor; /* HTTP version numbers */ http_status_t status; /* Transfer status */ ipp_state_t ipp_state; /* State of IPP transfer */ int bytes; /* Number of bytes to POST */ @@ -680,25 +559,34 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ static unsigned request_id = 0; /* Request ID for temp files */ - status = HTTP_CONTINUE; - - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "[Client %d] cupsdReadClient " - "error=%d, " - "used=%d, " - "state=%s, " - "data_encoding=HTTP_ENCODE_%s, " - "data_remaining=" CUPS_LLFMT ", " - "request=%p(%s), " - "file=%d", - con->http.fd, con->http.error, con->http.used, - http_states[con->http.state], - con->http.data_encoding == HTTP_ENCODE_CHUNKED ? - "CHUNKED" : "LENGTH", - CUPS_LLCAST con->http.data_remaining, - con->request, - con->request ? ipp_states[con->request->state] : "", - con->file); + status = HTTP_STATUS_CONTINUE; + + cupsdLogClient(con, CUPSD_LOG_DEBUG2, "cupsdReadClient: error=%d, used=%d, state=%s, data_encoding=HTTP_ENCODING_%s, data_remaining=" CUPS_LLFMT ", request=%p(%s), file=%d", httpError(con->http), (int)httpGetReady(con->http), httpStateString(httpGetState(con->http)), httpIsChunked(con->http) ? "CHUNKED" : "LENGTH", CUPS_LLCAST httpGetRemaining(con->http), con->request, con->request ? ippStateString(ippGetState(con->request)) : "", con->file); + + if (httpGetState(con->http) == HTTP_STATE_GET_SEND || + httpGetState(con->http) == HTTP_STATE_POST_SEND || + httpGetState(con->http) == HTTP_STATE_STATUS) + { + /* + * If we get called in the wrong state, then something went wrong with the + * connection and we need to shut it down... + */ + + if (!httpGetReady(con->http) && recv(httpGetFd(con->http), buf, 1, MSG_PEEK) < 1) + { + /* + * Connection closed... + */ + + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Closing on EOF."); + cupsdCloseClient(con); + return; + } + + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Closing on unexpected HTTP read state %s.", httpStateString(httpGetState(con->http))); + cupsdCloseClient(con); + return; + } #ifdef HAVE_SSL if (con->auto_ssl) @@ -709,18 +597,16 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ con->auto_ssl = 0; - if (recv(con->http.fd, buf, 1, MSG_PEEK) == 1 && + if (recv(httpGetFd(con->http), buf, 1, MSG_PEEK) == 1 && (!buf[0] || !strchr("DGHOPT", buf[0]))) { /* * Encrypt this connection... */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "[Client %d] Saw first byte %02X, auto-negotiating " - "SSL/TLS session.", con->http.fd, buf[0] & 255); + cupsdLogClient(con, CUPSD_LOG_DEBUG2, "Saw first byte %02X, auto-negotiating SSL/TLS session.", buf[0] & 255); - if (!cupsdStartTLS(con)) + if (cupsd_start_tls(con, HTTP_ENCRYPTION_ALWAYS)) cupsdCloseClient(con); return; @@ -728,24 +614,26 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ } #endif /* HAVE_SSL */ - switch (con->http.state) + switch (httpGetState(con->http)) { - case HTTP_WAITING : + case HTTP_STATE_WAITING : /* * See if we've received a request line... */ - if (httpGets(line, sizeof(line) - 1, HTTP(con)) == NULL) + con->operation = httpReadRequest(con->http, con->uri, sizeof(con->uri)); + if (con->operation == HTTP_STATE_ERROR || + con->operation == HTTP_STATE_UNKNOWN_METHOD || + con->operation == HTTP_STATE_UNKNOWN_VERSION) { - if (con->http.error && con->http.error != EPIPE) - cupsdLogMessage(CUPSD_LOG_DEBUG, - "[Client %d] HTTP_WAITING Closing for error %d " - "(%s)", con->http.fd, con->http.error, - strerror(con->http.error)); + if (httpError(con->http)) + cupsdLogClient(con, CUPSD_LOG_DEBUG, + "HTTP_STATE_WAITING Closing for error %d (%s)", + httpError(con->http), strerror(httpError(con->http))); else - cupsdLogMessage(CUPSD_LOG_DEBUG, - "[Client %d] HTTP_WAITING Closing on EOF", - con->http.fd); + cupsdLogClient(con, CUPSD_LOG_DEBUG, + "HTTP_STATE_WAITING Closing on error: %s", + cupsLastErrorString()); cupsdCloseClient(con); return; @@ -755,29 +643,19 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ * Ignore blank request lines... */ - if (line[0] == '\0') + if (con->operation == HTTP_STATE_WAITING) break; /* * Clear other state variables... */ - httpClearFields(HTTP(con)); - - con->http.activity = time(NULL); - con->http.version = HTTP_1_0; - con->http.keep_alive = HTTP_KEEPALIVE_OFF; - con->http.data_encoding = HTTP_ENCODE_LENGTH; - con->http.data_remaining = 0; - con->http._data_remaining = 0; - con->operation = HTTP_WAITING; - con->bytes = 0; - con->file = -1; - con->file_ready = 0; - con->pipe_pid = 0; - con->username[0] = '\0'; - con->password[0] = '\0'; - con->uri[0] = '\0'; + con->bytes = 0; + con->file = -1; + con->file_ready = 0; + con->pipe_pid = 0; + con->username[0] = '\0'; + con->password[0] = '\0'; cupsdClearString(&con->command); cupsdClearString(&con->options); @@ -807,62 +685,6 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ #endif /* HAVE_GSSAPI */ /* - * Grab the request line... - */ - - switch (sscanf(line, "%63s%1023s%63s", operation, con->uri, version)) - { - case 1 : - if (line[0]) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Bad request line \"%s\" from %s.", - con->http.fd, - _httpEncodeURI(buf, line, sizeof(buf)), - con->http.hostname); - cupsdSendError(con, HTTP_BAD_REQUEST, CUPSD_AUTH_NONE); - cupsdCloseClient(con); - } - return; - case 2 : - con->http.version = HTTP_0_9; - break; - case 3 : - if (sscanf(version, "HTTP/%d.%d", &major, &minor) != 2) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Bad request line \"%s\" from %s.", - con->http.fd, - _httpEncodeURI(buf, line, sizeof(buf)), - con->http.hostname); - cupsdSendError(con, HTTP_BAD_REQUEST, CUPSD_AUTH_NONE); - cupsdCloseClient(con); - return; - } - - if (major < 2) - { - con->http.version = (http_version_t)(major * 100 + minor); - if (con->http.version == HTTP_1_1 && KeepAlive) - con->http.keep_alive = HTTP_KEEPALIVE_ON; - else - con->http.keep_alive = HTTP_KEEPALIVE_OFF; - } - else - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Unsupported request line \"%s\" " - "from %s.", con->http.fd, - _httpEncodeURI(buf, line, sizeof(buf)), - con->http.hostname); - cupsdSendError(con, HTTP_NOT_SUPPORTED, CUPSD_AUTH_NONE); - cupsdCloseClient(con); - return; - } - break; - } - - /* * Handle full URLs in the request line... */ @@ -874,18 +696,24 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ resource[HTTP_MAX_URI]; /* Resource path */ int port; /* Port number */ - /* * Separate the URI into its components... */ - httpSeparateURI(HTTP_URI_CODING_MOST, con->uri, - scheme, sizeof(scheme), - userpass, sizeof(userpass), - hostname, sizeof(hostname), &port, - resource, sizeof(resource)); + if (httpSeparateURI(HTTP_URI_CODING_MOST, con->uri, + scheme, sizeof(scheme), + userpass, sizeof(userpass), + hostname, sizeof(hostname), &port, + resource, sizeof(resource)) < HTTP_URI_STATUS_OK) + { + cupsdLogClient(con, CUPSD_LOG_ERROR, "Bad URI \"%s\" in request.", + con->uri); + cupsdSendError(con, HTTP_STATUS_METHOD_NOT_ALLOWED, CUPSD_AUTH_NONE); + cupsdCloseClient(con); + return; + } - /* + /* * Only allow URIs with the servername, localhost, or an IP * address... */ @@ -893,16 +721,16 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ if (strcmp(scheme, "file") && _cups_strcasecmp(hostname, ServerName) && _cups_strcasecmp(hostname, "localhost") && + !cupsArrayFind(ServerAlias, hostname) && !isdigit(hostname[0]) && hostname[0] != '[') { /* * Nope, we don't do proxies... */ - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Bad URI \"%s\" in request.", - con->http.fd, con->uri); - cupsdSendError(con, HTTP_METHOD_NOT_ALLOWED, CUPSD_AUTH_NONE); + cupsdLogClient(con, CUPSD_LOG_ERROR, "Bad URI \"%s\" in request.", + con->uri); + cupsdSendError(con, HTTP_STATUS_METHOD_NOT_ALLOWED, CUPSD_AUTH_NONE); cupsdCloseClient(con); return; } @@ -912,45 +740,19 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ * con->uri are HTTP_MAX_URI bytes in size... */ - strcpy(con->uri, resource); + strlcpy(con->uri, resource, sizeof(con->uri)); } /* * Process the request... */ - if (!strcmp(operation, "GET")) - con->http.state = HTTP_GET; - else if (!strcmp(operation, "PUT")) - con->http.state = HTTP_PUT; - else if (!strcmp(operation, "POST")) - con->http.state = HTTP_POST; - else if (!strcmp(operation, "DELETE")) - con->http.state = HTTP_DELETE; - else if (!strcmp(operation, "TRACE")) - con->http.state = HTTP_TRACE; - else if (!strcmp(operation, "OPTIONS")) - con->http.state = HTTP_OPTIONS; - else if (!strcmp(operation, "HEAD")) - con->http.state = HTTP_HEAD; - else - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Bad operation \"%s\".", con->http.fd, - operation); - cupsdSendError(con, HTTP_BAD_REQUEST, CUPSD_AUTH_NONE); - cupsdCloseClient(con); - return; - } - gettimeofday(&(con->start), NULL); - con->operation = con->http.state; - cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] %s %s HTTP/%d.%d", - con->http.fd, operation, con->uri, - con->http.version / 100, con->http.version % 100); - - con->http.status = HTTP_OK; + cupsdLogClient(con, CUPSD_LOG_DEBUG, "%s %s HTTP/%d.%d", + httpStateString(con->operation) + 11, con->uri, + httpGetVersion(con->http) / 100, + httpGetVersion(con->http) % 100); if (!cupsArrayFind(ActiveClients, con)) { @@ -958,49 +760,45 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ cupsdSetBusyState(); } - case HTTP_OPTIONS : - case HTTP_DELETE : - case HTTP_GET : - case HTTP_HEAD : - case HTTP_POST : - case HTTP_PUT : - case HTTP_TRACE : + case HTTP_STATE_OPTIONS : + case HTTP_STATE_DELETE : + case HTTP_STATE_GET : + case HTTP_STATE_HEAD : + case HTTP_STATE_POST : + case HTTP_STATE_PUT : + case HTTP_STATE_TRACE : /* * Parse incoming parameters until the status changes... */ - while ((status = httpUpdate(HTTP(con))) == HTTP_CONTINUE) - if (!data_ready(con)) + while ((status = httpUpdate(con->http)) == HTTP_STATUS_CONTINUE) + if (!httpGetReady(con->http)) break; - if (status != HTTP_OK && status != HTTP_CONTINUE) + if (status != HTTP_STATUS_OK && status != HTTP_STATUS_CONTINUE) { - if (con->http.error && con->http.error != EPIPE) - cupsdLogMessage(CUPSD_LOG_DEBUG, - "[Client %d] Closing for error %d (%s) while " - "reading headers.", - con->http.fd, con->http.error, - strerror(con->http.error)); + if (httpError(con->http) && httpError(con->http) != EPIPE) + cupsdLogClient(con, CUPSD_LOG_DEBUG, + "Closing for error %d (%s) while reading headers.", + httpError(con->http), strerror(httpError(con->http))); else - cupsdLogMessage(CUPSD_LOG_DEBUG, - "[Client %d] Closing on EOF while reading headers.", - con->http.fd); + cupsdLogClient(con, CUPSD_LOG_DEBUG, + "Closing on EOF while reading headers."); - cupsdSendError(con, HTTP_BAD_REQUEST, CUPSD_AUTH_NONE); + cupsdSendError(con, HTTP_STATUS_BAD_REQUEST, CUPSD_AUTH_NONE); cupsdCloseClient(con); return; } break; default : - if (!data_ready(con) && recv(con->http.fd, buf, 1, MSG_PEEK) < 1) + if (!httpGetReady(con->http) && recv(httpGetFd(con->http), buf, 1, MSG_PEEK) < 1) { /* * Connection closed... */ - cupsdLogMessage(CUPSD_LOG_DEBUG, - "[Client %d] Closing on EOF", con->http.fd); + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Closing on EOF."); cupsdCloseClient(con); return; } @@ -1011,24 +809,26 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ * Handle new transfers... */ - if (status == HTTP_OK) + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Read: status=%d", status); + + if (status == HTTP_STATUS_OK) { - if (con->http.fields[HTTP_FIELD_ACCEPT_LANGUAGE][0]) + if (httpGetField(con->http, HTTP_FIELD_ACCEPT_LANGUAGE)[0]) { /* * Figure out the locale from the Accept-Language and Content-Type * fields... */ - if ((ptr = strchr(con->http.fields[HTTP_FIELD_ACCEPT_LANGUAGE], + if ((ptr = strchr(httpGetField(con->http, HTTP_FIELD_ACCEPT_LANGUAGE), ',')) != NULL) *ptr = '\0'; - if ((ptr = strchr(con->http.fields[HTTP_FIELD_ACCEPT_LANGUAGE], + if ((ptr = strchr(httpGetField(con->http, HTTP_FIELD_ACCEPT_LANGUAGE), ';')) != NULL) *ptr = '\0'; - if ((ptr = strstr(con->http.fields[HTTP_FIELD_CONTENT_TYPE], + if ((ptr = strstr(httpGetField(con->http, HTTP_FIELD_CONTENT_TYPE), "charset=")) != NULL) { /* @@ -1037,14 +837,14 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ */ snprintf(locale, sizeof(locale), "%s.%s", - con->http.fields[HTTP_FIELD_ACCEPT_LANGUAGE], ptr + 8); + httpGetField(con->http, HTTP_FIELD_ACCEPT_LANGUAGE), ptr + 8); if ((ptr = strchr(locale, ',')) != NULL) *ptr = '\0'; } else snprintf(locale, sizeof(locale), "%s.UTF-8", - con->http.fields[HTTP_FIELD_ACCEPT_LANGUAGE]); + httpGetField(con->http, HTTP_FIELD_ACCEPT_LANGUAGE)); con->language = cupsLangGet(locale); } @@ -1053,25 +853,23 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ cupsdAuthorize(con); - if (!_cups_strncasecmp(con->http.fields[HTTP_FIELD_CONNECTION], + if (!_cups_strncasecmp(httpGetField(con->http, HTTP_FIELD_CONNECTION), "Keep-Alive", 10) && KeepAlive) - con->http.keep_alive = HTTP_KEEPALIVE_ON; - else if (!_cups_strncasecmp(con->http.fields[HTTP_FIELD_CONNECTION], + httpSetKeepAlive(con->http, HTTP_KEEPALIVE_ON); + else if (!_cups_strncasecmp(httpGetField(con->http, HTTP_FIELD_CONNECTION), "close", 5)) - con->http.keep_alive = HTTP_KEEPALIVE_OFF; + httpSetKeepAlive(con->http, HTTP_KEEPALIVE_OFF); - if (!con->http.fields[HTTP_FIELD_HOST][0] && - con->http.version >= HTTP_1_1) + if (!httpGetField(con->http, HTTP_FIELD_HOST)[0] && + httpGetVersion(con->http) >= HTTP_VERSION_1_1) { /* * HTTP/1.1 and higher require the "Host:" field... */ - if (!cupsdSendError(con, HTTP_BAD_REQUEST, CUPSD_AUTH_NONE)) + if (!cupsdSendError(con, HTTP_STATUS_BAD_REQUEST, CUPSD_AUTH_NONE)) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Missing Host: field in request.", - con->http.fd); + cupsdLogClient(con, CUPSD_LOG_ERROR, "Missing Host: field in request."); cupsdCloseClient(con); return; } @@ -1083,18 +881,17 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ * or IPv6 values in the Host: field. */ - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Request from \"%s\" using invalid Host: " - "field \"%s\"", con->http.fd, con->http.hostname, - con->http.fields[HTTP_FIELD_HOST]); + cupsdLogClient(con, CUPSD_LOG_ERROR, + "Request from \"%s\" using invalid Host: field \"%s\".", + httpGetHostname(con->http, NULL, 0), httpGetField(con->http, HTTP_FIELD_HOST)); - if (!cupsdSendError(con, HTTP_BAD_REQUEST, CUPSD_AUTH_NONE)) + if (!cupsdSendError(con, HTTP_STATUS_BAD_REQUEST, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; } } - else if (con->operation == HTTP_OPTIONS) + else if (con->operation == HTTP_STATE_OPTIONS) { /* * Do OPTIONS command... @@ -1102,45 +899,37 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ if (con->best && con->best->type != CUPSD_AUTH_NONE) { - if (!cupsdSendHeader(con, HTTP_UNAUTHORIZED, NULL, CUPSD_AUTH_NONE)) + httpClearFields(con->http); + + if (!cupsdSendHeader(con, HTTP_STATUS_UNAUTHORIZED, NULL, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; } } - if (!_cups_strcasecmp(con->http.fields[HTTP_FIELD_CONNECTION], "Upgrade") && - con->http.tls == NULL) + if (!_cups_strcasecmp(httpGetField(con->http, HTTP_FIELD_CONNECTION), "Upgrade") && strstr(httpGetField(con->http, HTTP_FIELD_UPGRADE), "TLS/") != NULL && !httpIsEncrypted(con->http)) { #ifdef HAVE_SSL /* * Do encryption stuff... */ - if (!cupsdSendHeader(con, HTTP_SWITCHING_PROTOCOLS, NULL, CUPSD_AUTH_NONE)) - { - cupsdCloseClient(con); - return; - } - - httpPrintf(HTTP(con), "Connection: Upgrade\r\n"); - httpPrintf(HTTP(con), "Upgrade: TLS/1.0,HTTP/1.1\r\n"); - httpPrintf(HTTP(con), "Content-Length: 0\r\n"); - httpPrintf(HTTP(con), "\r\n"); + httpClearFields(con->http); - if (cupsdFlushHeader(con) < 0) - { + if (!cupsdSendHeader(con, HTTP_STATUS_SWITCHING_PROTOCOLS, NULL, CUPSD_AUTH_NONE)) + { cupsdCloseClient(con); return; } - if (!cupsdStartTLS(con)) + if (cupsd_start_tls(con, HTTP_ENCRYPTION_REQUIRED)) { cupsdCloseClient(con); return; } #else - if (!cupsdSendError(con, HTTP_NOT_IMPLEMENTED, CUPSD_AUTH_NONE)) + if (!cupsdSendError(con, HTTP_STATUS_NOT_IMPLEMENTED, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; @@ -1148,17 +937,12 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ #endif /* HAVE_SSL */ } - if (!cupsdSendHeader(con, HTTP_OK, NULL, CUPSD_AUTH_NONE)) - { - cupsdCloseClient(con); - return; - } - - httpPrintf(HTTP(con), "Allow: GET, HEAD, OPTIONS, POST, PUT\r\n"); - httpPrintf(HTTP(con), "Content-Length: 0\r\n"); - httpPrintf(HTTP(con), "\r\n"); + httpClearFields(con->http); + httpSetField(con->http, HTTP_FIELD_ALLOW, + "GET, HEAD, OPTIONS, POST, PUT"); + httpSetField(con->http, HTTP_FIELD_CONTENT_LENGTH, "0"); - if (cupsdFlushHeader(con) < 0) + if (!cupsdSendHeader(con, HTTP_STATUS_OK, NULL, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; @@ -1170,11 +954,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ * Protect against malicious users! */ - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Request for non-absolute resource \"%s\".", - con->http.fd, con->uri); + cupsdLogClient(con, CUPSD_LOG_ERROR, + "Request for non-absolute resource \"%s\".", con->uri); - if (!cupsdSendError(con, HTTP_FORBIDDEN, CUPSD_AUTH_NONE)) + if (!cupsdSendError(con, HTTP_STATUS_FORBIDDEN, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; @@ -1182,39 +965,30 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ } else { - if (!_cups_strcasecmp(con->http.fields[HTTP_FIELD_CONNECTION], - "Upgrade") && con->http.tls == NULL) + if (!_cups_strcasecmp(httpGetField(con->http, HTTP_FIELD_CONNECTION), + "Upgrade") && !httpIsEncrypted(con->http)) { #ifdef HAVE_SSL /* * Do encryption stuff... */ - if (!cupsdSendHeader(con, HTTP_SWITCHING_PROTOCOLS, NULL, + httpClearFields(con->http); + + if (!cupsdSendHeader(con, HTTP_STATUS_SWITCHING_PROTOCOLS, NULL, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; } - httpPrintf(HTTP(con), "Connection: Upgrade\r\n"); - httpPrintf(HTTP(con), "Upgrade: TLS/1.0,HTTP/1.1\r\n"); - httpPrintf(HTTP(con), "Content-Length: 0\r\n"); - httpPrintf(HTTP(con), "\r\n"); - - if (cupsdFlushHeader(con) < 0) - { - cupsdCloseClient(con); - return; - } - - if (!cupsdStartTLS(con)) + if (cupsd_start_tls(con, HTTP_ENCRYPTION_REQUIRED)) { cupsdCloseClient(con); return; } #else - if (!cupsdSendError(con, HTTP_NOT_IMPLEMENTED, CUPSD_AUTH_NONE)) + if (!cupsdSendError(con, HTTP_STATUS_NOT_IMPLEMENTED, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; @@ -1222,23 +996,23 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ #endif /* HAVE_SSL */ } - if ((status = cupsdIsAuthorized(con, NULL)) != HTTP_OK) + if ((status = cupsdIsAuthorized(con, NULL)) != HTTP_STATUS_OK) { cupsdSendError(con, status, CUPSD_AUTH_NONE); cupsdCloseClient(con); return; } - if (con->http.expect && - (con->operation == HTTP_POST || con->operation == HTTP_PUT)) + if (httpGetExpect(con->http) && + (con->operation == HTTP_STATE_POST || con->operation == HTTP_STATE_PUT)) { - if (con->http.expect == HTTP_CONTINUE) + if (httpGetExpect(con->http) == HTTP_STATUS_CONTINUE) { /* * Send 100-continue header... */ - if (!cupsdSendHeader(con, HTTP_CONTINUE, NULL, CUPSD_AUTH_NONE)) + if (httpWriteResponse(con->http, HTTP_STATUS_CONTINUE)) { cupsdCloseClient(con); return; @@ -1250,29 +1024,23 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ * Send 417-expectation-failed header... */ - if (!cupsdSendHeader(con, HTTP_EXPECTATION_FAILED, NULL, - CUPSD_AUTH_NONE)) - { - cupsdCloseClient(con); - return; - } - - httpPrintf(HTTP(con), "Content-Length: 0\r\n"); - httpPrintf(HTTP(con), "\r\n"); + httpClearFields(con->http); + httpSetField(con->http, HTTP_FIELD_CONTENT_LENGTH, "0"); - if (cupsdFlushHeader(con) < 0) - { - cupsdCloseClient(con); - return; - } + cupsdSendError(con, HTTP_STATUS_EXPECTATION_FAILED, CUPSD_AUTH_NONE); + cupsdCloseClient(con); + return; } } - switch (con->http.state) + switch (httpGetState(con->http)) { - case HTTP_GET_SEND : + case HTTP_STATE_GET_SEND : + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Processing GET %s", con->uri); + if ((!strncmp(con->uri, "/ppd/", 5) || - !strncmp(con->uri, "/printers/", 10)) && + !strncmp(con->uri, "/printers/", 10) || + !strncmp(con->uri, "/classes/", 9)) && !strcmp(con->uri + strlen(con->uri) - 4, ".ppd")) { /* @@ -1284,8 +1052,36 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ if (!strncmp(con->uri, "/ppd/", 5)) p = cupsdFindPrinter(con->uri + 5); - else + else if (!strncmp(con->uri, "/printers/", 10)) p = cupsdFindPrinter(con->uri + 10); + else + { + p = cupsdFindClass(con->uri + 9); + + if (p) + { + int i; /* Looping var */ + + for (i = 0; i < p->num_printers; i ++) + { + if (!(p->printers[i]->type & CUPS_PRINTER_CLASS)) + { + char ppdname[1024];/* PPD filename */ + + snprintf(ppdname, sizeof(ppdname), "%s/ppd/%s.ppd", + ServerRoot, p->printers[i]->name); + if (!access(ppdname, 0)) + { + p = p->printers[i]; + break; + } + } + } + + if (i >= p->num_printers) + p = NULL; + } + } if (p) { @@ -1293,7 +1089,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ } else { - if (!cupsdSendError(con, HTTP_NOT_FOUND, CUPSD_AUTH_NONE)) + if (!cupsdSendError(con, HTTP_STATUS_NOT_FOUND, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; @@ -1319,13 +1115,39 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ else if (!strncmp(con->uri, "/printers/", 10)) p = cupsdFindPrinter(con->uri + 10); else - p = cupsdFindClass(con->uri + 9); + { + p = cupsdFindClass(con->uri + 9); + + if (p) + { + int i; /* Looping var */ + + for (i = 0; i < p->num_printers; i ++) + { + if (!(p->printers[i]->type & CUPS_PRINTER_CLASS)) + { + char ppdname[1024];/* PPD filename */ + + snprintf(ppdname, sizeof(ppdname), "%s/ppd/%s.ppd", + ServerRoot, p->printers[i]->name); + if (!access(ppdname, 0)) + { + p = p->printers[i]; + break; + } + } + } + + if (i >= p->num_printers) + p = NULL; + } + } if (p) snprintf(con->uri, sizeof(con->uri), "/icons/%s.png", p->name); else { - if (!cupsdSendError(con, HTTP_NOT_FOUND, CUPSD_AUTH_NONE)) + if (!cupsdSendError(con, HTTP_STATUS_NOT_FOUND, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; @@ -1340,7 +1162,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ * Web interface is disabled. Show an appropriate message... */ - if (!cupsdSendError(con, HTTP_WEBIF_DISABLED, CUPSD_AUTH_NONE)) + if (!cupsdSendError(con, HTTP_STATUS_CUPS_WEBIF_DISABLED, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; @@ -1411,17 +1233,17 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ if (!cupsdSendCommand(con, con->command, con->options, 0)) { - if (!cupsdSendError(con, HTTP_NOT_FOUND, CUPSD_AUTH_NONE)) + if (!cupsdSendError(con, HTTP_STATUS_NOT_FOUND, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; } } else - cupsdLogRequest(con, HTTP_OK); + cupsdLogRequest(con, HTTP_STATUS_OK); - if (con->http.version <= HTTP_1_0) - con->http.keep_alive = HTTP_KEEPALIVE_OFF; + if (httpGetVersion(con->http) <= HTTP_VERSION_1_0) + httpSetKeepAlive(con->http, HTTP_KEEPALIVE_OFF); } else if ((!strncmp(con->uri, "/admin/conf/", 12) && (strchr(con->uri + 12, '/') || @@ -1435,10 +1257,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ * /admin/conf... */ - cupsdLogMessage(CUPSD_LOG_ERROR, + cupsdLogClient(con, CUPSD_LOG_ERROR, "Request for subdirectory \"%s\"!", con->uri); - if (!cupsdSendError(con, HTTP_FORBIDDEN, CUPSD_AUTH_NONE)) + if (!cupsdSendError(con, HTTP_STATUS_FORBIDDEN, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; @@ -1455,7 +1277,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ if ((filename = get_file(con, &filestats, buf, sizeof(buf))) == NULL) { - if (!cupsdSendError(con, HTTP_NOT_FOUND, CUPSD_AUTH_NONE)) + if (!cupsdSendError(con, HTTP_STATUS_NOT_FOUND, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; @@ -1466,6 +1288,8 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ type = mimeFileType(MimeDatabase, filename, NULL, NULL); + cupsdLogClient(con, CUPSD_LOG_DEBUG, "filename=\"%s\", type=%s/%s", filename, type ? type->super : "", type ? type->type : ""); + if (is_cgi(con, filename, &filestats, type)) { /* @@ -1475,23 +1299,23 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ if (!cupsdSendCommand(con, con->command, con->options, 0)) { - if (!cupsdSendError(con, HTTP_NOT_FOUND, CUPSD_AUTH_NONE)) + if (!cupsdSendError(con, HTTP_STATUS_NOT_FOUND, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; } } else - cupsdLogRequest(con, HTTP_OK); + cupsdLogRequest(con, HTTP_STATUS_OK); - if (con->http.version <= HTTP_1_0) - con->http.keep_alive = HTTP_KEEPALIVE_OFF; + if (httpGetVersion(con->http) <= HTTP_VERSION_1_0) + httpSetKeepAlive(con->http, HTTP_KEEPALIVE_OFF); break; } if (!check_if_modified(con, &filestats)) { - if (!cupsdSendError(con, HTTP_NOT_MODIFIED, CUPSD_AUTH_NONE)) + if (!cupsdSendError(con, HTTP_STATUS_NOT_MODIFIED, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; @@ -1500,11 +1324,11 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ else { if (type == NULL) - strcpy(line, "text/plain"); + strlcpy(line, "text/plain", sizeof(line)); else snprintf(line, sizeof(line), "%s/%s", type->super, type->type); - if (!write_file(con, HTTP_OK, filename, line, &filestats)) + if (!write_file(con, HTTP_STATUS_OK, filename, line, &filestats)) { cupsdCloseClient(con); return; @@ -1513,21 +1337,21 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ } break; - case HTTP_POST_RECV : + case HTTP_STATE_POST_RECV : /* * See if the POST request includes a Content-Length field, and if * so check the length against any limits that are set... */ - if (con->http.fields[HTTP_FIELD_CONTENT_LENGTH][0] && + if (httpGetField(con->http, HTTP_FIELD_CONTENT_LENGTH)[0] && MaxRequestSize > 0 && - con->http.data_remaining > MaxRequestSize) + httpGetLength2(con->http) > MaxRequestSize) { /* * Request too large... */ - if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE, CUPSD_AUTH_NONE)) + if (!cupsdSendError(con, HTTP_STATUS_REQUEST_TOO_LARGE, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; @@ -1535,15 +1359,13 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ break; } - else if (con->http.data_remaining < 0 || - (!con->http.fields[HTTP_FIELD_CONTENT_LENGTH][0] && - con->http.data_encoding == HTTP_ENCODE_LENGTH)) + else if (httpGetLength2(con->http) < 0) { /* * Negative content lengths are invalid! */ - if (!cupsdSendError(con, HTTP_BAD_REQUEST, CUPSD_AUTH_NONE)) + if (!cupsdSendError(con, HTTP_STATUS_BAD_REQUEST, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; @@ -1557,7 +1379,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ * content-type field will be "application/ipp"... */ - if (!strcmp(con->http.fields[HTTP_FIELD_CONTENT_TYPE], + if (!strcmp(httpGetField(con->http, HTTP_FIELD_CONTENT_TYPE), "application/ipp")) con->request = ippNew(); else if (!WebInterface) @@ -1566,7 +1388,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ * Web interface is disabled. Show an appropriate message... */ - if (!cupsdSendError(con, HTTP_WEBIF_DISABLED, CUPSD_AUTH_NONE)) + if (!cupsdSendError(con, HTTP_STATUS_CUPS_WEBIF_DISABLED, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; @@ -1634,8 +1456,8 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ cupsdSetString(&con->options, NULL); } - if (con->http.version <= HTTP_1_0) - con->http.keep_alive = HTTP_KEEPALIVE_OFF; + if (httpGetVersion(con->http) <= HTTP_VERSION_1_0) + httpSetKeepAlive(con->http, HTTP_KEEPALIVE_OFF); } else { @@ -1646,7 +1468,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ if ((filename = get_file(con, &filestats, buf, sizeof(buf))) == NULL) { - if (!cupsdSendError(con, HTTP_NOT_FOUND, CUPSD_AUTH_NONE)) + if (!cupsdSendError(con, HTTP_STATUS_NOT_FOUND, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; @@ -1663,7 +1485,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ * Only POST to CGI's... */ - if (!cupsdSendError(con, HTTP_UNAUTHORIZED, CUPSD_AUTH_NONE)) + if (!cupsdSendError(con, HTTP_STATUS_UNAUTHORIZED, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; @@ -1672,7 +1494,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ } break; - case HTTP_PUT_RECV : + case HTTP_STATE_PUT_RECV : /* * Validate the resource name... */ @@ -1683,11 +1505,10 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ * PUT can only be done to the cupsd.conf file... */ - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Disallowed PUT request for \"%s\".", - con->http.fd, con->uri); + cupsdLogClient(con, CUPSD_LOG_ERROR, + "Disallowed PUT request for \"%s\".", con->uri); - if (!cupsdSendError(con, HTTP_FORBIDDEN, CUPSD_AUTH_NONE)) + if (!cupsdSendError(con, HTTP_STATUS_FORBIDDEN, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; @@ -1701,15 +1522,15 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ * so check the length against any limits that are set... */ - if (con->http.fields[HTTP_FIELD_CONTENT_LENGTH][0] && + if (httpGetField(con->http, HTTP_FIELD_CONTENT_LENGTH)[0] && MaxRequestSize > 0 && - con->http.data_remaining > MaxRequestSize) + httpGetLength2(con->http) > MaxRequestSize) { /* * Request too large... */ - if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE, CUPSD_AUTH_NONE)) + if (!cupsdSendError(con, HTTP_STATUS_REQUEST_TOO_LARGE, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; @@ -1717,13 +1538,13 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ break; } - else if (con->http.data_remaining < 0) + else if (httpGetLength2(con->http) < 0) { /* * Negative content lengths are invalid! */ - if (!cupsdSendError(con, HTTP_BAD_REQUEST, CUPSD_AUTH_NONE)) + if (!cupsdSendError(con, HTTP_STATUS_BAD_REQUEST, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; @@ -1742,12 +1563,11 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ if (con->file < 0) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Unable to create request file " - "\"%s\": %s", con->http.fd, con->filename, - strerror(errno)); + cupsdLogClient(con, CUPSD_LOG_ERROR, + "Unable to create request file \"%s\": %s", + con->filename, strerror(errno)); - if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE, CUPSD_AUTH_NONE)) + if (!cupsdSendError(con, HTTP_STATUS_REQUEST_TOO_LARGE, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; @@ -1759,13 +1579,13 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ fcntl(con->file, F_SETFD, fcntl(con->file, F_GETFD) | FD_CLOEXEC); break; - case HTTP_DELETE : - case HTTP_TRACE : - cupsdSendError(con, HTTP_NOT_IMPLEMENTED, CUPSD_AUTH_NONE); + case HTTP_STATE_DELETE : + case HTTP_STATE_TRACE : + cupsdSendError(con, HTTP_STATUS_NOT_IMPLEMENTED, CUPSD_AUTH_NONE); cupsdCloseClient(con); return; - case HTTP_HEAD : + case HTTP_STATE_HEAD : if (!strncmp(con->uri, "/printers/", 10) && !strcmp(con->uri + strlen(con->uri) - 4, ".ppd")) { @@ -1780,12 +1600,13 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ snprintf(con->uri, sizeof(con->uri), "/ppd/%s.ppd", p->name); else { - if (!cupsdSendError(con, HTTP_NOT_FOUND, CUPSD_AUTH_NONE)) + if (!cupsdSendError(con, HTTP_STATUS_NOT_FOUND, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; } + cupsdLogRequest(con, HTTP_STATUS_NOT_FOUND); break; } } @@ -1803,36 +1624,27 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ snprintf(con->uri, sizeof(con->uri), "/icons/%s.png", p->name); else { - if (!cupsdSendError(con, HTTP_NOT_FOUND, CUPSD_AUTH_NONE)) + if (!cupsdSendError(con, HTTP_STATUS_NOT_FOUND, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; } + cupsdLogRequest(con, HTTP_STATUS_NOT_FOUND); break; } } else if (!WebInterface) { - if (!cupsdSendHeader(con, HTTP_OK, line, CUPSD_AUTH_NONE)) - { - cupsdCloseClient(con); - return; - } - - if (httpPrintf(HTTP(con), "\r\n") < 0) - { - cupsdCloseClient(con); - return; - } + httpClearFields(con->http); - if (cupsdFlushHeader(con) < 0) + if (!cupsdSendHeader(con, HTTP_STATUS_OK, NULL, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; } - con->http.state = HTTP_WAITING; + cupsdLogRequest(con, HTTP_STATUS_OK); break; } @@ -1848,25 +1660,15 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ * CGI output... */ - if (!cupsdSendHeader(con, HTTP_OK, "text/html", CUPSD_AUTH_NONE)) - { - cupsdCloseClient(con); - return; - } - - if (httpPrintf(HTTP(con), "\r\n") < 0) - { - cupsdCloseClient(con); - return; - } + httpClearFields(con->http); - if (cupsdFlushHeader(con) < 0) + if (!cupsdSendHeader(con, HTTP_STATUS_OK, "text/html", CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; } - cupsdLogRequest(con, HTTP_OK); + cupsdLogRequest(con, HTTP_STATUS_OK); } else if ((!strncmp(con->uri, "/admin/conf/", 12) && (strchr(con->uri + 12, '/') || @@ -1880,39 +1682,41 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ * /admin/conf... */ - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Request for subdirectory \"%s\".", - con->http.fd, con->uri); + cupsdLogClient(con, CUPSD_LOG_ERROR, + "Request for subdirectory \"%s\".", con->uri); - if (!cupsdSendError(con, HTTP_FORBIDDEN, CUPSD_AUTH_NONE)) + if (!cupsdSendError(con, HTTP_STATUS_FORBIDDEN, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; } + cupsdLogRequest(con, HTTP_STATUS_FORBIDDEN); break; } else if ((filename = get_file(con, &filestats, buf, sizeof(buf))) == NULL) { - if (!cupsdSendHeader(con, HTTP_NOT_FOUND, "text/html", + httpClearFields(con->http); + + if (!cupsdSendHeader(con, HTTP_STATUS_NOT_FOUND, "text/html", CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; } - cupsdLogRequest(con, HTTP_NOT_FOUND); + cupsdLogRequest(con, HTTP_STATUS_NOT_FOUND); } else if (!check_if_modified(con, &filestats)) { - if (!cupsdSendError(con, HTTP_NOT_MODIFIED, CUPSD_AUTH_NONE)) + if (!cupsdSendError(con, HTTP_STATUS_NOT_MODIFIED, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; } - cupsdLogRequest(con, HTTP_NOT_MODIFIED); + cupsdLogRequest(con, HTTP_STATUS_NOT_MODIFIED); } else { @@ -1922,46 +1726,24 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ type = mimeFileType(MimeDatabase, filename, NULL, NULL); if (type == NULL) - strcpy(line, "text/plain"); + strlcpy(line, "text/plain", sizeof(line)); else snprintf(line, sizeof(line), "%s/%s", type->super, type->type); - if (!cupsdSendHeader(con, HTTP_OK, line, CUPSD_AUTH_NONE)) - { - cupsdCloseClient(con); - return; - } + httpClearFields(con->http); - if (httpPrintf(HTTP(con), "Last-Modified: %s\r\n", - httpGetDateString(filestats.st_mtime)) < 0) - { - cupsdCloseClient(con); - return; - } + httpSetField(con->http, HTTP_FIELD_LAST_MODIFIED, + httpGetDateString(filestats.st_mtime)); + httpSetLength(con->http, (size_t)filestats.st_size); - if (httpPrintf(HTTP(con), "Content-Length: %lu\r\n", - (unsigned long)filestats.st_size) < 0) + if (!cupsdSendHeader(con, HTTP_STATUS_OK, line, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; } - cupsdLogRequest(con, HTTP_OK); - } - - if (httpPrintf(HTTP(con), "\r\n") < 0) - { - cupsdCloseClient(con); - return; - } - - if (cupsdFlushHeader(con) < 0) - { - cupsdCloseClient(con); - return; + cupsdLogRequest(con, HTTP_STATUS_OK); } - - con->http.state = HTTP_WAITING; break; default : @@ -1974,22 +1756,20 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ * Handle any incoming data... */ - switch (con->http.state) + switch (httpGetState(con->http)) { - case HTTP_PUT_RECV : + case HTTP_STATE_PUT_RECV : do { - if ((bytes = httpRead2(HTTP(con), line, sizeof(line))) < 0) + if ((bytes = httpRead2(con->http, line, sizeof(line))) < 0) { - if (con->http.error && con->http.error != EPIPE) - cupsdLogMessage(CUPSD_LOG_DEBUG, - "[Client %d] HTTP_PUT_RECV Closing for error " - "%d (%s)", con->http.fd, con->http.error, - strerror(con->http.error)); + if (httpError(con->http) && httpError(con->http) != EPIPE) + cupsdLogClient(con, CUPSD_LOG_DEBUG, + "HTTP_STATE_PUT_RECV Closing for error %d (%s)", + httpError(con->http), strerror(httpError(con->http))); else - cupsdLogMessage(CUPSD_LOG_DEBUG, - "[Client %d] HTTP_PUT_RECV Closing on EOF", - con->http.fd); + cupsdLogClient(con, CUPSD_LOG_DEBUG, + "HTTP_STATE_PUT_RECV Closing on EOF."); cupsdCloseClient(con); return; @@ -1998,29 +1778,47 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ { con->bytes += bytes; - if (write(con->file, line, bytes) < bytes) + if (MaxRequestSize > 0 && con->bytes > MaxRequestSize) + { + close(con->file); + con->file = -1; + unlink(con->filename); + cupsdClearString(&con->filename); + + if (!cupsdSendError(con, HTTP_STATUS_REQUEST_TOO_LARGE, CUPSD_AUTH_NONE)) + { + cupsdCloseClient(con); + return; + } + } + + if (write(con->file, line, (size_t)bytes) < bytes) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Unable to write %d bytes to " - "\"%s\": %s", con->http.fd, bytes, con->filename, - strerror(errno)); + cupsdLogClient(con, CUPSD_LOG_ERROR, + "Unable to write %d bytes to \"%s\": %s", bytes, + con->filename, strerror(errno)); close(con->file); con->file = -1; unlink(con->filename); cupsdClearString(&con->filename); - if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE, CUPSD_AUTH_NONE)) + if (!cupsdSendError(con, HTTP_STATUS_REQUEST_TOO_LARGE, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; } } } + else if (httpGetState(con->http) == HTTP_STATE_PUT_RECV) + { + cupsdCloseClient(con); + return; + } } - while (con->http.state == HTTP_PUT_RECV && data_ready(con)); + while (httpGetState(con->http) == HTTP_STATE_PUT_RECV && httpGetReady(con->http)); - if (con->http.state == HTTP_WAITING) + if (httpGetState(con->http) == HTTP_STATE_STATUS) { /* * End of file, see how big it is... @@ -2041,7 +1839,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ unlink(con->filename); cupsdClearString(&con->filename); - if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE, CUPSD_AUTH_NONE)) + if (!cupsdSendError(con, HTTP_STATUS_REQUEST_TOO_LARGE, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; @@ -2066,7 +1864,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ } break; - case HTTP_POST_RECV : + case HTTP_STATE_POST_RECV : do { if (con->request && con->file < 0) @@ -2075,39 +1873,43 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ * Grab any request data from the connection... */ - if ((ipp_state = ippRead(&(con->http), con->request)) == IPP_ERROR) + if (!httpWait(con->http, 0)) + return; + + if ((ipp_state = ippRead(con->http, con->request)) == IPP_STATE_ERROR) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] IPP read error: %s", con->http.fd, - cupsLastErrorString()); + cupsdLogClient(con, CUPSD_LOG_ERROR, "IPP read error: %s", + cupsLastErrorString()); - cupsdSendError(con, HTTP_BAD_REQUEST, CUPSD_AUTH_NONE); + cupsdSendError(con, HTTP_STATUS_BAD_REQUEST, CUPSD_AUTH_NONE); cupsdCloseClient(con); return; } - else if (ipp_state != IPP_DATA) + else if (ipp_state != IPP_STATE_DATA) { - if (con->http.state == HTTP_POST_SEND) + if (httpGetState(con->http) == HTTP_STATE_POST_SEND) { - cupsdSendError(con, HTTP_BAD_REQUEST, CUPSD_AUTH_NONE); + cupsdSendError(con, HTTP_STATUS_BAD_REQUEST, CUPSD_AUTH_NONE); cupsdCloseClient(con); return; } + if (httpGetReady(con->http)) + continue; break; } else { - cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] %d.%d %s %d", - con->http.fd, con->request->request.op.version[0], + cupsdLogClient(con, CUPSD_LOG_DEBUG, "%d.%d %s %d", + con->request->request.op.version[0], con->request->request.op.version[1], ippOpString(con->request->request.op.operation_id), con->request->request.op.request_id); - con->bytes += ippLength(con->request); + con->bytes += (off_t)ippLength(con->request); } } - if (con->file < 0 && con->http.state != HTTP_POST_SEND) + if (con->file < 0 && httpGetState(con->http) != HTTP_STATE_POST_SEND) { /* * Create a file as needed for the request data... @@ -2119,12 +1921,11 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ if (con->file < 0) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Unable to create request file " - "\"%s\": %s", con->http.fd, con->filename, - strerror(errno)); + cupsdLogClient(con, CUPSD_LOG_ERROR, + "Unable to create request file \"%s\": %s", + con->filename, strerror(errno)); - if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE, CUPSD_AUTH_NONE)) + if (!cupsdSendError(con, HTTP_STATUS_REQUEST_TOO_LARGE, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; @@ -2136,19 +1937,19 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ fcntl(con->file, F_SETFD, fcntl(con->file, F_GETFD) | FD_CLOEXEC); } - if (con->http.state != HTTP_POST_SEND) + if (httpGetState(con->http) != HTTP_STATE_POST_SEND) { - if ((bytes = httpRead2(HTTP(con), line, sizeof(line))) < 0) + if (!httpWait(con->http, 0)) + return; + else if ((bytes = httpRead2(con->http, line, sizeof(line))) < 0) { - if (con->http.error && con->http.error != EPIPE) - cupsdLogMessage(CUPSD_LOG_DEBUG, - "[Client %d] HTTP_POST_SEND Closing for " - "error %d (%s)", con->http.fd, con->http.error, - strerror(con->http.error)); + if (httpError(con->http) && httpError(con->http) != EPIPE) + cupsdLogClient(con, CUPSD_LOG_DEBUG, + "HTTP_STATE_POST_SEND Closing for error %d (%s)", + httpError(con->http), strerror(httpError(con->http))); else - cupsdLogMessage(CUPSD_LOG_DEBUG, - "[Client %d] HTTP_POST_SEND Closing on EOF", - con->http.fd); + cupsdLogClient(con, CUPSD_LOG_DEBUG, + "HTTP_STATE_POST_SEND Closing on EOF."); cupsdCloseClient(con); return; @@ -2157,19 +1958,32 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ { con->bytes += bytes; - if (write(con->file, line, bytes) < bytes) + if (MaxRequestSize > 0 && con->bytes > MaxRequestSize) + { + close(con->file); + con->file = -1; + unlink(con->filename); + cupsdClearString(&con->filename); + + if (!cupsdSendError(con, HTTP_STATUS_REQUEST_TOO_LARGE, CUPSD_AUTH_NONE)) + { + cupsdCloseClient(con); + return; + } + } + + if (write(con->file, line, (size_t)bytes) < bytes) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Unable to write %d bytes to " - "\"%s\": %s", con->http.fd, bytes, - con->filename, strerror(errno)); + cupsdLogClient(con, CUPSD_LOG_ERROR, + "Unable to write %d bytes to \"%s\": %s", + bytes, con->filename, strerror(errno)); close(con->file); con->file = -1; unlink(con->filename); cupsdClearString(&con->filename); - if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE, + if (!cupsdSendError(con, HTTP_STATUS_REQUEST_TOO_LARGE, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); @@ -2177,21 +1991,21 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ } } } - else if (con->http.state == HTTP_POST_RECV) + else if (httpGetState(con->http) == HTTP_STATE_POST_RECV) return; - else if (con->http.state != HTTP_POST_SEND) + else if (httpGetState(con->http) != HTTP_STATE_POST_SEND) { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "[Client %d] Closing on unexpected state %s.", - con->http.fd, http_states[con->http.state]); + cupsdLogClient(con, CUPSD_LOG_DEBUG, + "Closing on unexpected state %s.", + httpStateString(httpGetState(con->http))); cupsdCloseClient(con); return; } } } - while (con->http.state == HTTP_POST_RECV && data_ready(con)); + while (httpGetState(con->http) == HTTP_STATE_POST_RECV && httpGetReady(con->http)); - if (con->http.state == HTTP_POST_SEND) + if (httpGetState(con->http) == HTTP_STATE_POST_SEND) { if (con->file >= 0) { @@ -2220,7 +2034,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ con->request = NULL; } - if (!cupsdSendError(con, HTTP_REQUEST_TOO_LARGE, CUPSD_AUTH_NONE)) + if (!cupsdSendError(con, HTTP_STATUS_REQUEST_TOO_LARGE, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; @@ -2240,14 +2054,14 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ { if (!cupsdSendCommand(con, con->command, con->options, 0)) { - if (!cupsdSendError(con, HTTP_NOT_FOUND, CUPSD_AUTH_NONE)) + if (!cupsdSendError(con, HTTP_STATUS_NOT_FOUND, CUPSD_AUTH_NONE)) { cupsdCloseClient(con); return; } } else - cupsdLogRequest(con, HTTP_OK); + cupsdLogRequest(con, HTTP_STATUS_OK); } } @@ -2270,13 +2084,12 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ break; /* Anti-compiler-warning-code */ } - if (con->http.state == HTTP_WAITING) + if (httpGetState(con->http) == HTTP_STATE_WAITING) { - if (!con->http.keep_alive) + if (!httpGetKeepAlive(con->http)) { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "[Client %d] Closing because Keep-Alive disabled", - con->http.fd); + cupsdLogClient(con, CUPSD_LOG_DEBUG, + "Closing because Keep-Alive is disabled."); cupsdCloseClient(con); } else @@ -2308,10 +2121,10 @@ cupsdSendCommand( if (fd < 0) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Client %d] Unable to open \"%s\" for reading: %s", - con->http.fd, con->filename ? con->filename : "/dev/null", - strerror(errno)); + cupsdLogClient(con, CUPSD_LOG_ERROR, + "Unable to open \"%s\" for reading: %s", + con->filename ? con->filename : "/dev/null", + strerror(errno)); return (0); } @@ -2320,16 +2133,16 @@ cupsdSendCommand( else fd = -1; - con->pipe_pid = pipe_command(con, fd, &(con->file), command, options, root); + con->pipe_pid = pipe_command(con, fd, &(con->file), command, options, root); + con->pipe_status = HTTP_STATUS_OK; + + httpClearFields(con->http); if (fd >= 0) close(fd); - cupsdLogMessage(CUPSD_LOG_INFO, "[Client %d] Started \"%s\" (pid=%d)", - con->http.fd, command, con->pipe_pid); - - cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] file=%d", con->http.fd, - con->file); + cupsdLogClient(con, CUPSD_LOG_INFO, "Started \"%s\" (pid=%d, file=%d)", + command, con->pipe_pid, con->file); if (con->pipe_pid == 0) return (0); @@ -2338,6 +2151,8 @@ cupsdSendCommand( cupsdAddSelect(con->file, (cupsd_selfunc_t)write_pipe, NULL, con); + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Waiting for CGI data."); + con->sent_header = 0; con->file_ready = 0; con->got_fields = 0; @@ -2356,9 +2171,10 @@ cupsdSendError(cupsd_client_t *con, /* I - Connection */ http_status_t code, /* I - Error code */ int auth_type)/* I - Authentication type */ { - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "[Client %d] cupsdSendError code=%d, auth_type=%d", - con->http.fd, code, auth_type); + char location[HTTP_MAX_VALUE]; /* Location field */ + + + cupsdLogClient(con, CUPSD_LOG_DEBUG2, "cupsdSendError code=%d, auth_type=%d", code, auth_type); #ifdef HAVE_SSL /* @@ -2366,12 +2182,12 @@ cupsdSendError(cupsd_client_t *con, /* I - Connection */ * server is configured... */ - if (code == HTTP_UNAUTHORIZED && - DefaultEncryption == HTTP_ENCRYPT_REQUIRED && - _cups_strcasecmp(con->http.hostname, "localhost") && - !con->http.tls) + if (code == HTTP_STATUS_UNAUTHORIZED && + DefaultEncryption == HTTP_ENCRYPTION_REQUIRED && + _cups_strcasecmp(httpGetHostname(con->http, NULL, 0), "localhost") && + !httpIsEncrypted(con->http)) { - code = HTTP_UPGRADE_REQUIRED; + code = HTTP_STATUS_UPGRADE_REQUIRED; } #endif /* HAVE_SSL */ @@ -2389,34 +2205,20 @@ cupsdSendError(cupsd_client_t *con, /* I - Connection */ * never disable it in that case. */ - if (code >= HTTP_BAD_REQUEST && con->http.auth_type != CUPSD_AUTH_NEGOTIATE) - con->http.keep_alive = HTTP_KEEPALIVE_OFF; + strlcpy(location, httpGetField(con->http, HTTP_FIELD_LOCATION), sizeof(location)); - /* - * Send an error message back to the client. If the error code is a - * 400 or 500 series, make sure the message contains some text, too! - */ + httpClearFields(con->http); - if (!cupsdSendHeader(con, code, NULL, auth_type)) - return (0); + httpSetField(con->http, HTTP_FIELD_LOCATION, location); -#ifdef HAVE_SSL - if (code == HTTP_UPGRADE_REQUIRED) - if (httpPrintf(HTTP(con), "Connection: Upgrade\r\n") < 0) - return (0); + if (code >= HTTP_STATUS_BAD_REQUEST && con->type != CUPSD_AUTH_NEGOTIATE) + httpSetKeepAlive(con->http, HTTP_KEEPALIVE_OFF); - if (httpPrintf(HTTP(con), "Upgrade: TLS/1.0,HTTP/1.1\r\n") < 0) - return (0); -#endif /* HAVE_SSL */ + if (httpGetVersion(con->http) >= HTTP_VERSION_1_1 && + httpGetKeepAlive(con->http) == HTTP_KEEPALIVE_OFF) + httpSetField(con->http, HTTP_FIELD_CONNECTION, "close"); - if (con->http.version >= HTTP_1_1 && - con->http.keep_alive == HTTP_KEEPALIVE_OFF) - { - if (httpPrintf(HTTP(con), "Connection: close\r\n") < 0) - return (0); - } - - if (code >= HTTP_BAD_REQUEST) + if (code >= HTTP_STATUS_BAD_REQUEST) { /* * Send a human-readable error message. @@ -2430,13 +2232,13 @@ cupsdSendError(cupsd_client_t *con, /* I - Connection */ redirect[0] = '\0'; - if (code == HTTP_UNAUTHORIZED) + if (code == HTTP_STATUS_UNAUTHORIZED) text = _cupsLangString(con->language, _("Enter your username and password or the " "root username and password to access this " "page. If you are using Kerberos authentication, " "make sure you have a valid Kerberos ticket.")); - else if (code == HTTP_UPGRADE_REQUIRED) + else if (code == HTTP_STATUS_UPGRADE_REQUIRED) { text = urltext; @@ -2453,7 +2255,7 @@ cupsdSendError(cupsd_client_t *con, /* I - Connection */ "CONTENT=\"3;URL=https://%s:%d%s\">\n", con->servername, con->serverport, con->uri); } - else if (code == HTTP_WEBIF_DISABLED) + else if (code == HTTP_STATUS_CUPS_WEBIF_DISABLED) text = _cupsLangString(con->language, _("The web interface is currently disabled. Run " "\"cupsctl WebInterface=yes\" to enable it.")); @@ -2477,25 +2279,34 @@ cupsdSendError(cupsd_client_t *con, /* I - Connection */ "<P>%s</P>\n" "</BODY>\n" "</HTML>\n", - httpStatus(code), redirect, httpStatus(code), text); + _httpStatus(con->language, code), redirect, + _httpStatus(con->language, code), text); - if (httpPrintf(HTTP(con), "Content-Type: text/html; charset=utf-8\r\n") < 0) - return (0); - if (httpPrintf(HTTP(con), "Content-Length: %d\r\n", - (int)strlen(message)) < 0) + /* + * Send an error message back to the client. If the error code is a + * 400 or 500 series, make sure the message contains some text, too! + */ + + size_t length = strlen(message); /* Length of message */ + + httpSetLength(con->http, length); + + if (!cupsdSendHeader(con, code, "text/html", auth_type)) return (0); - if (httpPrintf(HTTP(con), "\r\n") < 0) + + if (httpWrite2(con->http, message, length) < 0) return (0); - if (httpPrintf(HTTP(con), "%s", message) < 0) + + if (httpFlushWrite(con->http) < 0) return (0); } - else if (httpPrintf(HTTP(con), "\r\n") < 0) - return (0); - - if (cupsdFlushHeader(con) < 0) - return (0); + else + { + httpSetField(con->http, HTTP_FIELD_CONTENT_LENGTH, "0"); - con->http.state = HTTP_WAITING; + if (!cupsdSendHeader(con, code, NULL, auth_type)) + return (0); + } return (1); } @@ -2515,54 +2326,29 @@ cupsdSendHeader( char auth_str[1024]; /* Authorization string */ + cupsdLogClient(con, CUPSD_LOG_DEBUG, "cupsdSendHeader: code=%d, type=\"%s\", auth_type=%d", code, type, auth_type); + /* * Send the HTTP status header... */ - if (code == HTTP_CONTINUE) - { - /* - * 100-continue doesn't send any headers... - */ - - return (httpPrintf(HTTP(con), "HTTP/%d.%d 100 Continue\r\n\r\n", - con->http.version / 100, con->http.version % 100) > 0); - } - else if (code == HTTP_WEBIF_DISABLED) + if (code == HTTP_STATUS_CUPS_WEBIF_DISABLED) { /* * Treat our special "web interface is disabled" status as "200 OK" for web * browsers. */ - code = HTTP_OK; + code = HTTP_STATUS_OK; } - httpFlushWrite(HTTP(con)); - - con->http.data_encoding = HTTP_ENCODE_FIELDS; - - if (httpPrintf(HTTP(con), "HTTP/%d.%d %d %s\r\n", con->http.version / 100, - con->http.version % 100, code, httpStatus(code)) < 0) - return (0); - if (httpPrintf(HTTP(con), "Date: %s\r\n", httpGetDateString(time(NULL))) < 0) - return (0); if (ServerHeader) - if (httpPrintf(HTTP(con), "Server: %s\r\n", ServerHeader) < 0) - return (0); - if (con->http.keep_alive && con->http.version >= HTTP_1_0) - { - if (httpPrintf(HTTP(con), "Connection: Keep-Alive\r\n") < 0) - return (0); - if (httpPrintf(HTTP(con), "Keep-Alive: timeout=%d\r\n", - KeepAliveTimeout) < 0) - return (0); - } - if (code == HTTP_METHOD_NOT_ALLOWED) - if (httpPrintf(HTTP(con), "Allow: GET, HEAD, OPTIONS, POST, PUT\r\n") < 0) - return (0); + httpSetField(con->http, HTTP_FIELD_SERVER, ServerHeader); + + if (code == HTTP_STATUS_METHOD_NOT_ALLOWED) + httpSetField(con->http, HTTP_FIELD_ALLOW, "GET, HEAD, OPTIONS, POST, PUT"); - if (code == HTTP_UNAUTHORIZED) + if (code == HTTP_STATUS_UNAUTHORIZED) { if (auth_type == CUPSD_AUTH_NONE) { @@ -2574,16 +2360,13 @@ cupsdSendHeader( auth_str[0] = '\0'; - if (auth_type == CUPSD_AUTH_BASIC || auth_type == CUPSD_AUTH_BASICDIGEST) + if (auth_type == CUPSD_AUTH_BASIC) strlcpy(auth_str, "Basic realm=\"CUPS\"", sizeof(auth_str)); - else if (auth_type == CUPSD_AUTH_DIGEST) - snprintf(auth_str, sizeof(auth_str), "Digest realm=\"CUPS\", nonce=\"%s\"", - con->http.hostname); #ifdef HAVE_GSSAPI else if (auth_type == CUPSD_AUTH_NEGOTIATE) { # ifdef AF_LOCAL - if (_httpAddrFamily(con->http.hostaddr) == AF_LOCAL) + if (httpAddrFamily(httpGetAddress(con->http)) == AF_LOCAL) strlcpy(auth_str, "Basic realm=\"CUPS\"", sizeof(auth_str)); else # endif /* AF_LOCAL */ @@ -2592,7 +2375,7 @@ cupsdSendHeader( #endif /* HAVE_GSSAPI */ if (con->best && auth_type != CUPSD_AUTH_NEGOTIATE && - !_cups_strcasecmp(con->http.hostname, "localhost")) + !_cups_strcasecmp(httpGetHostname(con->http, NULL, 0), "localhost")) { /* * Add a "trc" (try root certification) parameter for local non-Kerberos @@ -2608,7 +2391,7 @@ cupsdSendHeader( size_t auth_size; /* Size of remaining buffer */ auth_key = auth_str + strlen(auth_str); - auth_size = sizeof(auth_str) - (auth_key - auth_str); + auth_size = sizeof(auth_str) - (size_t)(auth_key - auth_str); for (name = (char *)cupsArrayFirst(con->best->names); name; @@ -2641,35 +2424,24 @@ cupsdSendHeader( if (auth_str[0]) { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "[Client %d] WWW-Authenticate: %s", con->http.fd, - auth_str); + cupsdLogClient(con, CUPSD_LOG_DEBUG, "WWW-Authenticate: %s", auth_str); - if (httpPrintf(HTTP(con), "WWW-Authenticate: %s\r\n", auth_str) < 0) - return (0); + httpSetField(con->http, HTTP_FIELD_WWW_AUTHENTICATE, auth_str); } } if (con->language && strcmp(con->language->language, "C")) - { - if (httpPrintf(HTTP(con), "Content-Language: %s\r\n", - con->language->language) < 0) - return (0); - } + httpSetField(con->http, HTTP_FIELD_CONTENT_LANGUAGE, con->language->language); if (type) { if (!strcmp(type, "text/html")) - { - if (httpPrintf(HTTP(con), - "Content-Type: text/html; charset=utf-8\r\n") < 0) - return (0); - } - else if (httpPrintf(HTTP(con), "Content-Type: %s\r\n", type) < 0) - return (0); + httpSetField(con->http, HTTP_FIELD_CONTENT_TYPE, "text/html; charset=utf-8"); + else + httpSetField(con->http, HTTP_FIELD_CONTENT_TYPE, type); } - return (1); + return (!httpWriteResponse(con->http, code)); } @@ -2722,36 +2494,35 @@ cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */ ipp_state_t ipp_state; /* IPP state value */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "[Client %d] cupsdWriteClient " - "error=%d, " - "used=%d, " - "state=%s, " - "data_encoding=HTTP_ENCODE_%s, " - "data_remaining=" CUPS_LLFMT ", " - "response=%p(%s), " - "pipe_pid=%d, " - "file=%d", - con->http.fd, con->http.error, con->http.used, - http_states[con->http.state], - con->http.data_encoding == HTTP_ENCODE_CHUNKED ? - "CHUNKED" : "LENGTH", - CUPS_LLCAST con->http.data_remaining, - con->response, - con->response ? ipp_states[con->response->state] : "", - con->pipe_pid, con->file); - - if (con->http.state != HTTP_GET_SEND && - con->http.state != HTTP_POST_SEND) + cupsdLogClient(con, CUPSD_LOG_DEBUG, "con->http=%p", con->http); + cupsdLogClient(con, CUPSD_LOG_DEBUG, + "cupsdWriteClient " + "error=%d, " + "used=%d, " + "state=%s, " + "data_encoding=HTTP_ENCODING_%s, " + "data_remaining=" CUPS_LLFMT ", " + "response=%p(%s), " + "pipe_pid=%d, " + "file=%d", + httpError(con->http), (int)httpGetReady(con->http), + httpStateString(httpGetState(con->http)), + httpIsChunked(con->http) ? "CHUNKED" : "LENGTH", + CUPS_LLCAST httpGetLength2(con->http), + con->response, + con->response ? ippStateString(ippGetState(con->request)) : "", + con->pipe_pid, con->file); + + if (httpGetState(con->http) != HTTP_STATE_GET_SEND && + httpGetState(con->http) != HTTP_STATE_POST_SEND) { /* * If we get called in the wrong state, then something went wrong with the * connection and we need to shut it down... */ - cupsdLogMessage(CUPSD_LOG_DEBUG, - "[Client %d] Closing on unexpected HTTP state %s.", - con->http.fd, http_states[con->http.state]); + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Closing on unexpected HTTP write state %s.", + httpStateString(httpGetState(con->http))); cupsdCloseClient(con); return; } @@ -2764,27 +2535,71 @@ cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */ cupsdAddSelect(con->file, (cupsd_selfunc_t)write_pipe, NULL, con); + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Waiting for CGI data."); + if (!con->file_ready) { /* * Try again later when there is CGI output available... */ - cupsdRemoveSelect(con->http.fd); + cupsdRemoveSelect(httpGetFd(con->http)); return; } con->file_ready = 0; } - if (con->response && con->response->state != IPP_DATA) + bytes = (ssize_t)(sizeof(con->header) - (size_t)con->header_used); + + if (!con->pipe_pid && bytes > (ssize_t)httpGetRemaining(con->http)) { - ipp_state = ippWrite(HTTP(con), con->response); - bytes = ipp_state != IPP_ERROR && - (con->file >= 0 || ipp_state != IPP_DATA); + /* + * Limit GET bytes to original size of file (STR #3265)... + */ + + bytes = (ssize_t)httpGetRemaining(con->http); } - else if ((bytes = read(con->file, con->header + con->header_used, - sizeof(con->header) - con->header_used)) > 0) + + if (con->response && con->response->state != IPP_STATE_DATA) + { + size_t wused = httpGetPending(con->http); /* Previous write buffer use */ + + do + { + /* + * Write a single attribute or the IPP message header... + */ + + ipp_state = ippWrite(con->http, con->response); + + /* + * If the write buffer has been flushed, stop buffering up attributes... + */ + + if (httpGetPending(con->http) <= wused) + break; + } + while (ipp_state != IPP_STATE_DATA && ipp_state != IPP_STATE_ERROR); + + cupsdLogClient(con, CUPSD_LOG_DEBUG, + "Writing IPP response, ipp_state=%s, old " + "wused=" CUPS_LLFMT ", new wused=" CUPS_LLFMT, + ippStateString(ipp_state), + CUPS_LLCAST wused, CUPS_LLCAST httpGetPending(con->http)); + + if (httpGetPending(con->http) > 0) + httpFlushWrite(con->http); + + bytes = ipp_state != IPP_STATE_ERROR && + (con->file >= 0 || ipp_state != IPP_STATE_DATA); + + cupsdLogClient(con, CUPSD_LOG_DEBUG, + "bytes=%d, http_state=%d, data_remaining=" CUPS_LLFMT, + (int)bytes, httpGetState(con->http), + CUPS_LLCAST httpGetLength2(con->http)); + } + else if ((bytes = read(con->file, con->header + con->header_used, (size_t)bytes)) > 0) { con->header_used += bytes; @@ -2809,7 +2624,7 @@ cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */ bufptr[-1] = '\0'; *bufptr++ = '\0'; - cupsdLogMessage(CUPSD_LOG_DEBUG, "Script header: %s", con->header); + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Script header: %s", con->header); if (!con->sent_header) { @@ -2817,46 +2632,43 @@ cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */ * Handle redirection and CGI status codes... */ - if (!_cups_strncasecmp(con->header, "Location:", 9)) + http_field_t field; /* HTTP field */ + char *value = strchr(con->header, ':'); + /* Value of field */ + + if (value) { - if (!cupsdSendHeader(con, HTTP_SEE_OTHER, NULL, CUPSD_AUTH_NONE)) - { - cupsdCloseClient(con); - return; - } + *value++ = '\0'; + while (isspace(*value & 255)) + value ++; + } - con->sent_header = 2; + field = httpFieldValue(con->header); - if (httpPrintf(HTTP(con), "Content-Length: 0\r\n") < 0) - return; + if (field != HTTP_FIELD_UNKNOWN && value) + { + httpSetField(con->http, field, value); + + if (field == HTTP_FIELD_LOCATION) + { + con->pipe_status = HTTP_STATUS_SEE_OTHER; + con->sent_header = 2; + } + else + con->sent_header = 1; } - else if (!_cups_strncasecmp(con->header, "Status:", 7)) + else if (!_cups_strcasecmp(con->header, "Status") && value) { - cupsdSendError(con, (http_status_t)atoi(con->header + 7), - CUPSD_AUTH_NONE); + con->pipe_status = (http_status_t)atoi(value); con->sent_header = 2; } - else + else if (!_cups_strcasecmp(con->header, "Set-Cookie") && value) { - if (!cupsdSendHeader(con, HTTP_OK, NULL, CUPSD_AUTH_NONE)) - { - cupsdCloseClient(con); - return; - } - + httpSetCookie(con->http, value); con->sent_header = 1; - - if (con->http.version == HTTP_1_1) - { - if (httpPrintf(HTTP(con), "Transfer-Encoding: chunked\r\n") < 0) - return; - } - } + } } - if (_cups_strncasecmp(con->header, "Status:", 7)) - httpPrintf(HTTP(con), "%s\r\n", con->header); - /* * Update buffer... */ @@ -2864,7 +2676,7 @@ cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */ con->header_used -= bufptr - con->header; if (con->header_used > 0) - memmove(con->header, bufptr, con->header_used); + memmove(con->header, bufptr, (size_t)con->header_used); bufptr = con->header - 1; @@ -2876,14 +2688,28 @@ cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */ { con->got_fields = 1; - if (cupsdFlushHeader(con) < 0) + if (httpGetVersion(con->http) == HTTP_VERSION_1_1 && + !httpGetField(con->http, HTTP_FIELD_CONTENT_LENGTH)[0]) + httpSetLength(con->http, 0); + + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Sending status %d for CGI.", con->pipe_status); + + if (con->pipe_status == HTTP_STATUS_OK) { - cupsdCloseClient(con); - return; + if (!cupsdSendHeader(con, con->pipe_status, NULL, CUPSD_AUTH_NONE)) + { + cupsdCloseClient(con); + return; + } + } + else + { + if (!cupsdSendError(con, con->pipe_status, CUPSD_AUTH_NONE)) + { + cupsdCloseClient(con); + return; + } } - - if (con->http.version == HTTP_1_1) - con->http.data_encoding = HTTP_ENCODE_CHUNKED; } else field_col = 0; @@ -2893,30 +2719,25 @@ cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */ } if (!con->got_fields) - { - con->http.activity = time(NULL); return; - } } if (con->header_used > 0) { - if (httpWrite2(HTTP(con), con->header, con->header_used) < 0) + if (httpWrite2(con->http, con->header, (size_t)con->header_used) < 0) { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "[Client %d] Closing for error %d (%s)", - con->http.fd, con->http.error, - strerror(con->http.error)); + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Closing for error %d (%s)", + httpError(con->http), strerror(httpError(con->http))); cupsdCloseClient(con); return; } - if (con->http.data_encoding == HTTP_ENCODE_CHUNKED) - httpFlushWrite(HTTP(con)); + if (httpIsChunked(con->http)) + httpFlushWrite(con->http); con->bytes += con->header_used; - if (con->http.state == HTTP_WAITING) + if (httpGetState(con->http) == HTTP_STATE_WAITING) bytes = 0; else bytes = con->header_used; @@ -2926,33 +2747,36 @@ cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */ } if (bytes <= 0 || - (con->http.state != HTTP_GET_SEND && con->http.state != HTTP_POST_SEND)) + (httpGetState(con->http) != HTTP_STATE_GET_SEND && + httpGetState(con->http) != HTTP_STATE_POST_SEND)) { if (!con->sent_header && con->pipe_pid) - cupsdSendError(con, HTTP_SERVER_ERROR, CUPSD_AUTH_NONE); + cupsdSendError(con, HTTP_STATUS_SERVER_ERROR, CUPSD_AUTH_NONE); else { - cupsdLogRequest(con, HTTP_OK); - - httpFlushWrite(HTTP(con)); + cupsdLogRequest(con, HTTP_STATUS_OK); - if (con->http.data_encoding == HTTP_ENCODE_CHUNKED && con->sent_header == 1) + if (httpIsChunked(con->http) && (!con->pipe_pid || con->sent_header > 0)) { - if (httpWrite2(HTTP(con), "", 0) < 0) + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Sending 0-length chunk."); + + if (httpWrite2(con->http, "", 0) < 0) { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "[Client %d] Closing for error %d (%s)", - con->http.fd, con->http.error, - strerror(con->http.error)); + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Closing for error %d (%s)", + httpError(con->http), strerror(httpError(con->http))); cupsdCloseClient(con); return; } } + + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Flushing write buffer."); + httpFlushWrite(con->http); + cupsdLogClient(con, CUPSD_LOG_DEBUG, "New state is %s", httpStateString(httpGetState(con->http))); } - con->http.state = HTTP_WAITING; + cupsdAddSelect(httpGetFd(con->http), (cupsd_selfunc_t)cupsdReadClient, NULL, con); - cupsdAddSelect(con->http.fd, (cupsd_selfunc_t)cupsdReadClient, NULL, con); + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Waiting for request."); if (con->file >= 0) { @@ -2988,11 +2812,10 @@ cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */ cupsdClearString(&con->options); cupsdClearString(&con->query_string); - if (!con->http.keep_alive) + if (!httpGetKeepAlive(con->http)) { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "[Client %d] Closing because Keep-Alive disabled.", - con->http.fd); + cupsdLogClient(con, CUPSD_LOG_DEBUG, + "Closing because Keep-Alive is disabled."); cupsdCloseClient(con); return; } @@ -3002,8 +2825,6 @@ cupsdWriteClient(cupsd_client_t *con) /* I - Client connection */ cupsdSetBusyState(); } } - - con->http.activity = time(NULL); } @@ -3016,23 +2837,19 @@ check_if_modified( cupsd_client_t *con, /* I - Client connection */ struct stat *filestats) /* I - File information */ { - char *ptr; /* Pointer into field */ + const char *ptr; /* Pointer into field */ time_t date; /* Time/date value */ off_t size; /* Size/length value */ size = 0; date = 0; - ptr = con->http.fields[HTTP_FIELD_IF_MODIFIED_SINCE]; + ptr = httpGetField(con->http, HTTP_FIELD_IF_MODIFIED_SINCE); if (*ptr == '\0') return (1); - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "[Client %d] check_if_modified " - "filestats=%p(" CUPS_LLFMT ", %d)) If-Modified-Since=\"%s\"", - con->http.fd, filestats, CUPS_LLCAST filestats->st_size, - (int)filestats->st_mtime, ptr); + cupsdLogClient(con, CUPSD_LOG_DEBUG2, "check_if_modified: filestats=%p(" CUPS_LLFMT ", %d)) If-Modified-Since=\"%s\"", filestats, CUPS_LLCAST filestats->st_size, (int)filestats->st_mtime, ptr); while (*ptr != '\0') { @@ -3083,35 +2900,26 @@ compare_clients(cupsd_client_t *a, /* I - First client */ } +#ifdef HAVE_SSL /* - * 'data_ready()' - Check whether data is available from a client. + * 'cupsd_start_tls()' - Start encryption on a connection. */ -static int /* O - 1 if data is ready, 0 otherwise */ -data_ready(cupsd_client_t *con) /* I - Client */ +static int /* O - 0 on success, -1 on error */ +cupsd_start_tls(cupsd_client_t *con, /* I - Client connection */ + http_encryption_t e) /* I - Encryption mode */ { - if (con->http.used > 0) - return (1); -#ifdef HAVE_SSL - else if (con->http.tls) + if (httpEncryption(con->http, e)) { -# ifdef HAVE_LIBSSL - if (SSL_pending((SSL *)(con->http.tls))) - return (1); -# elif defined(HAVE_GNUTLS) - if (gnutls_record_check_pending(con->http.tls)) - return (1); -# elif defined(HAVE_CDSASSL) - size_t bytes; /* Bytes that are available */ - - if (!SSLGetBufferedReadSize(con->http.tls, &bytes) && bytes > 0) - return (1); -# endif /* HAVE_LIBSSL */ + cupsdLogClient(con, CUPSD_LOG_ERROR, "Unable to encrypt connection: %s", + cupsLastErrorString()); + return (-1); } -#endif /* HAVE_SSL */ + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Connection now encrypted."); return (0); } +#endif /* HAVE_SSL */ /* @@ -3122,12 +2930,14 @@ static char * /* O - Real filename */ get_file(cupsd_client_t *con, /* I - Client connection */ struct stat *filestats, /* O - File information */ char *filename, /* IO - Filename buffer */ - int len) /* I - Buffer length */ + size_t len) /* I - Buffer length */ { int status; /* Status of filesystem calls */ char *ptr; /* Pointer info filename */ - int plen; /* Remaining length after pointer */ - char language[7]; /* Language subdirectory, if any */ + size_t plen; /* Remaining length after pointer */ + char language[7], /* Language subdirectory, if any */ + dest[1024]; /* Destination name */ + int perm_check = 1; /* Do permissions check? */ /* @@ -3137,17 +2947,59 @@ get_file(cupsd_client_t *con, /* I - Client connection */ language[0] = '\0'; if (!strncmp(con->uri, "/ppd/", 5) && !strchr(con->uri + 5, '/')) + { + strlcpy(dest, con->uri + 5, sizeof(dest)); + ptr = dest + strlen(dest) - 4; + + if (ptr <= dest || strcmp(ptr, ".ppd")) + { + cupsdLogClient(con, CUPSD_LOG_INFO, "Disallowed path \"%s\".", con->uri); + return (NULL); + } + + *ptr = '\0'; + if (!cupsdFindPrinter(dest)) + { + cupsdLogClient(con, CUPSD_LOG_INFO, "No printer \"%s\" found.", dest); + return (NULL); + } + snprintf(filename, len, "%s%s", ServerRoot, con->uri); + + perm_check = 0; + } else if (!strncmp(con->uri, "/icons/", 7) && !strchr(con->uri + 7, '/')) { - snprintf(filename, len, "%s/%s", CacheDir, con->uri + 7); + strlcpy(dest, con->uri + 7, sizeof(dest)); + ptr = dest + strlen(dest) - 4; + + if (ptr <= dest || strcmp(ptr, ".png")) + { + cupsdLogClient(con, CUPSD_LOG_INFO, "Disallowed path \"%s\".", con->uri); + return (NULL); + } + + *ptr = '\0'; + if (!cupsdFindDest(dest)) + { + cupsdLogClient(con, CUPSD_LOG_INFO, "No printer \"%s\" found.", dest); + return (NULL); + } + + snprintf(filename, len, "%s/%s.png", CacheDir, dest); if (access(filename, F_OK) < 0) snprintf(filename, len, "%s/images/generic.png", DocumentRoot); + + perm_check = 0; } else if (!strncmp(con->uri, "/rss/", 5) && !strchr(con->uri + 5, '/')) snprintf(filename, len, "%s/rss/%s", CacheDir, con->uri + 5); - else if (!strncmp(con->uri, "/admin/conf/", 12)) - snprintf(filename, len, "%s%s", ServerRoot, con->uri + 11); + else if (!strcmp(con->uri, "/admin/conf/cupsd.conf")) + { + strlcpy(filename, ConfigurationFile, len); + + perm_check = 0; + } else if (!strncmp(con->uri, "/admin/log/", 11)) { if (!strncmp(con->uri + 11, "access_log", 10) && AccessLog[0] == '/') @@ -3158,6 +3010,8 @@ get_file(cupsd_client_t *con, /* I - Client connection */ strlcpy(filename, PageLog, len); else return (NULL); + + perm_check = 0; } else if (con->language) { @@ -3175,7 +3029,7 @@ get_file(cupsd_client_t *con, /* I - Client connection */ * then fallback to the default one... */ - if ((status = stat(filename, filestats)) != 0 && language[0] && + if ((status = lstat(filename, filestats)) != 0 && language[0] && strncmp(con->uri, "/icons/", 7) && strncmp(con->uri, "/ppd/", 5) && strncmp(con->uri, "/rss/", 5) && @@ -3192,7 +3046,7 @@ get_file(cupsd_client_t *con, /* I - Client connection */ if ((ptr = strchr(filename, '?')) != NULL) *ptr = '\0'; - if ((status = stat(filename, filestats)) != 0) + if ((status = lstat(filename, filestats)) != 0) { /* * Drop the language prefix and try the root directory... @@ -3204,12 +3058,33 @@ get_file(cupsd_client_t *con, /* I - Client connection */ if ((ptr = strchr(filename, '?')) != NULL) *ptr = '\0'; - status = stat(filename, filestats); + status = lstat(filename, filestats); } } /* - * If we're found a directory, get the index.html file instead... + * If we've found a symlink, 404 the sucker to avoid disclosing information. + */ + + if (!status && S_ISLNK(filestats->st_mode)) + { + cupsdLogClient(con, CUPSD_LOG_INFO, "Symlinks such as \"%s\" are not allowed.", filename); + return (NULL); + } + + /* + * Similarly, if the file/directory does not have world read permissions, do + * not allow access... + */ + + if (!status && perm_check && !(filestats->st_mode & S_IROTH)) + { + cupsdLogClient(con, CUPSD_LOG_INFO, "Files/directories such as \"%s\" must be world-readable.", filename); + return (NULL); + } + + /* + * If we've found a directory, get the index.html file instead... */ if (!status && S_ISDIR(filestats->st_mode)) @@ -3249,16 +3124,16 @@ get_file(cupsd_client_t *con, /* I - Client connection */ *ptr = '\0'; ptr = filename + strlen(filename); - plen = len - (ptr - filename); + plen = len - (size_t)(ptr - filename); strlcpy(ptr, "index.html", plen); - status = stat(filename, filestats); + status = lstat(filename, filestats); #ifdef HAVE_JAVA if (status) { strlcpy(ptr, "index.class", plen); - status = stat(filename, filestats); + status = lstat(filename, filestats); } #endif /* HAVE_JAVA */ @@ -3266,7 +3141,7 @@ get_file(cupsd_client_t *con, /* I - Client connection */ if (status) { strlcpy(ptr, "index.pl", plen); - status = stat(filename, filestats); + status = lstat(filename, filestats); } #endif /* HAVE_PERL */ @@ -3274,7 +3149,7 @@ get_file(cupsd_client_t *con, /* I - Client connection */ if (status) { strlcpy(ptr, "index.php", plen); - status = stat(filename, filestats); + status = lstat(filename, filestats); } #endif /* HAVE_PHP */ @@ -3282,24 +3157,42 @@ get_file(cupsd_client_t *con, /* I - Client connection */ if (status) { strlcpy(ptr, "index.pyc", plen); - status = stat(filename, filestats); + status = lstat(filename, filestats); } if (status) { strlcpy(ptr, "index.py", plen); - status = stat(filename, filestats); + status = lstat(filename, filestats); } #endif /* HAVE_PYTHON */ } while (status && language[0]); + + /* + * If we've found a symlink, 404 the sucker to avoid disclosing information. + */ + + if (!status && S_ISLNK(filestats->st_mode)) + { + cupsdLogClient(con, CUPSD_LOG_INFO, "Symlinks such as \"%s\" are not allowed.", filename); + return (NULL); + } + + /* + * Similarly, if the file/directory does not have world read permissions, do + * not allow access... + */ + + if (!status && perm_check && !(filestats->st_mode & S_IROTH)) + { + cupsdLogClient(con, CUPSD_LOG_INFO, "Files/directories such as \"%s\" must be world-readable.", filename); + return (NULL); + } } - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "[Client %d] get_file filestats=%p, filename=%p, len=%d, " - "returning \"%s\".", con->http.fd, filestats, filename, len, - status ? "(null)" : filename); + cupsdLogClient(con, CUPSD_LOG_DEBUG2, "get_file: filestats=%p, filename=%p, len=" CUPS_LLFMT ", returning \"%s\".", filestats, filename, CUPS_LLCAST len, status ? "(null)" : filename); if (status) return (NULL); @@ -3328,9 +3221,9 @@ install_cupsd_conf(cupsd_client_t *con) /* I - Connection */ if ((in = cupsFileOpen(con->filename, "rb")) == NULL) { - cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to open request file \"%s\": %s", + cupsdLogClient(con, CUPSD_LOG_ERROR, "Unable to open request file \"%s\": %s", con->filename, strerror(errno)); - return (HTTP_SERVER_ERROR); + goto server_error; } /* @@ -3340,10 +3233,10 @@ install_cupsd_conf(cupsd_client_t *con) /* I - Connection */ if ((out = cupsdCreateConfFile(ConfigurationFile, ConfigFilePerm)) == NULL) { cupsFileClose(in); - return (HTTP_SERVER_ERROR); + goto server_error; } - cupsdLogMessage(CUPSD_LOG_INFO, "Installing config file \"%s\"...", + cupsdLogClient(con, CUPSD_LOG_INFO, "Installing config file \"%s\"...", ConfigurationFile); /* @@ -3351,9 +3244,9 @@ install_cupsd_conf(cupsd_client_t *con) /* I - Connection */ */ while ((bytes = cupsFileRead(in, buffer, sizeof(buffer))) > 0) - if (cupsFileWrite(out, buffer, bytes) < bytes) + if (cupsFileWrite(out, buffer, (size_t)bytes) < bytes) { - cupsdLogMessage(CUPSD_LOG_ERROR, + cupsdLogClient(con, CUPSD_LOG_ERROR, "Unable to copy to config file \"%s\": %s", ConfigurationFile, strerror(errno)); @@ -3361,9 +3254,9 @@ install_cupsd_conf(cupsd_client_t *con) /* I - Connection */ cupsFileClose(out); snprintf(filename, sizeof(filename), "%s.N", ConfigurationFile); - cupsdRemoveFile(filename); + cupsdUnlinkOrRemoveFile(filename); - return (HTTP_SERVER_ERROR); + goto server_error; } /* @@ -3373,13 +3266,13 @@ install_cupsd_conf(cupsd_client_t *con) /* I - Connection */ cupsFileClose(in); if (cupsdCloseCreatedConfFile(out, ConfigurationFile)) - return (HTTP_SERVER_ERROR); + goto server_error; /* * Remove the request file... */ - cupsdRemoveFile(con->filename); + cupsdUnlinkOrRemoveFile(con->filename); cupsdClearString(&con->filename); /* @@ -3393,7 +3286,18 @@ install_cupsd_conf(cupsd_client_t *con) /* I - Connection */ * Return that the file was created successfully... */ - return (HTTP_CREATED); + return (HTTP_STATUS_CREATED); + + /* + * Common exit for errors... + */ + + server_error: + + cupsdUnlinkOrRemoveFile(con->filename); + cupsdClearString(&con->filename); + + return (HTTP_STATUS_SERVER_ERROR); } @@ -3426,11 +3330,7 @@ is_cgi(cupsd_client_t *con, /* I - Client connection */ if (!type || _cups_strcasecmp(type->super, "application")) { - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "[Client %d] is_cgi filename=\"%s\", filestats=%p, " - "type=%s/%s, returning 0", con->http.fd, filename, - filestats, type ? type->super : "unknown", - type ? type->type : "unknown"); + cupsdLogClient(con, CUPSD_LOG_DEBUG2, "is_cgi: filename=\"%s\", filestats=%p, type=%s/%s, returning 0.", filename, filestats, type ? type->super : "unknown", type ? type->type : "unknown"); return (0); } @@ -3446,10 +3346,7 @@ is_cgi(cupsd_client_t *con, /* I - Client connection */ if (options) cupsdSetStringf(&con->options, " %s", options); - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "[Client %d] is_cgi filename=\"%s\", filestats=%p, " - "type=%s/%s, returning 1", con->http.fd, filename, - filestats, type->super, type->type); + cupsdLogClient(con, CUPSD_LOG_DEBUG2, "is_cgi: filename=\"%s\", filestats=%p, type=%s/%s, returning 1.", filename, filestats, type->super, type->type); return (1); } #ifdef HAVE_JAVA @@ -3466,10 +3363,7 @@ is_cgi(cupsd_client_t *con, /* I - Client connection */ else cupsdSetStringf(&con->options, " %s", filename); - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "[Client %d] is_cgi filename=\"%s\", filestats=%p, " - "type=%s/%s, returning 1", con->http.fd, filename, - filestats, type->super, type->type); + cupsdLogClient(con, CUPSD_LOG_DEBUG2, "is_cgi: filename=\"%s\", filestats=%p, type=%s/%s, returning 1.", filename, filestats, type->super, type->type); return (1); } #endif /* HAVE_JAVA */ @@ -3487,10 +3381,7 @@ is_cgi(cupsd_client_t *con, /* I - Client connection */ else cupsdSetStringf(&con->options, " %s", filename); - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "[Client %d] is_cgi filename=\"%s\", filestats=%p, " - "type=%s/%s, returning 1", con->http.fd, filename, - filestats, type->super, type->type); + cupsdLogClient(con, CUPSD_LOG_DEBUG2, "is_cgi: filename=\"%s\", filestats=%p, type=%s/%s, returning 1.", filename, filestats, type->super, type->type); return (1); } #endif /* HAVE_PERL */ @@ -3508,10 +3399,7 @@ is_cgi(cupsd_client_t *con, /* I - Client connection */ else cupsdSetStringf(&con->options, " %s", filename); - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "[Client %d] is_cgi filename=\"%s\", filestats=%p, " - "type=%s/%s, returning 1", con->http.fd, filename, - filestats, type->super, type->type); + cupsdLogClient(con, CUPSD_LOG_DEBUG2, "is_cgi: filename=\"%s\", filestats=%p, type=%s/%s, returning 1.", filename, filestats, type->super, type->type); return (1); } #endif /* HAVE_PHP */ @@ -3529,18 +3417,12 @@ is_cgi(cupsd_client_t *con, /* I - Client connection */ else cupsdSetStringf(&con->options, " %s", filename); - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "[Client %d] is_cgi filename=\"%s\", filestats=%p, " - "type=%s/%s, returning 1", con->http.fd, filename, - filestats, type->super, type->type); + cupsdLogClient(con, CUPSD_LOG_DEBUG2, "is_cgi: filename=\"%s\", filestats=%p, type=%s/%s, returning 1.", filename, filestats, type->super, type->type); return (1); } #endif /* HAVE_PYTHON */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "[Client %d] is_cgi filename=\"%s\", filestats=%p, " - "type=%s/%s, returning 0", con->http.fd, filename, - filestats, type->super, type->type); + cupsdLogClient(con, CUPSD_LOG_DEBUG2, "is_cgi: filename=\"%s\", filestats=%p, type=%s/%s, returning 0.", filename, filestats, type->super, type->type); return (0); } @@ -3560,6 +3442,14 @@ is_path_absolute(const char *path) /* I - Input path */ return (0); /* + * Check for "<" or quotes in the path and reject since this is probably + * someone trying to inject HTML... + */ + + if (strchr(path, '<') != NULL || strchr(path, '\"') != NULL || strchr(path, '\'') != NULL) + return (0); + + /* * Check for "/.." in the path... */ @@ -3639,21 +3529,12 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */ * be consistent with Apache... */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "[Client %d] pipe_command infile=%d, outfile=%p, " - "command=\"%s\", options=\"%s\", root=%d", - con->http.fd, infile, outfile, command, - options ? options : "(null)", root); + cupsdLogClient(con, CUPSD_LOG_DEBUG2, "pipe_command: infile=%d, outfile=%p, command=\"%s\", options=\"%s\", root=%d", infile, outfile, command, options ? options : "(null)", root); argv[0] = command; if (options) - { - commptr = options; - if (*commptr == ' ') - commptr ++; - strlcpy(argbuf, commptr, sizeof(argbuf)); - } + strlcpy(argbuf, options, sizeof(argbuf)); else argbuf[0] = '\0'; @@ -3680,7 +3561,7 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */ commptr ++; } - if (*commptr == '?' && con->operation == HTTP_GET && !con->query_string) + if (*commptr == '?' && con->operation == HTTP_STATE_GET && !con->query_string) { commptr ++; cupsdSetStringf(&(con->query_string), "QUERY_STRING=%s", commptr); @@ -3723,9 +3604,9 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */ */ if (commptr[1] >= '0' && commptr[1] <= '9') - *commptr = (commptr[1] - '0') << 4; + *commptr = (char)((commptr[1] - '0') << 4); else - *commptr = (tolower(commptr[1]) - 'a' + 10) << 4; + *commptr = (char)((tolower(commptr[1]) - 'a' + 10) << 4); if (commptr[2] >= '0' && commptr[2] <= '9') *commptr |= commptr[2] - '0'; @@ -3753,7 +3634,7 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */ if (con->username[0]) { snprintf(auth_type, sizeof(auth_type), "AUTH_TYPE=%s", - httpGetField(HTTP(con), HTTP_FIELD_AUTHORIZATION)); + httpGetField(con->http, HTTP_FIELD_AUTHORIZATION)); if ((uriptr = strchr(auth_type + 10, ' ')) != NULL) *uriptr = '\0'; @@ -3773,7 +3654,7 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */ * the POSIX locale... */ - strcpy(lang, "LANG=C"); + strlcpy(lang, "LANG=C", sizeof(lang)); break; case 2 : @@ -3801,14 +3682,14 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */ else if (con->language) snprintf(lang, sizeof(lang), "LANG=%s.UTF8", con->language->language); else - strcpy(lang, "LANG=C"); + strlcpy(lang, "LANG=C", sizeof(lang)); - strcpy(remote_addr, "REMOTE_ADDR="); - httpAddrString(con->http.hostaddr, remote_addr + 12, + strlcpy(remote_addr, "REMOTE_ADDR=", sizeof(remote_addr)); + httpAddrString(httpGetAddress(con->http), remote_addr + 12, sizeof(remote_addr) - 12); snprintf(remote_host, sizeof(remote_host), "REMOTE_HOST=%s", - con->http.hostname); + httpGetHostname(con->http, NULL, 0)); snprintf(script_name, sizeof(script_name), "SCRIPT_NAME=%s", con->uri); if ((uriptr = strchr(script_name, '?')) != NULL) @@ -3817,14 +3698,14 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */ snprintf(script_filename, sizeof(script_filename), "SCRIPT_FILENAME=%s%s", DocumentRoot, script_name + 12); - sprintf(server_port, "SERVER_PORT=%d", con->serverport); + snprintf(server_port, sizeof(server_port), "SERVER_PORT=%d", con->serverport); - if (con->http.fields[HTTP_FIELD_HOST][0]) + if (httpGetField(con->http, HTTP_FIELD_HOST)[0]) { char *nameptr; /* Pointer to ":port" */ snprintf(server_name, sizeof(server_name), "SERVER_NAME=%s", - con->http.fields[HTTP_FIELD_HOST]); + httpGetField(con->http, HTTP_FIELD_HOST)); if ((nameptr = strrchr(server_name, ':')) != NULL && !strchr(nameptr, ']')) *nameptr = '\0'; /* Strip trailing ":port" */ } @@ -3857,35 +3738,35 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */ envp[envc ++] = remote_user; } - if (con->http.version == HTTP_1_1) + if (httpGetVersion(con->http) == HTTP_VERSION_1_1) envp[envc ++] = "SERVER_PROTOCOL=HTTP/1.1"; - else if (con->http.version == HTTP_1_0) + else if (httpGetVersion(con->http) == HTTP_VERSION_1_0) envp[envc ++] = "SERVER_PROTOCOL=HTTP/1.0"; else envp[envc ++] = "SERVER_PROTOCOL=HTTP/0.9"; - if (con->http.cookie) + if (httpGetCookie(con->http)) { snprintf(http_cookie, sizeof(http_cookie), "HTTP_COOKIE=%s", - con->http.cookie); + httpGetCookie(con->http)); envp[envc ++] = http_cookie; } - if (con->http.fields[HTTP_FIELD_USER_AGENT][0]) + if (httpGetField(con->http, HTTP_FIELD_USER_AGENT)[0]) { snprintf(http_user_agent, sizeof(http_user_agent), "HTTP_USER_AGENT=%s", - con->http.fields[HTTP_FIELD_USER_AGENT]); + httpGetField(con->http, HTTP_FIELD_USER_AGENT)); envp[envc ++] = http_user_agent; } - if (con->http.fields[HTTP_FIELD_REFERER][0]) + if (httpGetField(con->http, HTTP_FIELD_REFERER)[0]) { snprintf(http_referer, sizeof(http_referer), "HTTP_REFERER=%s", - con->http.fields[HTTP_FIELD_REFERER]); + httpGetField(con->http, HTTP_FIELD_REFERER)); envp[envc ++] = http_referer; } - if (con->operation == HTTP_GET) + if (con->operation == HTTP_STATE_GET) { envp[envc ++] = "REQUEST_METHOD=GET"; @@ -3905,7 +3786,7 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */ sprintf(content_length, "CONTENT_LENGTH=" CUPS_LLFMT, CUPS_LLCAST con->bytes); snprintf(content_type, sizeof(content_type), "CONTENT_TYPE=%s", - con->http.fields[HTTP_FIELD_CONTENT_TYPE]); + httpGetField(con->http, HTTP_FIELD_CONTENT_TYPE)); envp[envc ++] = "REQUEST_METHOD=POST"; envp[envc ++] = content_length; @@ -3916,7 +3797,7 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */ * Tell the CGI if we are using encryption... */ - if (con->http.tls) + if (httpIsEncrypted(con->http)) envp[envc ++] = "HTTPS=ON"; /* @@ -3991,31 +3872,42 @@ valid_host(cupsd_client_t *con) /* I - Client connection */ { cupsd_alias_t *a; /* Current alias */ cupsd_netif_t *netif; /* Current network interface */ - const char *host, /* Host field */ - *end; /* End character */ + const char *end; /* End character */ + char *ptr; /* Pointer into host value */ + + /* + * Copy the Host: header for later use... + */ + + strlcpy(con->clientname, httpGetField(con->http, HTTP_FIELD_HOST), + sizeof(con->clientname)); + if ((ptr = strrchr(con->clientname, ':')) != NULL && !strchr(ptr, ']')) + { + *ptr++ = '\0'; + con->clientport = atoi(ptr); + } + else + con->clientport = con->serverport; - host = con->http.fields[HTTP_FIELD_HOST]; + /* + * Then validate... + */ - if (httpAddrLocalhost(con->http.hostaddr)) + if (httpAddrLocalhost(httpGetAddress(con->http))) { /* * Only allow "localhost" or the equivalent IPv4 or IPv6 numerical * addresses when accessing CUPS via the loopback interface... */ - return (!_cups_strcasecmp(host, "localhost") || - !_cups_strncasecmp(host, "localhost:", 10) || - !_cups_strcasecmp(host, "localhost.") || - !_cups_strncasecmp(host, "localhost.:", 11) || + return (!_cups_strcasecmp(con->clientname, "localhost") || + !_cups_strcasecmp(con->clientname, "localhost.") || #ifdef __linux - !_cups_strcasecmp(host, "localhost.localdomain") || - !_cups_strncasecmp(host, "localhost.localdomain:", 22) || + !_cups_strcasecmp(con->clientname, "localhost.localdomain") || #endif /* __linux */ - !strcmp(host, "127.0.0.1") || - !strncmp(host, "127.0.0.1:", 10) || - !strcmp(host, "[::1]") || - !strncmp(host, "[::1]:", 6)); + !strcmp(con->clientname, "127.0.0.1") || + !strcmp(con->clientname, "[::1]")); } #if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) @@ -4023,19 +3915,18 @@ valid_host(cupsd_client_t *con) /* I - Client connection */ * Check if the hostname is something.local (Bonjour); if so, allow it. */ - if ((end = strrchr(host, '.')) != NULL && end > host && - (!end[1] || end[1] == ':')) + if ((end = strrchr(con->clientname, '.')) != NULL && end > con->clientname && + !end[1]) { /* * "." on end, work back to second-to-last "."... */ - for (end --; end > host && *end != '.'; end --); + + for (end --; end > con->clientname && *end != '.'; end --); } if (end && (!_cups_strcasecmp(end, ".local") || - !_cups_strncasecmp(end, ".local:", 7) || - !_cups_strcasecmp(end, ".local.") || - !_cups_strncasecmp(end, ".local.:", 8))) + !_cups_strcasecmp(end, ".local."))) return (1); #endif /* HAVE_DNSSD || HAVE_AVAHI */ @@ -4043,22 +3934,16 @@ valid_host(cupsd_client_t *con) /* I - Client connection */ * Check if the hostname is an IP address... */ - if (isdigit(*host & 255) || *host == '[') + if (isdigit(con->clientname[0] & 255) || con->clientname[0] == '[') { /* * Possible IPv4/IPv6 address... */ - char temp[1024], /* Temporary string */ - *ptr; /* Pointer into temporary string */ http_addrlist_t *addrlist; /* List of addresses */ - strlcpy(temp, host, sizeof(temp)); - if ((ptr = strrchr(temp, ':')) != NULL && !strchr(ptr, ']')) - *ptr = '\0'; /* Strip :port from host value */ - - if ((addrlist = httpAddrGetList(temp, AF_UNSPEC, NULL)) != NULL) + if ((addrlist = httpAddrGetList(con->clientname, AF_UNSPEC, NULL)) != NULL) { /* * Good IPv4/IPv6 address... @@ -4084,16 +3969,15 @@ valid_host(cupsd_client_t *con) /* I - Client connection */ if (!strcmp(a->name, "*")) return (1); - if (!_cups_strncasecmp(host, a->name, a->namelen)) + if (!_cups_strncasecmp(con->clientname, a->name, a->namelen)) { /* - * Prefix matches; check the character at the end - it must be ":", ".", - * ".:", or nul... + * Prefix matches; check the character at the end - it must be "." or nul. */ - end = host + a->namelen; + end = con->clientname + a->namelen; - if (!*end || *end == ':' || (*end == '.' && (!end[1] || end[1] == ':'))) + if (!*end || (*end == '.' && !end[1])) return (1); } } @@ -4110,16 +3994,15 @@ valid_host(cupsd_client_t *con) /* I - Client connection */ if (!strcmp(a->name, "*")) return (1); - if (!_cups_strncasecmp(host, a->name, a->namelen)) + if (!_cups_strncasecmp(con->clientname, a->name, a->namelen)) { /* - * Prefix matches; check the character at the end - it must be ":", ".", - * ".:", or nul... + * Prefix matches; check the character at the end - it must be "." or nul. */ - end = host + a->namelen; + end = con->clientname + a->namelen; - if (!*end || *end == ':' || (*end == '.' && (!end[1] || end[1] == ':'))) + if (!*end || (*end == '.' && !end[1])) return (1); } } @@ -4133,16 +4016,15 @@ valid_host(cupsd_client_t *con) /* I - Client connection */ netif; netif = (cupsd_netif_t *)cupsArrayNext(NetIFList)) { - if (!_cups_strncasecmp(host, netif->hostname, netif->hostlen)) + if (!_cups_strncasecmp(con->clientname, netif->hostname, netif->hostlen)) { /* - * Prefix matches; check the character at the end - it must be ":", ".", - * ".:", or nul... + * Prefix matches; check the character at the end - it must be "." or nul. */ - end = host + netif->hostlen; + end = con->clientname + netif->hostlen; - if (!*end || *end == ':' || (*end == '.' && (!end[1] || end[1] == ':'))) + if (!*end || (*end == '.' && !end[1])) return (1); } } @@ -4164,43 +4046,29 @@ write_file(cupsd_client_t *con, /* I - Client connection */ { con->file = open(filename, O_RDONLY); - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "[Client %d] write_file code=%d, filename=\"%s\" (%d), " - "type=\"%s\", filestats=%p", con->http.fd, - code, filename, con->file, type ? type : "(null)", filestats); + cupsdLogClient(con, CUPSD_LOG_DEBUG2, "write_file: code=%d, filename=\"%s\" (%d), type=\"%s\", filestats=%p.", code, filename, con->file, type ? type : "(null)", filestats); if (con->file < 0) return (0); fcntl(con->file, F_SETFD, fcntl(con->file, F_GETFD) | FD_CLOEXEC); - con->pipe_pid = 0; + con->pipe_pid = 0; + con->sent_header = 1; - if (!cupsdSendHeader(con, code, type, CUPSD_AUTH_NONE)) - return (0); + httpClearFields(con->http); - if (httpPrintf(HTTP(con), "Last-Modified: %s\r\n", - httpGetDateString(filestats->st_mtime)) < 0) - return (0); - if (httpPrintf(HTTP(con), "Content-Length: " CUPS_LLFMT "\r\n", - CUPS_LLCAST filestats->st_size) < 0) - return (0); - if (httpPrintf(HTTP(con), "\r\n") < 0) - return (0); + httpSetLength(con->http, (size_t)filestats->st_size); - if (cupsdFlushHeader(con) < 0) - return (0); + httpSetField(con->http, HTTP_FIELD_LAST_MODIFIED, + httpGetDateString(filestats->st_mtime)); - con->http.data_encoding = HTTP_ENCODE_LENGTH; - con->http.data_remaining = filestats->st_size; + if (!cupsdSendHeader(con, code, type, CUPSD_AUTH_NONE)) + return (0); - if (con->http.data_remaining <= INT_MAX) - con->http._data_remaining = con->http.data_remaining; - else - con->http._data_remaining = INT_MAX; + cupsdAddSelect(httpGetFd(con->http), NULL, (cupsd_selfunc_t)cupsdWriteClient, con); - cupsdAddSelect(con->http.fd, (cupsd_selfunc_t)cupsdReadClient, - (cupsd_selfunc_t)cupsdWriteClient, con); + cupsdLogClient(con, CUPSD_LOG_DEBUG, "Sending file."); return (1); } @@ -4213,17 +4081,17 @@ write_file(cupsd_client_t *con, /* I - Client connection */ static void write_pipe(cupsd_client_t *con) /* I - Client connection */ { - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "[Client %d] write_pipe CGI output on fd %d", - con->http.fd, con->file); + cupsdLogClient(con, CUPSD_LOG_DEBUG2, "write_pipe: CGI output on fd %d.", con->file); con->file_ready = 1; cupsdRemoveSelect(con->file); - cupsdAddSelect(con->http.fd, NULL, (cupsd_selfunc_t)cupsdWriteClient, con); + cupsdAddSelect(httpGetFd(con->http), NULL, (cupsd_selfunc_t)cupsdWriteClient, con); + + cupsdLogClient(con, CUPSD_LOG_DEBUG, "CGI data ready to be sent."); } /* - * End of "$Id: client.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: client.c 12978 2015-11-17 19:29:52Z msweet $". */ diff --git a/scheduler/client.h b/scheduler/client.h index 106e43e..5096c4f 100644 --- a/scheduler/client.h +++ b/scheduler/client.h @@ -1,16 +1,16 @@ /* - * "$Id: client.h 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: client.h 11717 2014-03-21 16:42:53Z msweet $" * - * Client definitions for the CUPS scheduler. + * Client definitions for the CUPS scheduler. * - * Copyright 2007-2011 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. + * Copyright 2007-2014 by Apple Inc. + * Copyright 1997-2007 by Easy Software Products, all rights reserved. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ #ifdef HAVE_AUTHORIZATION_H @@ -24,7 +24,8 @@ struct cupsd_client_s { - http_t http; /* HTTP client connection */ + int number; /* Connection number */ + http_t *http; /* HTTP client connection */ ipp_t *request, /* IPP request information */ *response; /* IPP response information */ cupsd_location_t *best; /* Best match for AAA */ @@ -45,6 +46,7 @@ struct cupsd_client_s int file; /* Input/output file */ int file_ready; /* Input ready on file/pipe? */ int pipe_pid; /* Pipe process ID (or 0 if not a pipe) */ + http_status_t pipe_status; /* HTTP status from pipe process */ int sent_header, /* Non-zero if sent HTTP header */ got_fields, /* Non-zero if all fields seen */ header_used; /* Number of header bytes used */ @@ -53,7 +55,9 @@ struct cupsd_client_s #ifdef HAVE_SSL int auto_ssl; /* Automatic test for SSL/TLS */ #endif /* HAVE_SSL */ - http_addr_t clientaddr; /* Client address */ + http_addr_t clientaddr; /* Client's server address */ + char clientname[256];/* Client's server name for connection */ + int clientport; /* Client's server port for connection */ char servername[256];/* Server name for connection */ int serverport; /* Server port for connection */ #ifdef HAVE_GSSAPI @@ -65,7 +69,7 @@ struct cupsd_client_s #endif /* HAVE_AUTHORIZATION_H */ }; -#define HTTP(con) &((con)->http) +#define HTTP(con) ((con)->http) /* @@ -77,6 +81,9 @@ typedef struct int fd; /* File descriptor for this server */ http_addr_t address; /* Bind address of socket */ http_encryption_t encryption; /* To encrypt or not to encrypt... */ +#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) + int on_demand; /* Is this a socket from launchd/systemd? */ +#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ } cupsd_listener_t; @@ -84,7 +91,9 @@ typedef struct * Globals... */ -VAR int ListenBackLog VALUE(SOMAXCONN), +VAR int LastClientNumber VALUE(0), + /* Last client connection number */ + ListenBackLog VALUE(SOMAXCONN), /* Max backlog of pending connections */ LocalPort VALUE(631), /* Local port to use */ @@ -116,7 +125,6 @@ extern void cupsdAcceptClient(cupsd_listener_t *lis); extern void cupsdCloseAllClients(void); extern int cupsdCloseClient(cupsd_client_t *con); extern void cupsdDeleteAllListeners(void); -extern int cupsdFlushHeader(cupsd_client_t *con); extern void cupsdPauseListening(void); extern int cupsdProcessIPPRequest(cupsd_client_t *con); extern void cupsdReadClient(cupsd_client_t *con); @@ -140,5 +148,5 @@ extern int cupsdStartTLS(cupsd_client_t *con); /* - * End of "$Id: client.h 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: client.h 11717 2014-03-21 16:42:53Z msweet $". */ diff --git a/scheduler/colorman.c b/scheduler/colorman.c index be064b6..0d90dde 100644 --- a/scheduler/colorman.c +++ b/scheduler/colorman.c @@ -1,22 +1,22 @@ /* - * "$Id: colorman.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: colorman.c 12619 2015-05-06 21:00:19Z msweet $" * - * Color management routines for the CUPS scheduler. + * Color management routines for the CUPS scheduler. * - * Copyright 2007-2013 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. + * Copyright 2007-2014 by Apple Inc. + * Copyright 1997-2007 by Easy Software Products, all rights reserved. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". * - * Original DBUS/colord code is Copyright 2011 Red Hat, Inc. + * Original DBUS/colord code is Copyright 2011 Red Hat, Inc. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. @@ -25,40 +25,18 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Contents: - * - * cupsdRegisterColor() - Register vendor color profiles in a PPD - * file. - * cupsdStartColor() - Initialize color management. - * cupsdStopColor() - Shutdown color management. - * cupsdUnregisterColor() - Unregister vendor color profiles in a PPD - * file. - * apple_init_profile() - Initialize a color profile. - * apple_register_profiles() - Register color profiles for a printer. - * apple_unregister_profiles() - Remove color profiles for the specified - * printer. - * colord_create_device() - Create a device and register profiles. - * colord_create_profile() - Create a color profile for a printer. - * colord_delete_device() - Delete a device - * colord_device_add_profile() - Assign a profile to a device. - * colord_dict_add_strings() - Add two strings to a dictionary. - * colord_find_device() - Finds a device - * colord_get_qualifier_format() - Get the qualifier format. - * colord_register_printer() - Register profiles for a printer. - * colord_unregister_printer() - Unregister profiles for a printer. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. */ /* @@ -173,8 +151,11 @@ cupsdRegisterColor(cupsd_printer_t *p) /* I - Printer */ } #elif defined(HAVE_DBUS) - colord_unregister_printer(p); - colord_register_printer(p); + if (!RunUser) + { + colord_unregister_printer(p); + colord_register_printer(p); + } #endif /* __APPLE__ */ } @@ -208,7 +189,8 @@ void cupsdStopColor(void) { #if !defined(__APPLE__) && defined(HAVE_DBUS) - dbus_connection_unref(colord_con); + if (colord_con) + dbus_connection_unref(colord_con); colord_con = NULL; #endif /* !__APPLE__ && HAVE_DBUS */ } @@ -226,7 +208,8 @@ cupsdUnregisterColor(cupsd_printer_t *p)/* I - Printer */ apple_unregister_profiles(p); #elif defined(HAVE_DBUS) - colord_unregister_printer(p); + if (!RunUser) + colord_unregister_printer(p); #endif /* __APPLE__ */ } @@ -327,9 +310,7 @@ apple_init_profile( if (iccfile && *iccfile) { - url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, - (const UInt8 *)iccfile, - strlen(iccfile), false); + url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8 *)iccfile, (CFIndex)strlen(iccfile), false); if (url) { @@ -387,7 +368,7 @@ apple_register_profiles( * Make sure ColorSync is available... */ - if (ColorSyncRegisterDevice == NULL) + if (&ColorSyncRegisterDevice == NULL) return; /* @@ -887,7 +868,7 @@ apple_unregister_profiles( * Make sure ColorSync is available... */ - if (ColorSyncUnregisterDevice != NULL) + if (&ColorSyncUnregisterDevice != NULL) { CFUUIDRef deviceUUID; /* Device UUID */ @@ -1538,5 +1519,5 @@ colord_unregister_printer( /* - * End of "$Id: colorman.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: colorman.c 12619 2015-05-06 21:00:19Z msweet $". */ diff --git a/scheduler/colorman.h b/scheduler/colorman.h index a95adcf..3360fd4 100644 --- a/scheduler/colorman.h +++ b/scheduler/colorman.h @@ -1,5 +1,5 @@ /* - * "$Id: colorman.h 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: colorman.h 3833 2012-05-23 22:51:18Z msweet $" * * Color management definitions for the CUPS scheduler. * @@ -24,5 +24,5 @@ extern void cupsdUnregisterColor(cupsd_printer_t *p); /* - * End of "$Id: colorman.h 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: colorman.h 3833 2012-05-23 22:51:18Z msweet $". */ diff --git a/scheduler/conf.c b/scheduler/conf.c index 7ae8fed..f3e6514 100644 --- a/scheduler/conf.c +++ b/scheduler/conf.c @@ -1,39 +1,16 @@ /* - * "$Id: conf.c 11221 2013-08-06 16:16:01Z msweet $" + * "$Id: conf.c 12819 2015-07-31 13:52:00Z msweet $" * - * Configuration routines for the CUPS scheduler. + * Configuration routines for the CUPS scheduler. * - * Copyright 2007-2013 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. + * Copyright 2007-2015 by Apple Inc. + * Copyright 1997-2007 by Easy Software Products, all rights reserved. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * cupsdAddAlias() - Add a host alias. - * cupsdCheckPermissions() - Fix the mode and ownership of a file or - * directory. - * cupsdDefaultAuthType() - Get the default AuthType. - * cupsdFreeAliases() - Free all of the alias entries. - * cupsdReadConfiguration() - Read the cupsd.conf file. - * get_address() - Get an address + port number from a line. - * get_addr_and_mask() - Get an IP address and netmask. - * mime_error_cb() - Log a MIME error. - * parse_aaa() - Parse authentication, authorization, and access - * control lines. - * parse_fatal_errors() - Parse FatalErrors values in a string. - * parse_groups() - Parse system group names in a string. - * parse_protocols() - Parse browse protocols in a string. - * parse_variable() - Parse a variable line. - * read_cupsd_conf() - Read the cupsd.conf configuration file. - * read_cups_files_conf() - Read the cups-files.conf configuration file. - * read_location() - Read a <Location path> definition. - * read_policy() - Read a <Policy name> definition. - * set_policy_defaults() - Set default policy values as needed. + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -44,6 +21,12 @@ #include <stdarg.h> #include <grp.h> #include <sys/utsname.h> +#ifdef HAVE_ASL_H +# include <asl.h> +#elif defined(HAVE_SYSTEMD_SD_JOURNAL_H) +# define SD_JOURNAL_SUPPRESS_LOCATION +# include <systemd/sd-journal.h> +#endif /* HAVE_ASL_H */ #include <syslog.h> #ifdef HAVE_LIBPAPER @@ -70,7 +53,8 @@ typedef enum CUPSD_VARTYPE_TIME, /* Time interval option */ CUPSD_VARTYPE_STRING, /* String option */ CUPSD_VARTYPE_BOOLEAN, /* Boolean option */ - CUPSD_VARTYPE_PATHNAME /* File/directory name option */ + CUPSD_VARTYPE_PATHNAME, /* File/directory name option */ + CUPSD_VARTYPE_PERM /* File/directory permissions */ } cupsd_vartype_t; typedef struct @@ -107,13 +91,16 @@ static const cupsd_var_t cupsd_vars[] = #ifdef HAVE_GSSAPI { "GSSServiceName", &GSSServiceName, CUPSD_VARTYPE_STRING }, #endif /* HAVE_GSSAPI */ +#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) + { "IdleExitTimeout", &IdleExitTimeout, CUPSD_VARTYPE_TIME }, +#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ { "JobKillDelay", &JobKillDelay, CUPSD_VARTYPE_TIME }, { "JobRetryLimit", &JobRetryLimit, CUPSD_VARTYPE_INTEGER }, { "JobRetryInterval", &JobRetryInterval, CUPSD_VARTYPE_TIME }, { "KeepAliveTimeout", &KeepAliveTimeout, CUPSD_VARTYPE_TIME }, { "KeepAlive", &KeepAlive, CUPSD_VARTYPE_BOOLEAN }, #ifdef HAVE_LAUNCHD - { "LaunchdTimeout", &LaunchdTimeout, CUPSD_VARTYPE_TIME }, + { "LaunchdTimeout", &IdleExitTimeout, CUPSD_VARTYPE_TIME }, #endif /* HAVE_LAUNCHD */ { "LimitRequestBody", &MaxRequestSize, CUPSD_VARTYPE_INTEGER }, { "ListenBackLog", &ListenBackLog, CUPSD_VARTYPE_INTEGER }, @@ -127,7 +114,7 @@ static const cupsd_var_t cupsd_vars[] = { "MaxJobs", &MaxJobs, CUPSD_VARTYPE_INTEGER }, { "MaxJobsPerPrinter", &MaxJobsPerPrinter, CUPSD_VARTYPE_INTEGER }, { "MaxJobsPerUser", &MaxJobsPerUser, CUPSD_VARTYPE_INTEGER }, - { "MaxJobTime", &MaxJobTime, CUPSD_VARTYPE_INTEGER }, + { "MaxJobTime", &MaxJobTime, CUPSD_VARTYPE_TIME }, { "MaxLeaseDuration", &MaxLeaseDuration, CUPSD_VARTYPE_TIME }, { "MaxLogSize", &MaxLogSize, CUPSD_VARTYPE_INTEGER }, { "MaxRequestSize", &MaxRequestSize, CUPSD_VARTYPE_INTEGER }, @@ -152,13 +139,13 @@ static const cupsd_var_t cupsfiles_vars[] = { { "AccessLog", &AccessLog, CUPSD_VARTYPE_STRING }, { "CacheDir", &CacheDir, CUPSD_VARTYPE_STRING }, - { "ConfigFilePerm", &ConfigFilePerm, CUPSD_VARTYPE_INTEGER }, + { "ConfigFilePerm", &ConfigFilePerm, CUPSD_VARTYPE_PERM }, { "DataDir", &DataDir, CUPSD_VARTYPE_STRING }, { "DocumentRoot", &DocumentRoot, CUPSD_VARTYPE_STRING }, { "ErrorLog", &ErrorLog, CUPSD_VARTYPE_STRING }, { "FileDevice", &FileDevice, CUPSD_VARTYPE_BOOLEAN }, { "FontPath", &FontPath, CUPSD_VARTYPE_STRING }, - { "LogFilePerm", &LogFilePerm, CUPSD_VARTYPE_INTEGER }, + { "LogFilePerm", &LogFilePerm, CUPSD_VARTYPE_PERM }, { "LPDConfigFile", &LPDConfigFile, CUPSD_VARTYPE_STRING }, { "PageLog", &PageLog, CUPSD_VARTYPE_STRING }, { "Printcap", &Printcap, CUPSD_VARTYPE_STRING }, @@ -166,10 +153,7 @@ static const cupsd_var_t cupsfiles_vars[] = { "RequestRoot", &RequestRoot, CUPSD_VARTYPE_STRING }, { "ServerBin", &ServerBin, CUPSD_VARTYPE_PATHNAME }, #ifdef HAVE_SSL - { "ServerCertificate", &ServerCertificate, CUPSD_VARTYPE_PATHNAME }, -# if defined(HAVE_LIBSSL) || defined(HAVE_GNUTLS) - { "ServerKey", &ServerKey, CUPSD_VARTYPE_PATHNAME }, -# endif /* HAVE_LIBSSL || HAVE_GNUTLS */ + { "ServerKeychain", &ServerKeychain, CUPSD_VARTYPE_PATHNAME }, #endif /* HAVE_SSL */ { "ServerRoot", &ServerRoot, CUPSD_VARTYPE_PATHNAME }, { "SMBConfigFile", &SMBConfigFile, CUPSD_VARTYPE_STRING }, @@ -236,7 +220,7 @@ cupsdAddAlias(cups_array_t *aliases, /* I - Array of aliases */ return; a->namelen = namelen; - strcpy(a->name, name); /* OK since a->name is allocated */ + memcpy(a->name, name, namelen + 1); /* OK since a->name is allocated */ cupsArrayAdd(aliases, a); } @@ -250,9 +234,9 @@ int /* O - 0 on success, -1 on error, 1 on warning */ cupsdCheckPermissions( const char *filename, /* I - File/directory name */ const char *suffix, /* I - Additional file/directory name */ - int mode, /* I - Permissions */ - int user, /* I - Owner */ - int group, /* I - Group */ + mode_t mode, /* I - Permissions */ + uid_t user, /* I - Owner */ + gid_t group, /* I - Group */ int is_dir, /* I - 1 = directory, 0 = file */ int create_dir) /* I - 1 = create directory, -1 = create w/o logging, 0 = not */ { @@ -291,8 +275,20 @@ cupsdCheckPermissions( "Unable to create directory \"%s\" - %s", filename, strerror(errno)); else - syslog(LOG_ERR, "Unable to create directory \"%s\" - %s", filename, - strerror(errno)); +#ifdef HAVE_ASL_H + { + asl_object_t m; /* Log message */ + + m = asl_new(ASL_TYPE_MSG); + asl_set(m, ASL_KEY_FACILITY, "org.cups.cupsd"); + asl_log(NULL, m, ASL_LEVEL_ERR, "Unable to create directory \"%s\" - %s", filename, strerror(errno)); + asl_release(m); + } +#elif defined(HAVE_SYSTEMD_SD_JOURNAL_H) + sd_journal_print(LOG_ERR, "Unable to create directory \"%s\" - %s", filename, strerror(errno)); +#else + syslog(LOG_ERR, "Unable to create directory \"%s\" - %s", filename, strerror(errno)); +#endif /* HAVE_ASL_H */ return (-1); } @@ -329,7 +325,20 @@ cupsdCheckPermissions( if (create_dir >= 0) cupsdLogMessage(CUPSD_LOG_ERROR, "\"%s\" is not a directory.", filename); else +#ifdef HAVE_ASL_H + { + asl_object_t m; /* Log message */ + + m = asl_new(ASL_TYPE_MSG); + asl_set(m, ASL_KEY_FACILITY, "org.cups.cupsd"); + asl_log(NULL, m, ASL_LEVEL_ERR, "\"%s\" is not a directory.", filename); + asl_release(m); + } +#elif defined(HAVE_SYSTEMD_SD_JOURNAL_H) + sd_journal_print(LOG_ERR, "\"%s\" is not a directory.", filename); +#else syslog(LOG_ERR, "\"%s\" is not a directory.", filename); +#endif /* HAVE_ASL_H */ return (-1); } @@ -358,8 +367,20 @@ cupsdCheckPermissions( "Unable to change ownership of \"%s\" - %s", filename, strerror(errno)); else - syslog(LOG_ERR, "Unable to change ownership of \"%s\" - %s", filename, - strerror(errno)); +#ifdef HAVE_ASL_H + { + asl_object_t m; /* Log message */ + + m = asl_new(ASL_TYPE_MSG); + asl_set(m, ASL_KEY_FACILITY, "org.cups.cupsd"); + asl_log(NULL, m, ASL_LEVEL_ERR, "Unable to change ownership of \"%s\" - %s", filename, strerror(errno)); + asl_release(m); + } +#elif defined(HAVE_SYSTEMD_SD_JOURNAL_H) + sd_journal_print(LOG_ERR, "Unable to change ownership of \"%s\" - %s", filename, strerror(errno)); +#else + syslog(LOG_ERR, "Unable to change ownership of \"%s\" - %s", filename, strerror(errno)); +#endif /* HAVE_ASL_H */ return (1); } @@ -378,8 +399,20 @@ cupsdCheckPermissions( "Unable to change permissions of \"%s\" - %s", filename, strerror(errno)); else - syslog(LOG_ERR, "Unable to change permissions of \"%s\" - %s", filename, - strerror(errno)); +#ifdef HAVE_ASL_H + { + asl_object_t m; /* Log message */ + + m = asl_new(ASL_TYPE_MSG); + asl_set(m, ASL_KEY_FACILITY, "org.cups.cupsd"); + asl_log(NULL, m, ASL_LEVEL_ERR, "Unable to change permissions of \"%s\" - %s", filename, strerror(errno)); + asl_release(m); + } +#elif defined(HAVE_SYSTEMD_SD_JOURNAL_H) + sd_journal_print(LOG_ERR, "Unable to change permissions of \"%s\" - %s", filename, strerror(errno)); +#else + syslog(LOG_ERR, "Unable to change permissions of \"%s\" - %s", filename, strerror(errno)); +#endif /* HAVE_ASL_H */ return (1); } @@ -429,7 +462,7 @@ cupsdDefaultAuthType(void) * to use it... */ - if (gss_init_sec_context == NULL) + if (&gss_init_sec_context == NULL) return (default_auth_type = CUPSD_AUTH_BASIC); # endif /* __APPLE__ */ @@ -589,7 +622,6 @@ cupsdReadConfiguration(void) "%p %u %j %T %P %C %{job-billing} " "%{job-originating-host-name} %{job-name} %{media} %{sides}"); cupsdSetString(&Printcap, CUPS_DEFAULT_PRINTCAP); - cupsdSetString(&PrintcapGUI, "/usr/bin/glpoptions"); cupsdSetString(&FontPath, CUPS_FONTPATH); cupsdSetString(&RemoteRoot, "remroot"); cupsdSetStringf(&ServerHeader, "CUPS/%d.%d IPP/2.1", CUPS_VERSION_MAJOR, @@ -614,12 +646,13 @@ cupsdReadConfiguration(void) ClassifyOverride = 0; #ifdef HAVE_SSL -# ifdef HAVE_CDSASSL - cupsdSetString(&ServerCertificate, "/Library/Keychains/System.keychain"); +# ifdef HAVE_GNUTLS + cupsdSetString(&ServerKeychain, "ssl"); # else - cupsdSetString(&ServerCertificate, "ssl/server.crt"); - cupsdSetString(&ServerKey, "ssl/server.key"); -# endif /* HAVE_CDSASSL */ + cupsdSetString(&ServerKeychain, "/Library/Keychains/System.keychain"); +# endif /* HAVE_GNUTLS */ + + _httpTLSSetOptions(0); #endif /* HAVE_SSL */ language = cupsLangDefault(); @@ -709,7 +742,6 @@ cupsdReadConfiguration(void) default_auth_type = CUPSD_AUTH_BASIC; #ifdef HAVE_SSL DefaultEncryption = HTTP_ENCRYPT_REQUIRED; - SSLOptions = CUPSD_SSL_NONE; #endif /* HAVE_SSL */ DirtyCleanInterval = DEFAULT_KEEPALIVE; JobKillDelay = DEFAULT_TIMEOUT; @@ -735,6 +767,7 @@ cupsdReadConfiguration(void) NumSystemGroups = 0; ReloadTimeout = DEFAULT_KEEPALIVE; RootCertDuration = 300; + Sandboxing = CUPSD_SANDBOXING_STRICT; StrictConformance = FALSE; SyncOnClose = FALSE; Timeout = DEFAULT_TIMEOUT; @@ -779,9 +812,9 @@ cupsdReadConfiguration(void) DefaultLeaseDuration = 86400; MaxLeaseDuration = 0; -#ifdef HAVE_LAUNCHD - LaunchdTimeout = 10; -#endif /* HAVE_LAUNCHD */ +#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) + IdleExitTimeout = 60; +#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ /* * Setup environment variables... @@ -804,8 +837,20 @@ cupsdReadConfiguration(void) if (TestConfigFile) printf("\"%s\" contains errors.\n", CupsFilesFile); else - syslog(LOG_LPR, "Unable to read \"%s\" due to errors.", - CupsFilesFile); +#ifdef HAVE_ASL_H + { + asl_object_t m; /* Log message */ + + m = asl_new(ASL_TYPE_MSG); + asl_set(m, ASL_KEY_FACILITY, "org.cups.cupsd"); + asl_log(NULL, m, ASL_LEVEL_ERR, "Unable to read \"%s\" due to errors.", CupsFilesFile); + asl_release(m); + } +#elif defined(HAVE_SYSTEMD_SD_JOURNAL_H) + sd_journal_print(LOG_ERR, "Unable to read \"%s\" due to errors.", CupsFilesFile); +#else + syslog(LOG_LPR, "Unable to read \"%s\" due to errors.", CupsFilesFile); +#endif /* HAVE_ASL_H */ return (0); } @@ -814,8 +859,20 @@ cupsdReadConfiguration(void) cupsdLogMessage(CUPSD_LOG_INFO, "No %s, using defaults.", CupsFilesFile); else { - syslog(LOG_LPR, "Unable to open \"%s\": %s", CupsFilesFile, - strerror(errno)); +#ifdef HAVE_ASL_H + asl_object_t m; /* Log message */ + + m = asl_new(ASL_TYPE_MSG); + asl_set(m, ASL_KEY_FACILITY, "org.cups.cupsd"); + asl_log(NULL, m, ASL_LEVEL_ERR, "Unable to open \"%s\" - %s", CupsFilesFile, strerror(errno)); + asl_release(m); + +#elif defined(HAVE_SYSTEMD_SD_JOURNAL_H) + sd_journal_print(LOG_ERR, "Unable to open \"%s\" - %s", CupsFilesFile, strerror(errno)); +#else + syslog(LOG_LPR, "Unable to open \"%s\" - %s", CupsFilesFile, strerror(errno)); +#endif /* HAVE_ASL_H */ + return (0); } @@ -828,8 +885,19 @@ cupsdReadConfiguration(void) if ((fp = cupsFileOpen(ConfigurationFile, "r")) == NULL) { - syslog(LOG_LPR, "Unable to open \"%s\": %s", ConfigurationFile, - strerror(errno)); +#ifdef HAVE_ASL_H + asl_object_t m; /* Log message */ + + m = asl_new(ASL_TYPE_MSG); + asl_set(m, ASL_KEY_FACILITY, "org.cups.cupsd"); + asl_log(NULL, m, ASL_LEVEL_ERR, "Unable to open \"%s\" - %s", ConfigurationFile, strerror(errno)); + asl_release(m); +#elif defined(HAVE_SYSTEMD_SD_JOURNAL_H) + sd_journal_print(LOG_ERR, "Unable to open \"%s\" - %s", ConfigurationFile, strerror(errno)); +#else + syslog(LOG_LPR, "Unable to open \"%s\" - %s", ConfigurationFile, strerror(errno)); +#endif /* HAVE_ASL_H */ + return (0); } @@ -842,8 +910,20 @@ cupsdReadConfiguration(void) if (TestConfigFile) printf("\"%s\" contains errors.\n", ConfigurationFile); else - syslog(LOG_LPR, "Unable to read \"%s\" due to errors.", - ConfigurationFile); +#ifdef HAVE_ASL_H + { + asl_object_t m; /* Log message */ + + m = asl_new(ASL_TYPE_MSG); + asl_set(m, ASL_KEY_FACILITY, "org.cups.cupsd"); + asl_log(NULL, m, ASL_LEVEL_ERR, "Unable to read \"%s\" due to errors.", ConfigurationFile); + asl_release(m); + } +#elif defined(HAVE_SYSTEMD_SD_JOURNAL_H) + sd_journal_print(LOG_ERR, "Unable to read \"%s\" due to errors.", ConfigurationFile); +#else + syslog(LOG_LPR, "Unable to read \"%s\" due to errors.", ConfigurationFile); +#endif /* HAVE_ASL_H */ return (0); } @@ -970,12 +1050,24 @@ cupsdReadConfiguration(void) * Open the system log for cupsd if necessary... */ -#ifdef HAVE_VSYSLOG + if (!LogStderr) + { + if (!strcmp(AccessLog, "stderr")) + cupsdSetString(&AccessLog, "syslog"); + + if (!strcmp(ErrorLog, "stderr")) + cupsdSetString(&ErrorLog, "syslog"); + + if (!strcmp(PageLog, "stderr")) + cupsdSetString(&PageLog, "syslog"); + } + +#if defined(HAVE_VSYSLOG) && !defined(HAVE_ASL_H) && !defined(HAVE_SYSTEMD_SD_JOURNAL_H) if (!strcmp(AccessLog, "syslog") || !strcmp(ErrorLog, "syslog") || !strcmp(PageLog, "syslog")) openlog("cupsd", LOG_PID | LOG_NOWAIT | LOG_NDELAY, LOG_LPR); -#endif /* HAVE_VSYSLOG */ +#endif /* HAVE_VSYSLOG && !HAVE_ASL_H && !HAVE_SYSTEMD_SD_JOURNAL_H */ /* * Make sure each of the log files exists and gets rotated as necessary... @@ -1015,8 +1107,11 @@ cupsdReadConfiguration(void) * Log the error and reset the group to a safe value... */ - cupsdLogMessage(CUPSD_LOG_NOTICE, + cupsdLogMessage(CUPSD_LOG_ERROR, "Group and SystemGroup cannot use the same groups."); + if (FatalErrors & (CUPSD_FATAL_CONFIG | CUPSD_FATAL_PERMISSIONS)) + return (0); + cupsdLogMessage(CUPSD_LOG_INFO, "Resetting Group to \"nobody\"..."); group = getgrnam("nobody"); @@ -1084,24 +1179,11 @@ cupsdReadConfiguration(void) cupsdSetStringf(&CacheDir, "%s/%s", ServerRoot, CacheDir); #ifdef HAVE_SSL - if (ServerCertificate[0] != '/') - cupsdSetStringf(&ServerCertificate, "%s/%s", ServerRoot, ServerCertificate); - - if (!strncmp(ServerRoot, ServerCertificate, strlen(ServerRoot)) && - cupsdCheckPermissions(ServerCertificate, NULL, 0600, RunUser, Group, - 0, 0) < 0 && - (FatalErrors & CUPSD_FATAL_PERMISSIONS)) - return (0); + if (ServerKeychain[0] != '/') + cupsdSetStringf(&ServerKeychain, "%s/%s", ServerRoot, ServerKeychain); -# if defined(HAVE_LIBSSL) || defined(HAVE_GNUTLS) - if (ServerKey[0] != '/') - cupsdSetStringf(&ServerKey, "%s/%s", ServerRoot, ServerKey); - - if (!strncmp(ServerRoot, ServerKey, strlen(ServerRoot)) && - cupsdCheckPermissions(ServerKey, NULL, 0600, RunUser, Group, 0, 0) < 0 && - (FatalErrors & CUPSD_FATAL_PERMISSIONS)) - return (0); -# endif /* HAVE_LIBSSL || HAVE_GNUTLS */ + cupsdLogMessage(CUPSD_LOG_DEBUG, "Using keychain \"%s\" for server name \"%s\".", ServerKeychain, ServerName); + cupsSetServerCredentials(ServerKeychain, ServerName, 1); #endif /* HAVE_SSL */ /* @@ -1113,7 +1195,7 @@ cupsdReadConfiguration(void) if ((cupsdCheckPermissions(RequestRoot, NULL, 0710, RunUser, Group, 1, 1) < 0 || - cupsdCheckPermissions(CacheDir, NULL, 0775, RunUser, + cupsdCheckPermissions(CacheDir, NULL, 0770, RunUser, Group, 1, 1) < 0 || cupsdCheckPermissions(temp, NULL, 0775, RunUser, Group, 1, 1) < 0 || @@ -1189,6 +1271,8 @@ cupsdReadConfiguration(void) cupsdSetStringf(&TempDir, "%s/tmp", RequestRoot); } + setenv("TMPDIR", TempDir, 1); + /* * Make sure the temporary directory has the right permissions... */ @@ -1212,6 +1296,19 @@ cupsdReadConfiguration(void) cupsdUpdateEnv(); + /* + * Validate the default error policy... + */ + + if (strcmp(ErrorPolicy, "retry-current-job") && + strcmp(ErrorPolicy, "abort-job") && + strcmp(ErrorPolicy, "retry-job") && + strcmp(ErrorPolicy, "stop-printer")) + { + cupsdLogMessage(CUPSD_LOG_ALERT, "Invalid ErrorPolicy \"%s\", resetting to \"stop-printer\".", ErrorPolicy); + cupsdSetString(&ErrorPolicy, "stop-printer"); + } + /* * Update default paper size setting as needed... */ @@ -1334,6 +1431,7 @@ cupsdReadConfiguration(void) cupsdAddString(&(p->job_attrs), "job-name"); cupsdAddString(&(p->job_attrs), "job-originating-host-name"); cupsdAddString(&(p->job_attrs), "job-originating-user-name"); + cupsdAddString(&(p->job_attrs), "phone"); cupsdLogMessage(CUPSD_LOG_INFO, "SubscriptionPrivateAccess default"); cupsdAddString(&(p->sub_access), "@OWNER"); @@ -1542,7 +1640,7 @@ cupsdReadConfiguration(void) if (!mimeType(MimeDatabase, "application", "octet-stream")) NumMimeTypes ++; - if ((MimeTypes = calloc(NumMimeTypes, sizeof(const char *))) == NULL) + if ((MimeTypes = calloc((size_t)NumMimeTypes, sizeof(const char *))) == NULL) { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to allocate memory for %d MIME types.", @@ -1816,7 +1914,8 @@ get_addr_and_mask(const char *value, /* I - String from config file */ * Merge everything into a 32-bit IPv4 address in ip[3]... */ - ip[3] = (((((val[0] << 8) | val[1]) << 8) | val[2]) << 8) | val[3]; + ip[3] = ((((((unsigned)val[0] << 8) | (unsigned)val[1]) << 8) | + (unsigned)val[2]) << 8) | (unsigned)val[3]; if (ipcount < 4) mask[3] = (0xffffffff << (32 - 8 * ipcount)) & 0xffffffff; @@ -1884,7 +1983,8 @@ get_addr_and_mask(const char *value, /* I - String from config file */ * Merge everything into a 32-bit IPv4 address in ip[3]... */ - ip[3] = (((((val[0] << 8) | val[1]) << 8) | val[2]) << 8) | val[3]; + ip[3] = ((((((unsigned)val[0] << 8) | (unsigned)val[1]) << 8) | + (unsigned)val[2]) << 8) | (unsigned)val[3]; if (ipcount < 4) mask[3] = (0xffffffff << (32 - 8 * ipcount)) & 0xffffffff; @@ -1911,7 +2011,8 @@ get_addr_and_mask(const char *value, /* I - String from config file */ mask + 3) != 4) return (0); - mask[3] |= ((((mask[0] << 8) | mask[1]) << 8) | mask[2]) << 8; + mask[3] |= (((((unsigned)mask[0] << 8) | (unsigned)mask[1]) << 8) | + (unsigned)mask[2]) << 8; mask[0] = mask[1] = mask[2] = 0; } else @@ -2034,8 +2135,8 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */ else if (!_cups_strcasecmp(value, "always")) { cupsdLogMessage(CUPSD_LOG_ERROR, - "Encryption value \"%s\" on line %d is invalid in this " - "context. Using \"required\" instead.", value, linenum); + "Encryption value \"%s\" on line %d of %s is invalid in this " + "context. Using \"required\" instead.", value, linenum, ConfigurationFile); loc->encryption = HTTP_ENCRYPT_REQUIRED; } @@ -2046,7 +2147,7 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */ else { cupsdLogMessage(CUPSD_LOG_ERROR, - "Unknown Encryption value %s on line %d.", value, linenum); + "Unknown Encryption value %s on line %d of %s.", value, linenum, ConfigurationFile); return (0); } } @@ -2062,8 +2163,8 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */ loc->order_type = CUPSD_AUTH_DENY; else { - cupsdLogMessage(CUPSD_LOG_ERROR, "Unknown Order value %s on line %d.", - value, linenum); + cupsdLogMessage(CUPSD_LOG_ERROR, "Unknown Order value %s on line %d of %s.", + value, linenum, ConfigurationFile); return (0); } } @@ -2165,8 +2266,8 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */ if (!get_addr_and_mask(value, ip, mask)) { - cupsdLogMessage(CUPSD_LOG_ERROR, "Bad netmask value %s on line %d.", - value, linenum); + cupsdLogMessage(CUPSD_LOG_ERROR, "Bad netmask value %s on line %d of %s.", + value, linenum, ConfigurationFile); return (0); } @@ -2201,20 +2302,6 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */ if (loc->level == CUPSD_AUTH_ANON) loc->level = CUPSD_AUTH_USER; } - else if (!_cups_strcasecmp(value, "digest")) - { - loc->type = CUPSD_AUTH_DIGEST; - - if (loc->level == CUPSD_AUTH_ANON) - loc->level = CUPSD_AUTH_USER; - } - else if (!_cups_strcasecmp(value, "basicdigest")) - { - loc->type = CUPSD_AUTH_BASICDIGEST; - - if (loc->level == CUPSD_AUTH_ANON) - loc->level = CUPSD_AUTH_USER; - } else if (!_cups_strcasecmp(value, "default")) { loc->type = CUPSD_AUTH_DEFAULT; @@ -2234,8 +2321,8 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */ else { cupsdLogMessage(CUPSD_LOG_WARN, - "Unknown authorization type %s on line %d.", - value, linenum); + "Unknown authorization type %s on line %d of %s.", + value, linenum, ConfigurationFile); return (0); } } @@ -2261,8 +2348,8 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */ cupsdLogMessage(CUPSD_LOG_WARN, "\"AuthClass %s\" is deprecated; consider using " - "\"Require valid-user\" on line %d.", - value, linenum); + "\"Require valid-user\" on line %d of %s.", + value, linenum, ConfigurationFile); } else if (!_cups_strcasecmp(value, "group")) { @@ -2270,8 +2357,8 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */ cupsdLogMessage(CUPSD_LOG_WARN, "\"AuthClass %s\" is deprecated; consider using " - "\"Require user @groupname\" on line %d.", - value, linenum); + "\"Require user @groupname\" on line %d of %s.", + value, linenum, ConfigurationFile); } else if (!_cups_strcasecmp(value, "system")) { @@ -2281,14 +2368,14 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */ cupsdLogMessage(CUPSD_LOG_WARN, "\"AuthClass %s\" is deprecated; consider using " - "\"Require user @SYSTEM\" on line %d.", - value, linenum); + "\"Require user @SYSTEM\" on line %d of %s.", + value, linenum, ConfigurationFile); } else { cupsdLogMessage(CUPSD_LOG_WARN, - "Unknown authorization class %s on line %d.", - value, linenum); + "Unknown authorization class %s on line %d of %s.", + value, linenum, ConfigurationFile); return (0); } } @@ -2298,8 +2385,8 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */ cupsdLogMessage(CUPSD_LOG_WARN, "\"AuthGroupName %s\" directive is deprecated; consider " - "using \"Require user @%s\" on line %d.", - value, value, linenum); + "using \"Require user @%s\" on line %d of %s.", + value, value, linenum, ConfigurationFile); } else if (!_cups_strcasecmp(line, "Require")) { @@ -2325,8 +2412,8 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */ loc->level = CUPSD_AUTH_GROUP; else { - cupsdLogMessage(CUPSD_LOG_WARN, "Unknown Require type %s on line %d.", - value, linenum); + cupsdLogMessage(CUPSD_LOG_WARN, "Unknown Require type %s on line %d of %s.", + value, linenum, ConfigurationFile); return (0); } @@ -2388,8 +2475,8 @@ parse_aaa(cupsd_location_t *loc, /* I - Location */ loc->satisfy = CUPSD_AUTH_SATISFY_ANY; else { - cupsdLogMessage(CUPSD_LOG_WARN, "Unknown Satisfy value %s on line %d.", - value, linenum); + cupsdLogMessage(CUPSD_LOG_WARN, "Unknown Satisfy value %s on line %d of %s.", + value, linenum, ConfigurationFile); return (0); } } @@ -2714,6 +2801,41 @@ parse_variable( } break; + case CUPSD_VARTYPE_PERM : + if (!value) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Missing permissions value for %s on line %d of %s.", + line, linenum, filename); + return (0); + } + else if (!isdigit(*value & 255)) + { + /* TODO: Add chmod UGO syntax support */ + cupsdLogMessage(CUPSD_LOG_ERROR, + "Bad permissions value for %s on line %d of %s.", + line, linenum, filename); + return (0); + } + else + { + int n = strtol(value, NULL, 8); + /* Permissions value */ + + if (n < 0) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Bad negative permissions value for %s on line %d of " + "%s.", line, linenum, filename); + return (0); + } + else + { + *((mode_t *)var->ptr) = (mode_t)n; + } + } + break; + case CUPSD_VARTYPE_TIME : if (!value) { @@ -2930,15 +3052,60 @@ read_cupsd_conf(cups_file_t *fp) /* I - File to read from */ JobRetryInterval = atoi(value); cupsdLogMessage(CUPSD_LOG_WARN, "FaxRetryInterval is deprecated; use " - "JobRetryInterval on line %d.", linenum); + "JobRetryInterval on line %d of %s.", linenum, ConfigurationFile); } else if (!_cups_strcasecmp(line, "FaxRetryLimit") && value) { JobRetryLimit = atoi(value); cupsdLogMessage(CUPSD_LOG_WARN, "FaxRetryLimit is deprecated; use " - "JobRetryLimit on line %d.", linenum); + "JobRetryLimit on line %d of %s.", linenum, ConfigurationFile); } +#ifdef HAVE_SSL + else if (!_cups_strcasecmp(line, "SSLOptions")) + { + /* + * SSLOptions [AllowRC4] [AllowSSL3] [None] + */ + + int options = 0; /* SSL/TLS options */ + + if (value) + { + char *start, /* Start of option */ + *end; /* End of option */ + + for (start = value; *start; start = end) + { + /* + * Find end of keyword... + */ + + end = start; + while (*end && !_cups_isspace(*end)) + end ++; + + if (*end) + *end++ = '\0'; + + /* + * Compare... + */ + + if (!_cups_strcasecmp(start, "AllowRC4")) + options |= _HTTP_TLS_ALLOW_RC4; + else if (!_cups_strcasecmp(start, "AllowSSL3")) + options |= _HTTP_TLS_ALLOW_SSL3; + else if (!_cups_strcasecmp(start, "None")) + options = 0; + else if (_cups_strcasecmp(start, "NoEmptyFragments")) + cupsdLogMessage(CUPSD_LOG_WARN, "Unknown SSL option %s at line %d.", start, linenum); + } + } + + _httpTLSSetOptions(options); + } +#endif /* HAVE_SSL */ else if ((!_cups_strcasecmp(line, "Port") || !_cups_strcasecmp(line, "Listen") #ifdef HAVE_SSL || !_cups_strcasecmp(line, "SSLPort") || !_cups_strcasecmp(line, "SSLListen") @@ -2979,14 +3146,20 @@ read_cupsd_conf(cups_file_t *fp) /* I - File to read from */ lis; lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) if (httpAddrEqual(&(addr->addr), &(lis->address)) && - _httpAddrPort(&(addr->addr)) == _httpAddrPort(&(lis->address))) + httpAddrPort(&(addr->addr)) == httpAddrPort(&(lis->address))) break; if (lis) { - httpAddrString(&lis->address, temp, sizeof(temp)); - cupsdLogMessage(CUPSD_LOG_WARN, - "Duplicate listen address \"%s\" ignored.", temp); +#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) + if (!lis->on_demand) +#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ + { + httpAddrString(&lis->address, temp, sizeof(temp)); + cupsdLogMessage(CUPSD_LOG_WARN, + "Duplicate listen address \"%s\" ignored.", temp); + } + continue; } @@ -3035,11 +3208,11 @@ read_cupsd_conf(cups_file_t *fp) /* I - File to read from */ else #endif /* AF_LOCAL */ cupsdLogMessage(CUPSD_LOG_INFO, "Listening to %s:%d (IPv%d)", temp, - _httpAddrPort(&(lis->address)), - _httpAddrFamily(&(lis->address)) == AF_INET ? 4 : 6); + httpAddrPort(&(lis->address)), + httpAddrFamily(&(lis->address)) == AF_INET ? 4 : 6); if (!httpAddrLocalhost(&(lis->address))) - RemotePort = _httpAddrPort(&(lis->address)); + RemotePort = httpAddrPort(&(lis->address)); } /* @@ -3061,8 +3234,8 @@ read_cupsd_conf(cups_file_t *fp) /* I - File to read from */ if (protocols < 0) { cupsdLogMessage(CUPSD_LOG_ERROR, - "Unknown browse protocol \"%s\" on line %d.", - value, linenum); + "Unknown browse protocol \"%s\" on line %d of %s.", + value, linenum, ConfigurationFile); break; } @@ -3078,10 +3251,6 @@ read_cupsd_conf(cups_file_t *fp) /* I - File to read from */ default_auth_type = CUPSD_AUTH_NONE; else if (!_cups_strcasecmp(value, "basic")) default_auth_type = CUPSD_AUTH_BASIC; - else if (!_cups_strcasecmp(value, "digest")) - default_auth_type = CUPSD_AUTH_DIGEST; - else if (!_cups_strcasecmp(value, "basicdigest")) - default_auth_type = CUPSD_AUTH_BASICDIGEST; #ifdef HAVE_GSSAPI else if (!_cups_strcasecmp(value, "negotiate")) default_auth_type = CUPSD_AUTH_NEGOTIATE; @@ -3091,8 +3260,8 @@ read_cupsd_conf(cups_file_t *fp) /* I - File to read from */ else { cupsdLogMessage(CUPSD_LOG_WARN, - "Unknown default authorization type %s on line %d.", - value, linenum); + "Unknown default authorization type %s on line %d of %s.", + value, linenum, ConfigurationFile); if (FatalErrors & CUPSD_FATAL_CONFIG) return (0); } @@ -3113,8 +3282,8 @@ read_cupsd_conf(cups_file_t *fp) /* I - File to read from */ else { cupsdLogMessage(CUPSD_LOG_WARN, - "Unknown default encryption %s on line %d.", - value, linenum); + "Unknown default encryption %s on line %d of %s.", + value, linenum, ConfigurationFile); if (FatalErrors & CUPSD_FATAL_CONFIG) return (0); } @@ -3135,8 +3304,8 @@ read_cupsd_conf(cups_file_t *fp) /* I - File to read from */ else if (!_cups_strcasecmp(value, "double")) HostNameLookups = 2; else - cupsdLogMessage(CUPSD_LOG_WARN, "Unknown HostNameLookups %s on line %d.", - value, linenum); + cupsdLogMessage(CUPSD_LOG_WARN, "Unknown HostNameLookups %s on line %d of %s.", + value, linenum, ConfigurationFile); } else if (!_cups_strcasecmp(line, "AccessLogLevel") && value) { @@ -3150,9 +3319,11 @@ read_cupsd_conf(cups_file_t *fp) /* I - File to read from */ AccessLogLevel = CUPSD_ACCESSLOG_ACTIONS; else if (!_cups_strcasecmp(value, "config")) AccessLogLevel = CUPSD_ACCESSLOG_CONFIG; + else if (!_cups_strcasecmp(value, "none")) + AccessLogLevel = CUPSD_ACCESSLOG_NONE; else - cupsdLogMessage(CUPSD_LOG_WARN, "Unknown AccessLogLevel %s on line %d.", - value, linenum); + cupsdLogMessage(CUPSD_LOG_WARN, "Unknown AccessLogLevel %s on line %d of %s.", + value, linenum, ConfigurationFile); } else if (!_cups_strcasecmp(line, "LogLevel") && value) { @@ -3181,8 +3352,8 @@ read_cupsd_conf(cups_file_t *fp) /* I - File to read from */ else if (!_cups_strcasecmp(value, "none")) LogLevel = CUPSD_LOG_NONE; else - cupsdLogMessage(CUPSD_LOG_WARN, "Unknown LogLevel %s on line %d.", - value, linenum); + cupsdLogMessage(CUPSD_LOG_WARN, "Unknown LogLevel %s on line %d of %s.", + value, linenum, ConfigurationFile); } else if (!_cups_strcasecmp(line, "LogTimeFormat") && value) { @@ -3195,8 +3366,8 @@ read_cupsd_conf(cups_file_t *fp) /* I - File to read from */ else if (!_cups_strcasecmp(value, "usecs")) LogTimeFormat = CUPSD_TIME_USECS; else - cupsdLogMessage(CUPSD_LOG_WARN, "Unknown LogTimeFormat %s on line %d.", - value, linenum); + cupsdLogMessage(CUPSD_LOG_WARN, "Unknown LogTimeFormat %s on line %d of %s.", + value, linenum, ConfigurationFile); } else if (!_cups_strcasecmp(line, "ServerTokens") && value) { @@ -3227,8 +3398,8 @@ read_cupsd_conf(cups_file_t *fp) /* I - File to read from */ else if (!_cups_strcasecmp(value, "None")) cupsdClearString(&ServerHeader); else - cupsdLogMessage(CUPSD_LOG_WARN, "Unknown ServerTokens %s on line %d.", - value, linenum); + cupsdLogMessage(CUPSD_LOG_WARN, "Unknown ServerTokens %s on line %d of %s.", + value, linenum, ConfigurationFile); } else if (!_cups_strcasecmp(line, "PassEnv") && value) { @@ -3304,26 +3475,9 @@ read_cupsd_conf(cups_file_t *fp) /* I - File to read from */ } else cupsdLogMessage(CUPSD_LOG_ERROR, - "Missing value for SetEnv directive on line %d.", - linenum); + "Missing value for SetEnv directive on line %d of %s.", + linenum, ConfigurationFile); } -#ifdef HAVE_SSL - else if (!_cups_strcasecmp(line, "SSLOptions")) - { - /* - * SSLOptions options - */ - - if (!value || !_cups_strcasecmp(value, "none")) - SSLOptions = CUPSD_SSL_NONE; - else if (!_cups_strcasecmp(value, "noemptyfragments")) - SSLOptions = CUPSD_SSL_NOEMPTY; - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unknown value \"%s\" for SSLOptions directive on " - "line %d.", value, linenum); - } -#endif /* HAVE_SSL */ else if (!_cups_strcasecmp(line, "AccessLog") || !_cups_strcasecmp(line, "CacheDir") || !_cups_strcasecmp(line, "ConfigFilePerm") || @@ -3344,6 +3498,7 @@ read_cupsd_conf(cups_file_t *fp) /* I - File to read from */ !_cups_strcasecmp(line, "ServerBin") || !_cups_strcasecmp(line, "ServerCertificate") || !_cups_strcasecmp(line, "ServerKey") || + !_cups_strcasecmp(line, "ServerKeychain") || !_cups_strcasecmp(line, "ServerRoot") || !_cups_strcasecmp(line, "SMBConfigFile") || !_cups_strcasecmp(line, "StateDir") || @@ -3397,7 +3552,7 @@ read_cups_files_conf(cups_file_t *fp) /* I - File to read from */ */ if (isdigit(value[0])) - Group = atoi(value); + Group = (gid_t)atoi(value); else { endgrent(); @@ -3436,6 +3591,30 @@ read_cups_files_conf(cups_file_t *fp) /* I - File to read from */ return (0); } } + else if (!_cups_strcasecmp(line, "Sandboxing") && value) + { + /* + * Level of sandboxing? + */ + + if (!_cups_strcasecmp(value, "off") && getuid()) + { + Sandboxing = CUPSD_SANDBOXING_OFF; + cupsdLogMessage(CUPSD_LOG_WARN, "Disabling sandboxing is not recommended (line %d of %s)", linenum, CupsFilesFile); + } + else if (!_cups_strcasecmp(value, "relaxed")) + Sandboxing = CUPSD_SANDBOXING_RELAXED; + else if (!_cups_strcasecmp(value, "strict")) + Sandboxing = CUPSD_SANDBOXING_STRICT; + else + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Unknown Sandboxing \"%s\" on line %d of %s.", + value, linenum, CupsFilesFile); + if (FatalErrors & CUPSD_FATAL_CONFIG) + return (0); + } + } else if (!_cups_strcasecmp(line, "SystemGroup") && value) { /* @@ -3472,7 +3651,7 @@ read_cups_files_conf(cups_file_t *fp) /* I - File to read from */ return (0); } else - User = atoi(value); + User = (uid_t)atoi(value); } else { @@ -3506,6 +3685,15 @@ read_cups_files_conf(cups_file_t *fp) /* I - File to read from */ } } } + else if (!_cups_strcasecmp(line, "ServerCertificate") || + !_cups_strcasecmp(line, "ServerKey")) + { + cupsdLogMessage(CUPSD_LOG_INFO, + "The \"%s\" directive on line %d of %s is no longer " + "supported; this will become an error in a future " + "release.", + line, linenum, CupsFilesFile); + } else if (!parse_variable(CupsFilesFile, linenum, line, value, sizeof(cupsfiles_vars) / sizeof(cupsfiles_vars[0]), cupsfiles_vars) && @@ -3535,8 +3723,8 @@ read_location(cups_file_t *fp, /* I - Configuration file */ if ((parent = cupsdFindLocation(location)) != NULL) - cupsdLogMessage(CUPSD_LOG_WARN, "Duplicate <Location %s> on line %d.", - location, linenum); + cupsdLogMessage(CUPSD_LOG_WARN, "Duplicate <Location %s> on line %d of %s.", + location, linenum, ConfigurationFile); else if ((parent = cupsdNewLocation(location)) == NULL) return (0); else @@ -3561,7 +3749,7 @@ read_location(cups_file_t *fp, /* I - Configuration file */ { if (!value) { - cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d.", linenum); + cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of %s.", linenum, ConfigurationFile); if (FatalErrors & CUPSD_FATAL_CONFIG) return (0); else @@ -3596,8 +3784,8 @@ read_location(cups_file_t *fp, /* I - Configuration file */ else if (!strcmp(value, "TRACE")) loc->limit |= CUPSD_AUTH_LIMIT_TRACE; else - cupsdLogMessage(CUPSD_LOG_WARN, "Unknown request type %s on line %d.", - value, linenum); + cupsdLogMessage(CUPSD_LOG_WARN, "Unknown request type %s on line %d of %s.", + value, linenum, ConfigurationFile); for (value = valptr; isspace(*value & 255); value ++); } @@ -3612,15 +3800,15 @@ read_location(cups_file_t *fp, /* I - Configuration file */ loc = parent; else if (!value) { - cupsdLogMessage(CUPSD_LOG_ERROR, "Missing value on line %d.", linenum); + cupsdLogMessage(CUPSD_LOG_ERROR, "Missing value on line %d of %s.", linenum, ConfigurationFile); if (FatalErrors & CUPSD_FATAL_CONFIG) return (0); } else if (!parse_aaa(loc, line, value, linenum)) { cupsdLogMessage(CUPSD_LOG_ERROR, - "Unknown Location directive %s on line %d.", - line, linenum); + "Unknown Location directive %s on line %d of %s.", + line, linenum, ConfigurationFile); if (FatalErrors & CUPSD_FATAL_CONFIG) return (0); } @@ -3659,8 +3847,8 @@ read_policy(cups_file_t *fp, /* I - Configuration file */ */ if ((pol = cupsdFindPolicy(policy)) != NULL) - cupsdLogMessage(CUPSD_LOG_WARN, "Duplicate <Policy %s> on line %d.", - policy, linenum); + cupsdLogMessage(CUPSD_LOG_WARN, "Duplicate <Policy %s> on line %d of %s.", + policy, linenum, ConfigurationFile); else if ((pol = cupsdAddPolicy(policy)) == NULL) return (0); @@ -3681,8 +3869,8 @@ read_policy(cups_file_t *fp, /* I - Configuration file */ { if (op) cupsdLogMessage(CUPSD_LOG_WARN, - "Missing </Limit> before </Policy> on line %d.", - linenum); + "Missing </Limit> before </Policy> on line %d of %s.", + linenum, ConfigurationFile); set_policy_defaults(pol); @@ -3692,7 +3880,7 @@ read_policy(cups_file_t *fp, /* I - Configuration file */ { if (!value) { - cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d.", linenum); + cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of %s.", linenum, ConfigurationFile); if (FatalErrors & CUPSD_FATAL_CONFIG) return (0); else @@ -3718,15 +3906,15 @@ read_policy(cups_file_t *fp, /* I - Configuration file */ ops[num_ops] = IPP_ANY_OPERATION; else if ((ops[num_ops] = ippOpValue(value)) == IPP_BAD_OPERATION) cupsdLogMessage(CUPSD_LOG_ERROR, - "Bad IPP operation name \"%s\" on line %d.", - value, linenum); + "Bad IPP operation name \"%s\" on line %d of %s.", + value, linenum, ConfigurationFile); else num_ops ++; } else cupsdLogMessage(CUPSD_LOG_ERROR, - "Too many operations listed on line %d.", - linenum); + "Too many operations listed on line %d of %s.", + linenum, ConfigurationFile); for (value = valptr; isspace(*value & 255); value ++); } @@ -3767,7 +3955,7 @@ read_policy(cups_file_t *fp, /* I - Configuration file */ } else if (!value) { - cupsdLogMessage(CUPSD_LOG_ERROR, "Missing value on line %d.", linenum); + cupsdLogMessage(CUPSD_LOG_ERROR, "Missing value on line %d of %s.", linenum, ConfigurationFile); if (FatalErrors & CUPSD_FATAL_CONFIG) return (0); } @@ -3780,7 +3968,7 @@ read_policy(cups_file_t *fp, /* I - Configuration file */ { cupsdLogMessage(CUPSD_LOG_ERROR, "%s directive must appear outside <Limit>...</Limit> " - "on line %d.", line, linenum); + "on line %d of %s.", line, linenum, ConfigurationFile); if (FatalErrors & CUPSD_FATAL_CONFIG) return (0); } @@ -3878,16 +4066,16 @@ read_policy(cups_file_t *fp, /* I - Configuration file */ else if (!op) { cupsdLogMessage(CUPSD_LOG_ERROR, - "Missing <Limit ops> directive before %s on line %d.", - line, linenum); + "Missing <Limit ops> directive before %s on line %d of %s.", + line, linenum, ConfigurationFile); if (FatalErrors & CUPSD_FATAL_CONFIG) return (0); } else if (!parse_aaa(op, line, value, linenum)) { cupsdLogMessage(CUPSD_LOG_ERROR, - "Unknown Policy Limit directive %s on line %d.", - line, linenum); + "Unknown Policy Limit directive %s on line %d of %s.", + line, linenum, ConfigurationFile); if (FatalErrors & CUPSD_FATAL_CONFIG) return (0); @@ -3916,121 +4104,106 @@ set_policy_defaults(cupsd_policy_t *pol)/* I - Policy */ * Verify that we have an explicit policy for Validate-Job, Cancel-Jobs, * Cancel-My-Jobs, Close-Job, and CUPS-Get-Document, which ensures that * upgrades do not introduce new security issues... + * + * CUPS STR #4659: Allow a lone <Limit All> policy. */ - if ((op = cupsdFindPolicyOp(pol, IPP_VALIDATE_JOB)) == NULL || - op->op == IPP_ANY_OPERATION) + if (cupsArrayCount(pol->ops) > 1) { - if ((op = cupsdFindPolicyOp(pol, IPP_PRINT_JOB)) != NULL && - op->op != IPP_ANY_OPERATION) + if ((op = cupsdFindPolicyOp(pol, IPP_VALIDATE_JOB)) == NULL || + op->op == IPP_ANY_OPERATION) { - /* - * Add a new limit for Validate-Job using the Print-Job limit as a - * template... - */ + if ((op = cupsdFindPolicyOp(pol, IPP_PRINT_JOB)) != NULL && + op->op != IPP_ANY_OPERATION) + { + /* + * Add a new limit for Validate-Job using the Print-Job limit as a + * template... + */ - cupsdLogMessage(CUPSD_LOG_WARN, - "No limit for Validate-Job defined in policy %s " - "- using Print-Job's policy.", pol->name); + cupsdLogMessage(CUPSD_LOG_WARN, "No limit for Validate-Job defined in policy %s - using Print-Job's policy.", pol->name); - cupsdAddPolicyOp(pol, op, IPP_VALIDATE_JOB); + cupsdAddPolicyOp(pol, op, IPP_VALIDATE_JOB); + } + else + cupsdLogMessage(CUPSD_LOG_WARN, "No limit for Validate-Job defined in policy %s and no suitable template found.", pol->name); } - else - cupsdLogMessage(CUPSD_LOG_WARN, - "No limit for Validate-Job defined in policy %s " - "and no suitable template found.", pol->name); - } - if ((op = cupsdFindPolicyOp(pol, IPP_CANCEL_JOBS)) == NULL || - op->op == IPP_ANY_OPERATION) - { - if ((op = cupsdFindPolicyOp(pol, IPP_PAUSE_PRINTER)) != NULL && - op->op != IPP_ANY_OPERATION) + if ((op = cupsdFindPolicyOp(pol, IPP_CANCEL_JOBS)) == NULL || + op->op == IPP_ANY_OPERATION) { - /* - * Add a new limit for Cancel-Jobs using the Pause-Printer limit as a - * template... - */ + if ((op = cupsdFindPolicyOp(pol, IPP_PAUSE_PRINTER)) != NULL && + op->op != IPP_ANY_OPERATION) + { + /* + * Add a new limit for Cancel-Jobs using the Pause-Printer limit as a + * template... + */ - cupsdLogMessage(CUPSD_LOG_WARN, - "No limit for Cancel-Jobs defined in policy %s " - "- using Pause-Printer's policy.", pol->name); + cupsdLogMessage(CUPSD_LOG_WARN, "No limit for Cancel-Jobs defined in policy %s - using Pause-Printer's policy.", pol->name); - cupsdAddPolicyOp(pol, op, IPP_CANCEL_JOBS); + cupsdAddPolicyOp(pol, op, IPP_CANCEL_JOBS); + } + else + cupsdLogMessage(CUPSD_LOG_WARN, "No limit for Cancel-Jobs defined in policy %s and no suitable template found.", pol->name); } - else - cupsdLogMessage(CUPSD_LOG_WARN, - "No limit for Cancel-Jobs defined in policy %s " - "and no suitable template found.", pol->name); - } - if ((op = cupsdFindPolicyOp(pol, IPP_CANCEL_MY_JOBS)) == NULL || - op->op == IPP_ANY_OPERATION) - { - if ((op = cupsdFindPolicyOp(pol, IPP_SEND_DOCUMENT)) != NULL && - op->op != IPP_ANY_OPERATION) + if ((op = cupsdFindPolicyOp(pol, IPP_CANCEL_MY_JOBS)) == NULL || + op->op == IPP_ANY_OPERATION) { - /* - * Add a new limit for Cancel-My-Jobs using the Send-Document limit as - * a template... - */ + if ((op = cupsdFindPolicyOp(pol, IPP_SEND_DOCUMENT)) != NULL && + op->op != IPP_ANY_OPERATION) + { + /* + * Add a new limit for Cancel-My-Jobs using the Send-Document limit as + * a template... + */ - cupsdLogMessage(CUPSD_LOG_WARN, - "No limit for Cancel-My-Jobs defined in policy %s " - "- using Send-Document's policy.", pol->name); + cupsdLogMessage(CUPSD_LOG_WARN, "No limit for Cancel-My-Jobs defined in policy %s - using Send-Document's policy.", pol->name); - cupsdAddPolicyOp(pol, op, IPP_CANCEL_MY_JOBS); + cupsdAddPolicyOp(pol, op, IPP_CANCEL_MY_JOBS); + } + else + cupsdLogMessage(CUPSD_LOG_WARN, "No limit for Cancel-My-Jobs defined in policy %s and no suitable template found.", pol->name); } - else - cupsdLogMessage(CUPSD_LOG_WARN, - "No limit for Cancel-My-Jobs defined in policy %s " - "and no suitable template found.", pol->name); - } - if ((op = cupsdFindPolicyOp(pol, IPP_CLOSE_JOB)) == NULL || - op->op == IPP_ANY_OPERATION) - { - if ((op = cupsdFindPolicyOp(pol, IPP_SEND_DOCUMENT)) != NULL && - op->op != IPP_ANY_OPERATION) + if ((op = cupsdFindPolicyOp(pol, IPP_CLOSE_JOB)) == NULL || + op->op == IPP_ANY_OPERATION) { - /* - * Add a new limit for Close-Job using the Send-Document limit as a - * template... - */ + if ((op = cupsdFindPolicyOp(pol, IPP_SEND_DOCUMENT)) != NULL && + op->op != IPP_ANY_OPERATION) + { + /* + * Add a new limit for Close-Job using the Send-Document limit as a + * template... + */ - cupsdLogMessage(CUPSD_LOG_WARN, - "No limit for Close-Job defined in policy %s " - "- using Send-Document's policy.", pol->name); + cupsdLogMessage(CUPSD_LOG_WARN, "No limit for Close-Job defined in policy %s - using Send-Document's policy.", pol->name); - cupsdAddPolicyOp(pol, op, IPP_CLOSE_JOB); + cupsdAddPolicyOp(pol, op, IPP_CLOSE_JOB); + } + else + cupsdLogMessage(CUPSD_LOG_WARN, "No limit for Close-Job defined in policy %s and no suitable template found.", pol->name); } - else - cupsdLogMessage(CUPSD_LOG_WARN, - "No limit for Close-Job defined in policy %s " - "and no suitable template found.", pol->name); - } - if ((op = cupsdFindPolicyOp(pol, CUPS_GET_DOCUMENT)) == NULL || - op->op == IPP_ANY_OPERATION) - { - if ((op = cupsdFindPolicyOp(pol, IPP_SEND_DOCUMENT)) != NULL && - op->op != IPP_ANY_OPERATION) + if ((op = cupsdFindPolicyOp(pol, CUPS_GET_DOCUMENT)) == NULL || + op->op == IPP_ANY_OPERATION) { - /* - * Add a new limit for CUPS-Get-Document using the Send-Document - * limit as a template... - */ + if ((op = cupsdFindPolicyOp(pol, IPP_SEND_DOCUMENT)) != NULL && + op->op != IPP_ANY_OPERATION) + { + /* + * Add a new limit for CUPS-Get-Document using the Send-Document + * limit as a template... + */ - cupsdLogMessage(CUPSD_LOG_WARN, - "No limit for CUPS-Get-Document defined in policy %s " - "- using Send-Document's policy.", pol->name); + cupsdLogMessage(CUPSD_LOG_WARN, "No limit for CUPS-Get-Document defined in policy %s - using Send-Document's policy.", pol->name); - cupsdAddPolicyOp(pol, op, CUPS_GET_DOCUMENT); + cupsdAddPolicyOp(pol, op, CUPS_GET_DOCUMENT); + } + else + cupsdLogMessage(CUPSD_LOG_WARN, "No limit for CUPS-Get-Document defined in policy %s and no suitable template found.", pol->name); } - else - cupsdLogMessage(CUPSD_LOG_WARN, - "No limit for CUPS-Get-Document defined in policy %s " - "and no suitable template found.", pol->name); } /* @@ -4040,18 +4213,14 @@ set_policy_defaults(cupsd_policy_t *pol)/* I - Policy */ if (!pol->job_access) { - cupsdLogMessage(CUPSD_LOG_WARN, - "No JobPrivateAccess defined in policy %s " - "- using defaults.", pol->name); + cupsdLogMessage(CUPSD_LOG_WARN, "No JobPrivateAccess defined in policy %s - using defaults.", pol->name); cupsdAddString(&(pol->job_access), "@OWNER"); cupsdAddString(&(pol->job_access), "@SYSTEM"); } if (!pol->job_attrs) { - cupsdLogMessage(CUPSD_LOG_WARN, - "No JobPrivateValues defined in policy %s " - "- using defaults.", pol->name); + cupsdLogMessage(CUPSD_LOG_WARN, "No JobPrivateValues defined in policy %s - using defaults.", pol->name); cupsdAddString(&(pol->job_attrs), "job-name"); cupsdAddString(&(pol->job_attrs), "job-originating-host-name"); cupsdAddString(&(pol->job_attrs), "job-originating-user-name"); @@ -4060,18 +4229,14 @@ set_policy_defaults(cupsd_policy_t *pol)/* I - Policy */ if (!pol->sub_access) { - cupsdLogMessage(CUPSD_LOG_WARN, - "No SubscriptionPrivateAccess defined in policy %s " - "- using defaults.", pol->name); + cupsdLogMessage(CUPSD_LOG_WARN, "No SubscriptionPrivateAccess defined in policy %s - using defaults.", pol->name); cupsdAddString(&(pol->sub_access), "@OWNER"); cupsdAddString(&(pol->sub_access), "@SYSTEM"); } if (!pol->sub_attrs) { - cupsdLogMessage(CUPSD_LOG_WARN, - "No SubscriptionPrivateValues defined in policy %s " - "- using defaults.", pol->name); + cupsdLogMessage(CUPSD_LOG_WARN, "No SubscriptionPrivateValues defined in policy %s - using defaults.", pol->name); cupsdAddString(&(pol->sub_attrs), "notify-events"); cupsdAddString(&(pol->sub_attrs), "notify-pull-method"); cupsdAddString(&(pol->sub_attrs), "notify-recipient-uri"); @@ -4082,5 +4247,5 @@ set_policy_defaults(cupsd_policy_t *pol)/* I - Policy */ /* - * End of "$Id: conf.c 11221 2013-08-06 16:16:01Z msweet $". + * End of "$Id: conf.c 12819 2015-07-31 13:52:00Z msweet $". */ diff --git a/scheduler/conf.h b/scheduler/conf.h index 8bf0749..59cb157 100644 --- a/scheduler/conf.h +++ b/scheduler/conf.h @@ -1,16 +1,16 @@ /* - * "$Id: conf.h 11221 2013-08-06 16:16:01Z msweet $" + * "$Id: conf.h 12689 2015-06-03 19:49:54Z msweet $" * - * Configuration file definitions for the CUPS scheduler. + * Configuration file definitions for the CUPS scheduler. * - * Copyright 2007-2013 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. + * Copyright 2007-2015 by Apple Inc. + * Copyright 1997-2007 by Easy Software Products, all rights reserved. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ @@ -20,9 +20,10 @@ typedef enum { - CUPSD_LOG_PPD = -4, /* Used internally for PPD keywords */ + CUPSD_LOG_PPD = -5, /* Used internally for PPD keywords */ CUPSD_LOG_ATTR, /* Used internally for attributes */ - CUPSD_LOG_STATE, /* Used internally for state-reasons */ + CUPSD_LOG_STATE, /* Used internally for printer-state-reasons */ + CUPSD_LOG_JOBSTATE, /* Used internally for job-state-reasons */ CUPSD_LOG_PAGE, /* Used internally for page logging */ CUPSD_LOG_NONE, CUPSD_LOG_EMERG, /* Emergency issues */ @@ -38,6 +39,7 @@ typedef enum typedef enum { + CUPSD_ACCESSLOG_NONE, /* Log no requests */ CUPSD_ACCESSLOG_CONFIG, /* Log config requests */ CUPSD_ACCESSLOG_ACTIONS, /* Log config, print, and job management requests */ CUPSD_ACCESSLOG_ALL /* Log everything */ @@ -49,6 +51,13 @@ typedef enum CUPSD_TIME_USECS /* Standard format with microseconds */ } cupsd_time_t; +typedef enum +{ + CUPSD_SANDBOXING_OFF, /* No sandboxing */ + CUPSD_SANDBOXING_RELAXED, /* Relaxed sandboxing */ + CUPSD_SANDBOXING_STRICT /* Strict sandboxing */ +} cupsd_sandboxing_t; + /* * FatalErrors flags... @@ -73,14 +82,6 @@ typedef enum /* - * SSL options (bits)... - */ - -#define CUPSD_SSL_NONE 0 /* No special options */ -#define CUPSD_SSL_NOEMPTY 1 /* Do not insert empty fragments */ - - -/* * ServerAlias data... */ @@ -149,38 +150,44 @@ VAR char *AccessLog VALUE(NULL), /* Temporary directory */ *Printcap VALUE(NULL), /* Printcap file */ - *PrintcapGUI VALUE(NULL), - /* GUI program to use for IRIX */ *FontPath VALUE(NULL), /* Font search path */ *RemoteRoot VALUE(NULL), /* Remote root user */ *Classification VALUE(NULL); /* Classification of system */ -VAR uid_t User VALUE(1); +VAR uid_t User VALUE(1), /* User ID for server */ + RunUser VALUE(0); + /* User to run as, used for files */ VAR gid_t Group VALUE(0); /* Group ID for server */ VAR cupsd_accesslog_t AccessLogLevel VALUE(CUPSD_ACCESSLOG_ACTIONS); /* Access log level */ VAR int ClassifyOverride VALUE(0), /* Allow overrides? */ - ConfigFilePerm VALUE(0640), - /* Permissions for config files */ LogDebugHistory VALUE(200), /* Amount of automatic debug history */ FatalErrors VALUE(CUPSD_FATAL_CONFIG), /* Which errors are fatal? */ StrictConformance VALUE(FALSE), /* Require strict IPP conformance? */ - SyncOnClose VALUE(FALSE), + SyncOnClose VALUE(FALSE); /* Call fsync() when closing files? */ - LogFilePerm VALUE(0644); +VAR mode_t ConfigFilePerm VALUE(0640U), + /* Permissions for config files */ + LogFilePerm VALUE(0644U); /* Permissions for log files */ VAR cupsd_loglevel_t LogLevel VALUE(CUPSD_LOG_WARN); /* Error log level */ VAR cupsd_time_t LogTimeFormat VALUE(CUPSD_TIME_STANDARD); /* Log file time format */ +VAR cups_file_t *LogStderr VALUE(NULL); + /* Stderr file, if any */ +VAR cupsd_sandboxing_t Sandboxing VALUE(CUPSD_SANDBOXING_STRICT); + /* Sandboxing level */ +VAR int UseSandboxing VALUE(1); + /* Use sandboxing for child procs? */ VAR int MaxClients VALUE(100), /* Maximum number of clients */ MaxClientsPerHost VALUE(0), @@ -211,8 +218,6 @@ VAR int MaxClients VALUE(100), /* Timeout before reload from SIGHUP */ RootCertDuration VALUE(300), /* Root certificate update interval */ - RunUser VALUE(0), - /* User to run as, used for files */ PrintcapFormat VALUE(PRINTCAP_BSD), /* Format of printcap file? */ DefaultShared VALUE(TRUE), @@ -237,20 +242,14 @@ VAR const char **MimeTypes VALUE(NULL); /* Array of MIME types */ #ifdef HAVE_SSL -VAR char *ServerCertificate VALUE(NULL); - /* Server certificate file */ -# if defined(HAVE_LIBSSL) || defined(HAVE_GNUTLS) -VAR char *ServerKey VALUE(NULL); - /* Server key file */ -# endif /* HAVE_LIBSSL || HAVE_GNUTLS */ -VAR int SSLOptions VALUE(CUPSD_SSL_NONE); - /* SSL/TLS options */ +VAR char *ServerKeychain VALUE(NULL); + /* Keychain holding cert + key */ #endif /* HAVE_SSL */ -#ifdef HAVE_LAUNCHD -VAR int LaunchdTimeout VALUE(10); +#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) +VAR int IdleExitTimeout VALUE(60); /* Time after which an idle cupsd will exit */ -#endif /* HAVE_LAUNCHD */ +#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ #ifdef HAVE_AUTHORIZATION_H VAR char *SystemGroupAuthKey VALUE(NULL); @@ -273,18 +272,21 @@ gss_cred_id_t ServerCreds; /* Server's GSS credentials */ extern void cupsdAddAlias(cups_array_t *aliases, const char *name); extern int cupsdCheckLogFile(cups_file_t **lf, const char *logname); extern int cupsdCheckPermissions(const char *filename, - const char *suffix, int mode, - int user, int group, int is_dir, + const char *suffix, mode_t mode, + uid_t user, gid_t group, int is_dir, int create_dir); extern int cupsdCheckProgram(const char *filename, cupsd_printer_t *p); extern int cupsdDefaultAuthType(void); extern void cupsdFreeAliases(cups_array_t *aliases); extern char *cupsdGetDateTime(struct timeval *t, cupsd_time_t format); +extern int cupsdLogClient(cupsd_client_t *con, int level, + const char *message, ...) + __attribute__((__format__(__printf__, 3, 4))); extern void cupsdLogFCMessage(void *context, _cups_fc_result_t result, const char *message); #ifdef HAVE_GSSAPI -extern int cupsdLogGSSMessage(int level, int major_status, - int minor_status, +extern int cupsdLogGSSMessage(int level, OM_uint32 major_status, + OM_uint32 minor_status, const char *message, ...); #endif /* HAVE_GSSAPI */ extern int cupsdLogJob(cupsd_job_t *job, int level, const char *message, @@ -298,5 +300,5 @@ extern int cupsdWriteErrorLog(int level, const char *message); /* - * End of "$Id: conf.h 11221 2013-08-06 16:16:01Z msweet $". + * End of "$Id: conf.h 12689 2015-06-03 19:49:54Z msweet $". */ diff --git a/scheduler/cups-deviced.c b/scheduler/cups-deviced.c index 7a5929f..85264ed 100644 --- a/scheduler/cups-deviced.c +++ b/scheduler/cups-deviced.c @@ -1,27 +1,16 @@ /* - * "$Id: cups-deviced.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: cups-deviced.c 11782 2014-03-28 21:03:43Z msweet $" * - * Device scanning mini-daemon for CUPS. + * Device scanning mini-daemon for CUPS. * - * Copyright 2007-2011 by Apple Inc. - * Copyright 1997-2006 by Easy Software Products. + * Copyright 2007-2014 by Apple Inc. + * Copyright 1997-2006 by Easy Software Products. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * main() - Scan for devices and return an IPP response. - * add_device() - Add a new device to the list. - * compare_devices() - Compare device names to eliminate duplicates. - * get_current_time() - Get the current time as a double value in seconds. - * get_device() - Get a device from a backend. - * process_children() - Process all dead children... - * sigchld_handler() - Handle 'child' signals from old processes. - * start_backend() - Run a backend to gather the available devices. + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -82,7 +71,7 @@ static cupsd_backend_t backends[MAX_BACKENDS]; static struct pollfd backend_fds[MAX_BACKENDS]; /* Array for poll() */ static cups_array_t *devices; /* Array of devices */ -static int normal_user; /* Normal user ID */ +static uid_t normal_user; /* Normal user ID */ static int device_limit; /* Maximum number of devices */ static int send_class, /* Send device-class attribute? */ send_info, /* Send device-info attribute? */ @@ -182,7 +171,7 @@ main(int argc, /* I - Number of command-line args */ return (1); } - normal_user = atoi(argv[4]); + normal_user = (uid_t)atoi(argv[4]); if (normal_user <= 0) { fprintf(stderr, "ERROR: [cups-deviced] Bad user %d!\n", normal_user); @@ -281,8 +270,7 @@ main(int argc, /* I - Number of command-line args */ * all others run as the unprivileged user... */ - start_backend(dent->filename, - !(dent->fileinfo.st_mode & (S_IRWXG | S_IRWXO))); + start_backend(dent->filename, !(dent->fileinfo.st_mode & (S_IWGRP | S_IRWXO))); } cupsDirClose(dir); @@ -309,7 +297,7 @@ main(int argc, /* I - Number of command-line args */ timeout = (int)(1000 * (end_time - current_time)); - if (poll(backend_fds, num_backends, timeout) > 0) + if (poll(backend_fds, (nfds_t)num_backends, timeout) > 0) { for (i = 0; i < num_backends; i ++) if (backend_fds[i].revents && backends[i].pipe) @@ -326,8 +314,7 @@ main(int argc, /* I - Number of command-line args */ break; } } - while (bpipe->ptr && - memchr(bpipe->ptr, '\n', bpipe->end - bpipe->ptr)); + while (bpipe->ptr && memchr(bpipe->ptr, '\n', (size_t)(bpipe->end - bpipe->ptr))); } } @@ -806,5 +793,5 @@ start_backend(const char *name, /* I - Backend to run */ /* - * End of "$Id: cups-deviced.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: cups-deviced.c 11782 2014-03-28 21:03:43Z msweet $". */ diff --git a/scheduler/cups-driverd.cxx b/scheduler/cups-driverd.cxx index 4a3d34f..7da6572 100644 --- a/scheduler/cups-driverd.cxx +++ b/scheduler/cups-driverd.cxx @@ -1,48 +1,20 @@ /* - * "$Id: cups-driverd.cxx 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: cups-driverd.cxx 12733 2015-06-12 01:21:05Z msweet $" * - * PPD/driver support for CUPS. + * PPD/driver support for CUPS. * - * This program handles listing and installing static PPD files, PPD files - * created from driver information files, and dynamically generated PPD files - * using driver helper programs. + * This program handles listing and installing static PPD files, PPD files + * created from driver information files, and dynamically generated PPD files + * using driver helper programs. * - * Copyright 2007-2012 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products. + * Copyright 2007-2015 by Apple Inc. + * Copyright 1997-2007 by Easy Software Products. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * main() - Scan for drivers and return an IPP response. - * add_ppd() - Add a PPD file. - * cat_drv() - Generate a PPD from a driver info file. - * cat_ppd() - Copy a PPD file to stdout. - * copy_static() - Copy a static PPD file to stdout. - * cat_tar() - Copy an archived PPD file to stdout. - * compare_inodes() - Compare two inodes. - * compare_matches() - Compare PPD match scores for sorting. - * compare_names() - Compare PPD filenames for sorting. - * compare_ppds() - Compare PPD file make and model names for sorting. - * dump_ppds_dat() - Dump the contents of the ppds.dat file. - * free_array() - Free an array of strings. - * get_file() - Get the filename associated with a request. - * list_ppds() - List PPD files. - * load_drv() - Load the PPDs from a driver information file. - * load_drivers() - Load driver-generated PPD files. - * load_ppd() - Load a PPD file. - * load_ppds() - Load PPD files recursively. - * load_ppds_dat() - Load the ppds.dat file. - * load_tar() - Load archived PPD files. - * read_tar() - Read a file header from an archive. - * regex_device_id() - Compile a regular expression based on the 1284 device - * ID. - * regex_string() - Construct a regular expression to compare a simple - * string. + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -61,7 +33,7 @@ * Constants... */ -#define PPD_SYNC 0x50504437 /* Sync word for ppds.dat (PPD7) */ +#define PPD_SYNC 0x50504438 /* Sync word for ppds.dat (PPD8) */ #define PPD_MAX_LANG 32 /* Maximum languages */ #define PPD_MAX_PROD 32 /* Maximum products */ #define PPD_MAX_VERS 32 /* Maximum versions */ @@ -70,9 +42,12 @@ #define PPD_TYPE_PDF 1 /* PDF PPD */ #define PPD_TYPE_RASTER 2 /* CUPS raster PPD */ #define PPD_TYPE_FAX 3 /* Facsimile/MFD PPD */ -#define PPD_TYPE_UNKNOWN 4 /* Other/hybrid PPD */ -#define PPD_TYPE_DRV 5 /* Driver info file */ -#define PPD_TYPE_ARCHIVE 6 /* Archive file */ +#define PPD_TYPE_OBJECT_ANY 4 /* 3D (AMF/STL/g-code) PPD */ +#define PPD_TYPE_OBJECT_DIRECT 5 /* 3D (AMF/STL/g-code) PPD over any connection */ +#define PPD_TYPE_OBJECT_STORAGE 6 /* 3D (AMF/STL/g-code) PPD for storage to SD card, etc. */ +#define PPD_TYPE_UNKNOWN 7 /* Other/hybrid PPD */ +#define PPD_TYPE_DRV 8 /* Driver info file */ +#define PPD_TYPE_ARCHIVE 9 /* Archive file */ #define TAR_BLOCK 512 /* Number of bytes in a block */ #define TAR_BLOCKS 10 /* Blocking factor */ @@ -163,6 +138,9 @@ static const char * const PPDTypes[] = /* ppd-type values */ "pdf", "raster", "fax", + "object", + "object-direct", + "object-storage", "unknown", "drv", "archive" @@ -291,7 +269,7 @@ add_ppd(const char *filename, /* I - PPD filename */ ppd->found = 1; ppd->record.mtime = mtime; - ppd->record.size = size; + ppd->record.size = (off_t)size; ppd->record.model_number = model_number; ppd->record.type = type; @@ -645,7 +623,7 @@ cat_tar(const char *name, /* I - PPD name */ */ if ((fp = get_file(name, request_id, "model", filename, sizeof(filename), - &ppdname)) == NULL) + &ppdname)) == NULL || !ppdname) return (1); /* @@ -674,7 +652,7 @@ cat_tar(const char *name, /* I - PPD name */ if ((size_t)(bytes = (curinfo.st_size - total)) > sizeof(buffer)) bytes = sizeof(buffer); - if ((bytes = cupsFileRead(fp, buffer, bytes)) < 0) + if ((bytes = cupsFileRead(fp, buffer, (size_t)bytes)) < 0) { if (errno == EINTR || errno == EAGAIN) { @@ -686,7 +664,7 @@ cat_tar(const char *name, /* I - PPD name */ break; } } - else if (bytes > 0 && fwrite(buffer, bytes, 1, stdout) != 1) + else if (bytes > 0 && fwrite(buffer, (size_t)bytes, 1, stdout) != 1) break; } @@ -1053,8 +1031,6 @@ list_ppds(int request_id, /* I - Request ID */ *type_str; /* ppd-type option */ int model_number, /* ppd-model-number value */ type, /* ppd-type value */ - make_and_model_len, /* Length of ppd-make-and-model */ - product_len, /* Length of ppd-product */ send_device_id, /* Send ppd-device-id? */ send_make, /* Send ppd-make? */ send_make_and_model, /* Send ppd-make-and-model? */ @@ -1065,6 +1041,8 @@ list_ppds(int request_id, /* I - Request ID */ send_psversion, /* Send ppd-psversion? */ send_type, /* Send ppd-type? */ sent_header; /* Sent the IPP header? */ + size_t make_and_model_len, /* Length of ppd-make-and-model */ + product_len; /* Length of ppd-product */ regex_t *device_id_re, /* Regular expression for matching device ID */ *make_and_model_re; /* Regular expression for matching make and model */ regmatch_t re_matches[6]; /* Regular expression matches */ @@ -1349,7 +1327,7 @@ list_ppds(int request_id, /* I - Request ID */ if (device_id_re && !regexec(device_id_re, ppd->record.device_id, - (int)(sizeof(re_matches) / sizeof(re_matches[0])), + (size_t)(sizeof(re_matches) / sizeof(re_matches[0])), re_matches, 0)) { /* @@ -1379,13 +1357,13 @@ list_ppds(int request_id, /* I - Request ID */ if (make_and_model_re && !regexec(make_and_model_re, ppd->record.make_and_model, - (int)(sizeof(re_matches) / sizeof(re_matches[0])), + (size_t)(sizeof(re_matches) / sizeof(re_matches[0])), re_matches, 0)) { // See how much of the make-and-model string we matched... if (re_matches[0].rm_so == 0) { - if (re_matches[0].rm_eo == make_and_model_len) + if ((size_t)re_matches[0].rm_eo == make_and_model_len) ppd->matches += 3; // Exact match else ppd->matches += 2; // Prefix match @@ -1637,8 +1615,7 @@ load_drv(const char *filename, /* I - Actual filename */ * Add a dummy entry for the file... */ - add_ppd(name, name, "", "", "", "", "", "", mtime, size, 0, - PPD_TYPE_DRV, "drv"); + add_ppd(name, name, "", "", "", "", "", "", mtime, (size_t)size, 0, PPD_TYPE_DRV, "drv"); ChangedPPD = 1; /* @@ -1696,14 +1673,10 @@ load_drv(const char *filename, /* I - Actual filename */ if (!strcmp(product->name->value, "Product")) { if (!products_found) - ppd = add_ppd(name, uri, "en", d->manufacturer->value, make_model, - device_id ? device_id->value->value : "", - product->value->value, - ps_version ? ps_version->value->value : "(3010) 0", - mtime, size, d->model_number, type, "drv"); + ppd = add_ppd(name, uri, "en", d->manufacturer->value, make_model, device_id ? device_id->value->value : "", product->value->value, + ps_version ? ps_version->value->value : "(3010) 0", mtime, (size_t)size, d->model_number, type, "drv"); else if (products_found < PPD_MAX_PROD) - strlcpy(ppd->record.products[products_found], product->value->value, - sizeof(ppd->record.products[0])); + strlcpy(ppd->record.products[products_found], product->value->value, sizeof(ppd->record.products[0])); else break; @@ -1711,11 +1684,7 @@ load_drv(const char *filename, /* I - Actual filename */ } if (!products_found) - add_ppd(name, uri, "en", d->manufacturer->value, make_model, - device_id ? device_id->value->value : "", - d->model_name->value, - ps_version ? ps_version->value->value : "(3010) 0", - mtime, size, d->model_number, type, "drv"); + add_ppd(name, uri, "en", d->manufacturer->value, make_model, device_id ? device_id->value->value : "", d->model_name->value, ps_version ? ps_version->value->value : "(3010) 0", mtime, (size_t)size, d->model_number, type, "drv"); } src->release(); @@ -1810,7 +1779,7 @@ load_drivers(cups_array_t *include, /* I - Drivers to include */ scheme_end = scheme + strlen(scheme) - 1; if ((scheme_end > scheme && *scheme_end == '*' && - !strncmp(scheme, dent->filename, scheme_end - scheme)) || + !strncmp(scheme, dent->filename, (size_t)(scheme_end - scheme))) || !strcmp(scheme, dent->filename)) { fputs("DEBUG: [cups-driverd] Yes, exclude!\n", stderr); @@ -1837,7 +1806,7 @@ load_drivers(cups_array_t *include, /* I - Drivers to include */ scheme_end = scheme + strlen(scheme) - 1; if ((scheme_end > scheme && *scheme_end == '*' && - !strncmp(scheme, dent->filename, scheme_end - scheme)) || + !strncmp(scheme, dent->filename, (size_t)(scheme_end - scheme))) || !strcmp(scheme, dent->filename)) { fputs("DEBUG: [cups-driverd] Yes, include!\n", stderr); @@ -1877,7 +1846,7 @@ load_drivers(cups_array_t *include, /* I - Drivers to include */ device_id[0] = '\0'; product[0] = '\0'; psversion[0] = '\0'; - strcpy(type_str, "postscript"); + strlcpy(type_str, "postscript", sizeof(type_str)); if (sscanf(line, "\"%511[^\"]\"%127s%*[ \t]\"%127[^\"]\"" "%*[ \t]\"%127[^\"]\"%*[ \t]\"%255[^\"]\"" @@ -2043,7 +2012,7 @@ load_ppd(const char *filename, /* I - Real filename */ manufacturer[0] = '\0'; device_id[0] = '\0'; lang_encoding[0] = '\0'; - strcpy(lang_version, "en"); + strlcpy(lang_version, "en", sizeof(lang_version)); model_number = 0; install_group = 0; type = PPD_TYPE_POSTSCRIPT; @@ -2132,12 +2101,28 @@ load_ppd(const char *filename, /* I - Real filename */ if (!_cups_strncasecmp(ptr, "true", 4)) type = PPD_TYPE_FAX; } - else if (!strncmp(line, "*cupsFilter:", 12) && type == PPD_TYPE_POSTSCRIPT) + else if ((!strncmp(line, "*cupsFilter:", 12) || !strncmp(line, "*cupsFilter2:", 13)) && type == PPD_TYPE_POSTSCRIPT) { if (strstr(line + 12, "application/vnd.cups-raster")) type = PPD_TYPE_RASTER; else if (strstr(line + 12, "application/vnd.cups-pdf")) type = PPD_TYPE_PDF; + else if (strstr(line + 12, "application/amf") || + strstr(line + 12, "application/g-code") || + strstr(line + 12, "application/sla")) + type = PPD_TYPE_OBJECT_ANY; + } + else if (!strncmp(line, "*cups3DWorkflows:", 17)) + { + int is_direct = strstr(line + 17, "direct") != NULL; + int is_storage = strstr(line + 17, "storage") != NULL; + + if (is_direct && !is_storage) + type = PPD_TYPE_OBJECT_DIRECT; + if (!is_direct && is_storage) + type = PPD_TYPE_OBJECT_STORAGE; + else + type = PPD_TYPE_OBJECT_ANY; } else if (!strncmp(line, "*cupsModelNumber:", 17)) sscanf(line, "*cupsModelNumber:%d", &model_number); @@ -2166,7 +2151,7 @@ load_ppd(const char *filename, /* I - Real filename */ cupsCharsetToUTF8((cups_utf8_t *)make_model, nick_name, sizeof(make_model), _ppdGetEncoding(lang_encoding)); else - strcpy(make_model, model_name); + strlcpy(make_model, model_name, sizeof(make_model)); while (isspace(make_model[0] & 255)) _cups_strcpy(make_model, make_model + 1); @@ -2236,13 +2221,13 @@ load_ppd(const char *filename, /* I - Real filename */ if (*ptr && ptr > manufacturer) *ptr = '\0'; else - strcpy(manufacturer, "Other"); + strlcpy(manufacturer, "Other", sizeof(manufacturer)); } else if (!_cups_strncasecmp(manufacturer, "LHAG", 4) || !_cups_strncasecmp(manufacturer, "linotype", 8)) - strcpy(manufacturer, "LHAG"); + strlcpy(manufacturer, "LHAG", sizeof(manufacturer)); else if (!_cups_strncasecmp(manufacturer, "Hewlett", 7)) - strcpy(manufacturer, "HP"); + strlcpy(manufacturer, "HP", sizeof(manufacturer)); /* * Fix the lang_version as needed... @@ -2290,7 +2275,7 @@ load_ppd(const char *filename, /* I - Real filename */ * Unknown language; use "xx"... */ - strcpy(lang_version, "xx"); + strlcpy(lang_version, "xx", sizeof(lang_version)); } /* @@ -2307,11 +2292,7 @@ load_ppd(const char *filename, /* I - Real filename */ fprintf(stderr, "DEBUG2: [cups-driverd] Adding ppd \"%s\"...\n", name); - ppd = add_ppd(name, name, lang_version, manufacturer, make_model, - device_id, (char *)cupsArrayFirst(products), - (char *)cupsArrayFirst(psversions), - fileinfo->st_mtime, fileinfo->st_size, - model_number, type, scheme); + ppd = add_ppd(name, name, lang_version, manufacturer, make_model, device_id, (char *)cupsArrayFirst(products), (char *)cupsArrayFirst(psversions), fileinfo->st_mtime, (size_t)fileinfo->st_size, model_number, type, scheme); if (!ppd) return; @@ -2519,8 +2500,8 @@ load_ppds(const char *d, /* I - Actual directory */ * See if this file has been scanned before... */ - strcpy(key.record.filename, name); - strcpy(key.record.name, name); + strlcpy(key.record.filename, name, sizeof(key.record.filename)); + strlcpy(key.record.name, name, sizeof(key.record.name)); ppd = (ppd_info_t *)cupsArrayFind(PPDsByName, &key); @@ -2634,13 +2615,11 @@ load_ppds_dat(char *filename, /* I - Filename buffer */ unsigned ppdsync; /* Sync word */ int num_ppds; /* Number of PPDs */ - if (cupsFileRead(fp, (char *)&ppdsync, sizeof(ppdsync)) - == sizeof(ppdsync) && + if (cupsFileRead(fp, (char *)&ppdsync, sizeof(ppdsync)) == sizeof(ppdsync) && ppdsync == PPD_SYNC && !stat(filename, &fileinfo) && - ((fileinfo.st_size - sizeof(ppdsync)) % sizeof(ppd_rec_t)) == 0 && - (num_ppds = (fileinfo.st_size - sizeof(ppdsync)) / - sizeof(ppd_rec_t)) > 0) + (((size_t)fileinfo.st_size - sizeof(ppdsync)) % sizeof(ppd_rec_t)) == 0 && + (num_ppds = ((size_t)fileinfo.st_size - sizeof(ppdsync)) / sizeof(ppd_rec_t)) > 0) { /* * We have a ppds.dat file, so read it! @@ -2702,8 +2681,7 @@ load_tar(const char *filename, /* I - Actual filename */ (void)filename; - add_ppd(name, name, "", "", "", "", "", "", mtime, size, 0, - PPD_TYPE_ARCHIVE, "file"); + add_ppd(name, name, "", "", "", "", "", "", mtime, (size_t)size, 0, PPD_TYPE_ARCHIVE, "file"); ChangedPPD = 1; /* @@ -2947,5 +2925,5 @@ regex_string(const char *s) /* I - String to compare */ /* - * End of "$Id: cups-driverd.cxx 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: cups-driverd.cxx 12733 2015-06-12 01:21:05Z msweet $". */ diff --git a/scheduler/cups-exec.c b/scheduler/cups-exec.c index 6d0d3d8..e63b163 100644 --- a/scheduler/cups-exec.c +++ b/scheduler/cups-exec.c @@ -1,23 +1,19 @@ /* - * "$Id: cups-exec.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: cups-exec.c 11817 2014-04-15 16:31:11Z msweet $" * - * Sandbox helper for CUPS. + * Sandbox helper for CUPS. * - * Copyright 2007-2012 by Apple Inc. + * Copyright 2007-2014 by Apple Inc. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". * * Usage: * - * cups-exec /path/to/profile /path/to/program argv0 argv1 ... argvN - * - * Contents: - * - * main() - Apply sandbox profile and execute program. + * cups-exec /path/to/profile [-u UID] [-g GID] [-n NICE] /path/to/program argv0 argv1 ... argvN */ /* @@ -25,7 +21,11 @@ */ #include <cups/string-private.h> +#include <cups/file.h> #include <unistd.h> +#include <fcntl.h> +#include <grp.h> +#include <sys/stat.h> #ifdef HAVE_SANDBOX_H # include <sandbox.h> # ifndef SANDBOX_NAMED_EXTERNAL @@ -36,6 +36,13 @@ /* + * Local functions... + */ + +static void usage(void) __attribute__((noreturn)); + + +/* * 'main()' - Apply sandbox profile and execute program. */ @@ -43,67 +50,157 @@ int /* O - Exit status */ main(int argc, /* I - Number of command-line args */ char *argv[]) /* I - Command-line arguments */ { - int i; /* Looping var */ + int i; /* Looping var */ + const char *opt; /* Current option character */ + uid_t uid = getuid(); /* UID */ + gid_t gid = getgid(); /* GID */ + int niceval = 0; /* Nice value */ #ifdef HAVE_SANDBOX_H - char *sandbox_error = NULL; /* Sandbox error, if any */ + char *sandbox_error = NULL; /* Sandbox error, if any */ #endif /* HAVE_SANDBOX_H */ /* + * Parse command-line... + */ + + for (i = 1; i < argc; i ++) + { + if (argv[i][0] == '-') + { + for (opt = argv[i] + 1; *opt; opt ++) + { + switch (*opt) + { + case 'g' : /* -g gid */ + i ++; + if (i >= argc) + usage(); + + gid = (gid_t)atoi(argv[i]); + break; + + case 'n' : /* -n nice-value */ + i ++; + if (i >= argc) + usage(); + + niceval = atoi(argv[i]); + break; + + case 'u' : /* -g gid */ + i ++; + if (i >= argc) + usage(); + + uid = (uid_t)atoi(argv[i]); + break; + + default : + fprintf(stderr, "cups-exec: Unknown option '-%c'.\n", *opt); + usage(); + } + } + } + else + break; + } + + /* * Check that we have enough arguments... */ - if (argc < 4) + if ((i + 3) > argc) + { + fputs("cups-exec: Insufficient arguments.\n", stderr); + usage(); + } + + /* + * Make sure side and back channel FDs are non-blocking... + */ + + fcntl(3, F_SETFL, O_NDELAY); + fcntl(4, F_SETFL, O_NDELAY); + + /* + * Change UID, GID, and nice value... + */ + + if (uid) + nice(niceval); + + if (!getuid()) { - puts("Usage: cups-exec /path/to/profile /path/to/program argv0 argv1 ... " - "argvN"); - return (1); + if (setgid(gid)) + exit(errno + 100); + + if (setgroups(1, &gid)) + exit(errno + 100); + + if (uid && setuid(uid)) + exit(errno + 100); } + umask(077); + #ifdef HAVE_SANDBOX_H /* * Run in a separate security profile... */ - if (strcmp(argv[1], "none") && - sandbox_init(argv[1], SANDBOX_NAMED_EXTERNAL, &sandbox_error)) + if (strcmp(argv[i], "none") && + sandbox_init(argv[i], SANDBOX_NAMED_EXTERNAL, &sandbox_error)) { + cups_file_t *fp; /* File */ + char line[1024]; /* Line from file */ + int linenum = 0; /* Line number in file */ + fprintf(stderr, "DEBUG: sandbox_init failed: %s (%s)\n", sandbox_error, strerror(errno)); sandbox_free_error(sandbox_error); - return (1); + + if ((fp = cupsFileOpen(argv[i], "r")) != NULL) + { + while (cupsFileGets(fp, line, sizeof(line))) + { + linenum ++; + fprintf(stderr, "DEBUG: %4d %s\n", linenum, line); + } + cupsFileClose(fp); + } + + return (100 + EINVAL); } #endif /* HAVE_SANDBOX_H */ /* - * Close file descriptors we don't need (insurance): - * - * 0 = stdin - * 1 = stdout - * 2 = stderr - * 3 = back-channel - * 4 = side-channel - * 5-N = unused - */ - - for (i = 5; i < 1024; i ++) - close(i); - - /* * Execute the program... */ - execv(argv[2], argv + 3); + execv(argv[i + 1], argv + i + 2); /* * If we get here, execv() failed... */ fprintf(stderr, "DEBUG: execv failed: %s\n", strerror(errno)); - return (1); + return (errno + 100); +} + + +/* + * 'usage()' - Show program usage. + */ + +static void +usage(void) +{ + fputs("Usage: cups-exec [-g gid] [-n nice-value] [-u uid] /path/to/profile /path/to/program argv0 argv1 ... argvN\n", stderr); + exit(1); } /* - * End of "$Id: cups-exec.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: cups-exec.c 11817 2014-04-15 16:31:11Z msweet $". */ diff --git a/scheduler/cups-lpd.c b/scheduler/cups-lpd.c index bd6757b..4748ce0 100644 --- a/scheduler/cups-lpd.c +++ b/scheduler/cups-lpd.c @@ -1,27 +1,16 @@ /* - * "$Id: cups-lpd.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: cups-lpd.c 12611 2015-05-06 15:30:36Z msweet $" * - * Line Printer Daemon interface for CUPS. + * Line Printer Daemon interface for CUPS. * - * Copyright 2007-2012 by Apple Inc. - * Copyright 1997-2006 by Easy Software Products, all rights reserved. + * Copyright 2007-2015 by Apple Inc. + * Copyright 1997-2006 by Easy Software Products, all rights reserved. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * main() - Process an incoming LPD request... - * create_job() - Create a new print job. - * get_printer() - Get the named printer and its options. - * print_file() - Add a file to the current job. - * recv_print_job() - Receive a print job from the client. - * remove_jobs() - Cancel one or more jobs. - * send_state() - Send the queue state. - * smart_gets() - Get a line of text, removing the trailing CR and/or LF. + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -40,6 +29,9 @@ #ifdef HAVE_INTTYPES_H # include <inttypes.h> #endif /* HAVE_INTTYPES_H */ +#ifdef __APPLE__ +# include <vproc.h> +#endif /* __APPLE__ */ /* @@ -70,7 +62,7 @@ static int create_job(http_t *http, const char *dest, const char *title, const char *docname, const char *user, int num_options, cups_option_t *options); static int get_printer(http_t *http, const char *name, char *dest, - int destsize, cups_option_t **options, + size_t destsize, cups_option_t **options, int *accepting, int *shared, ipp_pstate_t *state); static int print_file(http_t *http, int id, const char *filename, const char *docname, const char *user, @@ -107,6 +99,9 @@ main(int argc, /* I - Number of command-line arguments */ hostip[256], /* IP address */ *hostfamily; /* Address family */ int hostlookups; /* Do hostname lookups? */ +#ifdef __APPLE__ + vproc_transaction_t vtran = vproc_transaction_begin(NULL); +#endif /* __APPLE__ */ /* @@ -184,7 +179,7 @@ main(int argc, /* I - Number of command-line arguments */ if (getpeername(0, (struct sockaddr *)&hostaddr, &hostlen)) { syslog(LOG_WARNING, "Unable to get client address - %s", strerror(errno)); - strcpy(hostname, "unknown"); + strlcpy(hostname, "unknown", sizeof(hostname)); } else { @@ -222,6 +217,11 @@ main(int argc, /* I - Number of command-line arguments */ syslog(LOG_ERR, "Unable to get command line from client!"); putchar(1); + +#ifdef __APPLE__ + vproc_transaction_end(NULL, vtran); +#endif /* __APPLE__ */ + return (1); } @@ -230,8 +230,10 @@ main(int argc, /* I - Number of command-line arguments */ * resource list, and/or user name. */ - command = line[0]; - dest = line + 1; + if ((command = line[0]) == '\0') + dest = line; + else + dest = line + 1; if (command == 0x02) list = NULL; @@ -268,21 +270,21 @@ main(int argc, /* I - Number of command-line arguments */ syslog(LOG_INFO, "Receive print job for %s", dest); /* recv_print_job() sends initial status byte */ - status = recv_print_job(dest, num_defaults, defaults); + status = (char)recv_print_job(dest, num_defaults, defaults); break; case 0x03 : /* Send queue state (short) */ syslog(LOG_INFO, "Send queue state (short) for %s %s", dest, list); /* no status byte for this command */ - status = send_state(dest, list, 0); + status = (char)send_state(dest, list, 0); break; case 0x04 : /* Send queue state (long) */ syslog(LOG_INFO, "Send queue state (long) for %s %s", dest, list); /* no status byte for this command */ - status = send_state(dest, list, 1); + status = (char)send_state(dest, list, 1); break; case 0x05 : /* Remove jobs */ @@ -300,7 +302,7 @@ main(int argc, /* I - Number of command-line arguments */ syslog(LOG_INFO, "Remove jobs %s on %s by %s", list, dest, agent); - status = remove_jobs(dest, agent, list); + status = (char)remove_jobs(dest, agent, list); } else status = 1; @@ -312,6 +314,10 @@ main(int argc, /* I - Number of command-line arguments */ syslog(LOG_INFO, "Closing connection"); closelog(); +#ifdef __APPLE__ + vproc_transaction_end(NULL, vtran); +#endif /* __APPLE__ */ + return (status); } @@ -409,7 +415,7 @@ static int /* O - Number of options or -1 on error */ get_printer(http_t *http, /* I - HTTP connection */ const char *name, /* I - Printer name from request */ char *dest, /* I - Destination buffer */ - int destsize, /* I - Size of destination buffer */ + size_t destsize, /* I - Size of destination buffer */ cups_option_t **options, /* O - Printer options */ int *accepting, /* O - printer-is-accepting-jobs value */ int *shared, /* O - printer-is-shared value */ @@ -744,7 +750,7 @@ print_file(http_t *http, /* I - HTTP connection */ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", NULL, format); - ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", last); + ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", (char)last); /* * Do the request... @@ -781,7 +787,8 @@ recv_print_job( int fd; /* Temporary file */ FILE *fp; /* File pointer */ char filename[1024]; /* Temporary filename */ - int bytes; /* Bytes received */ + ssize_t bytes; /* Bytes received */ + size_t total; /* Total bytes */ char line[256], /* Line from file/stdin */ command, /* Command from line */ *count, /* Number of bytes */ @@ -914,7 +921,7 @@ recv_print_job( break; } - strcpy(filename, control); + strlcpy(filename, control, sizeof(filename)); } break; @@ -950,7 +957,7 @@ recv_print_job( break; } - strcpy(filename, temp[num_data]); + strlcpy(filename, temp[num_data], sizeof(filename)); num_data ++; break; @@ -965,15 +972,15 @@ recv_print_job( * Copy the data or control file from the client... */ - for (i = atoi(count); i > 0; i -= bytes) + for (total = (size_t)strtoll(count, NULL, 10); total > 0; total -= (size_t)bytes) { - if (i > sizeof(line)) - bytes = sizeof(line); + if (total > sizeof(line)) + bytes = (ssize_t)sizeof(line); else - bytes = i; + bytes = (ssize_t)total; - if ((bytes = fread(line, 1, bytes, stdin)) > 0) - bytes = write(fd, line, bytes); + if ((bytes = (ssize_t)fread(line, 1, (size_t)bytes, stdin)) > 0) + bytes = write(fd, line, (size_t)bytes); if (bytes < 1) { @@ -1116,7 +1123,7 @@ recv_print_job( { syslog(LOG_WARNING, "No username specified by client! " "Using \"anonymous\"..."); - strcpy(user, "anonymous"); + strlcpy(user, "anonymous", sizeof(user)); } /* @@ -1528,7 +1535,7 @@ send_state(const char *queue, /* I - Destination */ */ if (jobstate == IPP_JOB_PROCESSING) - strcpy(rankstr, "active"); + strlcpy(rankstr, "active", sizeof(rankstr)); else { snprintf(rankstr, sizeof(rankstr), "%d%s", rank, ranks[rank % 10]); @@ -1609,7 +1616,7 @@ smart_gets(char *s, /* I - Pointer to line buffer */ break; } else if (ptr < end) - *ptr++ = ch; + *ptr++ = (char)ch; } *ptr = '\0'; @@ -1622,5 +1629,5 @@ smart_gets(char *s, /* I - Pointer to line buffer */ /* - * End of "$Id: cups-lpd.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: cups-lpd.c 12611 2015-05-06 15:30:36Z msweet $". */ diff --git a/scheduler/cups.sh.in b/scheduler/cups.sh.in index ff72c1c..c50e893 100644 --- a/scheduler/cups.sh.in +++ b/scheduler/cups.sh.in @@ -1,17 +1,17 @@ #!/bin/sh # -# "$Id: cups.sh.in 11173 2013-07-23 12:31:34Z msweet $" +# "$Id: cups.sh.in 11342 2013-10-18 20:36:01Z msweet $" # -# Startup/shutdown script for CUPS. +# Startup/shutdown script for CUPS. # -# Copyright 2007-2011 by Apple Inc. -# Copyright 1997-2007 by Easy Software Products, all rights reserved. +# Copyright 2007-2013 by Apple Inc. +# Copyright 1997-2007 by Easy Software Products, all rights reserved. # -# These coded instructions, statements, and computer programs are the -# property of Apple Inc. and are protected by Federal copyright -# law. Distribution and use rights are outlined in the file "LICENSE.txt" -# which should have been included with this file. If this file is -# file is missing or damaged, see the license at "http://www.cups.org/". +# These coded instructions, statements, and computer programs are the +# property of Apple Inc. and are protected by Federal copyright +# law. Distribution and use rights are outlined in the file "LICENSE.txt" +# which should have been included with this file. If this file is +# file is missing or damaged, see the license at "http://www.cups.org/". # #### OS-Dependent Information @@ -35,18 +35,6 @@ #### OS-Dependent Configuration case "`uname`" in - IRIX*) - IS_ON=/sbin/chkconfig - - if $IS_ON verbose; then - ECHO=echo - else - ECHO=: - fi - ECHO_OK=: - ECHO_ERROR=: - ;; - *BSD*) IS_ON=: ECHO=echo @@ -127,8 +115,7 @@ unset TMPDIR # # Make sure we have the standard program directories in the path -# since some operating systems (this means YOU HP-UX!) don't -# provide a standard path on boot-up... +# since some operating systems don't provide a standard path on boot-up... # if test "x$PATH" = x; then @@ -144,19 +131,9 @@ export PATH # case "`uname`" in - HP-UX* | AIX* | SINIX*) - pid=`ps -e | awk '{if (match($4, ".*/cupsd$") || $4 == "cupsd") print $1}'` - ;; - IRIX* | SunOS*) + SunOS*) pid=`ps -e | nawk '{if (match($4, ".*/cupsd$") || $4 == "cupsd") print $1}'` ;; - UnixWare*) - pid=`ps -e | awk '{if (match($6, ".*/cupsd$") || $6 == "cupsd") print $1}'` - . /etc/TIMEZONE - ;; - OSF1*) - pid=`ps -e | awk '{if (match($5, ".*/cupsd$") || $5 == "cupsd") print $1}'` - ;; Linux* | *BSD* | Darwin*) pid=`ps ax | awk '{if (match($5, ".*/cupsd$") || $5 == "cupsd") print $1}'` ;; @@ -209,16 +186,6 @@ case $1 in fi ;; - start_msg) - # HP-UX non-standard... - echo "Starting CUPS Server" - ;; - - stop_msg) - # HP-UX non-standard... - echo "Starting CUPS Server" - ;; - *) echo "Usage: cups {reload|restart|start|status|stop}" exit 1 @@ -233,5 +200,5 @@ exit 0 # -# End of "$Id: cups.sh.in 11173 2013-07-23 12:31:34Z msweet $". +# End of "$Id: cups.sh.in 11342 2013-10-18 20:36:01Z msweet $". # diff --git a/scheduler/cups.xml.in b/scheduler/cups.xml.in index b76ad02..ac63585 100644 --- a/scheduler/cups.xml.in +++ b/scheduler/cups.xml.in @@ -1,7 +1,7 @@ <?xml version="1.0"?> <!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1"> <!-- - $Id: cups.xml.in 11173 2013-07-23 12:31:34Z msweet $ + $Id: cups.xml.in 2309 2010-07-08 20:45:48Z msweet $ Service manifest for CUPS. diff --git a/scheduler/cupsd.h b/scheduler/cupsd.h index 48ea1d7..f8b2c11 100644 --- a/scheduler/cupsd.h +++ b/scheduler/cupsd.h @@ -1,16 +1,16 @@ /* - * "$Id: cupsd.h 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: cupsd.h 11717 2014-03-21 16:42:53Z msweet $" * - * Main header file for the CUPS scheduler. + * Main header file for the CUPS scheduler. * - * Copyright 2007-2012 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. + * Copyright 2007-2014 by Apple Inc. + * Copyright 1997-2007 by Easy Software Products, all rights reserved. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * "LICENSE" which should have been included with this file. If this - * file is missing or damaged, see the license at "http://www.cups.org/". + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * "LICENSE" which should have been included with this file. If this + * file is missing or damaged, see the license at "http://www.cups.org/". */ @@ -144,10 +144,8 @@ typedef void (*cupsd_selfunc_t)(void *data); * Globals... */ -VAR int TestConfigFile VALUE(0), +VAR int TestConfigFile VALUE(0); /* Test the cupsd.conf file? */ - UseProfiles VALUE(1); - /* Use security profiles for child procs? */ VAR int MaxFDs VALUE(0); /* Maximum number of files */ @@ -160,10 +158,10 @@ VAR int NeedReload VALUE(RELOAD_ALL), VAR void *DefaultProfile VALUE(0); /* Default security profile */ -#ifdef HAVE_LAUNCH_H -VAR int Launchd VALUE(0); - /* Running from launchd */ -#endif /* HAVE_LAUNCH_H */ +#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) +VAR int OnDemand VALUE(0); + /* Launched on demand */ +#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ /* @@ -187,6 +185,7 @@ extern cups_file_t *cupsdCreateConfFile(const char *filename, mode_t mode); extern cups_file_t *cupsdOpenConfFile(const char *filename); extern int cupsdOpenPipe(int *fds); extern int cupsdRemoveFile(const char *filename); +extern int cupsdUnlinkOrRemoveFile(const char *filename); /* main.c */ extern int cupsdAddString(cups_array_t **a, const char *s); @@ -202,11 +201,10 @@ extern void cupsdSetStringf(char **s, const char *f, ...) __attribute__ ((__format__ (__printf__, 2, 3))); /* process.c */ -extern void *cupsdCreateProfile(int job_id); +extern void *cupsdCreateProfile(int job_id, int allow_networking); extern void cupsdDestroyProfile(void *profile); extern int cupsdEndProcess(int pid, int force); -extern const char *cupsdFinishProcess(int pid, char *name, int namelen, - int *job_id); +extern const char *cupsdFinishProcess(int pid, char *name, size_t namelen, int *job_id); extern int cupsdStartProcess(const char *command, char *argv[], char *envp[], int infd, int outfd, int errfd, int backfd, int sidefd, @@ -230,5 +228,5 @@ extern void cupsdStopServer(void); /* - * End of "$Id: cupsd.h 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: cupsd.h 11717 2014-03-21 16:42:53Z msweet $". */ diff --git a/scheduler/cupsfilter.c b/scheduler/cupsfilter.c index 4b471d5..81e159d 100644 --- a/scheduler/cupsfilter.c +++ b/scheduler/cupsfilter.c @@ -1,34 +1,16 @@ /* - * "$Id: cupsfilter.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: cupsfilter.c 12304 2014-12-09 16:16:28Z msweet $" * - * Filtering program for CUPS. + * Filtering program for CUPS. * - * Copyright 2007-2013 by Apple Inc. - * Copyright 1997-2006 by Easy Software Products, all rights reserved. + * Copyright 2007-2014 by Apple Inc. + * Copyright 1997-2006 by Easy Software Products, all rights reserved. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * main() - Main entry for the test program. - * add_printer_filter() - Add a single filters from a PPD file. - * add_printer_filters() - Add filters from a PPD file. - * check_cb() - Callback function for _cupsFileCheck. - * compare_pids() - Compare two filter PIDs... - * escape_options() - Convert an options array to a string. - * exec_filter() - Execute a single filter. - * exec_filters() - Execute filters for the given file and options. - * get_job_file() - Get the specified job file. - * open_pipe() - Create a pipe which is closed on exec. - * read_cupsd_conf() - Read the cupsd.conf file to get the filter - * settings. - * set_string() - Copy and set a string. - * sighandler() - Signal catcher for when we print from stdin... - * usage() - Show program usage... + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -99,7 +81,7 @@ static int exec_filters(mime_type_t *srctype, cups_option_t *options); static void get_job_file(const char *job); static int open_pipe(int *fds); -static int read_cupsd_conf(const char *filename); +static int read_cups_files_conf(const char *filename); static void set_string(char **s, const char *val); static void sighandler(int sig); static void usage(const char *opt) __attribute__((noreturn)); @@ -113,7 +95,8 @@ int /* O - Exit status */ main(int argc, /* I - Number of command-line args */ char *argv[]) /* I - Command-line arguments */ { - int i; /* Looping vars */ + int i, /* Looping vars */ + list_filters = 0; /* Just list the filters? */ const char *command, /* Command name */ *opt, /* Current option */ *printer; /* Printer name */ @@ -129,7 +112,7 @@ main(int argc, /* I - Number of command-line args */ char mimedir[1024]; /* MIME directory */ char *infile, /* File to filter */ *outfile; /* File to create */ - char cupsdconf[1024]; /* cupsd.conf file */ + char cupsfilesconf[1024]; /* cups-files.conf file */ const char *server_root; /* CUPS_SERVERROOT environment variable */ mime_type_t *src, /* Source type */ *dst; /* Destination type */ @@ -173,7 +156,7 @@ main(int argc, /* I - Number of command-line args */ if ((server_root = getenv("CUPS_SERVERROOT")) == NULL) server_root = CUPS_SERVERROOT; - snprintf(cupsdconf, sizeof(cupsdconf), "%s/cupsd.conf", server_root); + snprintf(cupsfilesconf, sizeof(cupsfilesconf), "%s/cups-files.conf", server_root); /* * Process command-line arguments... @@ -182,168 +165,175 @@ main(int argc, /* I - Number of command-line args */ _cupsSetLocale(argv); for (i = 1; i < argc; i ++) + { if (argv[i][0] == '-') { - for (opt = argv[i] + 1; *opt; opt ++) - switch (*opt) + if (!strcmp(argv[i], "--list-filters")) + { + list_filters = 1; + } + else if (!strcmp(argv[i], "--")) + { + i ++; + if (i < argc && !infile) + infile = argv[i]; + else + usage(NULL); + } + else + { + for (opt = argv[i] + 1; *opt; opt ++) { - case '-' : /* Next argument is a filename... */ - i ++; - if (i < argc && !infile) - infile = argv[i]; - else - usage(opt); - break; - - case 'a' : /* Specify option... */ - i ++; - if (i < argc) - num_options = cupsParseOptions(argv[i], num_options, &options); - else - usage(opt); - break; - - case 'c' : /* Specify cupsd.conf file location... */ - i ++; - if (i < argc) - { - if (!strcmp(command, "convert")) - num_options = cupsAddOption("copies", argv[i], num_options, - &options); + switch (*opt) + { + case 'a' : /* Specify option... */ + i ++; + if (i < argc) + num_options = cupsParseOptions(argv[i], num_options, &options); else - strlcpy(cupsdconf, argv[i], sizeof(cupsdconf)); - } - else - usage(opt); - break; - - case 'd' : /* Specify the real printer name */ - i ++; - if (i < argc) - printer = argv[i]; - else - usage(opt); - break; - - case 'D' : /* Delete input file after conversion */ - removeinfile = 1; - break; - - case 'e' : /* Use every filter from the PPD file */ - all_filters = 1; - break; - - case 'f' : /* Specify input file... */ - i ++; - if (i < argc && !infile) - infile = argv[i]; - else - usage(opt); - break; - - case 'i' : /* Specify source MIME type... */ - i ++; - if (i < argc) - { - if (sscanf(argv[i], "%15[^/]/%255s", super, type) != 2) usage(opt); + break; - srctype = argv[i]; - } - else - usage(opt); - break; + case 'c' : /* Specify cups-files.conf file location... */ + i ++; + if (i < argc) + { + if (!strcmp(command, "convert")) + num_options = cupsAddOption("copies", argv[i], num_options, &options); + else + strlcpy(cupsfilesconf, argv[i], sizeof(cupsfilesconf)); + } + else + usage(opt); + break; - case 'j' : /* Get job file or specify destination MIME type... */ - if (strcmp(command, "convert")) - { - i ++; + case 'd' : /* Specify the real printer name */ + i ++; + if (i < argc) + printer = argv[i]; + else + usage(opt); + break; + + case 'D' : /* Delete input file after conversion */ + removeinfile = 1; + break; + + case 'e' : /* Use every filter from the PPD file */ + all_filters = 1; + break; + + case 'f' : /* Specify input file... */ + i ++; + if (i < argc && !infile) + infile = argv[i]; + else + usage(opt); + break; + + case 'i' : /* Specify source MIME type... */ + i ++; if (i < argc) { - get_job_file(argv[i]); - infile = TempFile; + if (sscanf(argv[i], "%15[^/]/%255s", super, type) != 2) + usage(opt); + + srctype = argv[i]; } else usage(opt); + break; + + case 'j' : /* Get job file or specify destination MIME type... */ + if (strcmp(command, "convert")) + { + i ++; + if (i < argc) + { + get_job_file(argv[i]); + infile = TempFile; + } + else + usage(opt); - break; - } + break; + } + + case 'm' : /* Specify destination MIME type... */ + i ++; + if (i < argc) + { + if (sscanf(argv[i], "%15[^/]/%255s", super, type) != 2) + usage(opt); - case 'm' : /* Specify destination MIME type... */ - i ++; - if (i < argc) - { - if (sscanf(argv[i], "%15[^/]/%255s", super, type) != 2) + dsttype = argv[i]; + } + else usage(opt); + break; - dsttype = argv[i]; - } - else - usage(opt); - break; - - case 'n' : /* Specify number of copies... */ - i ++; - if (i < argc) - num_options = cupsAddOption("copies", argv[i], num_options, - &options); - else - usage(opt); - break; - - case 'o' : /* Specify option(s) or output filename */ - i ++; - if (i < argc) - { - if (!strcmp(command, "convert")) + case 'n' : /* Specify number of copies... */ + i ++; + if (i < argc) + num_options = cupsAddOption("copies", argv[i], num_options, &options); + else + usage(opt); + break; + + case 'o' : /* Specify option(s) or output filename */ + i ++; + if (i < argc) { - if (outfile) - usage(NULL); + if (!strcmp(command, "convert")) + { + if (outfile) + usage(NULL); + else + outfile = argv[i]; + } else - outfile = argv[i]; + num_options = cupsParseOptions(argv[i], num_options, &options); } else - num_options = cupsParseOptions(argv[i], num_options, - &options); - } - else - usage(opt); - break; - - case 'p' : /* Specify PPD file... */ - case 'P' : /* Specify PPD file... */ - i ++; - if (i < argc) - ppdfile = argv[i]; - else - usage(opt); - break; - - case 't' : /* Specify title... */ - case 'J' : /* Specify title... */ - i ++; - if (i < argc) - title = argv[i]; - else - usage(opt); - break; - - case 'u' : /* Delete PPD file after conversion */ - removeppd = 1; - break; - - case 'U' : /* Specify username... */ - i ++; - if (i < argc) - user = argv[i]; - else - usage(opt); - break; - - default : /* Something we don't understand... */ - usage(opt); - break; + usage(opt); + break; + + case 'p' : /* Specify PPD file... */ + case 'P' : /* Specify PPD file... */ + i ++; + if (i < argc) + ppdfile = argv[i]; + else + usage(opt); + break; + + case 't' : /* Specify title... */ + case 'J' : /* Specify title... */ + i ++; + if (i < argc) + title = argv[i]; + else + usage(opt); + break; + + case 'u' : /* Delete PPD file after conversion */ + removeppd = 1; + break; + + case 'U' : /* Specify username... */ + i ++; + if (i < argc) + user = argv[i]; + else + usage(opt); + break; + + default : /* Something we don't understand... */ + usage(opt); + break; + } } + } } else if (!infile) { @@ -358,6 +348,7 @@ main(int argc, /* I - Number of command-line args */ _("cupsfilter: Only one filename can be specified.")); usage(NULL); } + } if (!infile && !srctype) usage(NULL); @@ -373,10 +364,10 @@ main(int argc, /* I - Number of command-line args */ } /* - * Load the cupsd.conf file and create the MIME database... + * Load the cups-files.conf file and create the MIME database... */ - if (read_cupsd_conf(cupsdconf)) + if (read_cups_files_conf(cupsfilesconf)) return (1); snprintf(mimedir, sizeof(mimedir), "%s/mime", DataDir); @@ -491,12 +482,31 @@ main(int argc, /* I - Number of command-line args */ filters = prefilters; } - /* - * Do it! - */ + if (list_filters) + { + /* + * List filters... + */ + + mime_filter_t *filter; /* Current filter */ - status = exec_filters(src, filters, infile, outfile, ppdfile, printer, user, - title, num_options, options); + for (filter = (mime_filter_t *)cupsArrayFirst(filters); + filter; + filter = (mime_filter_t *)cupsArrayNext(filters)) + if (strcmp(filter->filter, "-")) + _cupsLangPuts(stdout, filter->filter); + + status = 0; + } + else + { + /* + * Run filters... + */ + + status = exec_filters(src, filters, infile, outfile, ppdfile, printer, user, + title, num_options, options); + } /* * Remove files as needed, then exit... @@ -576,7 +586,7 @@ add_printer_filter( { char *ptr; /* Pointer into maxsize(nnnn) program */ - maxsize = strtoll(program + 8, &ptr, 10); + maxsize = (size_t)strtoll(program + 8, &ptr, 10); if (*ptr != ')') { @@ -745,7 +755,7 @@ escape_options( { int i; /* Looping var */ cups_option_t *option; /* Current option */ - int bytes; /* Number of bytes needed */ + size_t bytes; /* Number of bytes needed */ char *s, /* Option string */ *sptr, /* Pointer into string */ *vptr; /* Pointer into value */ @@ -773,7 +783,7 @@ escape_options( if (sptr > s) *sptr++ = ' '; - strcpy(sptr, option->name); + strlcpy(sptr, option->name, bytes - (size_t)(sptr - s)); sptr += strlen(sptr); *sptr++ = '='; @@ -917,7 +927,7 @@ exec_filters(mime_type_t *srctype, /* I - Source type */ { int i; /* Looping var */ const char *argv[8], /* Command-line arguments */ - *envp[16], /* Environment variables */ + *envp[17], /* Environment variables */ *temp; /* Temporary string */ char *optstr, /* Filter options */ content_type[1024], /* CONTENT_TYPE */ @@ -925,6 +935,8 @@ exec_filters(mime_type_t *srctype, /* I - Source type */ cups_fontpath[1024], /* CUPS_FONTPATH */ cups_serverbin[1024], /* CUPS_SERVERBIN */ cups_serverroot[1024], /* CUPS_SERVERROOT */ + final_content_type[1024] = "", + /* FINAL_CONTENT_TYPE */ lang[1024], /* LANG */ path[1024], /* PATH */ ppd[1024], /* PPD */ @@ -948,6 +960,39 @@ exec_filters(mime_type_t *srctype, /* I - Source type */ /* + * Figure out the final content type... + */ + + for (filter = (mime_filter_t *)cupsArrayLast(filters); + filter && filter->dst; + filter = (mime_filter_t *)cupsArrayPrev(filters)) + if (strcmp(filter->dst->super, "printer")) + break; + + if (filter && filter->dst) + { + const char *ptr; /* Pointer in type name */ + + if ((ptr = strchr(filter->dst->type, '/')) != NULL) + snprintf(final_content_type, sizeof(final_content_type), + "FINAL_CONTENT_TYPE=%s", ptr + 1); + else + snprintf(final_content_type, sizeof(final_content_type), + "FINAL_CONTENT_TYPE=%s/%s", filter->dst->super, + filter->dst->type); + } + + /* + * Remove NULL ("-") filters... + */ + + for (filter = (mime_filter_t *)cupsArrayFirst(filters); + filter; + filter = (mime_filter_t *)cupsArrayNext(filters)) + if (!strcmp(filter->filter, "-")) + cupsArrayRemove(filters, filter); + + /* * Setup the filter environment and command-line... */ @@ -1041,7 +1086,13 @@ exec_filters(mime_type_t *srctype, /* I - Source type */ envp[12] = rip_max_cache; envp[13] = userenv; envp[14] = "CHARSET=utf-8"; - envp[15] = NULL; + if (final_content_type[0]) + { + envp[15] = final_content_type; + envp[16] = NULL; + } + else + envp[15] = NULL; for (i = 0; argv[i]; i ++) fprintf(stderr, "DEBUG: argv[%d]=\"%s\"\n", i, argv[i]); @@ -1313,13 +1364,14 @@ open_pipe(int *fds) /* O - Pipe file descriptors (2) */ /* - * 'read_cupsd_conf()' - Read the cupsd.conf file to get the filter settings. + * 'read_cups_files_conf()' - Read the cups-files.conf file to get the filter settings. */ static int /* O - 0 on success, 1 on error */ -read_cupsd_conf(const char *filename) /* I - File to read */ +read_cups_files_conf( + const char *filename) /* I - File to read */ { - cups_file_t *fp; /* cupsd.conf file */ + cups_file_t *fp; /* cups-files.conf file */ const char *temp; /* Temporary string */ char line[1024], /* Line from file */ *ptr; /* Pointer into line */ @@ -1372,9 +1424,7 @@ read_cupsd_conf(const char *filename) /* I - File to read */ cupsFileClose(fp); } - snprintf(line, sizeof(line), - "%s/filter:" CUPS_BINDIR ":" CUPS_SBINDIR ":/bin:/usr/bin", - ServerBin); + snprintf(line, sizeof(line), "%s/filter:" CUPS_BINDIR ":" CUPS_SBINDIR ":/bin:/usr/bin", ServerBin); set_string(&Path, line); return (0); @@ -1426,38 +1476,30 @@ static void usage(const char *opt) /* I - Incorrect option, if any */ { if (opt) - _cupsLangPrintf(stderr, _("%s: Unknown option \"%c\"."), "cupsfilter", - *opt); + _cupsLangPrintf(stderr, _("%s: Unknown option \"%c\"."), "cupsfilter", *opt); - _cupsLangPuts(stdout, _("Usage: cupsfilter [ options ] filename")); + _cupsLangPuts(stdout, _("Usage: cupsfilter [ options ] [ -- ] filename")); _cupsLangPuts(stdout, _("Options:")); - _cupsLangPuts(stdout, _(" -D Remove the input file " - "when finished.")); + _cupsLangPuts(stdout, _(" --list-filters List filters that will be used.")); + _cupsLangPuts(stdout, _(" -D Remove the input file when finished.")); _cupsLangPuts(stdout, _(" -P filename.ppd Set PPD file.")); _cupsLangPuts(stdout, _(" -U username Specify username.")); - _cupsLangPuts(stdout, _(" -c cupsd.conf Set cupsd.conf file to " - "use.")); - _cupsLangPuts(stdout, _(" -d printer Use the named " - "printer.")); - _cupsLangPuts(stdout, _(" -e Use every filter from " - "the PPD file.")); - _cupsLangPuts(stdout, _(" -i mime/type Set input MIME type " - "(otherwise auto-typed).")); - _cupsLangPuts(stdout, _(" -j job-id[,N] Filter file N from the " - "specified job (default is file 1).")); - _cupsLangPuts(stdout, _(" -m mime/type Set output MIME type " - "(otherwise application/pdf).")); + _cupsLangPuts(stdout, _(" -c cups-files.conf Set cups-files.conf file to use.")); + _cupsLangPuts(stdout, _(" -d printer Use the named printer.")); + _cupsLangPuts(stdout, _(" -e Use every filter from the PPD file.")); + _cupsLangPuts(stdout, _(" -i mime/type Set input MIME type (otherwise auto-typed).")); + _cupsLangPuts(stdout, _(" -j job-id[,N] Filter file N from the specified job (default is file 1).")); + _cupsLangPuts(stdout, _(" -m mime/type Set output MIME type (otherwise application/pdf).")); _cupsLangPuts(stdout, _(" -n copies Set number of copies.")); _cupsLangPuts(stdout, _(" -o name=value Set option(s).")); _cupsLangPuts(stdout, _(" -p filename.ppd Set PPD file.")); _cupsLangPuts(stdout, _(" -t title Set title.")); - _cupsLangPuts(stdout, _(" -u Remove the PPD file " - "when finished.")); + _cupsLangPuts(stdout, _(" -u Remove the PPD file when finished.")); exit(1); } /* - * End of "$Id: cupsfilter.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: cupsfilter.c 12304 2014-12-09 16:16:28Z msweet $". */ diff --git a/scheduler/dirsvc.c b/scheduler/dirsvc.c index bce0d64..54a08e2 100644 --- a/scheduler/dirsvc.c +++ b/scheduler/dirsvc.c @@ -1,46 +1,16 @@ /* - * "$Id: dirsvc.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: dirsvc.c 12458 2015-01-30 16:15:53Z msweet $" * - * Directory services routines for the CUPS scheduler. + * Directory services routines for the CUPS scheduler. * - * Copyright 2007-2012 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. + * Copyright 2007-2015 by Apple Inc. + * Copyright 1997-2007 by Easy Software Products, all rights reserved. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * cupsdDeregisterPrinter() - Stop sending broadcast information for a local - * printer and remove any pending references to - * remote printers. - * cupsdRegisterPrinter() - Start sending broadcast information for a - * printer or update the broadcast contents. - * cupsdStartBrowsing() - Start sending and receiving broadcast - * information. - * cupsdStopBrowsing() - Stop sending and receiving broadcast - * information. - * cupsdUpdateDNSSDName() - Update the computer name we use for - * browsing... - * dnssdAddAlias() - Add a DNS-SD alias name. - * dnssdBuildTxtRecord() - Build a TXT record from printer info. - * dnssdDeregisterInstance() - Deregister a DNS-SD service instance. - * dnssdDeregisterPrinter() - Deregister all services for a printer. - * dnssdErrorString() - Return an error string for an error code. - * dnssdRegisterCallback() - Free a TXT record. - * dnssdRegisterCallback() - DNSServiceRegister callback. - * dnssdRegisterInstance() - Register an instance of a printer service. - * dnssdRegisterPrinter() - Start sending broadcast information for a - * printer or update the broadcast contents. - * dnssdStop() - Stop all DNS-SD registrations. - * dnssdUpdate() - Handle DNS-SD queries. - * get_auth_info_required() - Get the auth-info-required value to advertise. - * get_hostconfig() - Get an /etc/hostconfig service setting. - * update_lpd() - Update the LPD configuration as needed. - * update_smb() - Update the SMB configuration as needed. + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -58,6 +28,15 @@ /* + * Local globals... + */ + +#ifdef HAVE_AVAHI +static int avahi_running = 0; +#endif /* HAVE_AVAHI */ + + +/* * Local functions... */ @@ -78,11 +57,15 @@ static void dnssdAddAlias(const void *key, const void *value, void *context); # endif /* __APPLE__ */ static cupsd_txt_t dnssdBuildTxtRecord(cupsd_printer_t *p, int for_lpd); -static void dnssdDeregisterInstance(cupsd_srv_t *srv); -static void dnssdDeregisterPrinter(cupsd_printer_t *p, - int clear_name); +# ifdef HAVE_AVAHI +static void dnssdClientCallback(AvahiClient *c, AvahiClientState state, void *userdata); +# endif /* HAVE_AVAHI */ +static void dnssdDeregisterAllPrinters(int from_callback); +static void dnssdDeregisterInstance(cupsd_srv_t *srv, int from_callback); +static void dnssdDeregisterPrinter(cupsd_printer_t *p, int clear_name, int from_callback); static const char *dnssdErrorString(int error); static void dnssdFreeTxtRecord(cupsd_txt_t *txt); +static void dnssdRegisterAllPrinters(int from_callback); # ifdef HAVE_DNSSD static void dnssdRegisterCallback(DNSServiceRef sdRef, DNSServiceFlags flags, @@ -96,16 +79,13 @@ static void dnssdRegisterCallback(AvahiEntryGroup *p, AvahiEntryGroupState state, void *context); # endif /* HAVE_DNSSD */ -static int dnssdRegisterInstance(cupsd_srv_t *srv, - cupsd_printer_t *p, - char *name, const char *type, - const char *subtypes, int port, - cupsd_txt_t *txt, int commit); -static void dnssdRegisterPrinter(cupsd_printer_t *p); +static int dnssdRegisterInstance(cupsd_srv_t *srv, cupsd_printer_t *p, char *name, const char *type, const char *subtypes, int port, cupsd_txt_t *txt, int commit, int from_callback); +static void dnssdRegisterPrinter(cupsd_printer_t *p, int from_callback); static void dnssdStop(void); # ifdef HAVE_DNSSD static void dnssdUpdate(void); # endif /* HAVE_DNSSD */ +static void dnssdUpdateDNSSDName(int from_callback); #endif /* HAVE_DNSSD || HAVE_AVAHI */ @@ -138,7 +118,7 @@ cupsdDeregisterPrinter( #if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) if (removeit && (BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDMaster) - dnssdDeregisterPrinter(p, 1); + dnssdDeregisterPrinter(p, 1, 0); #endif /* HAVE_DNSSD || HAVE_AVAHI */ } @@ -160,7 +140,7 @@ cupsdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */ #if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) if ((BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDMaster) - dnssdRegisterPrinter(p); + dnssdRegisterPrinter(p, 0); #endif /* HAVE_DNSSD || HAVE_AVAHI */ } @@ -172,16 +152,12 @@ cupsdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */ void cupsdStartBrowsing(void) { - cupsd_printer_t *p; /* Current printer */ - - if (!Browsing || !BrowseLocalProtocols) return; #if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) if (BrowseLocalProtocols & BROWSE_DNSSD) { - cupsd_listener_t *lis; /* Current listening socket */ # ifdef HAVE_DNSSD DNSServiceErrorType error; /* Error from service creation */ @@ -211,6 +187,13 @@ cupsdStartBrowsing(void) cupsdAddSelect(fd, (cupsd_selfunc_t)dnssdUpdate, NULL, NULL); } + /* + * Set the computer name and register the web interface... + */ + + DNSSDPort = 0; + cupsdUpdateDNSSDName(); + # else /* HAVE_AVAHI */ if ((DNSSDMaster = avahi_threaded_poll_new()) == NULL) { @@ -223,8 +206,7 @@ cupsdStartBrowsing(void) { int error; /* Error code, if any */ - DNSSDClient = avahi_client_new(avahi_threaded_poll_get(DNSSDMaster), 0, - NULL, NULL, &error); + DNSSDClient = avahi_client_new(avahi_threaded_poll_get(DNSSDMaster), AVAHI_CLIENT_NO_FAIL, dnssdClientCallback, NULL, &error); if (DNSSDClient == NULL) { @@ -242,31 +224,6 @@ cupsdStartBrowsing(void) avahi_threaded_poll_start(DNSSDMaster); } # endif /* HAVE_DNSSD */ - - /* - * Then get the port we use for registrations. If we are not listening - * on any non-local ports, there is no sense sharing local printers via - * Bonjour... - */ - - DNSSDPort = 0; - - for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); - lis; - lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) - { - if (httpAddrLocalhost(&(lis->address))) - continue; - - DNSSDPort = _httpAddrPort(&(lis->address)); - break; - } - - /* - * Set the computer name and register the web interface... - */ - - cupsdUpdateDNSSDName(); } #endif /* HAVE_DNSSD || HAVE_AVAHI */ @@ -280,15 +237,13 @@ cupsdStartBrowsing(void) if (BrowseLocalProtocols & BROWSE_SMB) update_smb(1); +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) /* * Register the individual printers */ - for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); - p; - p = (cupsd_printer_t *)cupsArrayNext(Printers)) - if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_SCANNER))) - cupsdRegisterPrinter(p); + dnssdRegisterAllPrinters(0); +#endif /* HAVE_DNSSD || HAVE_AVAHI */ } @@ -299,27 +254,20 @@ cupsdStartBrowsing(void) void cupsdStopBrowsing(void) { - cupsd_printer_t *p; /* Current printer */ - - if (!Browsing || !BrowseLocalProtocols) return; +#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) /* * De-register the individual printers */ - for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); - p; - p = (cupsd_printer_t *)cupsArrayNext(Printers)) - if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_SCANNER))) - cupsdDeregisterPrinter(p, 1); + dnssdDeregisterAllPrinters(0); /* * Shut down browsing sockets... */ -#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) if ((BrowseLocalProtocols & BROWSE_DNSSD) && DNSSDMaster) dnssdStop(); #endif /* HAVE_DNSSD || HAVE_AVAHI */ @@ -344,161 +292,7 @@ cupsdStopBrowsing(void) void cupsdUpdateDNSSDName(void) { - char webif[1024]; /* Web interface share name */ -# ifdef __APPLE__ - SCDynamicStoreRef sc; /* Context for dynamic store */ - CFDictionaryRef btmm; /* Back-to-My-Mac domains */ - CFStringEncoding nameEncoding; /* Encoding of computer name */ - CFStringRef nameRef; /* Host name CFString */ - char nameBuffer[1024]; /* C-string buffer */ -# endif /* __APPLE__ */ - - - /* - * Only share the web interface and printers when non-local listening is - * enabled... - */ - - if (!DNSSDPort) - return; - - /* - * Get the computer name as a c-string... - */ - -# ifdef __APPLE__ - sc = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("cupsd"), NULL, NULL); - - if (sc) - { - /* - * Get the computer name from the dynamic store... - */ - - cupsdClearString(&DNSSDComputerName); - - if ((nameRef = SCDynamicStoreCopyComputerName(sc, &nameEncoding)) != NULL) - { - if (CFStringGetCString(nameRef, nameBuffer, sizeof(nameBuffer), - kCFStringEncodingUTF8)) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Dynamic store computer name is \"%s\".", nameBuffer); - cupsdSetString(&DNSSDComputerName, nameBuffer); - } - - CFRelease(nameRef); - } - - if (!DNSSDComputerName) - { - /* - * Use the ServerName instead... - */ - - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Using ServerName \"%s\" as computer name.", ServerName); - cupsdSetString(&DNSSDComputerName, ServerName); - } - - /* - * Get the local hostname from the dynamic store... - */ - - cupsdClearString(&DNSSDHostName); - - if ((nameRef = SCDynamicStoreCopyLocalHostName(sc)) != NULL) - { - if (CFStringGetCString(nameRef, nameBuffer, sizeof(nameBuffer), - kCFStringEncodingUTF8)) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Dynamic store host name is \"%s\".", nameBuffer); - cupsdSetString(&DNSSDHostName, nameBuffer); - } - - CFRelease(nameRef); - } - - if (!DNSSDHostName) - { - /* - * Use the ServerName instead... - */ - - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Using ServerName \"%s\" as host name.", ServerName); - cupsdSetString(&DNSSDHostName, ServerName); - } - - /* - * Get any Back-to-My-Mac domains and add them as aliases... - */ - - cupsdFreeAliases(DNSSDAlias); - DNSSDAlias = NULL; - - btmm = SCDynamicStoreCopyValue(sc, CFSTR("Setup:/Network/BackToMyMac")); - if (btmm && CFGetTypeID(btmm) == CFDictionaryGetTypeID()) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, "%d Back to My Mac aliases to add.", - (int)CFDictionaryGetCount(btmm)); - CFDictionaryApplyFunction(btmm, dnssdAddAlias, NULL); - } - else if (btmm) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Bad Back to My Mac data in dynamic store!"); - else - cupsdLogMessage(CUPSD_LOG_DEBUG, "No Back to My Mac aliases to add."); - - if (btmm) - CFRelease(btmm); - - CFRelease(sc); - } - else -# endif /* __APPLE__ */ -# ifdef HAVE_AVAHI - if (DNSSDClient) - { - const char *host_name = avahi_client_get_host_name(DNSSDClient); - const char *host_fqdn = avahi_client_get_host_name_fqdn(DNSSDClient); - - cupsdSetString(&DNSSDComputerName, host_name ? host_name : ServerName); - - if (host_fqdn) - cupsdSetString(&DNSSDHostName, host_fqdn); - else if (strchr(ServerName, '.')) - cupsdSetString(&DNSSDHostName, ServerName); - else - cupsdSetStringf(&DNSSDHostName, "%s.local", ServerName); - } - else -# endif /* HAVE_AVAHI */ - { - cupsdSetString(&DNSSDComputerName, ServerName); - - if (strchr(ServerName, '.')) - cupsdSetString(&DNSSDHostName, ServerName); - else - cupsdSetStringf(&DNSSDHostName, "%s.local", ServerName); - } - - /* - * Then (re)register the web interface if enabled... - */ - - if (BrowseWebIF) - { - if (DNSSDComputerName) - snprintf(webif, sizeof(webif), "CUPS @ %s", DNSSDComputerName); - else - strlcpy(webif, "CUPS", sizeof(webif)); - - dnssdDeregisterInstance(&WebIFSrv); - dnssdRegisterInstance(&WebIFSrv, NULL, webif, "_http._tcp", "_printer", - DNSSDPort, NULL, 1); - } + dnssdUpdateDNSSDName(0); } @@ -639,7 +433,9 @@ dnssdBuildTxtRecord( if (p->type & CUPS_PRINTER_FAX) { keyvalue[count ][0] = "Fax"; - keyvalue[count++][1] = (p->type & CUPS_PRINTER_FAX) ? "T" : "F"; + keyvalue[count++][1] = "T"; + keyvalue[count ][0] = "rfo"; + keyvalue[count++][1] = rp_str; } if (p->type & CUPS_PRINTER_COLOR) @@ -731,24 +527,158 @@ dnssdBuildTxtRecord( } +# ifdef HAVE_AVAHI +/* + * 'dnssdClientCallback()' - Client callback for Avahi. + * + * Called whenever the client or server state changes... + */ + +static void +dnssdClientCallback( + AvahiClient *c, /* I - Client */ + AvahiClientState state, /* I - Current state */ + void *userdata) /* I - User data (unused) */ +{ + int error; /* Error code, if any */ + + + (void)userdata; + + if (!c) + return; + + /* + * Make sure DNSSDClient is already set also if this callback function is + * already running before avahi_client_new() in dnssdStartBrowsing() + * finishes. + */ + + if (!DNSSDClient) + DNSSDClient = c; + + switch (state) + { + case AVAHI_CLIENT_S_REGISTERING: + case AVAHI_CLIENT_S_RUNNING: + case AVAHI_CLIENT_S_COLLISION: + cupsdLogMessage(CUPSD_LOG_DEBUG, "Avahi server connection now available, registering printers for Bonjour broadcasting."); + + /* + * Mark that Avahi server is running... + */ + + avahi_running = 1; + + /* + * Set the computer name and register the web interface... + */ + + DNSSDPort = 0; + dnssdUpdateDNSSDName(1); + + /* + * Register the individual printers + */ + + dnssdRegisterAllPrinters(1); + break; + + case AVAHI_CLIENT_FAILURE: + if (avahi_client_errno(c) == AVAHI_ERR_DISCONNECTED) + { + cupsdLogMessage(CUPSD_LOG_DEBUG, "Avahi server disappeared, unregistering printers for Bonjour broadcasting."); + + /* + * Unregister everything and close the client... + */ + + dnssdDeregisterAllPrinters(1); + dnssdDeregisterInstance(&WebIFSrv, 1); + avahi_client_free(DNSSDClient); + DNSSDClient = NULL; + + /* + * Mark that Avahi server is not running... + */ + + avahi_running = 0; + + /* + * Renew Avahi client... + */ + + DNSSDClient = avahi_client_new(avahi_threaded_poll_get(DNSSDMaster), AVAHI_CLIENT_NO_FAIL, dnssdClientCallback, NULL, &error); + + if (!DNSSDClient) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to communicate with avahi-daemon: %s", dnssdErrorString(error)); + if (FatalErrors & CUPSD_FATAL_BROWSE) + cupsdEndProcess(getpid(), 0); + } + } + else + { + cupsdLogMessage(CUPSD_LOG_ERROR, "Communication with avahi-daemon has failed: %s", avahi_strerror(avahi_client_errno(c))); + if (FatalErrors & CUPSD_FATAL_BROWSE) + cupsdEndProcess(getpid(), 0); + } + break; + + default: + break; + } +} +# endif /* HAVE_AVAHI */ + + +/* + * 'dnssdDeregisterAllPrinters()' - Deregister all printers. + */ + +static void +dnssdDeregisterAllPrinters( + int from_callback) /* I - Deregistering because of callback? */ +{ + cupsd_printer_t *p; /* Current printer */ + + + if (!DNSSDMaster) + return; + + for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); + p; + p = (cupsd_printer_t *)cupsArrayNext(Printers)) + if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_SCANNER))) + dnssdDeregisterPrinter(p, 1, from_callback); +} + + /* * 'dnssdDeregisterInstance()' - Deregister a DNS-SD service instance. */ static void dnssdDeregisterInstance( - cupsd_srv_t *srv) /* I - Service */ + cupsd_srv_t *srv, /* I - Service */ + int from_callback) /* I - Called from callback? */ { if (!srv || !*srv) return; # ifdef HAVE_DNSSD + (void)from_callback; + DNSServiceRefDeallocate(*srv); # else /* HAVE_AVAHI */ - avahi_threaded_poll_lock(DNSSDMaster); + if (!from_callback) + avahi_threaded_poll_lock(DNSSDMaster); + avahi_entry_group_free(*srv); - avahi_threaded_poll_unlock(DNSSDMaster); + + if (!from_callback) + avahi_threaded_poll_unlock(DNSSDMaster); # endif /* HAVE_DNSSD */ *srv = NULL; @@ -762,7 +692,8 @@ dnssdDeregisterInstance( static void dnssdDeregisterPrinter( cupsd_printer_t *p, /* I - Printer */ - int clear_name) /* I - Clear the name? */ + int clear_name, /* I - Clear the name? */ + int from_callback) /* I - Called from callback? */ { cupsdLogMessage(CUPSD_LOG_DEBUG2, @@ -771,13 +702,13 @@ dnssdDeregisterPrinter( if (p->ipp_srv) { - dnssdDeregisterInstance(&p->ipp_srv); + dnssdDeregisterInstance(&p->ipp_srv, from_callback); # ifdef HAVE_DNSSD # ifdef HAVE_SSL - dnssdDeregisterInstance(&p->ipps_srv); + dnssdDeregisterInstance(&p->ipps_srv, from_callback); # endif /* HAVE_SSL */ - dnssdDeregisterInstance(&p->printer_srv); + dnssdDeregisterInstance(&p->printer_srv, from_callback); # endif /* HAVE_DNSSD */ } @@ -929,6 +860,27 @@ dnssdFreeTxtRecord(cupsd_txt_t *txt) /* I - TXT record */ /* + * 'dnssdRegisterAllPrinters()' - Register all printers. + */ + +static void +dnssdRegisterAllPrinters(int from_callback) /* I - Called from callback? */ +{ + cupsd_printer_t *p; /* Current printer */ + + + if (!DNSSDMaster) + return; + + for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); + p; + p = (cupsd_printer_t *)cupsArrayNext(Printers)) + if (!(p->type & (CUPS_PRINTER_REMOTE | CUPS_PRINTER_SCANNER))) + dnssdRegisterPrinter(p, from_callback); +} + + +/* * 'dnssdRegisterCallback()' - DNSServiceRegister callback. */ @@ -1008,15 +960,19 @@ dnssdRegisterInstance( const char *subtypes, /* I - Subtypes to register or NULL */ int port, /* I - Port number or 0 */ cupsd_txt_t *txt, /* I - TXT record */ - int commit) /* I - Commit registration? */ + int commit, /* I - Commit registration? */ + int from_callback) /* I - Called from callback? */ { char temp[256], /* Temporary string */ *ptr; /* Pointer into string */ int error; /* Any error */ - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Registering \"%s\" with DNS-SD type \"%s\".", name, type); +# ifdef HAVE_DNSSD + (void)from_callback; +# endif /* HAVE_DNSSD */ + + cupsdLogMessage(CUPSD_LOG_DEBUG, "Registering \"%s\" with DNS-SD type \"%s\".", name, type); if (p && !srv) { @@ -1043,13 +999,15 @@ dnssdRegisterInstance( (void)commit; # else /* HAVE_AVAHI */ - avahi_threaded_poll_lock(DNSSDMaster); + if (!from_callback) + avahi_threaded_poll_lock(DNSSDMaster); if (!*srv) *srv = avahi_entry_group_new(DNSSDClient, dnssdRegisterCallback, NULL); if (!*srv) { - avahi_threaded_poll_unlock(DNSSDMaster); + if (!from_callback) + avahi_threaded_poll_unlock(DNSSDMaster); cupsdLogMessage(CUPSD_LOG_WARN, "DNS-SD registration of \"%s\" failed: %s", name, dnssdErrorString(avahi_client_errno(DNSSDClient))); @@ -1166,7 +1124,8 @@ dnssdRegisterInstance( name); } - avahi_threaded_poll_unlock(DNSSDMaster); + if (!from_callback) + avahi_threaded_poll_unlock(DNSSDMaster); # endif /* HAVE_DNSSD */ if (error) @@ -1188,7 +1147,9 @@ dnssdRegisterInstance( */ static void -dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */ +dnssdRegisterPrinter( + cupsd_printer_t *p, /* I - Printer */ + int from_callback) /* I - Called from callback? */ { char name[256]; /* Service name */ int printer_port; /* LPD port number */ @@ -1196,15 +1157,21 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */ cupsd_txt_t ipp_txt, /* IPP(S) TXT record */ printer_txt; /* LPD TXT record */ + cupsdLogMessage(CUPSD_LOG_DEBUG2, "dnssdRegisterPrinter(%s) %s", p->name, !p->ipp_srv ? "new" : "update"); +# ifdef HAVE_AVAHI + if (!avahi_running) + return; +# endif /* HAVE_AVAHI */ + /* * Remove the current registrations if we have them and then return if * per-printer sharing was just disabled... */ - dnssdDeregisterPrinter(p, 0); + dnssdDeregisterPrinter(p, 0, from_callback); if (!p->shared) return; @@ -1247,13 +1214,11 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */ else printer_port = 0; - status = dnssdRegisterInstance(NULL, p, name, "_printer._tcp", NULL, - printer_port, &printer_txt, 0); + status = dnssdRegisterInstance(NULL, p, name, "_printer._tcp", NULL, printer_port, &printer_txt, 0, from_callback); # ifdef HAVE_SSL if (status) - dnssdRegisterInstance(NULL, p, name, "_ipps._tcp", DNSSDSubTypes, - DNSSDPort, &ipp_txt, 0); + dnssdRegisterInstance(NULL, p, name, "_ipps._tcp", DNSSDSubTypes, DNSSDPort, &ipp_txt, 0, from_callback); # endif /* HAVE_SSL */ if (status) @@ -1263,11 +1228,9 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */ */ if (p->type & CUPS_PRINTER_FAX) - status = dnssdRegisterInstance(NULL, p, name, "_fax-ipp._tcp", - DNSSDSubTypes, DNSSDPort, &ipp_txt, 1); + status = dnssdRegisterInstance(NULL, p, name, "_fax-ipp._tcp", DNSSDSubTypes, DNSSDPort, &ipp_txt, 1, from_callback); else - status = dnssdRegisterInstance(NULL, p, name, "_ipp._tcp", DNSSDSubTypes, - DNSSDPort, &ipp_txt, 1); + status = dnssdRegisterInstance(NULL, p, name, "_ipp._tcp", DNSSDSubTypes, DNSSDPort, &ipp_txt, 1, from_callback); } dnssdFreeTxtRecord(&ipp_txt); @@ -1289,13 +1252,13 @@ dnssdRegisterPrinter(cupsd_printer_t *p)/* I - Printer */ * Registration failed for this printer... */ - dnssdDeregisterInstance(&p->ipp_srv); + dnssdDeregisterInstance(&p->ipp_srv, from_callback); # ifdef HAVE_DNSSD # ifdef HAVE_SSL - dnssdDeregisterInstance(&p->ipps_srv); + dnssdDeregisterInstance(&p->ipps_srv, from_callback); # endif /* HAVE_SSL */ - dnssdDeregisterInstance(&p->printer_srv); + dnssdDeregisterInstance(&p->printer_srv, from_callback); # endif /* HAVE_DNSSD */ } } @@ -1318,13 +1281,13 @@ dnssdStop(void) for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); p; p = (cupsd_printer_t *)cupsArrayNext(Printers)) - dnssdDeregisterPrinter(p, 1); + dnssdDeregisterPrinter(p, 1, 0); /* * Shutdown the rest of the service refs... */ - dnssdDeregisterInstance(&WebIFSrv); + dnssdDeregisterInstance(&WebIFSrv, 0); # ifdef HAVE_DNSSD cupsdRemoveSelect(DNSServiceRefSockFD(DNSSDMaster)); @@ -1333,11 +1296,20 @@ dnssdStop(void) DNSSDMaster = NULL; # else /* HAVE_AVAHI */ - avahi_client_free(DNSSDClient); - DNSSDClient = NULL; + if (DNSSDMaster) + avahi_threaded_poll_stop(DNSSDMaster); - avahi_threaded_poll_free(DNSSDMaster); - DNSSDMaster = NULL; + if (DNSSDClient) + { + avahi_client_free(DNSSDClient); + DNSSDClient = NULL; + } + + if (DNSSDMaster) + { + avahi_threaded_poll_free(DNSSDMaster); + DNSSDMaster = NULL; + } # endif /* HAVE_DNSSD */ cupsArrayDelete(DNSSDPrinters); @@ -1370,6 +1342,191 @@ dnssdUpdate(void) /* + * 'dnssdUpdateDNSSDName()' - Update the listen port, computer name, and web interface registration. + */ + +static void +dnssdUpdateDNSSDName(int from_callback) /* I - Called from callback? */ +{ + char webif[1024]; /* Web interface share name */ +# ifdef __APPLE__ + SCDynamicStoreRef sc; /* Context for dynamic store */ + CFDictionaryRef btmm; /* Back-to-My-Mac domains */ + CFStringEncoding nameEncoding; /* Encoding of computer name */ + CFStringRef nameRef; /* Host name CFString */ + char nameBuffer[1024]; /* C-string buffer */ +# endif /* __APPLE__ */ + + + /* + * Only share the web interface and printers when non-local listening is + * enabled... + */ + + if (!DNSSDPort) + { + /* + * Get the port we use for registrations. If we are not listening on any + * non-local ports, there is no sense sharing local printers via Bonjour... + */ + + cupsd_listener_t *lis; /* Current listening socket */ + + for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); + lis; + lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) + { + if (httpAddrLocalhost(&(lis->address))) + continue; + + DNSSDPort = httpAddrPort(&(lis->address)); + break; + } + } + + if (!DNSSDPort) + return; + + /* + * Get the computer name as a c-string... + */ + +# ifdef __APPLE__ + sc = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("cupsd"), NULL, NULL); + + if (sc) + { + /* + * Get the computer name from the dynamic store... + */ + + cupsdClearString(&DNSSDComputerName); + + if ((nameRef = SCDynamicStoreCopyComputerName(sc, &nameEncoding)) != NULL) + { + if (CFStringGetCString(nameRef, nameBuffer, sizeof(nameBuffer), + kCFStringEncodingUTF8)) + { + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Dynamic store computer name is \"%s\".", nameBuffer); + cupsdSetString(&DNSSDComputerName, nameBuffer); + } + + CFRelease(nameRef); + } + + if (!DNSSDComputerName) + { + /* + * Use the ServerName instead... + */ + + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Using ServerName \"%s\" as computer name.", ServerName); + cupsdSetString(&DNSSDComputerName, ServerName); + } + + /* + * Get the local hostname from the dynamic store... + */ + + cupsdClearString(&DNSSDHostName); + + if ((nameRef = SCDynamicStoreCopyLocalHostName(sc)) != NULL) + { + if (CFStringGetCString(nameRef, nameBuffer, sizeof(nameBuffer), + kCFStringEncodingUTF8)) + { + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Dynamic store host name is \"%s\".", nameBuffer); + cupsdSetString(&DNSSDHostName, nameBuffer); + } + + CFRelease(nameRef); + } + + if (!DNSSDHostName) + { + /* + * Use the ServerName instead... + */ + + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Using ServerName \"%s\" as host name.", ServerName); + cupsdSetString(&DNSSDHostName, ServerName); + } + + /* + * Get any Back-to-My-Mac domains and add them as aliases... + */ + + cupsdFreeAliases(DNSSDAlias); + DNSSDAlias = NULL; + + btmm = SCDynamicStoreCopyValue(sc, CFSTR("Setup:/Network/BackToMyMac")); + if (btmm && CFGetTypeID(btmm) == CFDictionaryGetTypeID()) + { + cupsdLogMessage(CUPSD_LOG_DEBUG, "%d Back to My Mac aliases to add.", + (int)CFDictionaryGetCount(btmm)); + CFDictionaryApplyFunction(btmm, dnssdAddAlias, NULL); + } + else if (btmm) + cupsdLogMessage(CUPSD_LOG_ERROR, + "Bad Back to My Mac data in dynamic store!"); + else + cupsdLogMessage(CUPSD_LOG_DEBUG, "No Back to My Mac aliases to add."); + + if (btmm) + CFRelease(btmm); + + CFRelease(sc); + } + else +# endif /* __APPLE__ */ +# ifdef HAVE_AVAHI + if (DNSSDClient) + { + const char *host_name = avahi_client_get_host_name(DNSSDClient); + const char *host_fqdn = avahi_client_get_host_name_fqdn(DNSSDClient); + + cupsdSetString(&DNSSDComputerName, host_name ? host_name : ServerName); + + if (host_fqdn) + cupsdSetString(&DNSSDHostName, host_fqdn); + else if (strchr(ServerName, '.')) + cupsdSetString(&DNSSDHostName, ServerName); + else + cupsdSetStringf(&DNSSDHostName, "%s.local", ServerName); + } + else +# endif /* HAVE_AVAHI */ + { + cupsdSetString(&DNSSDComputerName, ServerName); + + if (strchr(ServerName, '.')) + cupsdSetString(&DNSSDHostName, ServerName); + else + cupsdSetStringf(&DNSSDHostName, "%s.local", ServerName); + } + + /* + * Then (re)register the web interface if enabled... + */ + + if (BrowseWebIF) + { + if (DNSSDComputerName) + snprintf(webif, sizeof(webif), "CUPS @ %s", DNSSDComputerName); + else + strlcpy(webif, "CUPS", sizeof(webif)); + + dnssdDeregisterInstance(&WebIFSrv, from_callback); + dnssdRegisterInstance(&WebIFSrv, NULL, webif, "_http._tcp", "_printer", DNSSDPort, NULL, 1, from_callback); + } +} + + +/* * 'get_auth_info_required()' - Get the auth-info-required value to advertise. */ @@ -1400,7 +1557,7 @@ get_auth_info_required( if (i) *bufptr++ = ','; - strlcpy(bufptr, p->auth_info_required[i], bufsize - (bufptr - buffer)); + strlcpy(bufptr, p->auth_info_required[i], bufsize - (size_t)(bufptr - buffer)); bufptr += strlen(bufptr); } @@ -1666,5 +1823,5 @@ update_smb(int onoff) /* I - 1 = turn on, 0 = turn off */ /* - * End of "$Id: dirsvc.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: dirsvc.c 12458 2015-01-30 16:15:53Z msweet $". */ diff --git a/scheduler/dirsvc.h b/scheduler/dirsvc.h index edc5ad3..1326f8a 100644 --- a/scheduler/dirsvc.h +++ b/scheduler/dirsvc.h @@ -1,5 +1,5 @@ /* - * "$Id: dirsvc.h 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: dirsvc.h 10996 2013-05-29 11:51:34Z msweet $" * * Directory services definitions for the CUPS scheduler. * @@ -80,5 +80,5 @@ extern void cupsdUpdateDNSSDName(void); /* - * End of "$Id: dirsvc.h 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: dirsvc.h 10996 2013-05-29 11:51:34Z msweet $". */ diff --git a/scheduler/env.c b/scheduler/env.c index ba11aad..59eab27 100644 --- a/scheduler/env.c +++ b/scheduler/env.c @@ -1,27 +1,16 @@ /* - * "$Id: env.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: env.c 12700 2015-06-08 18:32:35Z msweet $" * - * Environment management routines for the CUPS scheduler. + * Environment management routines for the CUPS scheduler. * - * Copyright 2007-2011 by Apple Inc. - * Copyright 1997-2006 by Easy Software Products, all rights reserved. + * Copyright 2007-2014 by Apple Inc. + * Copyright 1997-2006 by Easy Software Products, all rights reserved. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * cupsdInitEnv() - Initialize the current environment with standard - * variables. - * cupsdLoadEnv() - Copy common environment variables into an array. - * cupsdSetEnv() - Set a common environment variable. - * cupsdSetEnvf() - Set a formatted common environment variable. - * cupsdUpdateEnv() - Update the environment for the configured directories. - * clear_env() - Clear common environment variables. - * find_env() - Find a common environment variable. + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -131,6 +120,13 @@ cupsdSetEnv(const char *name, /* I - Name of variable */ return; /* + * Do not allow dynamic linker variables when running as root... + */ + + if (!RunUser && (!strncmp(name, "DYLD_", 5) || !strncmp(name, "LD_", 3))) + return; + + /* * See if this variable has already been defined... */ @@ -269,5 +265,5 @@ find_env(const char *name) /* I - Variable name */ /* - * End of "$Id: env.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: env.c 12700 2015-06-08 18:32:35Z msweet $". */ diff --git a/scheduler/file.c b/scheduler/file.c index 84ceef1..ae91b9e 100644 --- a/scheduler/file.c +++ b/scheduler/file.c @@ -1,28 +1,16 @@ /* - * "$Id: file.c 11221 2013-08-06 16:16:01Z msweet $" + * "$Id: file.c 11594 2014-02-14 20:09:01Z msweet $" * - * File functions for the CUPS scheduler. + * File functions for the CUPS scheduler. * - * Copyright 2007-2011 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. + * Copyright 2007-2014 by Apple Inc. + * Copyright 1997-2007 by Easy Software Products, all rights reserved. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * "LICENSE" which should have been included with this file. If this - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * cupsdCleanFiles() - Clean out old files. - * cupsdCloseCreatedConfFile() - Close a created configuration file and move - * into place. - * cupsdClosePipe() - Close a pipe as necessary. - * cupsdCreateConfFile() - Create a configuration file safely. - * cupsdOpenConfFile() - Open a configuration file. - * cupsdOpenPipe() - Create a pipe which is closed on exec. - * cupsdRemoveFile() - Remove a file using the 7-pass US DoD method. - * overwrite_data() - Overwrite the data in a file. + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * "LICENSE" which should have been included with this file. If this + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -43,7 +31,7 @@ static int overwrite_data(int fd, const char *buffer, int bufsize, /* * 'cupsdCleanFiles()' - Clean out old files. */ - + void cupsdCleanFiles(const char *path, /* I - Directory to clean */ const char *pattern) /* I - Filename pattern or NULL */ @@ -65,7 +53,7 @@ cupsdCleanFiles(const char *path, /* I - Directory to clean */ return; } - cupsdLogMessage(CUPSD_LOG_INFO, "Cleaning out old files in \"%s\"...", path); + cupsdLogMessage(CUPSD_LOG_INFO, "Cleaning out old files in \"%s\".", path); while ((dent = cupsDirRead(dir)) != NULL) { @@ -81,13 +69,11 @@ cupsdCleanFiles(const char *path, /* I - Directory to clean */ status = rmdir(filename); } else - status = unlink(filename); + status = cupsdUnlinkOrRemoveFile(filename); if (status) cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to remove \"%s\" - %s", filename, strerror(errno)); - else - cupsdLogMessage(CUPSD_LOG_DEBUG, "Removed \"%s\"...", filename); } cupsDirClose(dir); @@ -146,7 +132,7 @@ cupsdCloseCreatedConfFile( snprintf(newfile, sizeof(newfile), "%s.N", filename); snprintf(oldfile, sizeof(oldfile), "%s.O", filename); - if ((cupsdRemoveFile(oldfile) && errno != ENOENT) || + if ((cupsdUnlinkOrRemoveFile(oldfile) && errno != ENOENT) || (rename(filename, oldfile) && errno != ENOENT) || rename(newfile, filename)) { @@ -308,14 +294,27 @@ cupsdOpenPipe(int *fds) /* O - Pipe file descriptors (2) */ /* - * 'cupsdRemoveFile()' - Remove a file using the 7-pass US DoD method. + * 'cupsdRemoveFile()' - Remove a file securely. */ int /* O - 0 on success, -1 on error */ cupsdRemoveFile(const char *filename) /* I - File to remove */ { #ifdef HAVE_REMOVEFILE - return (removefile(filename, NULL, REMOVEFILE_SECURE_7_PASS)); + /* + * See if the file exists... + */ + + if (access(filename, 0)) + return (0); + + cupsdLogMessage(CUPSD_LOG_DEBUG, "Securely removing \"%s\".", filename); + + /* + * Remove the file... + */ + + return (removefile(filename, NULL, REMOVEFILE_SECURE_1_PASS)); #else int fd; /* File descriptor */ @@ -325,6 +324,15 @@ cupsdRemoveFile(const char *filename) /* I - File to remove */ /* + * See if the file exists... + */ + + if (access(filename, 0)) + return (0); + + cupsdLogMessage(CUPSD_LOG_DEBUG, "Securely removing \"%s\".", filename); + + /* * First open the file for writing in exclusive mode. */ @@ -353,31 +361,9 @@ cupsdRemoveFile(const char *filename) /* I - File to remove */ } /* - * Overwrite the file 7 times with 0xF6, 0x00, 0xFF, random, 0x00, 0xFF, - * and more random data. + * Overwrite the file with random data. */ - memset(buffer, 0xF6, sizeof(buffer)); - if (overwrite_data(fd, buffer, sizeof(buffer), (int)info.st_size)) - { - close(fd); - return (-1); - } - - memset(buffer, 0x00, sizeof(buffer)); - if (overwrite_data(fd, buffer, sizeof(buffer), (int)info.st_size)) - { - close(fd); - return (-1); - } - - memset(buffer, 0xFF, sizeof(buffer)); - if (overwrite_data(fd, buffer, sizeof(buffer), (int)info.st_size)) - { - close(fd); - return (-1); - } - CUPS_SRAND(time(NULL)); for (i = 0; i < sizeof(buffer); i ++) @@ -388,39 +374,31 @@ cupsdRemoveFile(const char *filename) /* I - File to remove */ return (-1); } - memset(buffer, 0x00, sizeof(buffer)); - if (overwrite_data(fd, buffer, sizeof(buffer), (int)info.st_size)) - { - close(fd); - return (-1); - } - - memset(buffer, 0xFF, sizeof(buffer)); - if (overwrite_data(fd, buffer, sizeof(buffer), (int)info.st_size)) - { - close(fd); - return (-1); - } - - for (i = 0; i < sizeof(buffer); i ++) - buffer[i] = CUPS_RAND(); - if (overwrite_data(fd, buffer, sizeof(buffer), (int)info.st_size)) - { - close(fd); - return (-1); - } - /* - * Whew! Close the file (which will lead to the actual deletion) and - * return success... + * Close the file, which will lead to the actual deletion, and return... */ - close(fd); - return (0); + return (close(fd)); #endif /* HAVE_REMOVEFILE */ } +/* + * 'cupsdUnlinkOrRemoveFile()' - Unlink or securely remove a file depending + * on the configuration. + */ + +int /* O - 0 on success, -1 on error */ +cupsdUnlinkOrRemoveFile( + const char *filename) /* I - Filename */ +{ + if (Classification) + return (cupsdRemoveFile(filename)); + else + return (unlink(filename)); +} + + #ifndef HAVE_REMOVEFILE /* * 'overwrite_data()' - Overwrite the data in a file. @@ -453,7 +431,7 @@ overwrite_data(int fd, /* I - File descriptor */ else bytes = filesize; - if ((bytes = write(fd, buffer, bytes)) < 0) + if ((bytes = write(fd, buffer, (size_t)bytes)) < 0) return (-1); filesize -= bytes; @@ -469,5 +447,5 @@ overwrite_data(int fd, /* I - File descriptor */ /* - * End of "$Id: file.c 11221 2013-08-06 16:16:01Z msweet $". + * End of "$Id: file.c 11594 2014-02-14 20:09:01Z msweet $". */ diff --git a/scheduler/filter.c b/scheduler/filter.c index 6979b5c..eec9611 100644 --- a/scheduler/filter.c +++ b/scheduler/filter.c @@ -1,5 +1,5 @@ /* - * "$Id: filter.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: filter.c 10996 2013-05-29 11:51:34Z msweet $" * * File type conversion routines for CUPS. * @@ -500,5 +500,5 @@ mime_find_filters( /* - * End of "$Id: filter.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: filter.c 10996 2013-05-29 11:51:34Z msweet $". */ diff --git a/scheduler/ipp.c b/scheduler/ipp.c index 6968cd5..763dc96 100644 --- a/scheduler/ipp.c +++ b/scheduler/ipp.c @@ -1,102 +1,19 @@ /* - * "$Id: ipp.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: ipp.c 12978 2015-11-17 19:29:52Z msweet $" * - * IPP routines for the CUPS scheduler. + * IPP routines for the CUPS scheduler. * - * Copyright 2007-2013 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. + * Copyright 2007-2015 by Apple Inc. + * Copyright 1997-2007 by Easy Software Products, all rights reserved. * - * This file contains Kerberos support code, copyright 2006 by - * Jelmer Vernooij. + * This file contains Kerberos support code, copyright 2006 by + * Jelmer Vernooij. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * cupsdProcessIPPRequest() - Process an incoming IPP request. - * cupsdTimeoutJob() - Timeout a job waiting on job files. - * accept_jobs() - Accept print jobs to a printer. - * add_class() - Add a class to the system. - * add_file() - Add a file to a job. - * add_job() - Add a job to a print queue. - * add_job_subscriptions() - Add any subscriptions for a job. - * add_job_uuid() - Add job-uuid attribute to a job. - * add_printer() - Add a printer to the system. - * add_printer_state_reasons() - Add the "printer-state-reasons" attribute - * based upon the printer state... - * add_queued_job_count() - Add the "queued-job-count" attribute for the - * specified printer or class. - * apply_printer_defaults() - Apply printer default options to a job. - * authenticate_job() - Set job authentication info. - * cancel_all_jobs() - Cancel all or selected print jobs. - * cancel_job() - Cancel a print job. - * cancel_subscription() - Cancel a subscription. - * check_rss_recipient() - Check that we do not have a duplicate RSS - * feed URI. - * check_quotas() - Check quotas for a printer and user. - * close_job() - Close a multi-file job. - * copy_attrs() - Copy attributes from one request to another. - * copy_banner() - Copy a banner file to the requests directory - * for the specified job. - * copy_file() - Copy a PPD file or interface script... - * copy_model() - Copy a PPD model file, substituting default - * values as needed... - * copy_job_attrs() - Copy job attributes. - * copy_printer_attrs() - Copy printer attributes. - * copy_subscription_attrs() - Copy subscription attributes. - * create_job() - Print a file to a printer or class. - * create_requested_array() - Create an array for the requested-attributes. - * create_subscription() - Create a notification subscription. - * delete_printer() - Remove a printer or class from the system. - * get_default() - Get the default destination. - * get_devices() - Get the list of available devices on the - * local system. - * get_document() - Get a copy of a job file. - * get_job_attrs() - Get job attributes. - * get_jobs() - Get a list of jobs for the specified printer. - * get_notifications() - Get events for a subscription. - * get_ppd() - Get a named PPD from the local system. - * get_ppds() - Get the list of PPD files on the local - * system. - * get_printer_attrs() - Get printer attributes. - * get_printer_supported() - Get printer supported values. - * get_printers() - Get a list of printers or classes. - * get_subscription_attrs() - Get subscription attributes. - * get_subscriptions() - Get subscriptions. - * get_username() - Get the username associated with a request. - * hold_job() - Hold a print job. - * hold_new_jobs() - Hold pending/new jobs on a printer or class. - * move_job() - Move a job to a new destination. - * ppd_parse_line() - Parse a PPD default line. - * print_job() - Print a file to a printer or class. - * read_job_ticket() - Read a job ticket embedded in a print file. - * reject_jobs() - Reject print jobs to a printer. - * release_held_new_jobs() - Release pending/new jobs on a printer or - * class. - * release_job() - Release a held print job. - * renew_subscription() - Renew an existing subscription... - * restart_job() - Restart an old print job. - * save_auth_info() - Save authentication information for a job. - * send_document() - Send a file to a printer or class. - * send_http_error() - Send a HTTP error back to the IPP client. - * send_ipp_status() - Send a status back to the IPP client. - * set_default() - Set the default destination... - * set_job_attrs() - Set job attributes. - * set_printer_attrs() - Set printer attributes. - * set_printer_defaults() - Set printer default options from a request. - * start_printer() - Start a printer. - * stop_printer() - Stop a printer. - * url_encode_attr() - URL-encode a string attribute. - * url_encode_string() - URL-encode a string. - * user_allowed() - See if a user is allowed to print to a queue. - * validate_job() - Validate printer options and destination. - * validate_name() - Make sure the printer name only contains - * valid chars. - * validate_user() - Validate the user for the request. + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -153,7 +70,7 @@ static void copy_attrs(ipp_t *to, ipp_t *from, cups_array_t *ra, cups_array_t *exclude); static int copy_banner(cupsd_client_t *con, cupsd_job_t *job, const char *name); -static int copy_file(const char *from, const char *to); +static int copy_file(const char *from, const char *to, mode_t mode); static int copy_model(cupsd_client_t *con, const char *from, const char *to); static void copy_job_attrs(cupsd_client_t *con, @@ -168,7 +85,7 @@ static void copy_subscription_attrs(cupsd_client_t *con, cups_array_t *exclude); static void create_job(cupsd_client_t *con, ipp_attribute_t *uri); static cups_array_t *create_requested_array(ipp_t *request); -static void create_subscription(cupsd_client_t *con, ipp_attribute_t *uri); +static void create_subscriptions(cupsd_client_t *con, ipp_attribute_t *uri); static void delete_printer(cupsd_client_t *con, ipp_attribute_t *uri); static void get_default(cupsd_client_t *con); static void get_devices(cupsd_client_t *con); @@ -212,15 +129,12 @@ static void set_printer_defaults(cupsd_client_t *con, cupsd_printer_t *printer); static void start_printer(cupsd_client_t *con, ipp_attribute_t *uri); static void stop_printer(cupsd_client_t *con, ipp_attribute_t *uri); -static void url_encode_attr(ipp_attribute_t *attr, char *buffer, - int bufsize); -static char *url_encode_string(const char *s, char *buffer, int bufsize); +static void url_encode_attr(ipp_attribute_t *attr, char *buffer, size_t bufsize); +static char *url_encode_string(const char *s, char *buffer, size_t bufsize); static int user_allowed(cupsd_printer_t *p, const char *username); static void validate_job(cupsd_client_t *con, ipp_attribute_t *uri); static int validate_name(const char *name); -static int validate_user(cupsd_job_t *job, cupsd_client_t *con, - const char *owner, char *username, - int userlen); +static int validate_user(cupsd_job_t *job, cupsd_client_t *con, const char *owner, char *username, size_t userlen); /* @@ -242,7 +156,7 @@ cupsdProcessIPPRequest( cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdProcessIPPRequest(%p[%d]): operation_id = %04x", - con, con->http.fd, con->request->request.op.operation_id); + con, con->number, con->request->request.op.operation_id); /* * First build an empty response message for this request... @@ -270,7 +184,7 @@ cupsdProcessIPPRequest( cupsdAddEvent(CUPSD_EVENT_SERVER_AUDIT, NULL, NULL, "%04X %s Bad request version number %d.%d", - IPP_VERSION_NOT_SUPPORTED, con->http.hostname, + IPP_VERSION_NOT_SUPPORTED, con->http->hostname, con->request->request.any.version[0], con->request->request.any.version[1]); @@ -287,7 +201,7 @@ cupsdProcessIPPRequest( cupsdAddEvent(CUPSD_EVENT_SERVER_AUDIT, NULL, NULL, "%04X %s Bad request ID %d", - IPP_BAD_REQUEST, con->http.hostname, + IPP_BAD_REQUEST, con->http->hostname, con->request->request.any.request_id); send_ipp_status(con, IPP_BAD_REQUEST, _("Bad request ID %d."), @@ -297,7 +211,7 @@ cupsdProcessIPPRequest( { cupsdAddEvent(CUPSD_EVENT_SERVER_AUDIT, NULL, NULL, "%04X %s No attributes in request", - IPP_BAD_REQUEST, con->http.hostname); + IPP_BAD_REQUEST, con->http->hostname); send_ipp_status(con, IPP_BAD_REQUEST, _("No attributes in request.")); } @@ -319,7 +233,7 @@ cupsdProcessIPPRequest( cupsdAddEvent(CUPSD_EVENT_SERVER_AUDIT, NULL, NULL, "%04X %s Attribute groups are out of order", - IPP_BAD_REQUEST, con->http.hostname); + IPP_BAD_REQUEST, con->http->hostname); send_ipp_status(con, IPP_BAD_REQUEST, _("Attribute groups are out of order (%x < %x)."), @@ -353,7 +267,20 @@ cupsdProcessIPPRequest( if (attr && attr->name && !strcmp(attr->name, "attributes-natural-language") && (attr->value_tag & IPP_TAG_MASK) == IPP_TAG_LANGUAGE) + { language = attr; + + /* + * Reset language for this request if different from Accept-Language. + */ + + if (!con->language || + strcmp(attr->values[0].string.text, con->language->language)) + { + cupsLangFree(con->language); + con->language = cupsLangGet(attr->values[0].string.text); + } + } else language = NULL; @@ -396,7 +323,7 @@ cupsdProcessIPPRequest( charset->values[0].string.text); cupsdAddEvent(CUPSD_EVENT_SERVER_AUDIT, NULL, NULL, "%04X %s Unsupported attributes-charset value \"%s\"", - IPP_CHARSET, con->http.hostname, + IPP_CHARSET, con->http->hostname, charset->values[0].string.text); send_ipp_status(con, IPP_BAD_REQUEST, _("Unsupported character set \"%s\"."), @@ -423,7 +350,7 @@ cupsdProcessIPPRequest( cupsdAddEvent(CUPSD_EVENT_SERVER_AUDIT, NULL, NULL, "%04X %s Missing attributes-charset attribute", - IPP_BAD_REQUEST, con->http.hostname); + IPP_BAD_REQUEST, con->http->hostname); } if (!language) @@ -433,7 +360,7 @@ cupsdProcessIPPRequest( cupsdAddEvent(CUPSD_EVENT_SERVER_AUDIT, NULL, NULL, "%04X %s Missing attributes-natural-language attribute", - IPP_BAD_REQUEST, con->http.hostname); + IPP_BAD_REQUEST, con->http->hostname); } if (!uri) @@ -444,7 +371,7 @@ cupsdProcessIPPRequest( cupsdAddEvent(CUPSD_EVENT_SERVER_AUDIT, NULL, NULL, "%04X %s Missing printer-uri, job-uri, or ppd-name " - "attribute", IPP_BAD_REQUEST, con->http.hostname); + "attribute", IPP_BAD_REQUEST, con->http->hostname); } cupsdLogMessage(CUPSD_LOG_DEBUG, "Request attributes follow..."); @@ -475,15 +402,14 @@ cupsdProcessIPPRequest( */ if (!strcmp(username->values[0].string.text, "root") && - _cups_strcasecmp(con->http.hostname, "localhost") && + _cups_strcasecmp(con->http->hostname, "localhost") && strcmp(con->username, "root")) { /* * Remote unauthenticated user masquerading as local root... */ - _cupsStrFree(username->values[0].string.text); - username->values[0].string.text = _cupsStrAlloc(RemoteRoot); + ippSetString(con->request, &username, 0, RemoteRoot); } } @@ -507,183 +433,183 @@ cupsdProcessIPPRequest( switch (con->request->request.op.operation_id) { - case IPP_PRINT_JOB : + case IPP_OP_PRINT_JOB : print_job(con, uri); break; - case IPP_VALIDATE_JOB : + case IPP_OP_VALIDATE_JOB : validate_job(con, uri); break; - case IPP_CREATE_JOB : + case IPP_OP_CREATE_JOB : create_job(con, uri); break; - case IPP_SEND_DOCUMENT : + case IPP_OP_SEND_DOCUMENT : send_document(con, uri); break; - case IPP_CANCEL_JOB : + case IPP_OP_CANCEL_JOB : cancel_job(con, uri); break; - case IPP_GET_JOB_ATTRIBUTES : + case IPP_OP_GET_JOB_ATTRIBUTES : get_job_attrs(con, uri); break; - case IPP_GET_JOBS : + case IPP_OP_GET_JOBS : get_jobs(con, uri); break; - case IPP_GET_PRINTER_ATTRIBUTES : + case IPP_OP_GET_PRINTER_ATTRIBUTES : get_printer_attrs(con, uri); break; - case IPP_GET_PRINTER_SUPPORTED_VALUES : + case IPP_OP_GET_PRINTER_SUPPORTED_VALUES : get_printer_supported(con, uri); break; - case IPP_HOLD_JOB : + case IPP_OP_HOLD_JOB : hold_job(con, uri); break; - case IPP_RELEASE_JOB : + case IPP_OP_RELEASE_JOB : release_job(con, uri); break; - case IPP_RESTART_JOB : + case IPP_OP_RESTART_JOB : restart_job(con, uri); break; - case IPP_PAUSE_PRINTER : + case IPP_OP_PAUSE_PRINTER : stop_printer(con, uri); break; - case IPP_RESUME_PRINTER : + case IPP_OP_RESUME_PRINTER : start_printer(con, uri); break; - case IPP_PURGE_JOBS : - case IPP_CANCEL_JOBS : - case IPP_CANCEL_MY_JOBS : + case IPP_OP_PURGE_JOBS : + case IPP_OP_CANCEL_JOBS : + case IPP_OP_CANCEL_MY_JOBS : cancel_all_jobs(con, uri); break; - case IPP_SET_JOB_ATTRIBUTES : + case IPP_OP_SET_JOB_ATTRIBUTES : set_job_attrs(con, uri); break; - case IPP_SET_PRINTER_ATTRIBUTES : + case IPP_OP_SET_PRINTER_ATTRIBUTES : set_printer_attrs(con, uri); break; - case IPP_HOLD_NEW_JOBS : + case IPP_OP_HOLD_NEW_JOBS : hold_new_jobs(con, uri); break; - case IPP_RELEASE_HELD_NEW_JOBS : + case IPP_OP_RELEASE_HELD_NEW_JOBS : release_held_new_jobs(con, uri); break; - case IPP_CLOSE_JOB : + case IPP_OP_CLOSE_JOB : close_job(con, uri); break; - case CUPS_GET_DEFAULT : + case IPP_OP_CUPS_GET_DEFAULT : get_default(con); break; - case CUPS_GET_PRINTERS : + case IPP_OP_CUPS_GET_PRINTERS : get_printers(con, 0); break; - case CUPS_GET_CLASSES : + case IPP_OP_CUPS_GET_CLASSES : get_printers(con, CUPS_PRINTER_CLASS); break; - case CUPS_ADD_PRINTER : + case IPP_OP_CUPS_ADD_MODIFY_PRINTER : add_printer(con, uri); break; - case CUPS_DELETE_PRINTER : + case IPP_OP_CUPS_DELETE_PRINTER : delete_printer(con, uri); break; - case CUPS_ADD_CLASS : + case IPP_OP_CUPS_ADD_MODIFY_CLASS : add_class(con, uri); break; - case CUPS_DELETE_CLASS : + case IPP_OP_CUPS_DELETE_CLASS : delete_printer(con, uri); break; - case CUPS_ACCEPT_JOBS : - case IPP_ENABLE_PRINTER : + case IPP_OP_CUPS_ACCEPT_JOBS : + case IPP_OP_ENABLE_PRINTER : accept_jobs(con, uri); break; - case CUPS_REJECT_JOBS : - case IPP_DISABLE_PRINTER : + case IPP_OP_CUPS_REJECT_JOBS : + case IPP_OP_DISABLE_PRINTER : reject_jobs(con, uri); break; - case CUPS_SET_DEFAULT : + case IPP_OP_CUPS_SET_DEFAULT : set_default(con, uri); break; - case CUPS_GET_DEVICES : + case IPP_OP_CUPS_GET_DEVICES : get_devices(con); break; - case CUPS_GET_DOCUMENT : + case IPP_OP_CUPS_GET_DOCUMENT : get_document(con, uri); break; - case CUPS_GET_PPD : + case IPP_OP_CUPS_GET_PPD : get_ppd(con, uri); break; - case CUPS_GET_PPDS : + case IPP_OP_CUPS_GET_PPDS : get_ppds(con); break; - case CUPS_MOVE_JOB : + case IPP_OP_CUPS_MOVE_JOB : move_job(con, uri); break; - case CUPS_AUTHENTICATE_JOB : + case IPP_OP_CUPS_AUTHENTICATE_JOB : authenticate_job(con, uri); break; - case IPP_CREATE_PRINTER_SUBSCRIPTION : - case IPP_CREATE_JOB_SUBSCRIPTION : - create_subscription(con, uri); + case IPP_OP_CREATE_PRINTER_SUBSCRIPTIONS : + case IPP_OP_CREATE_JOB_SUBSCRIPTIONS : + create_subscriptions(con, uri); break; - case IPP_GET_SUBSCRIPTION_ATTRIBUTES : + case IPP_OP_GET_SUBSCRIPTION_ATTRIBUTES : get_subscription_attrs(con, sub_id); break; - case IPP_GET_SUBSCRIPTIONS : + case IPP_OP_GET_SUBSCRIPTIONS : get_subscriptions(con, uri); break; - case IPP_RENEW_SUBSCRIPTION : + case IPP_OP_RENEW_SUBSCRIPTION : renew_subscription(con, sub_id); break; - case IPP_CANCEL_SUBSCRIPTION : + case IPP_OP_CANCEL_SUBSCRIPTION : cancel_subscription(con, sub_id); break; - case IPP_GET_NOTIFICATIONS : + case IPP_OP_GET_NOTIFICATIONS : get_notifications(con); break; default : cupsdAddEvent(CUPSD_EVENT_SERVER_AUDIT, NULL, NULL, "%04X %s Operation %04X (%s) not supported", - IPP_OPERATION_NOT_SUPPORTED, con->http.hostname, + IPP_OPERATION_NOT_SUPPORTED, con->http->hostname, con->request->request.op.operation_id, ippOpString(con->request->request.op.operation_id)); @@ -707,78 +633,63 @@ cupsdProcessIPPRequest( >= IPP_BAD_REQUEST && con->response->request.status.status_code != IPP_NOT_FOUND ? CUPSD_LOG_ERROR : CUPSD_LOG_DEBUG, - "Returning IPP %s for %s (%s) from %s", + "[Client %d] Returning IPP %s for %s (%s) from %s", + con->number, ippErrorString(con->response->request.status.status_code), ippOpString(con->request->request.op.operation_id), uri ? uri->values[0].string.text : "no URI", - con->http.hostname); + con->http->hostname); - if (LogLevel == CUPSD_LOG_DEBUG2) - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdProcessIPPRequest: ippLength(response)=%ld", - (long)ippLength(con->response)); + httpClearFields(con->http); - if (cupsdSendHeader(con, HTTP_OK, "application/ipp", CUPSD_AUTH_NONE)) - { #ifdef CUPSD_USE_CHUNKING - /* - * Because older versions of CUPS (1.1.17 and older) and some IPP - * clients do not implement chunking properly, we cannot use - * chunking by default. This may become the default in future - * CUPS releases, or we might add a configuration directive for - * it. - */ - - if (con->http.version == HTTP_1_1) - { - if (httpPrintf(HTTP(con), "Transfer-Encoding: chunked\r\n\r\n") < 0) - return (0); + /* + * Because older versions of CUPS (1.1.17 and older) and some IPP + * clients do not implement chunking properly, we cannot use + * chunking by default. This may become the default in future + * CUPS releases, or we might add a configuration directive for + * it. + */ - if (cupsdFlushHeader(con) < 0) - return (0); + if (con->http->version == HTTP_1_1) + { + cupsdLogMessage(CUPSD_LOG_DEBUG, + "[Client %d] Transfer-Encoding: chunked", + con->number); - con->http.data_encoding = HTTP_ENCODE_CHUNKED; - } - else + cupsdSetLength(con->http, 0); + } + else #endif /* CUPSD_USE_CHUNKING */ - { - size_t length; /* Length of response */ - - - length = ippLength(con->response); - - if (con->file >= 0 && !con->pipe_pid) - { - struct stat fileinfo; /* File information */ - - - if (!fstat(con->file, &fileinfo)) - length += fileinfo.st_size; - } + { + size_t length; /* Length of response */ - if (httpPrintf(HTTP(con), "Content-Length: " CUPS_LLFMT "\r\n\r\n", - CUPS_LLCAST length) < 0) - return (0); - if (cupsdFlushHeader(con) < 0) - return (0); + length = ippLength(con->response); - con->http.data_encoding = HTTP_ENCODE_LENGTH; - con->http.data_remaining = length; + if (con->file >= 0 && !con->pipe_pid) + { + struct stat fileinfo; /* File information */ - if (con->http.data_remaining <= INT_MAX) - con->http._data_remaining = con->http.data_remaining; - else - con->http._data_remaining = INT_MAX; + if (!fstat(con->file, &fileinfo)) + length += (size_t)fileinfo.st_size; } - cupsdAddSelect(con->http.fd, (cupsd_selfunc_t)cupsdReadClient, - (cupsd_selfunc_t)cupsdWriteClient, con); + cupsdLogMessage(CUPSD_LOG_DEBUG, + "[Client %d] Content-Length: " CUPS_LLFMT, + con->number, CUPS_LLCAST length); + httpSetLength(con->http, length); + } + if (cupsdSendHeader(con, HTTP_OK, "application/ipp", CUPSD_AUTH_NONE)) + { /* * Tell the caller the response header was sent successfully... */ + cupsdAddSelect(httpGetFd(con->http), (cupsd_selfunc_t)cupsdReadClient, + (cupsd_selfunc_t)cupsdWriteClient, con); + return (1); } else @@ -860,7 +771,7 @@ accept_jobs(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "accept_jobs(%p[%d], %s)", con, - con->http.fd, uri->values[0].string.text); + con->number, uri->values[0].string.text); /* * Is the destination valid? @@ -945,7 +856,7 @@ add_class(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_class(%p[%d], %s)", con, - con->http.fd, uri->values[0].string.text); + con->number, uri->values[0].string.text); /* * Do we have a valid URI? @@ -1034,10 +945,18 @@ add_class(cupsd_client_t *con, /* I - Client connection */ need_restart_job = 0; - if ((attr = ippFindAttribute(con->request, "printer-location", - IPP_TAG_TEXT)) != NULL) + if ((attr = ippFindAttribute(con->request, "printer-location", IPP_TAG_TEXT)) != NULL) cupsdSetString(&pclass->location, attr->values[0].string.text); + if ((attr = ippFindAttribute(con->request, "printer-geo-location", IPP_TAG_URI)) != NULL && !strncmp(attr->values[0].string.text, "geo:", 4)) + cupsdSetString(&pclass->geo_location, attr->values[0].string.text); + + if ((attr = ippFindAttribute(con->request, "printer-organization", IPP_TAG_TEXT)) != NULL) + cupsdSetString(&pclass->organization, attr->values[0].string.text); + + if ((attr = ippFindAttribute(con->request, "printer-organizational-unit", IPP_TAG_TEXT)) != NULL) + cupsdSetString(&pclass->organizational_unit, attr->values[0].string.text); + if ((attr = ippFindAttribute(con->request, "printer-info", IPP_TAG_TEXT)) != NULL) cupsdSetString(&pclass->info, attr->values[0].string.text); @@ -1059,6 +978,16 @@ add_class(cupsd_client_t *con, /* I - Client connection */ if ((attr = ippFindAttribute(con->request, "printer-is-shared", IPP_TAG_BOOLEAN)) != NULL) { + if (pclass->type & CUPS_PRINTER_REMOTE) + { + /* + * Cannot re-share remote printers. + */ + + send_ipp_status(con, IPP_BAD_REQUEST, _("Cannot change printer-is-shared for remote queues.")); + return; + } + if (pclass->shared && !attr->values[0].boolean) cupsdDeregisterPrinter(pclass, 1); @@ -1157,6 +1086,8 @@ add_class(cupsd_client_t *con, /* I - Client connection */ IPP_TAG_KEYWORD)) != NULL) cupsdSetAuthInfoRequired(pclass, NULL, attr); + pclass->config_time = time(NULL); + /* * Update the printer class attributes and return... */ @@ -1215,7 +1146,7 @@ add_file(cupsd_client_t *con, /* I - Connection to client */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_file(con=%p[%d], job=%d, filetype=%s/%s, " - "compression=%d)", con, con ? con->http.fd : -1, job->id, + "compression=%d)", con, con ? con->number : -1, job->id, filetype->super, filetype->type, compression); /* @@ -1230,12 +1161,18 @@ add_file(cupsd_client_t *con, /* I - Connection to client */ else { compressions = (int *)realloc(job->compressions, - (job->num_files + 1) * sizeof(int)); + (size_t)(job->num_files + 1) * sizeof(int)); filetypes = (mime_type_t **)realloc(job->filetypes, - (job->num_files + 1) * + (size_t)(job->num_files + 1) * sizeof(mime_type_t *)); } + if (compressions) + job->compressions = compressions; + + if (filetypes) + job->filetypes = filetypes; + if (!compressions || !filetypes) { cupsdSetJobState(job, IPP_JOB_ABORTED, CUPSD_JOB_PURGE, @@ -1248,9 +1185,7 @@ add_file(cupsd_client_t *con, /* I - Connection to client */ return (-1); } - job->compressions = compressions; job->compressions[job->num_files] = compression; - job->filetypes = filetypes; job->filetypes[job->num_files] = filetype; job->num_files ++; @@ -1274,6 +1209,7 @@ add_job(cupsd_client_t *con, /* I - Client connection */ http_status_t status; /* Policy status */ ipp_attribute_t *attr, /* Current attribute */ *auth_info; /* auth-info attribute */ + const char *mandatory; /* Current mandatory job attribute */ const char *val; /* Default option value */ int priority; /* Job priority */ cupsd_job_t *job; /* Current job */ @@ -1287,15 +1223,25 @@ add_job(cupsd_client_t *con, /* I - Client connection */ ipp_t *unsup_col; /* media-col in unsupported response */ static const char * const readonly[] =/* List of read-only attributes */ { + "date-time-at-completed", + "date-time-at-creation", + "date-time-at-processing", + "job-detailed-status-messages", + "job-document-access-errors", "job-id", - "job-k-octets", - /*"job-impressions",*/ /* For now we allow this since cupsd can't count */ "job-impressions-completed", - "job-media-sheets", + "job-k-octets-completed", "job-media-sheets-completed", + "job-pages-completed", + "job-printer-up-time", + "job-printer-uri", "job-state", "job-state-message", "job-state-reasons", + "job-uri", + "number-of-documents", + "number-of-intervening-jobs", + "output-device-assigned", "time-at-completed", "time-at-creation", "time-at-processing" @@ -1303,7 +1249,7 @@ add_job(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_job(%p[%d], %p(%s), %p(%s/%s))", - con, con->http.fd, printer, printer->name, + con, con->number, printer, printer->name, filetype, filetype ? filetype->super : "none", filetype ? filetype->type : "none"); @@ -1312,8 +1258,8 @@ add_job(cupsd_client_t *con, /* I - Client connection */ */ if (!printer->shared && - _cups_strcasecmp(con->http.hostname, "localhost") && - _cups_strcasecmp(con->http.hostname, ServerName)) + _cups_strcasecmp(con->http->hostname, "localhost") && + _cups_strcasecmp(con->http->hostname, ServerName)) { send_ipp_status(con, IPP_NOT_AUTHORIZED, _("The printer or class is not shared.")); @@ -1339,8 +1285,8 @@ add_job(cupsd_client_t *con, /* I - Client connection */ return (NULL); } #ifdef HAVE_SSL - else if (auth_info && !con->http.tls && - !httpAddrLocalhost(con->http.hostaddr)) + else if (auth_info && !con->http->tls && + !httpAddrLocalhost(con->http->hostaddr)) { /* * Require encryption of auth-info over non-local connections... @@ -1365,27 +1311,43 @@ add_job(cupsd_client_t *con, /* I - Client connection */ /* * Validate job template attributes; for now just document-format, - * copies, number-up, and page-ranges... + * copies, job-sheets, number-up, page-ranges, mandatory attributes, and + * media... */ for (i = 0; i < (int)(sizeof(readonly) / sizeof(readonly[0])); i ++) { - if ((attr = ippFindAttribute(con->request, readonly[i], - IPP_TAG_ZERO)) != NULL) + if ((attr = ippFindAttribute(con->request, readonly[i], IPP_TAG_ZERO)) != NULL) { ippDeleteAttribute(con->request, attr); if (StrictConformance) { - send_ipp_status(con, IPP_BAD_REQUEST, - _("The '%s' Job Description attribute cannot be " - "supplied in a job creation request."), readonly[i]); + send_ipp_status(con, IPP_BAD_REQUEST, _("The '%s' Job Status attribute cannot be supplied in a job creation request."), readonly[i]); return (NULL); } - cupsdLogMessage(CUPSD_LOG_WARN, - "Unexpected '%s' Job Description attribute in a job " - "creation request.", readonly[i]); + cupsdLogMessage(CUPSD_LOG_INFO, "Unexpected '%s' Job Status attribute in a job creation request.", readonly[i]); + } + } + + if (printer->pc) + { + for (mandatory = (char *)cupsArrayFirst(printer->pc->mandatory); + mandatory; + mandatory = (char *)cupsArrayNext(printer->pc->mandatory)) + { + if (!ippFindAttribute(con->request, mandatory, IPP_TAG_ZERO)) + { + /* + * Missing a required attribute... + */ + + send_ipp_status(con, IPP_CONFLICT, + _("The \"%s\" attribute is required for print jobs."), + mandatory); + return (NULL); + } } } @@ -1575,8 +1537,7 @@ add_job(cupsd_client_t *con, /* I - Client connection */ } if ((attr = ippFindAttribute(con->request, "job-name", IPP_TAG_ZERO)) == NULL) - ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_NAME, "job-name", NULL, - "Untitled"); + ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_NAME, "job-name", NULL, "Untitled"); else if ((attr->value_tag != IPP_TAG_NAME && attr->value_tag != IPP_TAG_NAMELANG) || attr->num_values != 1) @@ -1587,57 +1548,13 @@ add_job(cupsd_client_t *con, /* I - Client connection */ attr->group_tag = IPP_TAG_UNSUPPORTED_GROUP; return (NULL); } - else + else if (!ippValidateAttribute(attr)) { - const char *ptr; /* Pointer into string */ - - for (ptr = attr->values[0].string.text; *ptr; ptr ++) - { - if ((*ptr & 0xe0) == 0xc0) - { - ptr ++; - if ((*ptr & 0xc0) != 0x80) - break; - } - else if ((*ptr & 0xf0) == 0xe0) - { - ptr ++; - if ((*ptr & 0xc0) != 0x80) - break; - ptr ++; - if ((*ptr & 0xc0) != 0x80) - break; - } - else if ((*ptr & 0xf8) == 0xf0) - { - ptr ++; - if ((*ptr & 0xc0) != 0x80) - break; - ptr ++; - if ((*ptr & 0xc0) != 0x80) - break; - ptr ++; - if ((*ptr & 0xc0) != 0x80) - break; - } - else if (*ptr & 0x80) - break; - } - - if (*ptr || (ptr - attr->values[0].string.text) > (IPP_MAX_NAME - 1)) - { - if (*ptr) - send_ipp_status(con, IPP_ATTRIBUTES, - _("Bad job-name value: Bad UTF-8 sequence.")); - else - send_ipp_status(con, IPP_ATTRIBUTES, - _("Bad job-name value: Name too long.")); - - if ((attr = ippCopyAttribute(con->response, attr, 0)) != NULL) - attr->group_tag = IPP_TAG_UNSUPPORTED_GROUP; - - return (NULL); - } + send_ipp_status(con, IPP_ATTRIBUTES, _("Bad job-name value: %s"), + cupsLastErrorString()); + if ((attr = ippCopyAttribute(con->response, attr, 0)) != NULL) + attr->group_tag = IPP_TAG_UNSUPPORTED_GROUP; + return (NULL); } if ((job = cupsdAddJob(priority, printer->name)) == NULL) @@ -1665,7 +1582,7 @@ add_job(cupsd_client_t *con, /* I - Client connection */ cupsdSetString(&job->username, con->username); if (attr) - cupsdSetString(&attr->values[0].string.text, con->username); + ippSetString(job->attrs, &attr, 0, con->username); } else if (attr) { @@ -1683,9 +1600,8 @@ add_job(cupsd_client_t *con, /* I - Client connection */ "job-originating-user-name", NULL, job->username); else { - attr->group_tag = IPP_TAG_JOB; - _cupsStrFree(attr->name); - attr->name = _cupsStrAlloc("job-originating-user-name"); + ippSetGroupTag(job->attrs, &attr, IPP_TAG_JOB); + ippSetName(job->attrs, &attr, "job-originating-user-name"); } if (con->username[0] || auth_info) @@ -1700,6 +1616,9 @@ add_job(cupsd_client_t *con, /* I - Client connection */ ippDeleteAttribute(job->attrs, auth_info); } + if ((attr = ippFindAttribute(con->request, "job-name", IPP_TAG_NAME)) != NULL) + cupsdSetString(&(job->name), attr->values[0].string.text); + if ((attr = ippFindAttribute(job->attrs, "job-originating-host-name", IPP_TAG_ZERO)) != NULL) { @@ -1709,55 +1628,18 @@ add_job(cupsd_client_t *con, /* I - Client connection */ if (attr->value_tag != IPP_TAG_NAME || attr->num_values != 1 || - strcmp(con->http.hostname, "localhost")) + strcmp(con->http->hostname, "localhost")) { /* * Can't override the value if we aren't connected via localhost. * Also, we can only have 1 value and it must be a name value. */ - switch (attr->value_tag) - { - case IPP_TAG_STRING : - case IPP_TAG_TEXTLANG : - case IPP_TAG_NAMELANG : - case IPP_TAG_TEXT : - case IPP_TAG_NAME : - case IPP_TAG_KEYWORD : - case IPP_TAG_URI : - case IPP_TAG_URISCHEME : - case IPP_TAG_CHARSET : - case IPP_TAG_LANGUAGE : - case IPP_TAG_MIMETYPE : - /* - * Free old strings... - */ - - for (i = 0; i < attr->num_values; i ++) - { - _cupsStrFree(attr->values[i].string.text); - attr->values[i].string.text = NULL; - if (attr->values[i].string.language) - { - _cupsStrFree(attr->values[i].string.language); - attr->values[i].string.language = NULL; - } - } - - default : - break; - } - - /* - * Use the default connection hostname instead... - */ - - attr->value_tag = IPP_TAG_NAME; - attr->num_values = 1; - attr->values[0].string.text = _cupsStrAlloc(con->http.hostname); + ippDeleteAttribute(job->attrs, attr); + ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_NAME, "job-originating-host-name", NULL, con->http->hostname); } - - attr->group_tag = IPP_TAG_JOB; + else + ippSetGroupTag(job->attrs, &attr, IPP_TAG_JOB); } else { @@ -1767,17 +1649,15 @@ add_job(cupsd_client_t *con, /* I - Client connection */ */ ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_NAME, - "job-originating-host-name", NULL, con->http.hostname); + "job-originating-host-name", NULL, con->http->hostname); } - ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, "time-at-creation", - time(NULL)); - attr = ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, - "time-at-processing", 0); - attr->value_tag = IPP_TAG_NOVALUE; - attr = ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, - "time-at-completed", 0); - attr->value_tag = IPP_TAG_NOVALUE; + ippAddOutOfBand(job->attrs, IPP_TAG_JOB, IPP_TAG_NOVALUE, "date-time-at-completed"); + ippAddDate(job->attrs, IPP_TAG_JOB, "date-time-at-creation", ippTimeToDate(time(NULL))); + ippAddOutOfBand(job->attrs, IPP_TAG_JOB, IPP_TAG_NOVALUE, "date-time-at-processing"); + ippAddOutOfBand(job->attrs, IPP_TAG_JOB, IPP_TAG_NOVALUE, "time-at-completed"); + ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, "time-at-creation", time(NULL)); + ippAddOutOfBand(job->attrs, IPP_TAG_JOB, IPP_TAG_NOVALUE, "time-at-processing"); /* * Add remaining job attributes... @@ -1789,13 +1669,13 @@ add_job(cupsd_client_t *con, /* I - Client connection */ job->state_value = (ipp_jstate_t)job->state->values[0].integer; job->reasons = ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "job-incoming"); + job->impressions = ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-impressions-completed", 0); job->sheets = ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-media-sheets-completed", 0); ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_URI, "job-printer-uri", NULL, printer->uri); - if ((attr = ippFindAttribute(job->attrs, "job-k-octets", - IPP_TAG_INTEGER)) != NULL) + if ((attr = ippFindAttribute(job->attrs, "job-k-octets", IPP_TAG_INTEGER)) != NULL) attr->values[0].integer = 0; else ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-k-octets", 0); @@ -1854,8 +1734,8 @@ add_job(cupsd_client_t *con, /* I - Client connection */ attr = ippAddStrings(job->attrs, IPP_TAG_JOB, IPP_TAG_NAME, "job-sheets", 2, NULL, NULL); - attr->values[0].string.text = _cupsStrRetain(printer->job_sheets[0]); - attr->values[1].string.text = _cupsStrRetain(printer->job_sheets[1]); + ippSetString(job->attrs, &attr, 0, printer->job_sheets[0]); + ippSetString(job->attrs, &attr, 1, printer->job_sheets[1]); } job->job_sheets = attr; @@ -1881,7 +1761,7 @@ add_job(cupsd_client_t *con, /* I - Client connection */ * Force the leading banner to have the classification on it... */ - cupsdSetString(&attr->values[0].string.text, Classification); + ippSetString(job->attrs, &attr, 0, Classification); cupsdLogJob(job, CUPSD_LOG_NOTICE, "CLASSIFICATION FORCED " "job-sheets=\"%s,none\", " @@ -1898,7 +1778,7 @@ add_job(cupsd_client_t *con, /* I - Client connection */ * Can't put two different security markings on the same document! */ - cupsdSetString(&attr->values[1].string.text, attr->values[0].string.text); + ippSetString(job->attrs, &attr, 1, attr->values[0].string.text); cupsdLogJob(job, CUPSD_LOG_NOTICE, "CLASSIFICATION FORCED " "job-sheets=\"%s,%s\", " @@ -1938,18 +1818,18 @@ add_job(cupsd_client_t *con, /* I - Client connection */ if (attr->num_values > 1 && !strcmp(attr->values[0].string.text, attr->values[1].string.text)) { - cupsdSetString(&(attr->values[0].string.text), Classification); - cupsdSetString(&(attr->values[1].string.text), Classification); + ippSetString(job->attrs, &attr, 0, Classification); + ippSetString(job->attrs, &attr, 1, Classification); } else { if (attr->num_values == 1 || strcmp(attr->values[0].string.text, "none")) - cupsdSetString(&(attr->values[0].string.text), Classification); + ippSetString(job->attrs, &attr, 0, Classification); if (attr->num_values > 1 && strcmp(attr->values[1].string.text, "none")) - cupsdSetString(&(attr->values[1].string.text), Classification); + ippSetString(job->attrs, &attr, 1, Classification); } if (attr->num_values > 1) @@ -1997,7 +1877,7 @@ add_job(cupsd_client_t *con, /* I - Client connection */ */ httpAssembleURIf(HTTP_URI_CODING_ALL, job_uri, sizeof(job_uri), "ipp", NULL, - con->servername, con->serverport, "/jobs/%d", job->id); + con->clientname, con->clientport, "/jobs/%d", job->id); ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_URI, "job-uri", NULL, job_uri); @@ -2005,6 +1885,7 @@ add_job(cupsd_client_t *con, /* I - Client connection */ ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_ENUM, "job-state", job->state_value); + ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_TEXT, "job-state-message", NULL, ""); ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_KEYWORD, "job-state-reasons", NULL, job->reasons->values[0].string.text); @@ -2220,7 +2101,7 @@ add_job_subscriptions( { sub->user_data_len = user_data->values[0].unknown.length; memcpy(sub->user_data, user_data->values[0].unknown.data, - sub->user_data_len); + (size_t)sub->user_data_len); } ippAddSeparator(con->response); @@ -2289,8 +2170,8 @@ add_job_uuid(cupsd_job_t *job) /* I - Job */ if (!ippFindAttribute(job->attrs, "job-uuid", IPP_TAG_URI)) ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_URI, "job-uuid", NULL, - _httpAssembleUUID(ServerName, RemotePort, job->dest, job->id, - uuid, sizeof(uuid))); + httpAssembleUUID(ServerName, RemotePort, job->dest, job->id, + uuid, sizeof(uuid))); } @@ -2323,7 +2204,7 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_printer(%p[%d], %s)", con, - con->http.fd, uri->values[0].string.text); + con->number, uri->values[0].string.text); /* * Do we have a valid URI? @@ -2416,6 +2297,15 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ IPP_TAG_TEXT)) != NULL) cupsdSetString(&printer->location, attr->values[0].string.text); + if ((attr = ippFindAttribute(con->request, "printer-geo-location", IPP_TAG_URI)) != NULL && !strncmp(attr->values[0].string.text, "geo:", 4)) + cupsdSetString(&printer->geo_location, attr->values[0].string.text); + + if ((attr = ippFindAttribute(con->request, "printer-organization", IPP_TAG_TEXT)) != NULL) + cupsdSetString(&printer->organization, attr->values[0].string.text); + + if ((attr = ippFindAttribute(con->request, "printer-organizational-unit", IPP_TAG_TEXT)) != NULL) + cupsdSetString(&printer->organizational_unit, attr->values[0].string.text); + if ((attr = ippFindAttribute(con->request, "printer-info", IPP_TAG_TEXT)) != NULL) cupsdSetString(&printer->info, attr->values[0].string.text); @@ -2460,7 +2350,7 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG, "%s device-uri: %s", printer->name, - uri_status_strings[uri_status - HTTP_URI_OVERFLOW]); + uri_status_strings[uri_status - HTTP_URI_STATUS_OVERFLOW]); if (uri_status < HTTP_URI_OK) { @@ -2591,6 +2481,16 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ return; } + if (printer->type & CUPS_PRINTER_REMOTE) + { + /* + * Cannot re-share remote printers. + */ + + send_ipp_status(con, IPP_BAD_REQUEST, _("Cannot change printer-is-shared for remote queues.")); + return; + } + if (printer->shared && !attr->values[0].boolean) cupsdDeregisterPrinter(printer, 1); @@ -2735,7 +2635,7 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ * interfaces directory and make it executable... */ - if (copy_file(srcfile, dstfile)) + if (copy_file(srcfile, dstfile, ConfigFilePerm | 0110)) { send_ipp_status(con, IPP_INTERNAL_ERROR, _("Unable to copy interface script - %s"), @@ -2745,7 +2645,6 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG, "Copied interface script successfully"); - chmod(dstfile, 0755); } snprintf(dstfile, sizeof(dstfile), "%s/ppd/%s.ppd", ServerRoot, @@ -2758,7 +2657,7 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ * ppd directory and make it readable by all... */ - if (copy_file(srcfile, dstfile)) + if (copy_file(srcfile, dstfile, ConfigFilePerm)) { send_ipp_status(con, IPP_INTERNAL_ERROR, _("Unable to copy PPD file - %s"), @@ -2768,7 +2667,6 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG, "Copied PPD file successfully"); - chmod(dstfile, 0644); } else { @@ -2822,7 +2720,6 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG, "Copied PPD file successfully"); - chmod(dstfile, 0644); } } @@ -2890,6 +2787,8 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ } } + printer->config_time = time(NULL); + /* * Update the printer attributes and return... */ @@ -2944,7 +2843,7 @@ add_printer_state_reasons( { cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_printer_state_reasons(%p[%d], %p[%s])", - con, con->http.fd, p, p->name); + con, con->number, p, p->name); if (p->num_reasons == 0) ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, @@ -2970,7 +2869,7 @@ add_queued_job_count( cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_queued_job_count(%p[%d], %p[%s])", - con, con->http.fd, p, p->name); + con, con->number, p, p->name); count = cupsdGetPrinterJobCount(p->name); @@ -3042,7 +2941,7 @@ authenticate_job(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "authenticate_job(%p[%d], %s)", - con, con->http.fd, uri->values[0].string.text); + con, con->number, uri->values[0].string.text); /* * Start with "everything is OK" status... @@ -3177,8 +3076,8 @@ authenticate_job(cupsd_client_t *con, /* I - Client connection */ if (attr) { - attr->value_tag = IPP_TAG_KEYWORD; - cupsdSetString(&(attr->values[0].string.text), "no-hold"); + ippSetValueTag(job->attrs, &attr, IPP_TAG_KEYWORD); + ippSetString(job->attrs, &attr, 0, "no-hold"); } /* @@ -3221,7 +3120,7 @@ cancel_all_jobs(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cancel_all_jobs(%p[%d], %s)", con, - con->http.fd, uri->values[0].string.text); + con->number, uri->values[0].string.text); /* * Get the jobs to cancel/purge... @@ -3328,8 +3227,12 @@ cancel_all_jobs(cupsd_client_t *con, /* I - Client connection */ { for (i = 0; i < job_ids->num_values; i ++) { - if (!cupsdFindJob(job_ids->values[i].integer)) + if ((job = cupsdFindJob(job_ids->values[i].integer)) == NULL) break; + + if (con->request->request.op.operation_id == IPP_CANCEL_MY_JOBS && + _cups_strcasecmp(job->username, username)) + break; } if (i < job_ids->num_values) @@ -3385,6 +3288,10 @@ cancel_all_jobs(cupsd_client_t *con, /* I - Client connection */ if ((job = cupsdFindJob(job_ids->values[i].integer)) == NULL || _cups_strcasecmp(job->dest, printer->name)) break; + + if (con->request->request.op.operation_id == IPP_CANCEL_MY_JOBS && + _cups_strcasecmp(job->username, username)) + break; } if (i < job_ids->num_values) @@ -3423,6 +3330,8 @@ cancel_all_jobs(cupsd_client_t *con, /* I - Client connection */ } con->response->request.status.status_code = IPP_OK; + + cupsdCheckJobs(); } @@ -3448,7 +3357,7 @@ cancel_job(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cancel_job(%p[%d], %s)", con, - con->http.fd, uri->values[0].string.text); + con->number, uri->values[0].string.text); /* * See if we have a job URI or a printer URI... @@ -3648,7 +3557,7 @@ cancel_subscription( cupsdLogMessage(CUPSD_LOG_DEBUG2, "cancel_subscription(con=%p[%d], sub_id=%d)", - con, con->http.fd, sub_id); + con, con->number, sub_id); /* * Is the subscription ID valid? @@ -3754,7 +3663,7 @@ check_quotas(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "check_quotas(%p[%d], %p[%s])", - con, con->http.fd, p, p->name); + con, con->number, p, p->name); /* * Figure out who is printing... @@ -3977,7 +3886,7 @@ close_job(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "close_job(%p[%d], %s)", con, - con->http.fd, uri->values[0].string.text); + con->number, uri->values[0].string.text); /* * See if we have a job URI or a printer URI... @@ -4061,7 +3970,7 @@ close_job(cupsd_client_t *con, /* I - Client connection */ */ httpAssembleURIf(HTTP_URI_CODING_ALL, job_uri, sizeof(job_uri), "ipp", NULL, - con->servername, con->serverport, "/jobs/%d", job->id); + con->clientname, con->clientport, "/jobs/%d", job->id); ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_URI, "job-uri", NULL, job_uri); @@ -4112,7 +4021,11 @@ copy_attrs(ipp_t *to, /* I - Destination request */ fromattr->group_tag != IPP_TAG_ZERO) || !fromattr->name) continue; - if (!strcmp(fromattr->name, "job-printer-uri")) + if (!strcmp(fromattr->name, "document-password") || + !strcmp(fromattr->name, "job-authorization-uri") || + !strcmp(fromattr->name, "job-password") || + !strcmp(fromattr->name, "job-password-encryption") || + !strcmp(fromattr->name, "job-printer-uri")) continue; if (exclude && @@ -4177,7 +4090,7 @@ copy_banner(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "copy_banner(con=%p[%d], job=%p[%d], name=\"%s\")", - con, con ? con->http.fd : -1, job, job->id, + con, con ? con->number : -1, job, job->id, name ? name : "(null)"); /* @@ -4222,8 +4135,8 @@ copy_banner(cupsd_client_t *con, /* I - Client connection */ */ attrname[2] = '_'; - attrname[3] = toupper(attrname[3] & 255); - attrname[4] = toupper(attrname[4] & 255); + attrname[3] = (char)toupper(attrname[3] & 255); + attrname[4] = (char)toupper(attrname[4] & 255); } snprintf(filename, sizeof(filename), "%s/banners/%s/%s", DataDir, @@ -4277,7 +4190,7 @@ copy_banner(cupsd_client_t *con, /* I - Client connection */ if (!isalpha(ch & 255) && ch != '-' && ch != '?') break; else if (s < (attrname + sizeof(attrname) - 1)) - *s++ = ch; + *s++ = (char)ch; else break; @@ -4424,8 +4337,9 @@ copy_banner(cupsd_client_t *con, /* I - Client connection */ kbytes = (cupsFileTell(out) + 1023) / 1024; - if ((attr = ippFindAttribute(job->attrs, "job-k-octets", - IPP_TAG_INTEGER)) != NULL) + job->koctets += kbytes; + + if ((attr = ippFindAttribute(job->attrs, "job-k-octets", IPP_TAG_INTEGER)) != NULL) attr->values[0].integer += kbytes; cupsFileClose(out); @@ -4440,7 +4354,8 @@ copy_banner(cupsd_client_t *con, /* I - Client connection */ static int /* O - 0 = success, -1 = error */ copy_file(const char *from, /* I - Source file */ - const char *to) /* I - Destination file */ + const char *to, /* I - Destination file */ + mode_t mode) /* I - Permissions */ { cups_file_t *src, /* Source file */ *dst; /* Destination file */ @@ -4457,7 +4372,7 @@ copy_file(const char *from, /* I - Source file */ if ((src = cupsFileOpen(from, "rb")) == NULL) return (-1); - if ((dst = cupsFileOpen(to, "wb")) == NULL) + if ((dst = cupsdCreateConfFile(to, mode)) == NULL) { cupsFileClose(src); return (-1); @@ -4468,7 +4383,7 @@ copy_file(const char *from, /* I - Source file */ */ while ((bytes = cupsFileRead(src, buffer, sizeof(buffer))) > 0) - if (cupsFileWrite(dst, buffer, bytes) < bytes) + if (cupsFileWrite(dst, buffer, (size_t)bytes) < bytes) { cupsFileClose(src); cupsFileClose(dst); @@ -4481,7 +4396,7 @@ copy_file(const char *from, /* I - Source file */ cupsFileClose(src); - return (cupsFileClose(dst)); + return (cupsdCloseCreatedConfFile(dst, to)); } @@ -4536,7 +4451,7 @@ copy_model(cupsd_client_t *con, /* I - Client connection */ cupsdLoadEnv(envp, (int)(sizeof(envp) / sizeof(envp[0]))); snprintf(buffer, sizeof(buffer), "%s/daemon/cups-driverd", ServerBin); - snprintf(tempfile, sizeof(tempfile), "%s/%d.ppd", TempDir, con->http.fd); + snprintf(tempfile, sizeof(tempfile), "%s/%d.ppd", TempDir, con->number); tempfd = open(tempfile, O_WRONLY | O_CREAT | O_TRUNC, 0600); if (tempfd < 0 || cupsdOpenPipe(temppipe)) return (-1); @@ -4603,7 +4518,7 @@ copy_model(cupsd_client_t *con, /* I - Client connection */ if ((bytes = read(temppipe[0], buffer, sizeof(buffer))) > 0) { - if (write(tempfd, buffer, bytes) < bytes) + if (write(tempfd, buffer, (size_t)bytes) < bytes) break; total += bytes; @@ -4717,7 +4632,7 @@ copy_model(cupsd_client_t *con, /* I - Client connection */ * Open the destination file for a copy... */ - if ((dst = cupsFileOpen(to, "wb")) == NULL) + if ((dst = cupsdCreateConfFile(to, ConfigFilePerm)) == NULL) { cupsFreeOptions(num_defaults, defaults); cupsFileClose(src); @@ -4772,7 +4687,7 @@ copy_model(cupsd_client_t *con, /* I - Client connection */ unlink(tempfile); - return (cupsFileClose(dst)); + return (cupsdCloseCreatedConfFile(dst, to)); } @@ -4809,7 +4724,7 @@ copy_job_attrs(cupsd_client_t *con, /* I - Client connection */ (!ra || cupsArrayFind(ra, "job-more-info"))) { httpAssembleURIf(HTTP_URI_CODING_ALL, job_uri, sizeof(job_uri), "http", - NULL, con->servername, con->serverport, "/jobs/%d", + NULL, con->clientname, con->clientport, "/jobs/%d", job->id); ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_URI, "job-more-info", NULL, job_uri); @@ -4830,7 +4745,7 @@ copy_job_attrs(cupsd_client_t *con, /* I - Client connection */ if (!ra || cupsArrayFind(ra, "job-printer-uri")) { httpAssembleURIf(HTTP_URI_CODING_ALL, job_uri, sizeof(job_uri), "ipp", NULL, - con->servername, con->serverport, + con->clientname, con->clientport, (job->dtype & CUPS_PRINTER_CLASS) ? "/classes/%s" : "/printers/%s", job->dest); @@ -4841,13 +4756,67 @@ copy_job_attrs(cupsd_client_t *con, /* I - Client connection */ if (!ra || cupsArrayFind(ra, "job-uri")) { httpAssembleURIf(HTTP_URI_CODING_ALL, job_uri, sizeof(job_uri), "ipp", NULL, - con->servername, con->serverport, "/jobs/%d", + con->clientname, con->clientport, "/jobs/%d", job->id); ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_URI, "job-uri", NULL, job_uri); } - copy_attrs(con->response, job->attrs, ra, IPP_TAG_JOB, 0, exclude); + if (job->attrs) + { + copy_attrs(con->response, job->attrs, ra, IPP_TAG_JOB, 0, exclude); + } + else + { + /* + * Generate attributes from the job structure... + */ + + if (job->completed_time && (!ra || cupsArrayFind(ra, "date-time-at-completed"))) + ippAddDate(con->response, IPP_TAG_JOB, "date-time-at-completed", ippTimeToDate(job->completed_time)); + + if (job->creation_time && (!ra || cupsArrayFind(ra, "date-time-at-creation"))) + ippAddDate(con->response, IPP_TAG_JOB, "date-time-at-creation", ippTimeToDate(job->creation_time)); + + if (!ra || cupsArrayFind(ra, "job-id")) + ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-id", job->id); + + if (!ra || cupsArrayFind(ra, "job-k-octets")) + ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-k-octets", job->koctets); + + if (job->name && (!ra || cupsArrayFind(ra, "job-name"))) + ippAddString(con->response, IPP_TAG_JOB, IPP_CONST_TAG(IPP_TAG_NAME), "job-name", NULL, job->name); + + if (job->username && (!ra || cupsArrayFind(ra, "job-originating-user-name"))) + ippAddString(con->response, IPP_TAG_JOB, IPP_CONST_TAG(IPP_TAG_NAME), "job-originating-user-name", NULL, job->username); + + if (!ra || cupsArrayFind(ra, "job-state")) + ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_ENUM, "job-state", (int)job->state_value); + + if (!ra || cupsArrayFind(ra, "job-state-reasons")) + { + switch (job->state_value) + { + default : /* Should never get here for processing, pending, held, or stopped jobs since they don't get unloaded... */ + break; + case IPP_JSTATE_ABORTED : + ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "job-aborted-by-system"); + break; + case IPP_JSTATE_CANCELED : + ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "job-canceled-by-user"); + break; + case IPP_JSTATE_COMPLETED : + ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_KEYWORD, "job-state-reasons", NULL, "job-completed-successfully"); + break; + } + } + + if (job->completed_time && (!ra || cupsArrayFind(ra, "time-at-completed"))) + ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "time-at-completed", (int)job->completed_time); + + if (job->creation_time && (!ra || cupsArrayFind(ra, "time-at-creation"))) + ippAddInteger(con->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "time-at-creation", (int)job->creation_time); + } } @@ -4904,8 +4873,8 @@ copy_printer_attrs( else { httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, - sizeof(printer_uri), "ipp", NULL, con->servername, - con->serverport, + sizeof(printer_uri), "ipp", NULL, con->clientname, + con->clientport, (p2->type & CUPS_PRINTER_CLASS) ? "/classes/%s" : "/printers/%s", p2->name); member_uris->values[i].string.text = _cupsStrAlloc(printer_uri); @@ -4924,6 +4893,13 @@ copy_printer_attrs( "printer-alert-description", NULL, printer->alert_description); + if (!ra || cupsArrayFind(ra, "printer-config-change-date-time")) + ippAddDate(con->response, IPP_TAG_PRINTER, "printer-config-change-date-time", ippTimeToDate(printer->config_time)); + + if (!ra || cupsArrayFind(ra, "printer-config-change-time")) + ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER, + "printer-config-change-time", printer->config_time); + if (!ra || cupsArrayFind(ra, "printer-current-time")) ippAddDate(con->response, IPP_TAG_PRINTER, "printer-current-time", ippTimeToDate(curtime)); @@ -4966,7 +4942,7 @@ copy_printer_attrs( if (!ra || cupsArrayFind(ra, "printer-icons")) { httpAssembleURIf(HTTP_URI_CODING_ALL, printer_icons, sizeof(printer_icons), - "http", NULL, con->servername, con->serverport, + "http", NULL, con->clientname, con->clientport, "/icons/%s.png", printer->name); ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-icons", NULL, printer_icons); @@ -4974,17 +4950,15 @@ copy_printer_attrs( } if (!ra || cupsArrayFind(ra, "printer-is-accepting-jobs")) - ippAddBoolean(con->response, IPP_TAG_PRINTER, "printer-is-accepting-jobs", - printer->accepting); + ippAddBoolean(con->response, IPP_TAG_PRINTER, "printer-is-accepting-jobs", (char)printer->accepting); if (!ra || cupsArrayFind(ra, "printer-is-shared")) - ippAddBoolean(con->response, IPP_TAG_PRINTER, "printer-is-shared", - printer->shared); + ippAddBoolean(con->response, IPP_TAG_PRINTER, "printer-is-shared", (char)printer->shared); if (!ra || cupsArrayFind(ra, "printer-more-info")) { httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, sizeof(printer_uri), - "http", NULL, con->servername, con->serverport, + "http", NULL, con->clientname, con->clientport, (printer->type & CUPS_PRINTER_CLASS) ? "/classes/%s" : "/printers/%s", printer->name); ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_URI, @@ -4999,6 +4973,9 @@ copy_printer_attrs( ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state", printer->state); + if (!ra || cupsArrayFind(ra, "printer-state-change-date-time")) + ippAddDate(con->response, IPP_TAG_PRINTER, "printer-state-change-date-time", ippTimeToDate(printer->state_time)); + if (!ra || cupsArrayFind(ra, "printer-state-change-time")) ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "printer-state-change-time", printer->state_time); @@ -5012,7 +4989,7 @@ copy_printer_attrs( if (!ra || cupsArrayFind(ra, "printer-type")) { - int type; /* printer-type value */ + cups_ptype_t type; /* printer-type value */ /* * Add the CUPS-specific printer-type attribute... @@ -5029,8 +5006,7 @@ copy_printer_attrs( if (!printer->shared) type |= CUPS_PRINTER_NOT_SHARED; - ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-type", - type); + ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-type", (int)type); } if (!ra || cupsArrayFind(ra, "printer-up-time")) @@ -5040,7 +5016,7 @@ copy_printer_attrs( if (!ra || cupsArrayFind(ra, "printer-uri-supported")) { httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, sizeof(printer_uri), - "ipp", NULL, con->servername, con->serverport, + "ipp", NULL, con->clientname, con->clientport, (printer->type & CUPS_PRINTER_CLASS) ? "/classes/%s" : "/printers/%s", printer->name); ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_URI, @@ -5167,7 +5143,7 @@ copy_subscription_attrs( if (sub->dest && (!ra || cupsArrayFind(ra, "notify-printer-uri"))) { httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, sizeof(printer_uri), - "ipp", NULL, con->servername, con->serverport, + "ipp", NULL, con->clientname, con->clientport, "/printers/%s", sub->dest->name); ippAddString(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_URI, "notify-printer-uri", NULL, printer_uri); @@ -5200,7 +5176,7 @@ create_job(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "create_job(%p[%d], %s)", con, - con->http.fd, uri->values[0].string.text); + con->number, uri->values[0].string.text); /* * Is the destination valid? @@ -5265,251 +5241,34 @@ create_job(cupsd_client_t *con, /* I - Client connection */ static cups_array_t * /* O - Array of attributes or NULL */ create_requested_array(ipp_t *request) /* I - IPP request */ { - int i; /* Looping var */ - ipp_attribute_t *requested; /* requested-attributes attribute */ cups_array_t *ra; /* Requested attributes array */ - char *value; /* Current value */ /* - * Get the requested-attributes attribute, and return NULL if we don't - * have one... + * Create the array for standard attributes... */ - if ((requested = ippFindAttribute(request, "requested-attributes", - IPP_TAG_KEYWORD)) == NULL) - return (NULL); + ra = ippCreateRequestedArray(request); /* - * If the attribute contains a single "all" keyword, return NULL... + * Add CUPS defaults as needed... */ - if (requested->num_values == 1 && - !strcmp(requested->values[0].string.text, "all")) - return (NULL); + if (cupsArrayFind(ra, "printer-defaults")) + { + /* + * Include user-set defaults... + */ - /* - * Create an array using "strcmp" as the comparison function... - */ - - ra = cupsArrayNew((cups_array_func_t)strcmp, NULL); - - for (i = 0; i < requested->num_values; i ++) - { - value = requested->values[i].string.text; - - if (!strcmp(value, "job-template")) - { - /* Only includes the set of Job Template attributes supported by CUPS */ - cupsArrayAdd(ra, "copies"); - cupsArrayAdd(ra, "copies-default"); - cupsArrayAdd(ra, "copies-supported"); - cupsArrayAdd(ra, "finishings"); - cupsArrayAdd(ra, "finishings-default"); - cupsArrayAdd(ra, "finishings-supported"); - cupsArrayAdd(ra, "job-hold-until"); - cupsArrayAdd(ra, "job-hold-until-default"); - cupsArrayAdd(ra, "job-hold-until-supported"); - cupsArrayAdd(ra, "job-priority"); - cupsArrayAdd(ra, "job-priority-default"); - cupsArrayAdd(ra, "job-priority-supported"); - cupsArrayAdd(ra, "job-sheets"); - cupsArrayAdd(ra, "job-sheets-default"); - cupsArrayAdd(ra, "job-sheets-supported"); - cupsArrayAdd(ra, "media"); - cupsArrayAdd(ra, "media-col"); - cupsArrayAdd(ra, "media-col-default"); - cupsArrayAdd(ra, "media-default"); - cupsArrayAdd(ra, "media-supported"); - cupsArrayAdd(ra, "multiple-document-handling"); - cupsArrayAdd(ra, "multiple-document-handling-default"); - cupsArrayAdd(ra, "multiple-document-handling-supported"); - cupsArrayAdd(ra, "number-up"); - cupsArrayAdd(ra, "number-up-default"); - cupsArrayAdd(ra, "number-up-layout"); - cupsArrayAdd(ra, "number-up-layout-default"); - cupsArrayAdd(ra, "number-up-layout-supported"); - cupsArrayAdd(ra, "number-up-supported"); - cupsArrayAdd(ra, "orientation-requested"); - cupsArrayAdd(ra, "orientation-requested-default"); - cupsArrayAdd(ra, "orientation-requested-supported"); - cupsArrayAdd(ra, "output-bin"); - cupsArrayAdd(ra, "output-bin-default"); - cupsArrayAdd(ra, "output-bin-supported"); - cupsArrayAdd(ra, "page-delivery"); - cupsArrayAdd(ra, "page-delivery-default"); - cupsArrayAdd(ra, "page-delivery-supported"); - cupsArrayAdd(ra, "page-order-received"); - cupsArrayAdd(ra, "page-order-received-default"); - cupsArrayAdd(ra, "page-order-received-supported"); - cupsArrayAdd(ra, "page-ranges"); - cupsArrayAdd(ra, "page-ranges-supported"); - cupsArrayAdd(ra, "presentation-direction-number-up"); - cupsArrayAdd(ra, "presentation-direction-number-up-default"); - cupsArrayAdd(ra, "presentation-direction-number-up-supported"); - cupsArrayAdd(ra, "print-color-mode"); - cupsArrayAdd(ra, "print-color-mode-default"); - cupsArrayAdd(ra, "print-color-mode-supported"); - cupsArrayAdd(ra, "print-content-optimize"); - cupsArrayAdd(ra, "print-content-optimize-default"); - cupsArrayAdd(ra, "print-content-optimize-supported"); - cupsArrayAdd(ra, "print-quality"); - cupsArrayAdd(ra, "print-quality-default"); - cupsArrayAdd(ra, "print-quality-supported"); - cupsArrayAdd(ra, "printer-resolution"); - cupsArrayAdd(ra, "printer-resolution-default"); - cupsArrayAdd(ra, "printer-resolution-supported"); - cupsArrayAdd(ra, "sheet-collate"); - cupsArrayAdd(ra, "sheet-collate-default"); - cupsArrayAdd(ra, "sheet-collate-supported"); - cupsArrayAdd(ra, "sides"); - cupsArrayAdd(ra, "sides-default"); - cupsArrayAdd(ra, "sides-supported"); - } - else if (!strcmp(value, "job-description")) - { - /* Only includes the set of Job Description attributes supported by CUPS */ - cupsArrayAdd(ra, "date-time-at-completed"); - cupsArrayAdd(ra, "date-time-at-creation"); - cupsArrayAdd(ra, "date-time-at-processing"); - cupsArrayAdd(ra, "job-detailed-status-message"); - cupsArrayAdd(ra, "job-document-access-errors"); - cupsArrayAdd(ra, "job-id"); - cupsArrayAdd(ra, "job-impressions"); - cupsArrayAdd(ra, "job-impressions-completed"); - cupsArrayAdd(ra, "job-k-octets"); - cupsArrayAdd(ra, "job-k-octets-processed"); - cupsArrayAdd(ra, "job-mandatory-attributes"); - cupsArrayAdd(ra, "job-media-progress"); - cupsArrayAdd(ra, "job-media-sheets"); - cupsArrayAdd(ra, "job-media-sheets-completed"); - cupsArrayAdd(ra, "job-message-from-operator"); - cupsArrayAdd(ra, "job-more-info"); - cupsArrayAdd(ra, "job-name"); - cupsArrayAdd(ra, "job-originating-user-name"); - cupsArrayAdd(ra, "job-printer-up-time"); - cupsArrayAdd(ra, "job-printer-uri"); - cupsArrayAdd(ra, "job-state"); - cupsArrayAdd(ra, "job-state-message"); - cupsArrayAdd(ra, "job-state-reasons"); - cupsArrayAdd(ra, "job-uri"); - cupsArrayAdd(ra, "number-of-documents"); - cupsArrayAdd(ra, "number-of-intervening-jobs"); - cupsArrayAdd(ra, "output-device-assigned"); - cupsArrayAdd(ra, "time-at-completed"); - cupsArrayAdd(ra, "time-at-creation"); - cupsArrayAdd(ra, "time-at-processing"); - } - else if (!strcmp(value, "printer-description")) - { - /* Only includes the set of Printer Description attributes supported by CUPS */ - cupsArrayAdd(ra, "charset-configured"); - cupsArrayAdd(ra, "charset-supported"); - cupsArrayAdd(ra, "color-supported"); - cupsArrayAdd(ra, "compression-supported"); - cupsArrayAdd(ra, "document-format-default"); - cupsArrayAdd(ra, "document-format-supported"); - cupsArrayAdd(ra, "generated-natural-language-supported"); - cupsArrayAdd(ra, "ipp-versions-supported"); - cupsArrayAdd(ra, "job-creation-attributes-supported"); - cupsArrayAdd(ra, "job-ids-supported"); - cupsArrayAdd(ra, "job-impressions-supported"); - cupsArrayAdd(ra, "job-k-octets-supported"); - cupsArrayAdd(ra, "job-media-sheets-supported"); - cupsArrayAdd(ra, "job-settable-attributes-supported"); - cupsArrayAdd(ra, "jpeg-k-octets-supported"); - cupsArrayAdd(ra, "jpeg-x-dimension-supported"); - cupsArrayAdd(ra, "jpeg-y-dimension-supported"); - cupsArrayAdd(ra, "media-bottom-margin-supported"); - cupsArrayAdd(ra, "media-col-supported"); - cupsArrayAdd(ra, "media-key-supported"); - cupsArrayAdd(ra, "media-left-margin-supported"); - cupsArrayAdd(ra, "media-right-margin-supported"); - cupsArrayAdd(ra, "media-size-supported"); - cupsArrayAdd(ra, "media-source-supported"); - cupsArrayAdd(ra, "media-top-margin-supported"); - cupsArrayAdd(ra, "media-type-supported"); - cupsArrayAdd(ra, "multiple-document-jobs-supported"); - cupsArrayAdd(ra, "multiple-operation-time-out"); - cupsArrayAdd(ra, "natural-language-configured"); - cupsArrayAdd(ra, "notify-max-events-supported"); - cupsArrayAdd(ra, "notify-schemes-supported"); - cupsArrayAdd(ra, "operations-supported"); - cupsArrayAdd(ra, "pages-per-minute"); - cupsArrayAdd(ra, "pages-per-minute-color"); - cupsArrayAdd(ra, "pdf-k-octets-supported"); - cupsArrayAdd(ra, "pdl-override-supported"); - cupsArrayAdd(ra, "printer-alert"); - cupsArrayAdd(ra, "printer-alert-description"); - cupsArrayAdd(ra, "printer-commands"); - cupsArrayAdd(ra, "printer-current-time"); - cupsArrayAdd(ra, "printer-dns-sd-name"); - cupsArrayAdd(ra, "printer-info"); - cupsArrayAdd(ra, "printer-is-accepting-jobs"); - cupsArrayAdd(ra, "printer-is-shared"); - cupsArrayAdd(ra, "printer-location"); - cupsArrayAdd(ra, "printer-make-and-model"); - cupsArrayAdd(ra, "printer-message-from-operator"); - cupsArrayAdd(ra, "printer-more-info"); - cupsArrayAdd(ra, "printer-more-info-manufacturer"); - cupsArrayAdd(ra, "printer-name"); - cupsArrayAdd(ra, "printer-settable-attributes-supported"); - cupsArrayAdd(ra, "printer-state"); - cupsArrayAdd(ra, "printer-state-change-date-time"); - cupsArrayAdd(ra, "printer-state-change-time"); - cupsArrayAdd(ra, "printer-state-message"); - cupsArrayAdd(ra, "printer-state-reasons"); - cupsArrayAdd(ra, "printer-type"); - cupsArrayAdd(ra, "printer-up-time"); - cupsArrayAdd(ra, "printer-uri-supported"); - cupsArrayAdd(ra, "queued-job-count"); - cupsArrayAdd(ra, "reference-uri-schemes-supported"); - cupsArrayAdd(ra, "uri-authentication-supported"); - cupsArrayAdd(ra, "uri-security-supported"); - cupsArrayAdd(ra, "which-jobs-supported"); - } - else if (!strcmp(value, "printer-defaults")) - { - char *name; /* Option name */ - - - for (name = (char *)cupsArrayFirst(CommonDefaults); - name; - name = (char *)cupsArrayNext(CommonDefaults)) + char *name; /* Option name */ + + cupsArrayRemove(ra, "printer-defaults"); + + for (name = (char *)cupsArrayFirst(CommonDefaults); + name; + name = (char *)cupsArrayNext(CommonDefaults)) + if (!cupsArrayFind(ra, name)) cupsArrayAdd(ra, name); - } - else if (!strcmp(value, "subscription-description")) - { - /* Only includes the set of Subscription Description attributes supported by CUPS */ - cupsArrayAdd(ra, "notify-job-id"); - cupsArrayAdd(ra, "notify-lease-expiration-time"); - cupsArrayAdd(ra, "notify-printer-up-time"); - cupsArrayAdd(ra, "notify-printer-uri"); - cupsArrayAdd(ra, "notify-sequence-number"); - cupsArrayAdd(ra, "notify-subscriber-user-name"); - cupsArrayAdd(ra, "notify-subscription-id"); - } - else if (!strcmp(value, "subscription-template")) - { - /* Only includes the set of Subscription Template attributes supported by CUPS */ - cupsArrayAdd(ra, "notify-attributes"); - cupsArrayAdd(ra, "notify-attributes-supported"); - cupsArrayAdd(ra, "notify-charset"); - cupsArrayAdd(ra, "notify-events"); - cupsArrayAdd(ra, "notify-events-default"); - cupsArrayAdd(ra, "notify-events-supported"); - cupsArrayAdd(ra, "notify-lease-duration"); - cupsArrayAdd(ra, "notify-lease-duration-default"); - cupsArrayAdd(ra, "notify-lease-duration-supported"); - cupsArrayAdd(ra, "notify-natural-language"); - cupsArrayAdd(ra, "notify-pull-method"); - cupsArrayAdd(ra, "notify-pull-method-supported"); - cupsArrayAdd(ra, "notify-recipient-uri"); - cupsArrayAdd(ra, "notify-time-interval"); - cupsArrayAdd(ra, "notify-user-data"); - } - else - cupsArrayAdd(ra, value); } return (ra); @@ -5517,11 +5276,11 @@ create_requested_array(ipp_t *request) /* I - IPP request */ /* - * 'create_subscription()' - Create a notification subscription. + * 'create_subscriptions()' - Create one or more notification subscriptions. */ static void -create_subscription( +create_subscriptions( cupsd_client_t *con, /* I - Client connection */ ipp_attribute_t *uri) /* I - Printer URI */ { @@ -5569,9 +5328,7 @@ create_subscription( * Is the destination valid? */ - cupsdLogMessage(CUPSD_LOG_DEBUG, - "cupsdCreateSubscription(con=%p(%d), uri=\"%s\")", - con, con->http.fd, uri->values[0].string.text); + cupsdLogMessage(CUPSD_LOG_DEBUG, "create_subscriptions(con=%p(%d), uri=\"%s\")", con, con->number, uri->values[0].string.text); httpSeparateURI(HTTP_URI_CODING_ALL, uri->values[0].string.text, scheme, sizeof(scheme), userpass, sizeof(userpass), host, @@ -5822,7 +5579,7 @@ create_subscription( if (MaxLeaseDuration && (lease == 0 || lease > MaxLeaseDuration)) { cupsdLogMessage(CUPSD_LOG_INFO, - "create_subscription: Limiting notify-lease-duration to " + "create_subscriptions: Limiting notify-lease-duration to " "%d seconds.", MaxLeaseDuration); lease = MaxLeaseDuration; @@ -5868,7 +5625,7 @@ create_subscription( { sub->user_data_len = user_data->values[0].unknown.length; memcpy(sub->user_data, user_data->values[0].unknown.data, - sub->user_data_len); + (size_t)sub->user_data_len); } ippAddSeparator(con->response); @@ -5900,7 +5657,7 @@ delete_printer(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "delete_printer(%p[%d], %s)", con, - con->http.fd, uri->values[0].string.text); + con->number, uri->values[0].string.text); /* * Do we have a valid URI? @@ -5951,10 +5708,16 @@ delete_printer(cupsd_client_t *con, /* I - Client connection */ snprintf(filename, sizeof(filename), "%s/interfaces/%s", ServerRoot, printer->name); unlink(filename); + snprintf(filename, sizeof(filename), "%s/interfaces/%s.O", ServerRoot, + printer->name); + unlink(filename); snprintf(filename, sizeof(filename), "%s/ppd/%s.ppd", ServerRoot, printer->name); unlink(filename); + snprintf(filename, sizeof(filename), "%s/ppd/%s.ppd.O", ServerRoot, + printer->name); + unlink(filename); snprintf(filename, sizeof(filename), "%s/%s.png", CacheDir, printer->name); unlink(filename); @@ -6008,7 +5771,7 @@ get_default(cupsd_client_t *con) /* I - Client connection */ cups_array_t *ra; /* Requested attributes array */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_default(%p[%d])", con, con->http.fd); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_default(%p[%d])", con, con->number); /* * Check policy... @@ -6058,7 +5821,7 @@ get_devices(cupsd_client_t *con) /* I - Client connection */ /* String for included schemes */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_devices(%p[%d])", con, con->http.fd); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_devices(%p[%d])", con, con->number); /* * Check policy... @@ -6152,7 +5915,7 @@ get_document(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_document(%p[%d], %s)", con, - con->http.fd, uri->values[0].string.text); + con->number, uri->values[0].string.text); /* * See if we have a job URI or a printer URI... @@ -6299,7 +6062,7 @@ get_job_attrs(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_job_attrs(%p[%d], %s)", con, - con->http.fd, uri->values[0].string.text); + con->number, uri->values[0].string.text); /* * See if we have a job URI or a printer URI... @@ -6413,19 +6176,24 @@ get_jobs(cupsd_client_t *con, /* I - Client connection */ int port; /* Port portion of URI */ int job_comparison; /* Job comparison */ ipp_jstate_t job_state; /* job-state value */ - int first_job_id; /* First job ID */ - int limit; /* Maximum number of jobs to return */ + int first_job_id = 1, /* First job ID */ + first_index = 1, /* First index */ + current_index = 0; /* Current index */ + int limit = 0; /* Maximum number of jobs to return */ int count; /* Number of jobs that match */ + int need_load_job = 0; /* Do we need to load the job? */ + const char *job_attr; /* Job attribute requested */ ipp_attribute_t *job_ids; /* job-ids attribute */ cupsd_job_t *job; /* Current job pointer */ cupsd_printer_t *printer; /* Printer */ cups_array_t *list; /* Which job list... */ + int delete_list = 0; /* Delete the list afterwards? */ cups_array_t *ra, /* Requested attributes array */ *exclude; /* Private attributes array */ cupsd_policy_t *policy; /* Current policy */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_jobs(%p[%d], %s)", con, con->http.fd, + cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_jobs(%p[%d], %s)", con, con->number, uri->values[0].string.text); /* @@ -6513,19 +6281,21 @@ get_jobs(cupsd_client_t *con, /* I - Client connection */ { job_comparison = -1; job_state = IPP_JOB_STOPPED; - list = Jobs; + list = ActiveJobs; } else if (!strcmp(attr->values[0].string.text, "completed")) { job_comparison = 1; job_state = IPP_JOB_CANCELED; - list = Jobs; + list = cupsdGetCompletedJobs(printer); + delete_list = 1; } else if (!strcmp(attr->values[0].string.text, "aborted")) { job_comparison = 0; job_state = IPP_JOB_ABORTED; - list = Jobs; + list = cupsdGetCompletedJobs(printer); + delete_list = 1; } else if (!strcmp(attr->values[0].string.text, "all")) { @@ -6537,7 +6307,8 @@ get_jobs(cupsd_client_t *con, /* I - Client connection */ { job_comparison = 0; job_state = IPP_JOB_CANCELED; - list = Jobs; + list = cupsdGetCompletedJobs(printer); + delete_list = 1; } else if (!strcmp(attr->values[0].string.text, "pending")) { @@ -6577,8 +6348,7 @@ get_jobs(cupsd_client_t *con, /* I - Client connection */ * See if they want to limit the number of jobs reported... */ - if ((attr = ippFindAttribute(con->request, "limit", - IPP_TAG_INTEGER)) != NULL) + if ((attr = ippFindAttribute(con->request, "limit", IPP_TAG_INTEGER)) != NULL) { if (job_ids) { @@ -6590,11 +6360,20 @@ get_jobs(cupsd_client_t *con, /* I - Client connection */ limit = attr->values[0].integer; } - else - limit = 0; - if ((attr = ippFindAttribute(con->request, "first-job-id", - IPP_TAG_INTEGER)) != NULL) + if ((attr = ippFindAttribute(con->request, "first-index", IPP_TAG_INTEGER)) != NULL) + { + if (job_ids) + { + send_ipp_status(con, IPP_CONFLICT, + _("The %s attribute cannot be provided with job-ids."), + "first-index"); + return; + } + + first_index = attr->values[0].integer; + } + else if ((attr = ippFindAttribute(con->request, "first-job-id", IPP_TAG_INTEGER)) != NULL) { if (job_ids) { @@ -6606,15 +6385,12 @@ get_jobs(cupsd_client_t *con, /* I - Client connection */ first_job_id = attr->values[0].integer; } - else - first_job_id = 1; /* * See if we only want to see jobs for a specific user... */ - if ((attr = ippFindAttribute(con->request, "my-jobs", - IPP_TAG_BOOLEAN)) != NULL && job_ids) + if ((attr = ippFindAttribute(con->request, "my-jobs", IPP_TAG_BOOLEAN)) != NULL && job_ids) { send_ipp_status(con, IPP_CONFLICT, _("The %s attribute cannot be provided with job-ids."), @@ -6626,17 +6402,42 @@ get_jobs(cupsd_client_t *con, /* I - Client connection */ else username[0] = '\0'; - if ((ra = create_requested_array(con->request)) == NULL && - !ippFindAttribute(con->request, "requested-attributes", IPP_TAG_KEYWORD)) + ra = create_requested_array(con->request); + for (job_attr = (char *)cupsArrayFirst(ra); job_attr; job_attr = (char *)cupsArrayNext(ra)) + if (strcmp(job_attr, "job-id") && + strcmp(job_attr, "job-k-octets") && + strcmp(job_attr, "job-media-progress") && + strcmp(job_attr, "job-more-info") && + strcmp(job_attr, "job-name") && + strcmp(job_attr, "job-originating-user-name") && + strcmp(job_attr, "job-preserved") && + strcmp(job_attr, "job-printer-up-time") && + strcmp(job_attr, "job-printer-uri") && + strcmp(job_attr, "job-state") && + strcmp(job_attr, "job-state-reasons") && + strcmp(job_attr, "job-uri") && + strcmp(job_attr, "time-at-completed") && + strcmp(job_attr, "time-at-creation") && + strcmp(job_attr, "number-of-documents")) + { + need_load_job = 1; + break; + } + + if (need_load_job && (limit == 0 || limit > 500) && (list == Jobs || delete_list)) { /* - * IPP conformance - Get-Jobs has a default requested-attributes value of - * "job-id" and "job-uri". + * Limit expensive Get-Jobs for job history to 500 jobs... */ - ra = cupsArrayNew((cups_array_func_t)strcmp, NULL); - cupsArrayAdd(ra, "job-id"); - cupsArrayAdd(ra, "job-uri"); + ippAddInteger(con->response, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "limit", 500); + + if (limit) + ippAddInteger(con->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_INTEGER, "limit", limit); + + limit = 500; + + cupsdLogClient(con, CUPSD_LOG_INFO, "Limiting Get-Jobs response to %d jobs.", limit); } /* @@ -6664,13 +6465,15 @@ get_jobs(cupsd_client_t *con, /* I - Client connection */ { job = cupsdFindJob(job_ids->values[i].integer); - cupsdLoadJob(job); - - if (!job->attrs) + if (need_load_job && !job->attrs) { - cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_jobs: No attributes for job %d", - job->id); - continue; + cupsdLoadJob(job); + + if (!job->attrs) + { + cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_jobs: No attributes for job %d", job->id); + continue; + } } if (i > 0) @@ -6720,13 +6523,19 @@ get_jobs(cupsd_client_t *con, /* I - Client connection */ if (job->id < first_job_id) continue; - cupsdLoadJob(job); + current_index ++; + if (current_index < first_index) + continue; - if (!job->attrs) + if (need_load_job && !job->attrs) { - cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_jobs: No attributes for job %d", - job->id); - continue; + cupsdLoadJob(job); + + if (!job->attrs) + { + cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_jobs: No attributes for job %d", job->id); + continue; + } } if (username[0] && _cups_strcasecmp(username, job->username)) @@ -6750,6 +6559,9 @@ get_jobs(cupsd_client_t *con, /* I - Client connection */ cupsArrayDelete(ra); + if (delete_list) + cupsArrayDelete(list); + con->response->request.status.status_code = IPP_OK; } @@ -6771,7 +6583,7 @@ get_notifications(cupsd_client_t *con) /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_notifications(con=%p[%d])", - con, con->http.fd); + con, con->number); /* * Get subscription attributes... @@ -6905,7 +6717,7 @@ get_ppd(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_ppd(%p[%d], %p[%s=%s])", con, - con->http.fd, uri, uri->name, uri->values[0].string.text); + con->number, uri, uri->name, uri->values[0].string.text); if (!strcmp(uri->name, "ppd-name")) { @@ -7078,7 +6890,7 @@ get_ppds(cupsd_client_t *con) /* I - Client connection */ /* String for included schemes */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_ppds(%p[%d])", con, con->http.fd); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_ppds(%p[%d])", con, con->number); /* * Check policy... @@ -7223,7 +7035,7 @@ get_printer_attrs(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_printer_attrs(%p[%d], %s)", con, - con->http.fd, uri->values[0].string.text); + con->number, uri->values[0].string.text); /* * Is the destination valid? @@ -7279,7 +7091,7 @@ get_printer_supported( cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_printer_supported(%p[%d], %s)", con, - con->http.fd, uri->values[0].string.text); + con->number, uri->values[0].string.text); /* * Is the destination valid? @@ -7311,9 +7123,15 @@ get_printer_supported( */ ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_ADMINDEFINE, + "printer-geo-location", 0); + ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_ADMINDEFINE, "printer-info", 0); ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_ADMINDEFINE, "printer-location", 0); + ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_ADMINDEFINE, + "printer-organization", 0); + ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_ADMINDEFINE, + "printer-organizational-unit", 0); con->response->request.status.status_code = IPP_OK; } @@ -7332,7 +7150,7 @@ get_printers(cupsd_client_t *con, /* I - Client connection */ int limit; /* Max number of printers to return */ int count; /* Number of printers that match */ cupsd_printer_t *printer; /* Current printer pointer */ - int printer_type, /* printer-type attribute */ + cups_ptype_t printer_type, /* printer-type attribute */ printer_mask; /* printer-type-mask attribute */ char *location; /* Location string */ const char *username; /* Current user */ @@ -7342,7 +7160,7 @@ get_printers(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_printers(%p[%d], %x)", con, - con->http.fd, type); + con->number, type); /* * Check policy... @@ -7386,15 +7204,15 @@ get_printers(cupsd_client_t *con, /* I - Client connection */ if ((attr = ippFindAttribute(con->request, "printer-type", IPP_TAG_ENUM)) != NULL) - printer_type = attr->values[0].integer; + printer_type = (cups_ptype_t)attr->values[0].integer; else - printer_type = 0; + printer_type = (cups_ptype_t)0; if ((attr = ippFindAttribute(con->request, "printer-type-mask", IPP_TAG_ENUM)) != NULL) - printer_mask = attr->values[0].integer; + printer_mask = (cups_ptype_t)attr->values[0].integer; else - printer_mask = 0; + printer_mask = (cups_ptype_t)0; local = httpAddrLocalhost(&(con->clientaddr)); @@ -7488,7 +7306,7 @@ get_subscription_attrs( cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_subscription_attrs(con=%p[%d], sub_id=%d)", - con, con->http.fd, sub_id); + con, con->number, sub_id); /* * Is the subscription ID valid? @@ -7569,7 +7387,7 @@ get_subscriptions(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_subscriptions(con=%p[%d], uri=%s)", - con, con->http.fd, uri->values[0].string.text); + con, con->number, uri->values[0].string.text); /* * Is the destination valid? @@ -7730,7 +7548,7 @@ hold_job(cupsd_client_t *con, /* I - Client connection */ cupsd_job_t *job; /* Job information */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, "hold_job(%p[%d], %s)", con, con->http.fd, + cupsdLogMessage(CUPSD_LOG_DEBUG2, "hold_job(%p[%d], %s)", con, con->number, uri->values[0].string.text); /* @@ -7859,7 +7677,7 @@ hold_new_jobs(cupsd_client_t *con, /* I - Connection */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "hold_new_jobs(%p[%d], %s)", con, - con->http.fd, uri->values[0].string.text); + con->number, uri->values[0].string.text); /* * Is the destination valid? @@ -7935,7 +7753,7 @@ move_job(cupsd_client_t *con, /* I - Client connection */ *dprinter; /* Destination printer */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, "move_job(%p[%d], %s)", con, con->http.fd, + cupsdLogMessage(CUPSD_LOG_DEBUG2, "move_job(%p[%d], %s)", con, con->number, uri->values[0].string.text); /* @@ -8248,6 +8066,7 @@ print_job(cupsd_client_t *con, /* I - Client connection */ ipp_attribute_t *uri) /* I - Printer URI */ { ipp_attribute_t *attr; /* Current attribute */ + ipp_attribute_t *doc_name; /* document-name attribute */ ipp_attribute_t *format; /* Document-format attribute */ const char *default_format; /* document-format-default value */ cupsd_job_t *job; /* New job */ @@ -8263,7 +8082,7 @@ print_job(cupsd_client_t *con, /* I - Client connection */ int compression; /* Document compression */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, "print_job(%p[%d], %s)", con, con->http.fd, + cupsdLogMessage(CUPSD_LOG_DEBUG2, "print_job(%p[%d], %s)", con, con->number, uri->values[0].string.text); /* @@ -8325,6 +8144,10 @@ print_job(cupsd_client_t *con, /* I - Client connection */ * Is it a format we support? */ + doc_name = ippFindAttribute(con->request, "document-name", IPP_TAG_NAME); + if (doc_name) + ippSetName(con->request, &doc_name, "document-name-supplied"); + if ((format = ippFindAttribute(con->request, "document-format", IPP_TAG_MIMETYPE)) != NULL) { @@ -8340,6 +8163,8 @@ print_job(cupsd_client_t *con, /* I - Client connection */ format->values[0].string.text); return; } + + ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_MIMETYPE, "document-format-supplied", NULL, ippGetString(format, 0, NULL)); } else if ((default_format = cupsGetOption("document-format", printer->num_options, @@ -8363,8 +8188,8 @@ print_job(cupsd_client_t *con, /* I - Client connection */ * Auto-type it! */ - strcpy(super, "application"); - strcpy(type, "octet-stream"); + strlcpy(super, "application", sizeof(super)); + strlcpy(type, "octet-stream", sizeof(type)); } if (!strcmp(super, "application") && !strcmp(type, "octet-stream")) @@ -8373,12 +8198,9 @@ print_job(cupsd_client_t *con, /* I - Client connection */ * Auto-type the file... */ - ipp_attribute_t *doc_name; /* document-name attribute */ - - cupsdLogMessage(CUPSD_LOG_DEBUG, "[Job ???] Auto-typing file..."); - doc_name = ippFindAttribute(con->request, "document-name", IPP_TAG_NAME); + filetype = mimeFileType(MimeDatabase, con->filename, doc_name ? doc_name->values[0].string.text : NULL, &compression); @@ -8388,6 +8210,9 @@ print_job(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_INFO, "[Job ???] Request file type is %s/%s.", filetype->super, filetype->type); + + snprintf(mimetype, sizeof(mimetype), "%s/%s", filetype->super, filetype->type); + ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_MIMETYPE, "document-format-detected", NULL, mimetype); } else filetype = mimeType(MimeDatabase, super, type); @@ -8405,11 +8230,7 @@ print_job(cupsd_client_t *con, /* I - Client connection */ filetype->type); if (format) - { - _cupsStrFree(format->values[0].string.text); - - format->values[0].string.text = _cupsStrAlloc(mimetype); - } + ippSetString(con->request, &format, 0, mimetype); else ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_MIMETYPE, "document-format", NULL, mimetype); @@ -8457,8 +8278,9 @@ print_job(cupsd_client_t *con, /* I - Client connection */ cupsdUpdateQuota(printer, job->username, 0, kbytes); - if ((attr = ippFindAttribute(job->attrs, "job-k-octets", - IPP_TAG_INTEGER)) != NULL) + job->koctets += kbytes; + + if ((attr = ippFindAttribute(job->attrs, "job-k-octets", IPP_TAG_INTEGER)) != NULL) attr->values[0].integer += kbytes; /* @@ -8468,9 +8290,15 @@ print_job(cupsd_client_t *con, /* I - Client connection */ if (add_file(con, job, filetype, compression)) return; - snprintf(filename, sizeof(filename), "%s/d%05d-%03d", RequestRoot, job->id, - job->num_files); - rename(con->filename, filename); + snprintf(filename, sizeof(filename), "%s/d%05d-%03d", RequestRoot, job->id, job->num_files); + if (rename(con->filename, filename)) + { + cupsdLogJob(job, CUPSD_LOG_ERROR, "Unable to rename job document file \"%s\": %s", filename, strerror(errno)); + + send_ipp_status(con, IPP_INTERNAL_ERROR, _("Unable to rename job document file.")); + return; + } + cupsdClearString(&con->filename); /* @@ -8629,12 +8457,17 @@ read_job_ticket(cupsd_client_t *con) /* I - Client connection */ if (attr->group_tag != IPP_TAG_JOB || !attr->name) continue; - if (!strcmp(attr->name, "job-originating-host-name") || - !strcmp(attr->name, "job-originating-user-name") || + if (!strncmp(attr->name, "date-time-at-", 13) || + !strcmp(attr->name, "job-impressions-completed") || !strcmp(attr->name, "job-media-sheets-completed") || - !strcmp(attr->name, "job-k-octets") || + !strncmp(attr->name, "job-k-octets", 12) || !strcmp(attr->name, "job-id") || + !strcmp(attr->name, "job-originating-host-name") || + !strcmp(attr->name, "job-originating-user-name") || + !strcmp(attr->name, "job-pages-completed") || + !strcmp(attr->name, "job-printer-uri") || !strncmp(attr->name, "job-state", 9) || + !strcmp(attr->name, "job-uri") || !strncmp(attr->name, "time-at-", 8)) continue; /* Read-only attrs */ @@ -8697,7 +8530,7 @@ reject_jobs(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "reject_jobs(%p[%d], %s)", con, - con->http.fd, uri->values[0].string.text); + con->number, uri->values[0].string.text); /* * Is the destination valid? @@ -8732,7 +8565,8 @@ reject_jobs(cupsd_client_t *con, /* I - Client connection */ if ((attr = ippFindAttribute(con->request, "printer-state-message", IPP_TAG_TEXT)) == NULL) - strcpy(printer->state_message, "Rejecting Jobs"); + strlcpy(printer->state_message, "Rejecting Jobs", + sizeof(printer->state_message)); else strlcpy(printer->state_message, attr->values[0].string.text, sizeof(printer->state_message)); @@ -8778,7 +8612,7 @@ release_held_new_jobs( cupsdLogMessage(CUPSD_LOG_DEBUG2, "release_held_new_jobs(%p[%d], %s)", con, - con->http.fd, uri->values[0].string.text); + con->number, uri->values[0].string.text); /* * Is the destination valid? @@ -8849,7 +8683,7 @@ release_job(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "release_job(%p[%d], %s)", con, - con->http.fd, uri->values[0].string.text); + con->number, uri->values[0].string.text); /* * See if we have a job URI or a printer URI... @@ -8944,10 +8778,8 @@ release_job(cupsd_client_t *con, /* I - Client connection */ if (attr) { - _cupsStrFree(attr->values[0].string.text); - - attr->value_tag = IPP_TAG_KEYWORD; - attr->values[0].string.text = _cupsStrAlloc("no-hold"); + ippSetValueTag(job->attrs, &attr, IPP_TAG_KEYWORD); + ippSetString(job->attrs, &attr, 0, "no-hold"); cupsdAddEvent(CUPSD_EVENT_JOB_CONFIG_CHANGED, cupsdFindDest(job->dest), job, "Job job-hold-until value changed by user."); @@ -8987,7 +8819,7 @@ renew_subscription( cupsdLogMessage(CUPSD_LOG_DEBUG2, "renew_subscription(con=%p[%d], sub_id=%d)", - con, con->http.fd, sub_id); + con, con->number, sub_id); /* * Is the subscription ID valid? @@ -9075,7 +8907,7 @@ restart_job(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "restart_job(%p[%d], %s)", con, - con->http.fd, uri->values[0].string.text); + con->number, uri->values[0].string.text); /* * See if we have a job URI or a printer URI... @@ -9299,8 +9131,7 @@ save_auth_info( { if (strcmp(dest->auth_info_required[i], "negotiate")) { - httpEncode64_2(line, sizeof(line), auth_info->values[i].string.text, - strlen(auth_info->values[i].string.text)); + httpEncode64_2(line, sizeof(line), auth_info->values[i].string.text, (int)strlen(auth_info->values[i].string.text)); cupsFilePutConf(fp, dest->auth_info_required[i], line); } else @@ -9331,15 +9162,13 @@ save_auth_info( * Allow fallback to username+password for Kerberized queues... */ - httpEncode64_2(line, sizeof(line), auth_info->values[0].string.text, - strlen(auth_info->values[0].string.text)); + httpEncode64_2(line, sizeof(line), auth_info->values[0].string.text, (int)strlen(auth_info->values[0].string.text)); cupsFilePutConf(fp, "username", line); cupsdSetStringf(job->auth_env + 0, "AUTH_USERNAME=%s", auth_info->values[0].string.text); - httpEncode64_2(line, sizeof(line), auth_info->values[1].string.text, - strlen(auth_info->values[1].string.text)); + httpEncode64_2(line, sizeof(line), auth_info->values[1].string.text, (int)strlen(auth_info->values[1].string.text)); cupsFilePutConf(fp, "password", line); cupsdSetStringf(job->auth_env + 1, "AUTH_PASSWORD=%s", @@ -9351,7 +9180,7 @@ save_auth_info( * Write the authenticated username... */ - httpEncode64_2(line, sizeof(line), con->username, strlen(con->username)); + httpEncode64_2(line, sizeof(line), con->username, (int)strlen(con->username)); cupsFilePutConf(fp, "username", line); cupsdSetStringf(job->auth_env + 0, "AUTH_USERNAME=%s", con->username); @@ -9360,7 +9189,7 @@ save_auth_info( * Write the authenticated password... */ - httpEncode64_2(line, sizeof(line), con->password, strlen(con->password)); + httpEncode64_2(line, sizeof(line), con->password, (int)strlen(con->password)); cupsFilePutConf(fp, "password", line); cupsdSetStringf(job->auth_env + 1, "AUTH_PASSWORD=%s", con->password); @@ -9430,7 +9259,7 @@ send_document(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "send_document(%p[%d], %s)", con, - con->http.fd, uri->values[0].string.text); + con->number, uri->values[0].string.text); /* * See if we have a job URI or a printer URI... @@ -9562,6 +9391,8 @@ send_document(cupsd_client_t *con, /* I - Client connection */ * Is it a format we support? */ + cupsdLoadJob(job); + if ((format = ippFindAttribute(con->request, "document-format", IPP_TAG_MIMETYPE)) != NULL) { @@ -9576,6 +9407,8 @@ send_document(cupsd_client_t *con, /* I - Client connection */ format->values[0].string.text); return; } + + ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_MIMETYPE, "document-format-supplied", NULL, ippGetString(format, 0, NULL)); } else if ((default_format = cupsGetOption("document-format", printer->num_options, @@ -9598,8 +9431,8 @@ send_document(cupsd_client_t *con, /* I - Client connection */ * No document format attribute? Auto-type it! */ - strcpy(super, "application"); - strcpy(type, "octet-stream"); + strlcpy(super, "application", sizeof(super)); + strlcpy(type, "octet-stream", sizeof(type)); } if (!strcmp(super, "application") && !strcmp(type, "octet-stream")) @@ -9624,6 +9457,9 @@ send_document(cupsd_client_t *con, /* I - Client connection */ if (filetype) cupsdLogJob(job, CUPSD_LOG_DEBUG, "Request file type is %s/%s.", filetype->super, filetype->type); + + snprintf(mimetype, sizeof(mimetype), "%s/%s", filetype->super, filetype->type); + ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_MIMETYPE, "document-format-detected", NULL, mimetype); } else filetype = mimeType(MimeDatabase, super, type); @@ -9640,11 +9476,7 @@ send_document(cupsd_client_t *con, /* I - Client connection */ if ((jformat = ippFindAttribute(job->attrs, "document-format", IPP_TAG_MIMETYPE)) != NULL) - { - _cupsStrFree(jformat->values[0].string.text); - - jformat->values[0].string.text = _cupsStrAlloc(mimetype); - } + ippSetString(job->attrs, &jformat, 0, mimetype); else ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_MIMETYPE, "document-format", NULL, mimetype); @@ -9681,11 +9513,12 @@ send_document(cupsd_client_t *con, /* I - Client connection */ * Add the file to the job... */ - cupsdLoadJob(job); - if (add_file(con, job, filetype, compression)) return; + if ((attr = ippFindAttribute(con->request, "document-name", IPP_TAG_NAME)) != NULL) + ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_NAME, "document-name-supplied", NULL, ippGetString(attr, 0, NULL)); + if (stat(con->filename, &fileinfo)) kbytes = 0; else @@ -9693,13 +9526,19 @@ send_document(cupsd_client_t *con, /* I - Client connection */ cupsdUpdateQuota(printer, job->username, 0, kbytes); - if ((attr = ippFindAttribute(job->attrs, "job-k-octets", - IPP_TAG_INTEGER)) != NULL) + job->koctets += kbytes; + + if ((attr = ippFindAttribute(job->attrs, "job-k-octets", IPP_TAG_INTEGER)) != NULL) attr->values[0].integer += kbytes; - snprintf(filename, sizeof(filename), "%s/d%05d-%03d", RequestRoot, job->id, - job->num_files); - rename(con->filename, filename); + snprintf(filename, sizeof(filename), "%s/d%05d-%03d", RequestRoot, job->id, job->num_files); + if (rename(con->filename, filename)) + { + cupsdLogJob(job, CUPSD_LOG_ERROR, "Unable to rename job document file \"%s\": %s", filename, strerror(errno)); + + send_ipp_status(con, IPP_INTERNAL_ERROR, _("Unable to rename job document file.")); + return; + } cupsdClearString(&con->filename); @@ -9778,7 +9617,7 @@ send_document(cupsd_client_t *con, /* I - Client connection */ */ httpAssembleURIf(HTTP_URI_CODING_ALL, job_uri, sizeof(job_uri), "ipp", NULL, - con->servername, con->serverport, "/jobs/%d", jobid); + con->clientname, con->clientport, "/jobs/%d", jobid); ippAddString(con->response, IPP_TAG_JOB, IPP_TAG_URI, "job-uri", NULL, job_uri); @@ -9818,13 +9657,13 @@ send_http_error( uri = ippFindAttribute(con->request, "job-uri", IPP_TAG_URI); cupsdLogMessage(status == HTTP_FORBIDDEN ? CUPSD_LOG_ERROR : CUPSD_LOG_DEBUG, - "Returning HTTP %s for %s (%s) from %s", - httpStatus(status), + "[Client %d] Returning HTTP %s for %s (%s) from %s", + con->number, httpStatus(status), con->request ? ippOpString(con->request->request.op.operation_id) : "no operation-id", uri ? uri->values[0].string.text : "no URI", - con->http.hostname); + con->http->hostname); if (printer) { @@ -9945,7 +9784,7 @@ set_default(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "set_default(%p[%d], %s)", con, - con->http.fd, uri->values[0].string.text); + con->number, uri->values[0].string.text); /* * Is the destination valid? @@ -10027,7 +9866,7 @@ set_job_attrs(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "set_job_attrs(%p[%d], %s)", con, - con->http.fd, uri->values[0].string.text); + con->number, uri->values[0].string.text); /* * Start with "everything is OK" status... @@ -10135,15 +9974,18 @@ set_job_attrs(cupsd_client_t *con, /* I - Client connection */ if (!strcmp(attr->name, "attributes-charset") || !strcmp(attr->name, "attributes-natural-language") || - !strcmp(attr->name, "document-compression") || - !strcmp(attr->name, "document-format") || + !strncmp(attr->name, "date-time-at-", 13) || + !strncmp(attr->name, "document-compression", 20) || + !strncmp(attr->name, "document-format", 15) || !strcmp(attr->name, "job-detailed-status-messages") || !strcmp(attr->name, "job-document-access-errors") || !strcmp(attr->name, "job-id") || !strcmp(attr->name, "job-impressions-completed") || - !strcmp(attr->name, "job-k-octets") || + !strcmp(attr->name, "job-k-octets-completed") || + !strcmp(attr->name, "job-media-sheets-completed") || !strcmp(attr->name, "job-originating-host-name") || !strcmp(attr->name, "job-originating-user-name") || + !strcmp(attr->name, "job-pages-completed") || !strcmp(attr->name, "job-printer-up-time") || !strcmp(attr->name, "job-printer-uri") || !strcmp(attr->name, "job-sheets") || @@ -10153,9 +9995,6 @@ set_job_attrs(cupsd_client_t *con, /* I - Client connection */ !strcmp(attr->name, "number-of-documents") || !strcmp(attr->name, "number-of-intervening-jobs") || !strcmp(attr->name, "output-device-assigned") || - !strncmp(attr->name, "date-time-at-", 13) || - !strncmp(attr->name, "job-k-octets", 12) || - !strncmp(attr->name, "job-media-sheets", 16) || !strncmp(attr->name, "time-at-", 8)) { /* @@ -10229,9 +10068,7 @@ set_job_attrs(cupsd_client_t *con, /* I - Client connection */ { cupsdLogJob(job, CUPSD_LOG_DEBUG, "Setting job-state to %d", attr->values[0].integer); - cupsdSetJobState(job, attr->values[0].integer, - CUPSD_JOB_DEFAULT, - "Job state changed by \"%s\"", username); + cupsdSetJobState(job, (ipp_jstate_t)attr->values[0].integer, CUPSD_JOB_DEFAULT, "Job state changed by \"%s\"", username); check_jobs = 1; } break; @@ -10399,7 +10236,7 @@ set_printer_attrs(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "set_printer_attrs(%p[%d], %s)", con, - con->http.fd, uri->values[0].string.text); + con->number, uri->values[0].string.text); /* * Is the destination valid? @@ -10437,6 +10274,24 @@ set_printer_attrs(cupsd_client_t *con, /* I - Client connection */ changed = 1; } + if ((attr = ippFindAttribute(con->request, "printer-geo-location", IPP_TAG_URI)) != NULL && !strncmp(attr->values[0].string.text, "geo:", 4)) + { + cupsdSetString(&printer->geo_location, attr->values[0].string.text); + changed = 1; + } + + if ((attr = ippFindAttribute(con->request, "printer-organization", IPP_TAG_TEXT)) != NULL) + { + cupsdSetString(&printer->organization, attr->values[0].string.text); + changed = 1; + } + + if ((attr = ippFindAttribute(con->request, "printer-organizational-unit", IPP_TAG_TEXT)) != NULL) + { + cupsdSetString(&printer->organizational_unit, attr->values[0].string.text); + changed = 1; + } + if ((attr = ippFindAttribute(con->request, "printer-info", IPP_TAG_TEXT)) != NULL) { @@ -10450,6 +10305,8 @@ set_printer_attrs(cupsd_client_t *con, /* I - Client connection */ if (changed) { + printer->config_time = time(NULL); + cupsdSetPrinterAttrs(printer); cupsdMarkDirty(CUPSD_DIRTY_PRINTERS); @@ -10477,7 +10334,7 @@ set_printer_defaults( { int i; /* Looping var */ ipp_attribute_t *attr; /* Current attribute */ - int namelen; /* Length of attribute name */ + size_t namelen; /* Length of attribute name */ char name[256], /* New attribute name */ value[256]; /* String version of integer attrs */ @@ -10652,6 +10509,7 @@ set_printer_defaults( break; case IPP_TAG_NAME : + case IPP_TAG_TEXT : case IPP_TAG_KEYWORD : case IPP_TAG_URI : printer->num_options = cupsAddOption(name, @@ -10729,7 +10587,7 @@ start_printer(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "start_printer(%p[%d], %s)", con, - con->http.fd, uri->values[0].string.text); + con->number, uri->values[0].string.text); /* * Is the destination valid? @@ -10811,7 +10669,7 @@ stop_printer(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "stop_printer(%p[%d], %s)", con, - con->http.fd, uri->values[0].string.text); + con->number, uri->values[0].string.text); /* * Is the destination valid? @@ -10844,7 +10702,7 @@ stop_printer(cupsd_client_t *con, /* I - Client connection */ if ((attr = ippFindAttribute(con->request, "printer-state-message", IPP_TAG_TEXT)) == NULL) - strcpy(printer->state_message, "Paused"); + strlcpy(printer->state_message, "Paused", sizeof(printer->state_message)); else { strlcpy(printer->state_message, attr->values[0].string.text, @@ -10875,7 +10733,7 @@ stop_printer(cupsd_client_t *con, /* I - Client connection */ static void url_encode_attr(ipp_attribute_t *attr, /* I - Attribute */ char *buffer,/* I - String buffer */ - int bufsize)/* I - Size of buffer */ + size_t bufsize)/* I - Size of buffer */ { int i; /* Looping var */ char *bufptr, /* Pointer into buffer */ @@ -10901,8 +10759,7 @@ url_encode_attr(ipp_attribute_t *attr, /* I - Attribute */ *bufptr++ = '\''; - bufptr = url_encode_string(attr->values[i].string.text, - bufptr, bufend - bufptr + 1); + bufptr = url_encode_string(attr->values[i].string.text, bufptr, (size_t)(bufend - bufptr + 1)); if (bufptr >= bufend) break; @@ -10921,7 +10778,7 @@ url_encode_attr(ipp_attribute_t *attr, /* I - Attribute */ static char * /* O - End of string */ url_encode_string(const char *s, /* I - String */ char *buffer, /* I - String buffer */ - int bufsize) /* I - Size of buffer */ + size_t bufsize) /* I - Size of buffer */ { char *bufptr, /* Pointer into buffer */ *bufend; /* End of buffer */ @@ -11039,8 +10896,10 @@ validate_job(cupsd_client_t *con, /* I - Client connection */ ipp_attribute_t *uri) /* I - Printer URI */ { http_status_t status; /* Policy status */ - ipp_attribute_t *attr, /* Current attribute */ - *auth_info; /* auth-info attribute */ + ipp_attribute_t *attr; /* Current attribute */ +#ifdef HAVE_SSL + ipp_attribute_t *auth_info; /* auth-info attribute */ +#endif /* HAVE_SSL */ ipp_attribute_t *format, /* Document-format attribute */ *name; /* Job-name attribute */ cups_ptype_t dtype; /* Destination type (printer/class) */ @@ -11052,7 +10911,7 @@ validate_job(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "validate_job(%p[%d], %s)", con, - con->http.fd, uri->values[0].string.text); + con->number, uri->values[0].string.text); /* * OK, see if the client is sending the document compressed - CUPS @@ -11206,7 +11065,9 @@ validate_job(cupsd_client_t *con, /* I - Client connection */ * Check policy... */ +#ifdef HAVE_SSL auth_info = ippFindAttribute(con->request, "auth-info", IPP_TAG_TEXT); +#endif /* HAVE_SSL */ if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con, NULL)) != HTTP_OK) { @@ -11221,8 +11082,8 @@ validate_job(cupsd_client_t *con, /* I - Client connection */ return; } #ifdef HAVE_SSL - else if (auth_info && !con->http.tls && - !httpAddrLocalhost(con->http.hostaddr)) + else if (auth_info && !con->http->tls && + !httpAddrLocalhost(con->http->hostaddr)) { /* * Require encryption of auth-info over non-local connections... @@ -11276,16 +11137,12 @@ validate_user(cupsd_job_t *job, /* I - Job */ cupsd_client_t *con, /* I - Client connection */ const char *owner, /* I - Owner of job/resource */ char *username, /* O - Authenticated username */ - int userlen) /* I - Length of username */ + size_t userlen) /* I - Length of username */ { cupsd_printer_t *printer; /* Printer for job */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "validate_user(job=%d, con=%d, owner=\"%s\", username=%p, " - "userlen=%d)", - job->id, con ? con->http.fd : 0, - owner ? owner : "(null)", username, userlen); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "validate_user(job=%d, con=%d, owner=\"%s\", username=%p, userlen=" CUPS_LLFMT ")", job->id, con ? con->number : 0, owner ? owner : "(null)", username, CUPS_LLCAST userlen); /* * Validate input... @@ -11312,5 +11169,5 @@ validate_user(cupsd_job_t *job, /* I - Job */ /* - * End of "$Id: ipp.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: ipp.c 12978 2015-11-17 19:29:52Z msweet $". */ diff --git a/scheduler/job.c b/scheduler/job.c index d8f56b5..54ee4ed 100644 --- a/scheduler/job.c +++ b/scheduler/job.c @@ -1,71 +1,16 @@ /* - * "$Id: job.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: job.c 12856 2015-08-31 14:27:39Z msweet $" * - * Job management routines for the CUPS scheduler. + * Job management routines for the CUPS scheduler. * - * Copyright 2007-2012 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. + * Copyright 2007-2015 by Apple Inc. + * Copyright 1997-2007 by Easy Software Products, all rights reserved. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * cupsdAddJob() - Add a new job to the job queue. - * cupsdCancelJobs() - Cancel all jobs for the given - * destination/user. - * cupsdCheckJobs() - Check the pending jobs and start any if the - * destination is available. - * cupsdCleanJobs() - Clean out old jobs. - * cupsdContinueJob() - Continue printing with the next file in a - * job. - * cupsdDeleteJob() - Free all memory used by a job. - * cupsdFreeAllJobs() - Free all jobs from memory. - * cupsdFindJob() - Find the specified job. - * cupsdGetPrinterJobCount() - Get the number of pending, processing, or - * held jobs in a printer or class. - * cupsdGetUserJobCount() - Get the number of pending, processing, or - * held jobs for a user. - * cupsdLoadAllJobs() - Load all jobs from disk. - * cupsdLoadJob() - Load a single job. - * cupsdMoveJob() - Move the specified job to a different - * destination. - * cupsdReleaseJob() - Release the specified job. - * cupsdRestartJob() - Restart the specified job. - * cupsdSaveAllJobs() - Save a summary of all jobs to disk. - * cupsdSaveJob() - Save a job to disk. - * cupsdSetJobHoldUntil() - Set the hold time for a job. - * cupsdSetJobPriority() - Set the priority of a job, moving it up/down - * in the list as needed. - * cupsdSetJobState() - Set the state of the specified print job. - * cupsdStopAllJobs() - Stop all print jobs. - * cupsdUnloadCompletedJobs() - Flush completed job history from memory. - * cupsdUpdateJobs() - Update the history/file files for all jobs. - * compare_active_jobs() - Compare the job IDs and priorities of two - * jobs. - * compare_jobs() - Compare the job IDs of two jobs. - * dump_job_history() - Dump any debug messages for a job. - * free_job_history() - Free any log history. - * finalize_job() - Cleanup after job filter processes and - * support data. - * get_options() - Get a string containing the job options. - * ipp_length() - Compute the size of the buffer needed to hold - * the textual IPP attributes. - * load_job_cache() - Load jobs from the job.cache file. - * load_next_job_id() - Load the NextJobId value from the job.cache - * file. - * load_request_root() - Load jobs from the RequestRoot directory. - * remove_job_files() - Remove the document files for a job. - * remove_job_history() - Remove the control file for a job. - * set_time() - Set one of the "time-at-xyz" attributes. - * start_job() - Start a print job. - * stop_job() - Stop a print job. - * unload_job() - Unload a job from memory. - * update_job() - Read a status update from a job's filters. - * update_job_attrs() - Update the job-printer-* attributes. + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -174,6 +119,7 @@ static mime_filter_t gziptoany_filter = */ static int compare_active_jobs(void *first, void *second, void *data); +static int compare_completed_jobs(void *first, void *second, void *data); static int compare_jobs(void *first, void *second, void *data); static void dump_job_history(cupsd_job_t *job); static void finalize_job(cupsd_job_t *job, int set_job_state); @@ -267,8 +213,6 @@ cupsdCancelJobs(const char *dest, /* I - Destination to cancel */ "Job canceled by user."); } } - - cupsdCheckJobs(); } @@ -289,10 +233,7 @@ cupsdCheckJobs(void) curtime = time(NULL); - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdCheckJobs: %d active jobs, sleeping=%d, reload=%d, " - "curtime=%ld", cupsArrayCount(ActiveJobs), Sleeping, - NeedReload, (long)curtime); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCheckJobs: %d active jobs, sleeping=%d, ac-power=%d, reload=%d, curtime=%ld", cupsArrayCount(ActiveJobs), Sleeping, ACPower, NeedReload, (long)curtime); for (job = (cupsd_job_t *)cupsArrayFirst(ActiveJobs); job; @@ -312,8 +253,8 @@ cupsdCheckJobs(void) if (job->kill_time && job->kill_time <= curtime) { - cupsdLogMessage(CUPSD_LOG_ERROR, "[Job %d] Stopping unresponsive job.", - job->id); + if (!job->completed) + cupsdLogJob(job, CUPSD_LOG_ERROR, "Stopping unresponsive job."); stop_job(job, CUPSD_JOB_FORCE); continue; @@ -325,8 +266,15 @@ cupsdCheckJobs(void) if (job->cancel_time && job->cancel_time <= curtime) { - cupsdSetJobState(job, IPP_JOB_CANCELED, CUPSD_JOB_DEFAULT, - "Canceling stuck job after %d seconds.", MaxJobTime); + int cancel_after; /* job-cancel-after value */ + + attr = ippFindAttribute(job->attrs, "job-cancel-after", IPP_TAG_INTEGER); + cancel_after = attr ? ippGetInteger(attr, 0) : MaxJobTime; + + if (job->completed) + cupsdSetJobState(job, IPP_JOB_CANCELED, CUPSD_JOB_FORCE, "Marking stuck job as completed after %d seconds.", cancel_after); + else + cupsdSetJobState(job, IPP_JOB_CANCELED, CUPSD_JOB_DEFAULT, "Canceling stuck job after %d seconds.", cancel_after); continue; } @@ -379,10 +327,7 @@ cupsdCheckJobs(void) */ if (job->state_value == IPP_JOB_PENDING && !NeedReload && -#ifndef kIOPMAssertionTypeDenySystemSleep - !Sleeping && -#endif /* !kIOPMAssertionTypeDenySystemSleep */ - !DoingShutdown && !job->printer) + (!Sleeping || ACPower) && !DoingShutdown && !job->printer) { printer = cupsdFindDest(job->dest); pclass = NULL; @@ -430,7 +375,7 @@ cupsdCheckJobs(void) if ((attr = ippFindAttribute(job->attrs, "job-actual-printer-uri", IPP_TAG_URI)) != NULL) - cupsdSetString(&attr->values[0].string.text, printer->uri); + ippSetString(job->attrs, &attr, 0, printer->uri); else ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_URI, "job-actual-printer-uri", NULL, printer->uri); @@ -445,7 +390,9 @@ cupsdCheckJobs(void) * Start the job... */ + cupsArraySave(ActiveJobs); start_job(job, printer); + cupsArrayRestore(ActiveJobs); } } } @@ -495,6 +442,8 @@ cupsdCleanJobs(void) cupsdLogJob(job, CUPSD_LOG_DEBUG, "Removing document files."); remove_job_files(job); + cupsdMarkDirty(CUPSD_DIRTY_JOBS); + if (job->history_time < JobHistoryUpdate || !JobHistoryUpdate) JobHistoryUpdate = job->history_time; } @@ -542,6 +491,7 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */ /* Pipes used between filters */ int envc; /* Number of environment variables */ struct stat fileinfo; /* Job file information */ + int argc = 0; /* Number of arguments */ char **argv = NULL, /* Filter command-line arguments */ filename[1024], /* Job filename */ command[1024], /* Full path to command */ @@ -598,7 +548,6 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */ memset(job->filters, 0, sizeof(job->filters)); - if (job->printer->raw) { /* @@ -614,14 +563,37 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */ * Local jobs get filtered... */ + mime_type_t *dst = job->printer->filetype; + /* Destination file type */ + snprintf(filename, sizeof(filename), "%s/d%05d-%03d", RequestRoot, job->id, job->current_file + 1); if (stat(filename, &fileinfo)) fileinfo.st_size = 0; - filters = mimeFilter2(MimeDatabase, job->filetypes[job->current_file], - fileinfo.st_size, job->printer->filetype, - &(job->cost)); + if (job->retry_as_raster) + { + /* + * Need to figure out whether the printer supports image/pwg-raster or + * image/urf, and use the corresponding type... + */ + + char type[MIME_MAX_TYPE]; /* MIME media type for printer */ + + snprintf(type, sizeof(type), "%s/image/urf", job->printer->name); + if ((dst = mimeType(MimeDatabase, "printer", type)) == NULL) + { + snprintf(type, sizeof(type), "%s/image/pwg-raster", job->printer->name); + dst = mimeType(MimeDatabase, "printer", type); + } + + if (dst) + cupsdLogJob(job, CUPSD_LOG_DEBUG, "Retrying job as \"%s\".", strchr(dst->type, '/') + 1); + else + cupsdLogJob(job, CUPSD_LOG_ERROR, "Unable to retry job using a supported raster format."); + } + + filters = mimeFilter2(MimeDatabase, job->filetypes[job->current_file], (size_t)fileinfo.st_size, dst, &(job->cost)); if (!filters) { @@ -672,6 +644,9 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */ "FINAL_CONTENT_TYPE=%s/%s", filter->dst->super, filter->dst->type); } + else + snprintf(final_content_type, sizeof(final_content_type), + "FINAL_CONTENT_TYPE=printer/%s", job->printer->name); } /* @@ -757,9 +732,8 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */ * Add decompression/raw filter as needed... */ - if ((!job->printer->raw && job->compressions[job->current_file]) || - (!filters && !job->printer->remote && - (job->num_files > 1 || !strncmp(job->printer->device_uri, "file:", 5)))) + if (job->compressions[job->current_file] && + (!job->printer->remote || job->num_files == 1)) { /* * Add gziptoany filter to the front of the list... @@ -891,11 +865,11 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */ */ if (job->printer->remote) - argv = calloc(7 + job->num_files, sizeof(char *)); + argc = 6 + job->num_files; else - argv = calloc(8, sizeof(char *)); + argc = 7; - if (!argv) + if ((argv = calloc((size_t)argc + 1, sizeof(char *))) == NULL) { cupsdLogMessage(CUPSD_LOG_DEBUG, "Unable to allocate argument array - %s", strerror(errno)); @@ -927,7 +901,7 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */ { snprintf(filename, sizeof(filename), "%s/d%05d-%03d", RequestRoot, job->id, job->current_file + 1); - argv[6] = filename; + argv[6] = strdup(filename); } for (i = 0; argv[i]; i ++) @@ -941,7 +915,7 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */ IPP_TAG_LANGUAGE); #ifdef __APPLE__ - strcpy(apple_language, "APPLE_LANGUAGE="); + strlcpy(apple_language, "APPLE_LANGUAGE=", sizeof(apple_language)); _cupsAppleLanguage(attr->values[0].string.text, apple_language + 15, sizeof(apple_language) - 15); #endif /* __APPLE__ */ @@ -954,7 +928,7 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */ * the POSIX locale... */ - strcpy(lang, "LANG=C"); + strlcpy(lang, "LANG=C", sizeof(lang)); break; case 2 : @@ -1012,14 +986,14 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */ * All of these strcpy's are safe because we allocated the psr string... */ - strcpy(printer_state_reasons, "PRINTER_STATE_REASONS="); + strlcpy(printer_state_reasons, "PRINTER_STATE_REASONS=", psrlen); for (psrptr = printer_state_reasons + 22, i = 0; i < job->printer->num_reasons; i ++) { if (i) *psrptr++ = ','; - strcpy(psrptr, job->printer->reasons[i]); + strlcpy(psrptr, job->printer->reasons[i], psrlen - (size_t)(psrptr - printer_state_reasons)); psrptr += strlen(psrptr); } } @@ -1131,9 +1105,6 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */ * Now create processes for all of the filters... */ - cupsdSetPrinterReasons(job->printer, "-cups-missing-filter-warning," - "cups-insecure-filter-warning"); - for (i = 0, slot = 0, filter = (mime_filter_t *)cupsArrayFirst(filters); filter; i ++, filter = (mime_filter_t *)cupsArrayNext(filters)) @@ -1229,8 +1200,13 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */ cupsdLogJob(job, CUPSD_LOG_INFO, "Started filter %s (PID %d)", command, pid); - argv[6] = NULL; - slot = !slot; + if (argv[6]) + { + free(argv[6]); + argv[6] = NULL; + } + + slot = !slot; } cupsArrayDelete(filters); @@ -1257,7 +1233,7 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */ else if (stat(command, &backinfo)) backroot = 0; else - backroot = !(backinfo.st_mode & (S_IRWXG | S_IRWXO)); + backroot = !(backinfo.st_mode & (S_IWGRP | S_IRWXO)); argv[0] = job->printer->sanitized_device_uri; @@ -1267,7 +1243,7 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */ pid = cupsdStartProcess(command, argv, envp, filterfds[!slot][0], filterfds[slot][1], job->status_pipes[1], job->back_pipes[1], job->side_pipes[1], - backroot, job->profile, job, &(job->backend)); + backroot, job->bprofile, job, &(job->backend)); if (pid == 0) { @@ -1314,13 +1290,12 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */ cupsdClosePipe(filterfds[slot]); - if (job->printer->remote && job->num_files > 1) - { - for (i = 0; i < job->num_files; i ++) - free(argv[i + 6]); - } + for (i = 6; i < argc; i ++) + if (argv[i]) + free(argv[i]); free(argv); + if (printer_state_reasons) free(printer_state_reasons); @@ -1350,13 +1325,9 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */ if (argv) { - if (job->printer->remote && job->num_files > 1) - { - for (i = 0; i < job->num_files; i ++) - free(argv[i + 6]); - } - - free(argv); + for (i = 6; i < argc; i ++) + if (argv[i]) + free(argv[i]); } if (printer_state_reasons) @@ -1485,6 +1456,30 @@ cupsdFindJob(int id) /* I - Job ID */ /* + * 'cupsdGetCompletedJobs()'- Generate a completed jobs list. + */ + +cups_array_t * /* O - Array of jobs */ +cupsdGetCompletedJobs( + cupsd_printer_t *p) /* I - Printer */ +{ + cups_array_t *list; /* Array of jobs */ + cupsd_job_t *job; /* Current job */ + + + list = cupsArrayNew(compare_completed_jobs, NULL); + + for (job = (cupsd_job_t *)cupsArrayFirst(Jobs); + job; + job = (cupsd_job_t *)cupsArrayNext(Jobs)) + if ((!p || !_cups_strcasecmp(p->name, job->dest)) && job->state_value >= IPP_JOB_STOPPED && job->completed_time) + cupsArrayAdd(list, job); + + return (list); +} + + +/* * 'cupsdGetPrinterJobCount()' - Get the number of pending, processing, * or held jobs in a printer or class. */ @@ -1538,9 +1533,10 @@ void cupsdLoadAllJobs(void) { char filename[1024]; /* Full filename of job.cache file */ - struct stat fileinfo, /* Information on job.cache file */ - dirinfo; /* Information on RequestRoot dir */ - + struct stat fileinfo; /* Information on job.cache file */ + cups_dir_t *dir; /* RequestRoot dir */ + cups_dentry_t *dent; /* Entry in RequestRoot */ + int load_cache = 1; /* Load the job.cache file? */ /* @@ -1564,36 +1560,65 @@ cupsdLoadAllJobs(void) if (stat(filename, &fileinfo)) { - fileinfo.st_mtime = 0; + /* + * No job.cache file... + */ + + load_cache = 0; if (errno != ENOENT) cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to get file information for \"%s\" - %s", filename, strerror(errno)); } + else if ((dir = cupsDirOpen(RequestRoot)) == NULL) + { + /* + * No spool directory... + */ - if (stat(RequestRoot, &dirinfo)) + load_cache = 0; + } + else { - dirinfo.st_mtime = 0; + while ((dent = cupsDirRead(dir)) != NULL) + { + if (strlen(dent->filename) >= 6 && dent->filename[0] == 'c' && dent->fileinfo.st_mtime > fileinfo.st_mtime) + { + /* + * Job history file is newer than job.cache file... + */ - if (errno != ENOENT) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to get directory information for \"%s\" - %s", - RequestRoot, strerror(errno)); + load_cache = 0; + break; + } + } + + cupsDirClose(dir); } /* * Load the most recent source for job data... */ - if (dirinfo.st_mtime > fileinfo.st_mtime) + if (load_cache) { + /* + * Load the job.cache file... + */ + + load_job_cache(filename); + } + else + { + /* + * Load the job history files... + */ + load_request_root(); load_next_job_id(filename); } - else - load_job_cache(filename); /* * Clean out old jobs as needed... @@ -1640,7 +1665,7 @@ cupsdLoadJob(cupsd_job_t *job) /* I - Job */ * Load job attributes... */ - cupsdLogMessage(CUPSD_LOG_DEBUG, "[Job %d] Loading attributes...", job->id); + cupsdLogJob(job, CUPSD_LOG_DEBUG, "Loading attributes..."); snprintf(jobfile, sizeof(jobfile), "%s/c%05d", RequestRoot, job->id); if ((fp = cupsdOpenConfFile(jobfile)) == NULL) @@ -1648,9 +1673,8 @@ cupsdLoadJob(cupsd_job_t *job) /* I - Job */ if (ippReadIO(fp, (ipp_iocb_t)cupsFileRead, 1, NULL, job->attrs) != IPP_DATA) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Job %d] Unable to read job control file \"%s\".", job->id, - jobfile); + cupsdLogJob(job, CUPSD_LOG_ERROR, + "Unable to read job control file \"%s\".", jobfile); cupsFileClose(fp); goto error; } @@ -1663,18 +1687,16 @@ cupsdLoadJob(cupsd_job_t *job) /* I - Job */ if (!ippFindAttribute(job->attrs, "time-at-creation", IPP_TAG_INTEGER)) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Job %d] Missing or bad time-at-creation attribute in " - "control file.", job->id); + cupsdLogJob(job, CUPSD_LOG_ERROR, + "Missing or bad time-at-creation attribute in control file."); goto error; } if ((job->state = ippFindAttribute(job->attrs, "job-state", IPP_TAG_ENUM)) == NULL) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Job %d] Missing or bad job-state attribute in control " - "file.", job->id); + cupsdLogJob(job, CUPSD_LOG_ERROR, + "Missing or bad job-state attribute in control file."); goto error; } @@ -1682,10 +1704,13 @@ cupsdLoadJob(cupsd_job_t *job) /* I - Job */ job->file_time = 0; job->history_time = 0; - if (job->state_value >= IPP_JOB_CANCELED && - (attr = ippFindAttribute(job->attrs, "time-at-completed", - IPP_TAG_INTEGER)) != NULL) + if ((attr = ippFindAttribute(job->attrs, "time-at-creation", IPP_TAG_INTEGER)) != NULL) + job->creation_time = attr->values[0].integer; + + if (job->state_value >= IPP_JOB_CANCELED && (attr = ippFindAttribute(job->attrs, "time-at-completed", IPP_TAG_INTEGER)) != NULL) { + job->completed_time = attr->values[0].integer; + if (JobHistory < INT_MAX) job->history_time = attr->values[0].integer + JobHistory; else @@ -1714,18 +1739,17 @@ cupsdLoadJob(cupsd_job_t *job) /* I - Job */ if ((attr = ippFindAttribute(job->attrs, "job-printer-uri", IPP_TAG_URI)) == NULL) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Job %d] No job-printer-uri attribute in control file.", - job->id); + cupsdLogJob(job, CUPSD_LOG_ERROR, + "No job-printer-uri attribute in control file."); goto error; } if ((dest = cupsdValidateDest(attr->values[0].string.text, &(job->dtype), &destptr)) == NULL) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Job %d] Unable to queue job for destination \"%s\".", - job->id, attr->values[0].string.text); + cupsdLogJob(job, CUPSD_LOG_ERROR, + "Unable to queue job for destination \"%s\".", + attr->values[0].string.text); goto error; } @@ -1733,9 +1757,9 @@ cupsdLoadJob(cupsd_job_t *job) /* I - Job */ } else if ((destptr = cupsdFindDest(job->dest)) == NULL) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Job %d] Unable to queue job for destination \"%s\".", - job->id, job->dest); + cupsdLogJob(job, CUPSD_LOG_ERROR, + "Unable to queue job for destination \"%s\".", + job->dest); goto error; } @@ -1744,9 +1768,8 @@ cupsdLoadJob(cupsd_job_t *job) /* I - Job */ { const char *reason; /* job-state-reason keyword */ - cupsdLogMessage(CUPSD_LOG_DEBUG, - "[Job %d] Adding missing job-state-reasons attribute to " - " control file.", job->id); + cupsdLogJob(job, CUPSD_LOG_DEBUG, + "Adding missing job-state-reasons attribute to control file."); switch (job->state_value) { @@ -1802,18 +1825,20 @@ cupsdLoadJob(cupsd_job_t *job) /* I - Job */ ippSetString(job->attrs, &job->reasons, 0, "none"); } - job->sheets = ippFindAttribute(job->attrs, "job-media-sheets-completed", - IPP_TAG_INTEGER); - job->job_sheets = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_NAME); + job->impressions = ippFindAttribute(job->attrs, "job-impressions-completed", IPP_TAG_INTEGER); + job->sheets = ippFindAttribute(job->attrs, "job-media-sheets-completed", IPP_TAG_INTEGER); + job->job_sheets = ippFindAttribute(job->attrs, "job-sheets", IPP_TAG_NAME); + + if (!job->impressions) + job->impressions = ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-impressions-completed", 0); if (!job->priority) { if ((attr = ippFindAttribute(job->attrs, "job-priority", IPP_TAG_INTEGER)) == NULL) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Job %d] Missing or bad job-priority attribute in " - "control file.", job->id); + cupsdLogJob(job, CUPSD_LOG_ERROR, + "Missing or bad job-priority attribute in control file."); goto error; } @@ -1825,15 +1850,21 @@ cupsdLoadJob(cupsd_job_t *job) /* I - Job */ if ((attr = ippFindAttribute(job->attrs, "job-originating-user-name", IPP_TAG_NAME)) == NULL) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Job %d] Missing or bad job-originating-user-name " - "attribute in control file.", job->id); + cupsdLogJob(job, CUPSD_LOG_ERROR, + "Missing or bad job-originating-user-name " + "attribute in control file."); goto error; } cupsdSetString(&job->username, attr->values[0].string.text); } + if (!job->name) + { + if ((attr = ippFindAttribute(job->attrs, "job-name", IPP_TAG_NAME)) != NULL) + cupsdSetString(&job->name, attr->values[0].string.text); + } + /* * Set the job hold-until time and state... */ @@ -1858,6 +1889,9 @@ cupsdLoadJob(cupsd_job_t *job) /* I - Job */ job->state_value = IPP_JOB_PENDING; } + if ((attr = ippFindAttribute(job->attrs, "job-k-octets", IPP_TAG_INTEGER)) != NULL) + job->koctets = attr->values[0].integer; + if (!job->num_files) { /* @@ -1872,41 +1906,36 @@ cupsdLoadJob(cupsd_job_t *job) /* I - Job */ if (access(jobfile, 0)) break; - cupsdLogMessage(CUPSD_LOG_DEBUG, - "[Job %d] Auto-typing document file \"%s\"...", job->id, - jobfile); + cupsdLogJob(job, CUPSD_LOG_DEBUG, + "Auto-typing document file \"%s\"...", jobfile); if (fileid > job->num_files) { if (job->num_files == 0) { - compressions = (int *)calloc(fileid, sizeof(int)); - filetypes = (mime_type_t **)calloc(fileid, sizeof(mime_type_t *)); + compressions = (int *)calloc((size_t)fileid, sizeof(int)); + filetypes = (mime_type_t **)calloc((size_t)fileid, sizeof(mime_type_t *)); } else { - compressions = (int *)realloc(job->compressions, - sizeof(int) * fileid); - filetypes = (mime_type_t **)realloc(job->filetypes, - sizeof(mime_type_t *) * - fileid); + compressions = (int *)realloc(job->compressions, sizeof(int) * (size_t)fileid); + filetypes = (mime_type_t **)realloc(job->filetypes, sizeof(mime_type_t *) * (size_t)fileid); } + if (compressions) + job->compressions = compressions; + + if (filetypes) + job->filetypes = filetypes; + if (!compressions || !filetypes) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Job %d] Ran out of memory for job file types.", - job->id); + cupsdLogJob(job, CUPSD_LOG_ERROR, + "Ran out of memory for job file types."); ippDelete(job->attrs); job->attrs = NULL; - if (compressions) - free(compressions); - - if (filetypes) - free(filetypes); - if (job->compressions) { free(job->compressions); @@ -1923,9 +1952,7 @@ cupsdLoadJob(cupsd_job_t *job) /* I - Job */ return (0); } - job->compressions = compressions; - job->filetypes = filetypes; - job->num_files = fileid; + job->num_files = fileid; } job->filetypes[fileid - 1] = mimeFileType(MimeDatabase, jobfile, NULL, @@ -2074,7 +2101,7 @@ cupsdMoveJob(cupsd_job_t *job, /* I - Job */ if ((attr = ippFindAttribute(job->attrs, "job-printer-uri", IPP_TAG_URI)) != NULL) - cupsdSetString(&(attr->values[0].string.text), p->uri); + ippSetString(job->attrs, &attr, 0, p->uri); cupsdAddEvent(CUPSD_EVENT_JOB_STOPPED, p, job, "Job #%d moved from %s to %s.", job->id, olddest, @@ -2170,11 +2197,18 @@ cupsdSaveAllJobs(void) { cupsFilePrintf(fp, "<Job %d>\n", job->id); cupsFilePrintf(fp, "State %d\n", job->state_value); + cupsFilePrintf(fp, "Created %ld\n", (long)job->creation_time); + if (job->completed_time) + cupsFilePrintf(fp, "Completed %ld\n", (long)job->completed_time); cupsFilePrintf(fp, "Priority %d\n", job->priority); - cupsFilePrintf(fp, "HoldUntil %d\n", (int)job->hold_until); + if (job->hold_until) + cupsFilePrintf(fp, "HoldUntil %ld\n", (long)job->hold_until); cupsFilePrintf(fp, "Username %s\n", job->username); + if (job->name) + cupsFilePutConf(fp, "Name", job->name); cupsFilePrintf(fp, "Destination %s\n", job->dest); cupsFilePrintf(fp, "DestType %d\n", job->dtype); + cupsFilePrintf(fp, "KOctets %d\n", job->koctets); cupsFilePrintf(fp, "NumFiles %d\n", job->num_files); for (i = 0; i < job->num_files; i ++) cupsFilePrintf(fp, "File %d %s/%s %d\n", i + 1, job->filetypes[i]->super, @@ -2212,8 +2246,7 @@ cupsdSaveJob(cupsd_job_t *job) /* I - Job */ if (ippWriteIO(fp, (ipp_iocb_t)cupsFileWrite, 1, NULL, job->attrs) != IPP_DATA) { - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Job %d] Unable to write job control file.", job->id); + cupsdLogJob(job, CUPSD_LOG_ERROR, "Unable to write job control file."); cupsFileClose(fp); return; } @@ -2265,7 +2298,7 @@ cupsdSetJobHoldUntil(cupsd_job_t *job, /* I - Job */ attr = ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_NAME); if (attr) - cupsdSetString(&(attr->values[0].string.text), when); + ippSetString(job->attrs, &attr, 0, when); else attr = ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_KEYWORD, "job-hold-until", NULL, when); @@ -2281,9 +2314,10 @@ cupsdSetJobHoldUntil(cupsd_job_t *job, /* I - Job */ cupsdMarkDirty(CUPSD_DIRTY_JOBS); } - ippSetString(job->attrs, &job->reasons, 0, "job-hold-until-specified"); } + ippSetString(job->attrs, &job->reasons, 0, "job-hold-until-specified"); + /* * Update the hold time... */ @@ -2519,8 +2553,8 @@ cupsdSetJobState( if (attr) { - attr->value_tag = IPP_TAG_KEYWORD; - cupsdSetString(&(attr->values[0].string.text), "no-hold"); + ippSetValueTag(job->attrs, &attr, IPP_TAG_KEYWORD); + ippSetString(job->attrs, &attr, 0, "no-hold"); } default : @@ -2715,10 +2749,17 @@ cupsdStopAllJobs( job; job = (cupsd_job_t *)cupsArrayNext(PrintingJobs)) { - if (kill_delay) - job->kill_time = time(NULL) + kill_delay; + if (job->completed) + { + cupsdSetJobState(job, IPP_JOB_COMPLETED, CUPSD_JOB_FORCE, NULL); + } + else + { + if (kill_delay) + job->kill_time = time(NULL) + kill_delay; - cupsdSetJobState(job, IPP_JOB_PENDING, action, NULL); + cupsdSetJobState(job, IPP_JOB_PENDING, action, NULL); + } } } @@ -2829,6 +2870,28 @@ compare_active_jobs(void *first, /* I - First job */ /* + * 'compare_completed_jobs()' - Compare the job IDs and completion times of two jobs. + */ + +static int /* O - Difference */ +compare_completed_jobs(void *first, /* I - First job */ + void *second, /* I - Second job */ + void *data) /* I - App data (not used) */ +{ + int diff; /* Difference */ + + + (void)data; + + if ((diff = ((cupsd_job_t *)second)->completed_time - + ((cupsd_job_t *)first)->completed_time) != 0) + return (diff); + else + return (((cupsd_job_t *)first)->id - ((cupsd_job_t *)second)->id); +} + + +/* * 'compare_jobs()' - Compare the job IDs of two jobs. */ @@ -2923,7 +2986,7 @@ dump_job_history(cupsd_job_t *job) /* I - Job */ snprintf(temp, sizeof(temp), "[Job %d] printer-state-reasons=", job->id); ptr = temp + strlen(temp); if (printer->num_reasons == 0) - strlcpy(ptr, "none", sizeof(temp) - (ptr - temp)); + strlcpy(ptr, "none", sizeof(temp) - (size_t)(ptr - temp)); else { for (i = 0; @@ -2933,7 +2996,7 @@ dump_job_history(cupsd_job_t *job) /* I - Job */ if (i) *ptr++ = ','; - strlcpy(ptr, printer->reasons[i], sizeof(temp) - (ptr - temp)); + strlcpy(ptr, printer->reasons[i], sizeof(temp) - (size_t)(ptr - temp)); ptr += strlen(ptr); } } @@ -2994,11 +3057,13 @@ finalize_job(cupsd_job_t *job, /* I - Job */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "finalize_job(job=%p(%d))", job, job->id); /* - * Clear the "connecting-to-device" reason, which is only valid when a printer - * is processing, along with any remote printing job state... + * Clear the "connecting-to-device" and "cups-waiting-for-job-completed" + * reasons, which are only valid when a printer is processing, along with any + * remote printing job state... */ cupsdSetPrinterReasons(job->printer, "-connecting-to-device," + "cups-waiting-for-job-completed," "cups-remote-pending," "cups-remote-pending-held," "cups-remote-processing," @@ -3022,6 +3087,8 @@ finalize_job(cupsd_job_t *job, /* I - Job */ cupsdDestroyProfile(job->profile); job->profile = NULL; + cupsdDestroyProfile(job->bprofile); + job->bprofile = NULL; /* * Clear the unresponsive job watchdog timers... @@ -3068,8 +3135,9 @@ finalize_job(cupsd_job_t *job, /* I - Job */ job_state = IPP_JOB_COMPLETED; message = "Job completed."; - ippSetString(job->attrs, &job->reasons, 0, - "job-completed-successfully"); + if (!job->status) + ippSetString(job->attrs, &job->reasons, 0, + "job-completed-successfully"); break; case IPP_JOB_STOPPED : @@ -3255,13 +3323,48 @@ finalize_job(cupsd_job_t *job, /* I - Job */ * Hold the job... */ - cupsdSetJobHoldUntil(job, "indefinite", 1); - ippSetString(job->attrs, &job->reasons, 0, - "job-hold-until-specified"); + const char *reason = ippGetString(job->reasons, 0, NULL); - job_state = IPP_JOB_HELD; - message = "Job held indefinitely due to backend errors; please " + cupsdLogJob(job, CUPSD_LOG_DEBUG, "job-state-reasons=\"%s\"", + reason); + + if (!reason || strncmp(reason, "account-", 8)) + { + cupsdSetJobHoldUntil(job, "indefinite", 1); + + ippSetString(job->attrs, &job->reasons, 0, + "job-hold-until-specified"); + message = "Job held indefinitely due to backend errors; please " "consult the error_log file for details."; + } + else if (!strcmp(reason, "account-info-needed")) + { + cupsdSetJobHoldUntil(job, "indefinite", 0); + + message = "Job held indefinitely - account information is " + "required."; + } + else if (!strcmp(reason, "account-closed")) + { + cupsdSetJobHoldUntil(job, "indefinite", 0); + + message = "Job held indefinitely - account has been closed."; + } + else if (!strcmp(reason, "account-limit-reached")) + { + cupsdSetJobHoldUntil(job, "indefinite", 0); + + message = "Job held indefinitely - account limit has been " + "reached."; + } + else + { + cupsdSetJobHoldUntil(job, "indefinite", 0); + + message = "Job held indefinitely - account authorization failed."; + } + + job_state = IPP_JOB_HELD; } break; @@ -3295,8 +3398,9 @@ finalize_job(cupsd_job_t *job, /* I - Job */ job_state = IPP_JOB_HELD; message = "Job held for authentication."; - ippSetString(job->attrs, &job->reasons, 0, - "cups-held-for-authentication"); + if (strncmp(job->reasons->values[0].string.text, "account-", 8)) + ippSetString(job->attrs, &job->reasons, 0, + "cups-held-for-authentication"); } break; @@ -3422,13 +3526,6 @@ finalize_job(cupsd_job_t *job, /* I - Job */ job->printer->job = NULL; job->printer = NULL; - - /* - * Try printing another job... - */ - - if (printer_state != IPP_PRINTER_STOPPED) - cupsdCheckJobs(); } @@ -3480,19 +3577,16 @@ get_options(cupsd_job_t *job, /* I - Job */ "com.apple.print.DocumentTicket.PMSpoolFormat", IPP_TAG_ZERO) && !ippFindAttribute(job->attrs, "APPrinterPreset", IPP_TAG_ZERO) && - (ippFindAttribute(job->attrs, "output-mode", IPP_TAG_ZERO) || - ippFindAttribute(job->attrs, "print-color-mode", IPP_TAG_ZERO) || + (ippFindAttribute(job->attrs, "print-color-mode", IPP_TAG_ZERO) || ippFindAttribute(job->attrs, "print-quality", IPP_TAG_ZERO))) { /* - * Map output-mode and print-quality to a preset... + * Map print-color-mode and print-quality to a preset... */ if ((attr = ippFindAttribute(job->attrs, "print-color-mode", - IPP_TAG_KEYWORD)) == NULL) - attr = ippFindAttribute(job->attrs, "output-mode", IPP_TAG_KEYWORD); - - if (attr && !strcmp(attr->values[0].string.text, "monochrome")) + IPP_TAG_KEYWORD)) != NULL && + !strcmp(attr->values[0].string.text, "monochrome")) print_color_mode = _PWG_PRINT_COLOR_MODE_MONOCHROME; else print_color_mode = _PWG_PRINT_COLOR_MODE_COLOR; @@ -3679,7 +3773,8 @@ get_options(cupsd_job_t *job, /* I - Job */ attr->value_tag == IPP_TAG_MIMETYPE || attr->value_tag == IPP_TAG_NAMELANG || attr->value_tag == IPP_TAG_TEXTLANG || - (attr->value_tag == IPP_TAG_URI && strcmp(attr->name, "job-uuid")) || + (attr->value_tag == IPP_TAG_URI && strcmp(attr->name, "job-uuid") && + strcmp(attr->name, "job-authorization-uri")) || attr->value_tag == IPP_TAG_URISCHEME || attr->value_tag == IPP_TAG_BEGIN_COLLECTION) /* Not yet supported */ continue; @@ -3694,9 +3789,14 @@ get_options(cupsd_job_t *job, /* I - Job */ continue; if (!strncmp(attr->name, "job-", 4) && + strcmp(attr->name, "job-account-id") && + strcmp(attr->name, "job-accounting-user-id") && + strcmp(attr->name, "job-authorization-uri") && strcmp(attr->name, "job-billing") && strcmp(attr->name, "job-impressions") && strcmp(attr->name, "job-originating-host-name") && + strcmp(attr->name, "job-password") && + strcmp(attr->name, "job-password-encryption") && strcmp(attr->name, "job-uuid") && !(job->printer->type & CUPS_PRINTER_REMOTE)) continue; @@ -3721,18 +3821,18 @@ get_options(cupsd_job_t *job, /* I - Job */ */ if (optptr > options) - strlcat(optptr, " ", optlength - (optptr - options)); + strlcat(optptr, " ", optlength - (size_t)(optptr - options)); if (attr->value_tag != IPP_TAG_BOOLEAN) { - strlcat(optptr, attr->name, optlength - (optptr - options)); - strlcat(optptr, "=", optlength - (optptr - options)); + strlcat(optptr, attr->name, optlength - (size_t)(optptr - options)); + strlcat(optptr, "=", optlength - (size_t)(optptr - options)); } for (i = 0; i < attr->num_values; i ++) { if (i) - strlcat(optptr, ",", optlength - (optptr - options)); + strlcat(optptr, ",", optlength - (size_t)(optptr - options)); optptr += strlen(optptr); @@ -3740,30 +3840,29 @@ get_options(cupsd_job_t *job, /* I - Job */ { case IPP_TAG_INTEGER : case IPP_TAG_ENUM : - snprintf(optptr, optlength - (optptr - options), + snprintf(optptr, optlength - (size_t)(optptr - options), "%d", attr->values[i].integer); break; case IPP_TAG_BOOLEAN : if (!attr->values[i].boolean) - strlcat(optptr, "no", optlength - (optptr - options)); + strlcat(optptr, "no", optlength - (size_t)(optptr - options)); - strlcat(optptr, attr->name, - optlength - (optptr - options)); + strlcat(optptr, attr->name, optlength - (size_t)(optptr - options)); break; case IPP_TAG_RANGE : if (attr->values[i].range.lower == attr->values[i].range.upper) - snprintf(optptr, optlength - (optptr - options) - 1, + snprintf(optptr, optlength - (size_t)(optptr - options) - 1, "%d", attr->values[i].range.lower); else - snprintf(optptr, optlength - (optptr - options) - 1, + snprintf(optptr, optlength - (size_t)(optptr - options) - 1, "%d-%d", attr->values[i].range.lower, attr->values[i].range.upper); break; case IPP_TAG_RESOLUTION : - snprintf(optptr, optlength - (optptr - options) - 1, + snprintf(optptr, optlength - (size_t)(optptr - options) - 1, "%dx%d%s", attr->values[i].resolution.xres, attr->values[i].resolution.yres, attr->values[i].resolution.units == IPP_RES_PER_INCH ? @@ -3803,10 +3902,10 @@ get_options(cupsd_job_t *job, /* I - Job */ for (i = num_pwgppds, pwgppd = pwgppds; i > 0; i --, pwgppd ++) { *optptr++ = ' '; - strcpy(optptr, pwgppd->name); + strlcpy(optptr, pwgppd->name, optlength - (size_t)(optptr - options)); optptr += strlen(optptr); *optptr++ = '='; - strcpy(optptr, pwgppd->value); + strlcpy(optptr, pwgppd->value, optlength - (size_t)(optptr - options)); optptr += strlen(optptr); } @@ -3860,7 +3959,7 @@ ipp_length(ipp_t *ipp) /* I - IPP request */ */ bytes ++; /* " " separator */ - bytes += attr->num_values; /* "," separators */ + bytes += (size_t)attr->num_values; /* "," separators */ /* * Boolean attributes appear as "foo,nofoo,foo,nofoo", while @@ -3870,7 +3969,7 @@ ipp_length(ipp_t *ipp) /* I - IPP request */ if (attr->value_tag != IPP_TAG_BOOLEAN) bytes += strlen(attr->name); else - bytes += attr->num_values * strlen(attr->name); + bytes += (size_t)attr->num_values * strlen(attr->name); /* * Now add the size required for each value in the attribute... @@ -3884,7 +3983,7 @@ ipp_length(ipp_t *ipp) /* I - IPP request */ * Minimum value of a signed integer is -2147483647, or 11 digits. */ - bytes += attr->num_values * 11; + bytes += (size_t)attr->num_values * 11; break; case IPP_TAG_BOOLEAN : @@ -3903,7 +4002,7 @@ ipp_length(ipp_t *ipp) /* I - IPP request */ * 23 characters max. */ - bytes += attr->num_values * 23; + bytes += (size_t)attr->num_values * 23; break; case IPP_TAG_RESOLUTION : @@ -3912,7 +4011,7 @@ ipp_length(ipp_t *ipp) /* I - IPP request */ * suffixed by the units, or 26 characters max. */ - bytes += attr->num_values * 26; + bytes += (size_t)attr->num_values * 26; break; case IPP_TAG_STRING : @@ -3988,14 +4087,13 @@ load_job_cache(const char *filename) /* I - job.cache filename */ { if (job) { - cupsdLogMessage(CUPSD_LOG_ERROR, "Missing </Job> directive on line %d.", - linenum); + cupsdLogMessage(CUPSD_LOG_ERROR, "Missing </Job> directive on line %d of %s.", linenum, filename); continue; } if (!value) { - cupsdLogMessage(CUPSD_LOG_ERROR, "Missing job ID on line %d.", linenum); + cupsdLogMessage(CUPSD_LOG_ERROR, "Missing job ID on line %d of %s.", linenum, filename); continue; } @@ -4003,8 +4101,7 @@ load_job_cache(const char *filename) /* I - job.cache filename */ if (jobid < 1) { - cupsdLogMessage(CUPSD_LOG_ERROR, "Bad job ID %d on line %d.", jobid, - linenum); + cupsdLogMessage(CUPSD_LOG_ERROR, "Bad job ID %d on line %d of %s.", jobid, linenum, filename); continue; } @@ -4038,13 +4135,12 @@ load_job_cache(const char *filename) /* I - job.cache filename */ job->status_pipes[0] = -1; job->status_pipes[1] = -1; - cupsdLogMessage(CUPSD_LOG_DEBUG, "[Job %d] Loading from cache...", - job->id); + cupsdLogJob(job, CUPSD_LOG_DEBUG, "Loading from cache..."); } else if (!job) { cupsdLogMessage(CUPSD_LOG_ERROR, - "Missing <Job #> directive on line %d.", linenum); + "Missing <Job #> directive on line %d of %s.", linenum, filename); continue; } else if (!_cups_strcasecmp(line, "</Job>")) @@ -4053,12 +4149,20 @@ load_job_cache(const char *filename) /* I - job.cache filename */ if (job->state_value <= IPP_JOB_STOPPED && cupsdLoadJob(job)) cupsArrayAdd(ActiveJobs, job); + else if (job->state_value > IPP_JOB_STOPPED) + { + if (!job->completed_time || !job->creation_time || !job->name || !job->koctets) + { + cupsdLoadJob(job); + unload_job(job); + } + } job = NULL; } else if (!value) { - cupsdLogMessage(CUPSD_LOG_ERROR, "Missing value on line %d.", linenum); + cupsdLogMessage(CUPSD_LOG_ERROR, "Missing value on line %d of %s.", linenum, filename); continue; } else if (!_cups_strcasecmp(line, "State")) @@ -4070,9 +4174,21 @@ load_job_cache(const char *filename) /* I - job.cache filename */ else if (job->state_value > IPP_JOB_COMPLETED) job->state_value = IPP_JOB_COMPLETED; } + else if (!_cups_strcasecmp(line, "Name")) + { + cupsdSetString(&(job->name), value); + } + else if (!_cups_strcasecmp(line, "Created")) + { + job->creation_time = strtol(value, NULL, 10); + } + else if (!_cups_strcasecmp(line, "Completed")) + { + job->completed_time = strtol(value, NULL, 10); + } else if (!_cups_strcasecmp(line, "HoldUntil")) { - job->hold_until = atoi(value); + job->hold_until = strtol(value, NULL, 10); } else if (!_cups_strcasecmp(line, "Priority")) { @@ -4090,14 +4206,17 @@ load_job_cache(const char *filename) /* I - job.cache filename */ { job->dtype = (cups_ptype_t)atoi(value); } + else if (!_cups_strcasecmp(line, "KOctets")) + { + job->koctets = atoi(value); + } else if (!_cups_strcasecmp(line, "NumFiles")) { job->num_files = atoi(value); if (job->num_files < 0) { - cupsdLogMessage(CUPSD_LOG_ERROR, "Bad NumFiles value %d on line %d.", - job->num_files, linenum); + cupsdLogMessage(CUPSD_LOG_ERROR, "Bad NumFiles value %d on line %d of %s.", job->num_files, linenum, filename); job->num_files = 0; continue; } @@ -4108,20 +4227,19 @@ load_job_cache(const char *filename) /* I - job.cache filename */ job->id); if (access(jobfile, 0)) { - cupsdLogMessage(CUPSD_LOG_INFO, "[Job %d] Data files have gone away.", - job->id); + cupsdLogJob(job, CUPSD_LOG_INFO, "Data files have gone away."); job->num_files = 0; continue; } - job->filetypes = calloc(job->num_files, sizeof(mime_type_t *)); - job->compressions = calloc(job->num_files, sizeof(int)); + job->filetypes = calloc((size_t)job->num_files, sizeof(mime_type_t *)); + job->compressions = calloc((size_t)job->num_files, sizeof(int)); if (!job->filetypes || !job->compressions) { - cupsdLogMessage(CUPSD_LOG_EMERG, - "[Job %d] Unable to allocate memory for %d files.", - job->id, job->num_files); + cupsdLogJob(job, CUPSD_LOG_EMERG, + "Unable to allocate memory for %d files.", + job->num_files); break; } } @@ -4137,14 +4255,13 @@ load_job_cache(const char *filename) /* I - job.cache filename */ if (sscanf(value, "%d%*[ \t]%15[^/]/%255s%d", &number, super, type, &compression) != 4) { - cupsdLogMessage(CUPSD_LOG_ERROR, "Bad File on line %d.", linenum); + cupsdLogMessage(CUPSD_LOG_ERROR, "Bad File on line %d of %s.", linenum, filename); continue; } if (number < 1 || number > job->num_files) { - cupsdLogMessage(CUPSD_LOG_ERROR, "Bad File number %d on line %d.", - number, linenum); + cupsdLogMessage(CUPSD_LOG_ERROR, "Bad File number %d on line %d of %s.", number, linenum, filename); continue; } @@ -4159,9 +4276,9 @@ load_job_cache(const char *filename) /* I - job.cache filename */ * If the original MIME type is unknown, auto-type it! */ - cupsdLogMessage(CUPSD_LOG_ERROR, - "[Job %d] Unknown MIME type %s/%s for file %d.", - job->id, super, type, number + 1); + cupsdLogJob(job, CUPSD_LOG_ERROR, + "Unknown MIME type %s/%s for file %d.", + super, type, number + 1); snprintf(jobfile, sizeof(jobfile), "%s/d%05d-%03d", RequestRoot, job->id, number + 1); @@ -4178,8 +4295,14 @@ load_job_cache(const char *filename) /* I - job.cache filename */ } } else - cupsdLogMessage(CUPSD_LOG_ERROR, "Unknown %s directive on line %d.", - line, linenum); + cupsdLogMessage(CUPSD_LOG_ERROR, "Unknown %s directive on line %d of %s.", line, linenum, filename); + } + + if (job) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Missing </Job> directive on line %d of %s.", linenum, filename); + cupsdDeleteJob(job, CUPSD_JOB_PURGE); } cupsFileClose(fp); @@ -4343,10 +4466,7 @@ remove_job_files(cupsd_job_t *job) /* I - Job */ { snprintf(filename, sizeof(filename), "%s/d%05d-%03d", RequestRoot, job->id, i); - if (Classification) - cupsdRemoveFile(filename); - else - unlink(filename); + cupsdUnlinkOrRemoveFile(filename); } free(job->filetypes); @@ -4377,10 +4497,7 @@ remove_job_history(cupsd_job_t *job) /* I - Job */ snprintf(filename, sizeof(filename), "%s/c%05d", RequestRoot, job->id); - if (Classification) - cupsdRemoveFile(filename); - else - unlink(filename); + cupsdUnlinkOrRemoveFile(filename); LastEvent |= CUPSD_EVENT_PRINTER_STATE_CHANGED; } @@ -4394,6 +4511,7 @@ static void set_time(cupsd_job_t *job, /* I - Job to update */ const char *name) /* I - Name of attribute */ { + char date_name[128]; /* date-time-at-xxx */ ipp_attribute_t *attr; /* Time attribute */ time_t curtime; /* Current time */ @@ -4408,8 +4526,18 @@ set_time(cupsd_job_t *job, /* I - Job to update */ attr->values[0].integer = curtime; } + snprintf(date_name, sizeof(date_name), "date-%s", name); + + if ((attr = ippFindAttribute(job->attrs, date_name, IPP_TAG_ZERO)) != NULL) + { + attr->value_tag = IPP_TAG_DATE; + ippSetDate(job->attrs, &attr, 0, ippTimeToDate(curtime)); + } + if (!strcmp(name, "time-at-completed")) { + job->completed_time = curtime; + if (JobHistory < INT_MAX && attr) job->history_time = attr->values[0].integer + JobHistory; else @@ -4440,6 +4568,13 @@ static void start_job(cupsd_job_t *job, /* I - Job ID */ cupsd_printer_t *printer) /* I - Printer to print job */ { + const char *filename; /* Support filename */ + ipp_attribute_t *cancel_after = ippFindAttribute(job->attrs, + "job-cancel-after", + IPP_TAG_INTEGER); + /* job-cancel-after attribute */ + + cupsdLogMessage(CUPSD_LOG_DEBUG2, "start_job(job=%p(%d), printer=%p(%s))", job, job->id, printer, printer->name); @@ -4467,7 +4602,7 @@ start_job(cupsd_job_t *job, /* I - Job ID */ "job-printer-state-message", IPP_TAG_TEXT); if (job->printer_message) - cupsdSetString(&(job->printer_message->values[0].string.text), ""); + ippSetString(job->attrs, &job->printer_message, 0, ""); ippSetString(job->attrs, &job->reasons, 0, "job-printing"); cupsdSetJobState(job, IPP_JOB_PROCESSING, CUPSD_JOB_DEFAULT, NULL); @@ -4488,17 +4623,39 @@ start_job(cupsd_job_t *job, /* I - Job ID */ job->printer = printer; printer->job = job; - if (MaxJobTime > 0) + if (cancel_after) + job->cancel_time = time(NULL) + ippGetInteger(cancel_after, 0); + else if (MaxJobTime > 0) job->cancel_time = time(NULL) + MaxJobTime; else job->cancel_time = 0; /* + * Check for support files... + */ + + cupsdSetPrinterReasons(job->printer, "-cups-missing-filter-warning," + "cups-insecure-filter-warning"); + + if (printer->pc) + { + for (filename = (const char *)cupsArrayFirst(printer->pc->support_files); + filename; + filename = (const char *)cupsArrayNext(printer->pc->support_files)) + { + if (_cupsFileCheck(filename, _CUPS_FILE_CHECK_FILE, !RunUser, + cupsdLogFCMessage, printer)) + break; + } + } + + /* * Setup the last exit status and security profiles... */ - job->status = 0; - job->profile = cupsdCreateProfile(job->id); + job->status = 0; + job->profile = cupsdCreateProfile(job->id, 0); + job->bprofile = cupsdCreateProfile(job->id, 1); /* * Create the status pipes and buffer... @@ -4515,6 +4672,8 @@ start_job(cupsd_job_t *job, /* I - Job ID */ cupsdDestroyProfile(job->profile); job->profile = NULL; + cupsdDestroyProfile(job->bprofile); + job->bprofile = NULL; return; } @@ -4540,6 +4699,8 @@ start_job(cupsd_job_t *job, /* I - Job ID */ cupsdDestroyProfile(job->profile); job->profile = NULL; + cupsdDestroyProfile(job->bprofile); + job->bprofile = NULL; return; } @@ -4569,6 +4730,8 @@ start_job(cupsd_job_t *job, /* I - Job ID */ cupsdDestroyProfile(job->profile); job->profile = NULL; + cupsdDestroyProfile(job->bprofile); + job->bprofile = NULL; return; } @@ -4607,7 +4770,7 @@ stop_job(cupsd_job_t *job, /* I - Job */ FilterLevel -= job->cost; job->cost = 0; - if (action == CUPSD_JOB_DEFAULT && !job->kill_time) + if (action == CUPSD_JOB_DEFAULT && !job->kill_time && job->backend > 0) job->kill_time = time(NULL) + JobKillDelay; else if (action >= CUPSD_JOB_FORCE) job->kill_time = 0; @@ -4650,13 +4813,14 @@ unload_job(cupsd_job_t *job) /* I - Job */ if (!job->attrs) return; - cupsdLogMessage(CUPSD_LOG_DEBUG, "[Job %d] Unloading...", job->id); + cupsdLogJob(job, CUPSD_LOG_DEBUG, "Unloading..."); ippDelete(job->attrs); job->attrs = NULL; job->state = NULL; job->reasons = NULL; + job->impressions = NULL; job->sheets = NULL; job->job_sheets = NULL; job->printer_message = NULL; @@ -4678,6 +4842,8 @@ update_job(cupsd_job_t *job) /* I - Job to check */ *ptr; /* Pointer update... */ int loglevel, /* Log level for message */ event = 0; /* Events? */ + cupsd_printer_t *printer = job->printer; + /* Printer */ static const char * const levels[] = /* Log levels */ { "NONE", @@ -4715,6 +4881,25 @@ update_job(cupsd_job_t *job) /* I - Job to check */ cupsdLogJob(job, CUPSD_LOG_DEBUG, "PAGE: %s", message); + if (job->impressions) + { + if (!_cups_strncasecmp(message, "total ", 6)) + { + /* + * Got a total count of pages from a backend or filter... + */ + + copies = atoi(message + 6); + copies -= ippGetInteger(job->impressions, 0); /* Just track the delta */ + } + else if (!sscanf(message, "%*d%d", &copies)) + copies = 1; + + ippSetInteger(job->attrs, &job->impressions, 0, ippGetInteger(job->impressions, 0) + copies); + job->dirty = 1; + cupsdMarkDirty(CUPSD_DIRTY_JOBS); + } + if (job->sheets) { if (!_cups_strncasecmp(message, "total ", 6)) @@ -4724,12 +4909,14 @@ update_job(cupsd_job_t *job) /* I - Job to check */ */ copies = atoi(message + 6); - copies -= job->sheets->values[0].integer; /* Just track the delta */ + copies -= ippGetInteger(job->sheets, 0); /* Just track the delta */ } else if (!sscanf(message, "%*d%d", &copies)) copies = 1; - job->sheets->values[0].integer += copies; + ippSetInteger(job->attrs, &job->sheets, 0, ippGetInteger(job->sheets, 0) + copies); + job->dirty = 1; + cupsdMarkDirty(CUPSD_DIRTY_JOBS); if (job->printer->page_limit) cupsdUpdateQuota(job->printer, job->username, copies, 0); @@ -4738,8 +4925,21 @@ update_job(cupsd_job_t *job) /* I - Job to check */ cupsdLogPage(job, message); if (job->sheets) - cupsdAddEvent(CUPSD_EVENT_JOB_PROGRESS, job->printer, job, - "Printed %d page(s).", job->sheets->values[0].integer); + cupsdAddEvent(CUPSD_EVENT_JOB_PROGRESS, job->printer, job, "Printed %d page(s).", ippGetInteger(job->sheets, 0)); + } + else if (loglevel == CUPSD_LOG_JOBSTATE) + { + /* + * Support "keyword" to set job-state-reasons to the specified keyword. + * This is sufficient for the current paid printing stuff. + */ + + cupsdLogJob(job, CUPSD_LOG_DEBUG, "JOBSTATE: %s", message); + + if (!strcmp(message, "cups-retry-as-raster")) + job->retry_as_raster = 1; + else + ippSetString(job->attrs, &job->reasons, 0, message); } else if (loglevel == CUPSD_LOG_STATE) { @@ -4754,7 +4954,7 @@ update_job(cupsd_job_t *job) /* I - Job to check */ { event |= CUPSD_EVENT_PRINTER_STATE; - if (MaxJobTime > 0 && strstr(message, "connecting-to-device") != NULL) + if (MaxJobTime > 0) { /* * Reset cancel time after connecting to the device... @@ -4765,7 +4965,17 @@ update_job(cupsd_job_t *job) /* I - Job to check */ break; if (i >= job->printer->num_reasons) - job->cancel_time = time(NULL) + MaxJobTime; + { + ipp_attribute_t *cancel_after = ippFindAttribute(job->attrs, + "job-cancel-after", + IPP_TAG_INTEGER); + /* job-cancel-after attribute */ + + if (cancel_after) + job->cancel_time = time(NULL) + ippGetInteger(cancel_after, 0); + else + job->cancel_time = time(NULL) + MaxJobTime; + } } } @@ -4781,11 +4991,21 @@ update_job(cupsd_job_t *job) /* I - Job to check */ cups_option_t *attrs; /* Attributes */ const char *attr; /* Attribute */ - cupsdLogJob(job, CUPSD_LOG_DEBUG, "ATTR: %s", message); num_attrs = cupsParseOptions(message, 0, &attrs); + if ((attr = cupsGetOption("auth-info-default", num_attrs, + attrs)) != NULL) + { + job->printer->num_options = cupsAddOption("auth-info", attr, + job->printer->num_options, + &(job->printer->options)); + cupsdSetPrinterAttrs(job->printer); + + cupsdMarkDirty(CUPSD_DIRTY_PRINTERS); + } + if ((attr = cupsGetOption("auth-info-required", num_attrs, attrs)) != NULL) { @@ -4997,10 +5217,11 @@ update_job(cupsd_job_t *job) /* I - Job to check */ finalize_job(job, 1); /* - * Check for new jobs... + * Try printing another job... */ - cupsdCheckJobs(); + if (printer->state != IPP_PRINTER_STOPPED) + cupsdCheckJobs(); } } @@ -5045,15 +5266,14 @@ update_job_attrs(cupsd_job_t *job, /* I - Job to update */ if (job->state_value != IPP_JOB_PROCESSING && job->status_level == CUPSD_LOG_INFO) { - cupsdSetString(&(job->printer_message->values[0].string.text), ""); + ippSetString(job->attrs, &job->printer_message, 0, ""); job->dirty = 1; cupsdMarkDirty(CUPSD_DIRTY_JOBS); } else if (job->printer->state_message[0] && do_message) { - cupsdSetString(&(job->printer_message->values[0].string.text), - job->printer->state_message); + ippSetString(job->attrs, &job->printer_message, 0, job->printer->state_message); job->dirty = 1; cupsdMarkDirty(CUPSD_DIRTY_JOBS); @@ -5121,5 +5341,5 @@ update_job_attrs(cupsd_job_t *job, /* I - Job to update */ /* - * End of "$Id: job.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: job.c 12856 2015-08-31 14:27:39Z msweet $". */ diff --git a/scheduler/job.h b/scheduler/job.h index 6fb5ab8..2e3edc8 100644 --- a/scheduler/job.h +++ b/scheduler/job.h @@ -1,16 +1,16 @@ /* - * "$Id: job.h 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: job.h 12668 2015-05-27 19:30:32Z msweet $" * - * Print job definitions for the CUPS scheduler. + * Print job definitions for the CUPS scheduler. * - * Copyright 2007-2011 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. + * Copyright 2007-2015 by Apple Inc. + * Copyright 1997-2007 by Easy Software Products, all rights reserved. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -39,14 +39,19 @@ struct cupsd_job_s /**** Job request ****/ * waiting on files */ char *username; /* Printing user */ char *dest; /* Destination printer or class */ + char *name; /* Job name/title */ + int koctets; /* job-k-octets */ cups_ptype_t dtype; /* Destination type */ cupsd_printer_t *printer; /* Printer this job is assigned to */ int num_files; /* Number of files in job */ mime_type_t **filetypes; /* File types */ int *compressions; /* Compression status of each file */ - ipp_attribute_t *sheets; /* job-media-sheets-completed */ + ipp_attribute_t *impressions, /* job-impressions-completed */ + *sheets; /* job-media-sheets-completed */ time_t access_time, /* Last access time */ cancel_time, /* When to cancel/send SIGTERM */ + creation_time, /* When job was created */ + completed_time, /* When job was completed (0 if not) */ file_time, /* Job file retain time */ history_time, /* Job history retain time */ hold_until, /* Hold expiration date/time */ @@ -74,10 +79,13 @@ struct cupsd_job_s /**** Job request ****/ int backend; /* Backend process ID */ int status; /* Status code from filters */ int tries; /* Number of tries for this job */ + int completed; /* cups-waiting-for-job-completed seen */ + int retry_as_raster;/* Need to retry the job as raster */ char *auth_env[3], /* AUTH_xxx environment variables, * if any */ *auth_uid; /* AUTH_UID environment variable */ - void *profile; /* Security profile */ + void *profile, /* Security profile for filters */ + *bprofile; /* Security profile for backend */ cups_array_t *history; /* Debug log history */ int progress; /* Printing progress */ int num_keywords; /* Number of PPD keywords */ @@ -145,6 +153,7 @@ extern void cupsdDeleteJob(cupsd_job_t *job, cupsd_jobaction_t action); extern cupsd_job_t *cupsdFindJob(int id); extern void cupsdFreeAllJobs(void); +extern cups_array_t *cupsdGetCompletedJobs(cupsd_printer_t *p); extern int cupsdGetPrinterJobCount(const char *dest); extern int cupsdGetUserJobCount(const char *username); extern void cupsdLoadAllJobs(void); @@ -171,5 +180,5 @@ extern void cupsdUpdateJobs(void); /* - * End of "$Id: job.h 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: job.h 12668 2015-05-27 19:30:32Z msweet $". */ diff --git a/scheduler/listen.c b/scheduler/listen.c index a4c19c0..9fcc631 100644 --- a/scheduler/listen.c +++ b/scheduler/listen.c @@ -1,24 +1,16 @@ /* - * "$Id: listen.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: listen.c 12178 2014-09-30 18:56:48Z msweet $" * - * Server listening routines for the CUPS scheduler. + * Server listening routines for the CUPS scheduler. * - * Copyright 2007-2010 by Apple Inc. - * Copyright 1997-2006 by Easy Software Products, all rights reserved. + * Copyright 2007-2014 by Apple Inc. + * Copyright 1997-2006 by Easy Software Products, all rights reserved. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * cupsdDeleteAllListeners() - Delete all listeners. - * cupsdPauseListening() - Clear input polling on all listening sockets... - * cupsdResumeListening() - Set input polling on all listening sockets... - * cupsdStartListening() - Create all listening sockets... - * cupsdStopListening() - Close all listening sockets... + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -51,10 +43,19 @@ cupsdDeleteAllListeners(void) for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); lis; lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) - free(lis); +#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) + if (!lis->on_demand) +#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ + { + cupsArrayRemove(Listeners, lis); + free(lis); + } - cupsArrayDelete(Listeners); - Listeners = NULL; + if (cupsArrayCount(Listeners) == 0) + { + cupsArrayDelete(Listeners); + Listeners = NULL; + } } @@ -123,9 +124,7 @@ cupsdResumeListening(void) void cupsdStartListening(void) { - int status; /* Bind result */ - int p, /* Port number */ - val; /* Parameter value */ + int p; /* Port number */ cupsd_listener_t *lis; /* Current listening socket */ char s[256]; /* String addresss */ const char *have_domain; /* Have a domain socket? */ @@ -151,7 +150,7 @@ cupsdStartListening(void) lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) { httpAddrString(&(lis->address), s, sizeof(s)); - p = _httpAddrPort(&(lis->address)); + p = httpAddrPort(&(lis->address)); /* * If needed, create a socket for listening... @@ -163,7 +162,7 @@ cupsdStartListening(void) * Create a socket for listening... */ - lis->fd = socket(lis->address.addr.sa_family, SOCK_STREAM, 0); + lis->fd = httpAddrListen(&(lis->address), p); if (lis->fd == -1) { @@ -186,132 +185,15 @@ cupsdStartListening(void) continue; } - - /* - * Set things up to reuse the local address for this port. - */ - - val = 1; -#ifdef __sun - setsockopt(lis->fd, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val)); -#else - setsockopt(lis->fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); -#endif /* __sun */ - - /* - * Bind to the port we found... - */ - -#ifdef AF_INET6 - if (lis->address.addr.sa_family == AF_INET6) - { -# ifdef IPV6_V6ONLY - /* - * Accept only IPv6 connections on this socket, to avoid - * potential security issues and to make all platforms behave - * the same. - */ - - val = 1; -# ifdef __sun - setsockopt(lis->fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&val, sizeof(val)); -# else - setsockopt(lis->fd, IPPROTO_IPV6, IPV6_V6ONLY, &val, sizeof(val)); -# endif /* __sun */ -# endif /* IPV6_V6ONLY */ - - status = bind(lis->fd, (struct sockaddr *)&(lis->address), - httpAddrLength(&(lis->address))); - } - else -#endif /* AF_INET6 */ -#ifdef AF_LOCAL - if (lis->address.addr.sa_family == AF_LOCAL) - { - mode_t mask; /* Umask setting */ - - - /* - * Remove any existing domain socket file... - */ - - unlink(lis->address.un.sun_path); - - /* - * Save the current umask and set it to 0 so that all users can access - * the domain socket... - */ - - mask = umask(0); - - /* - * Bind the domain socket... - */ - - status = bind(lis->fd, (struct sockaddr *)&(lis->address), - httpAddrLength(&(lis->address))); - - /* - * Restore the umask... - */ - - umask(mask); - } - else -#endif /* AF_LOCAL */ - status = bind(lis->fd, (struct sockaddr *)&(lis->address), - sizeof(lis->address.ipv4)); - - if (status < 0) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to bind socket for address %s:%d - %s.", - s, p, strerror(errno)); - close(lis->fd); - lis->fd = -1; - - if (FatalErrors & CUPSD_FATAL_LISTEN) - cupsdEndProcess(getpid(), 0); - - continue; - } - - /* - * Listen for new clients. - */ - - if (listen(lis->fd, ListenBackLog) < 0) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to listen for clients on address %s:%d - %s.", - s, p, strerror(errno)); - - close(lis->fd); - lis->fd = -1; - - if (FatalErrors & CUPSD_FATAL_LISTEN) - cupsdEndProcess(getpid(), 0); - - continue; - } } - fcntl(lis->fd, F_SETFD, fcntl(lis->fd, F_GETFD) | FD_CLOEXEC); - if (p) cupsdLogMessage(CUPSD_LOG_INFO, "Listening to %s:%d on fd %d...", s, p, lis->fd); else - { cupsdLogMessage(CUPSD_LOG_INFO, "Listening to %s on fd %d...", s, lis->fd); - if (chmod(s, 0140777)) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to change permisssions on domain socket " - "\"%s\" - %s", s, strerror(errno)); - } - /* * Save the first port that is bound to the local loopback or * "any" address... @@ -339,7 +221,7 @@ cupsdStartListening(void) { cupsdLogMessage(CUPSD_LOG_EMERG, "No Listen or Port lines were found to allow access via " - "localhost!"); + "localhost."); if (FatalErrors & (CUPSD_FATAL_CONFIG | CUPSD_FATAL_LISTEN)) cupsdEndProcess(getpid(), 0); @@ -401,31 +283,24 @@ cupsdStopListening(void) lis; lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) { - if (lis->fd != -1) +#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) + if (!lis->on_demand && lis->fd != -1) { -#ifdef WIN32 - closesocket(lis->fd); -#else - close(lis->fd); -#endif /* WIN32 */ - -#ifdef AF_LOCAL - /* - * Remove domain sockets... - */ + httpAddrClose(&(lis->address), lis->fd); + lis->fd = -1; + } -# ifdef HAVE_LAUNCH_H - if (lis->address.addr.sa_family == AF_LOCAL && !Launchd) -# else - if (lis->address.addr.sa_family == AF_LOCAL) -# endif /* HAVE_LAUNCH_H */ - unlink(lis->address.un.sun_path); -#endif /* AF_LOCAL */ +#else + if (lis->fd != -1) + { + httpAddrClose(&(lis->address), lis->fd); + lis->fd = -1; } +#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ } } /* - * End of "$Id: listen.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: listen.c 12178 2014-09-30 18:56:48Z msweet $". */ diff --git a/scheduler/log.c b/scheduler/log.c index d739b58..55e8036 100644 --- a/scheduler/log.c +++ b/scheduler/log.c @@ -1,28 +1,16 @@ /* - * "$Id: log.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: log.c 12928 2015-10-23 21:31:58Z msweet $" * - * Log file routines for the CUPS scheduler. + * Log file routines for the CUPS scheduler. * - * Copyright 2007-2011 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. + * Copyright 2007-2015 by Apple Inc. + * Copyright 1997-2007 by Easy Software Products, all rights reserved. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * cupsdCheckLogFile() - Open/rotate a log file if it needs it. - * cupsdGetDateTime() - Returns a pointer to a date/time string. - * cupsdLogGSSMessage() - Log a GSSAPI error... - * cupsdLogJob() - Log a job message. - * cupsdLogMessage() - Log a message to the error log file. - * cupsdLogPage() - Log a page to the page log file. - * cupsdLogRequest() - Log an HTTP request in Common Log Format. - * cupsdWriteErrorLog() - Write a line to the ErrorLog. - * format_log_line() - Format a line for a log file. + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -31,18 +19,68 @@ #include "cupsd.h" #include <stdarg.h> +#ifdef HAVE_ASL_H +# include <asl.h> +#elif defined(HAVE_SYSTEMD_SD_JOURNAL_H) +# define SD_JOURNAL_SUPPRESS_LOCATION +# include <systemd/sd-journal.h> +#endif /* HAVE_ASL_H */ #include <syslog.h> /* + * Constants for log keys from PWG 5110.3 (PWG Common Log Format)... + */ + +#define PWG_DeviceUUID "DUU" +#define PWG_Event "E" +#define PWG_LogNaturalLanguage "NL" +#define PWG_Status "S" +#define PWG_ServiceURI "URI" +#define PWG_UserHost "UH" +#define PWG_UserName "UN" +#define PWG_UserURI "UU" +#define PWG_ServiceIsAcceptingJobs "IAJ" +#define PWG_ServiceState "ST" +#define PWG_ServiceStateReasons "SR" +#define PWG_ServiceUUID "SUU" +#define PWG_JobID "JID" +#define PWG_JobUUID "JUU" +#define PWG_JobImagesCompleted "JIM" +#define PWG_JobImpressionsCompleted "JIC" +#define PWG_JobDestinationURI "JD" +#define PWG_JobState "JS" +#define PWG_JobStateReasons "JR" +#define PWG_JobAccountingID "JA" +#define PWG_JobAcountingUserName "JAUN" +#define PWG_JobAccountingUserURI "JAUU" + + +/* * Local globals... */ -static int log_linesize = 0; /* Size of line for output file */ +static _cups_mutex_t log_mutex = _CUPS_MUTEX_INITIALIZER; + /* Mutex for logging */ +static size_t log_linesize = 0; /* Size of line for output file */ static char *log_line = NULL; /* Line for output file */ -#ifdef HAVE_VSYSLOG -static const int syslevels[] = /* SYSLOG levels... */ +#ifdef HAVE_ASL_H +static const int log_levels[] = /* ASL levels... */ + { + ASL_LEVEL_EMERG, + ASL_LEVEL_EMERG, + ASL_LEVEL_ALERT, + ASL_LEVEL_CRIT, + ASL_LEVEL_ERR, + ASL_LEVEL_WARNING, + ASL_LEVEL_NOTICE, + ASL_LEVEL_INFO, + ASL_LEVEL_DEBUG, + ASL_LEVEL_DEBUG + }; +#elif defined(HAVE_VSYSLOG) || defined(HAVE_SYSTEMD_SD_JOURNAL_H) +static const int log_levels[] = /* SYSLOG levels... */ { 0, LOG_EMERG, @@ -55,7 +93,7 @@ static const int syslevels[] = /* SYSLOG levels... */ LOG_DEBUG, LOG_DEBUG }; -#endif /* HAVE_VSYSLOG */ +#endif /* HAVE_ASL_H */ /* @@ -87,6 +125,16 @@ cupsdCheckLogFile(cups_file_t **lf, /* IO - Log file */ return (1); /* + * Handle logging to stderr... + */ + + if (!strcmp(logname, "stderr")) + { + *lf = LogStderr; + return (1); + } + + /* * Format the filename as needed... */ @@ -124,7 +172,7 @@ cupsdCheckLogFile(cups_file_t **lf, /* IO - Log file */ * Insert the server name... */ - strlcpy(ptr, ServerName, sizeof(filename) - (ptr - filename)); + strlcpy(ptr, ServerName, sizeof(filename) - (size_t)(ptr - filename)); ptr += strlen(ptr); } else @@ -165,23 +213,34 @@ cupsdCheckLogFile(cups_file_t **lf, /* IO - Log file */ * the log file permissions as a basis... */ - int log_dir_perm = 0300 | LogFilePerm; + mode_t log_dir_perm = (mode_t)(0300 | LogFilePerm); /* LogFilePerm + owner write/search */ if (log_dir_perm & 0040) log_dir_perm |= 0010; /* Add group search */ if (log_dir_perm & 0004) log_dir_perm |= 0001; /* Add other search */ - cupsdCheckPermissions(CUPS_LOGDIR, NULL, log_dir_perm, RunUser, Group, - 1, -1); + cupsdCheckPermissions(CUPS_LOGDIR, NULL, log_dir_perm, RunUser, Group, 1, -1); *lf = cupsFileOpen(filename, "a"); } if (*lf == NULL) { - syslog(LOG_ERR, "Unable to open log file \"%s\" - %s", filename, - strerror(errno)); +#ifdef HAVE_ASL_H + asl_object_t m; /* Log message */ + + m = asl_new(ASL_TYPE_MSG); + asl_set(m, ASL_KEY_FACILITY, "org.cups.cupsd"); + asl_log(NULL, m, ASL_LEVEL_ERR, "Unable to open log file \"%s\" - %s", filename, strerror(errno)); + asl_release(m); + +#elif defined(HAVE_SYSTEMD_SD_JOURNAL_H) + sd_journal_print(LOG_ERR, "Unable to open log file \"%s\" - %s", filename, strerror(errno)); + +#else + syslog(LOG_ERR, "Unable to open log file \"%s\" - %s", filename, strerror(errno)); +#endif /* HAVE_ASL_H */ if (FatalErrors & CUPSD_FATAL_LOG) cupsdEndProcess(getpid(), 0); @@ -214,7 +273,7 @@ cupsdCheckLogFile(cups_file_t **lf, /* IO - Log file */ cupsFileClose(*lf); - strcpy(backname, filename); + strlcpy(backname, filename, sizeof(backname)); strlcat(backname, ".O", sizeof(backname)); unlink(backname); @@ -222,8 +281,20 @@ cupsdCheckLogFile(cups_file_t **lf, /* IO - Log file */ if ((*lf = cupsFileOpen(filename, "a")) == NULL) { - syslog(LOG_ERR, "Unable to open log file \"%s\" - %s", filename, - strerror(errno)); +#ifdef HAVE_ASL_H + asl_object_t m; /* Log message */ + + m = asl_new(ASL_TYPE_MSG); + asl_set(m, ASL_KEY_FACILITY, "org.cups.cupsd"); + asl_log(NULL, m, ASL_LEVEL_ERR, "Unable to open log file \"%s\" - %s", filename, strerror(errno)); + asl_release(m); + +#elif defined(HAVE_SYSTEMD_SD_JOURNAL_H) + sd_journal_print(LOG_ERR, "Unable to open log file \"%s\" - %s", filename, strerror(errno)); + +#else + syslog(LOG_ERR, "Unable to open log file \"%s\" - %s", filename, strerror(errno)); +#endif /* HAVE_ASL_H */ if (FatalErrors & CUPSD_FATAL_LOG) cupsdEndProcess(getpid(), 0); @@ -382,8 +453,8 @@ cupsdLogFCMessage( int /* O - 1 on success, 0 on error */ cupsdLogGSSMessage( int level, /* I - Log level */ - int major_status, /* I - Major GSSAPI status */ - int minor_status, /* I - Minor GSSAPI status */ + OM_uint32 major_status, /* I - Major GSSAPI status */ + OM_uint32 minor_status, /* I - Minor GSSAPI status */ const char *message, /* I - printf-style message string */ ...) /* I - Additional args as needed */ { @@ -437,6 +508,61 @@ cupsdLogGSSMessage( /* + * 'cupsdLogClient()' - Log a client message. + */ + +int /* O - 1 on success, 0 on error */ +cupsdLogClient(cupsd_client_t *con, /* I - Client connection */ + int level, /* I - Log level */ + const char *message, /* I - Printf-style message string */ + ...) /* I - Additional arguments as needed */ +{ + va_list ap, ap2; /* Argument pointers */ + char clientmsg[1024];/* Format string for client message */ + int status; /* Formatting status */ + + + /* + * See if we want to log this message... + */ + + if (TestConfigFile || !ErrorLog) + return (1); + + if (level > LogLevel) + return (1); + + /* + * Format and write the log message... + */ + + if (con) + snprintf(clientmsg, sizeof(clientmsg), "[Client %d] %s", con->number, + message); + else + strlcpy(clientmsg, message, sizeof(clientmsg)); + + va_start(ap, message); + + do + { + va_copy(ap2, ap); + status = format_log_line(clientmsg, ap2); + va_end(ap2); + } + while (status == 0); + + va_end(ap); + + if (status > 0) + return (cupsdWriteErrorLog(level, log_line)); + else + return (cupsdWriteErrorLog(CUPSD_LOG_ERROR, + "Unable to allocate memory for log line.")); +} + + +/* * 'cupsdLogJob()' - Log a job message. */ @@ -463,6 +589,96 @@ cupsdLogJob(cupsd_job_t *job, /* I - Job */ LogDebugHistory <= 0) return (1); +#ifdef HAVE_ASL_H + if (!strcmp(ErrorLog, "syslog")) + { + asl_object_t m; /* Log message */ + char job_id[32], /* job-id string */ + completed[32]; /* job-impressions-completed string */ + cupsd_printer_t *printer = job ? (job->printer ? job->printer : (job->dest ? cupsdFindDest(job->dest) : NULL)) : NULL; + static const char * const job_states[] = + { /* job-state strings */ + "Pending", + "PendingHeld", + "Processing", + "ProcessingStopped", + "Canceled", + "Aborted", + "Completed" + }; + + m = asl_new(ASL_TYPE_MSG); + asl_set(m, ASL_KEY_FACILITY, "org.cups.cupsd"); + if (printer) + asl_set(m, PWG_ServiceURI, printer->uri); + if (job) + { + snprintf(job_id, sizeof(job_id), "%d", job->id); + + asl_set(m, PWG_Event, "JobStateChanged"); + asl_set(m, PWG_JobID, job_id); + asl_set(m, PWG_JobState, job->state_value < IPP_JSTATE_PENDING ? "" : job_states[job->state_value - IPP_JSTATE_PENDING]); + + if (job->impressions) + { + snprintf(completed, sizeof(completed), "%d", ippGetInteger(job->impressions, 0)); + asl_set(m, PWG_JobImpressionsCompleted, completed); + } + } + + va_start(ap, message); + asl_vlog(NULL, m, log_levels[level], message, ap); + va_end(ap); + + asl_release(m); + return (1); + } + +#elif defined(HAVE_SYSTEMD_SD_JOURNAL_H) + if (!strcmp(ErrorLog, "syslog")) + { + cupsd_printer_t *printer = job ? (job->printer ? job->printer : (job->dest ? cupsdFindDest(job->dest) : NULL)) : NULL; + static const char * const job_states[] = + { /* job-state strings */ + "Pending", + "PendingHeld", + "Processing", + "ProcessingStopped", + "Canceled", + "Aborted", + "Completed" + }; + + va_start(ap, message); + + do + { + va_copy(ap2, ap); + status = format_log_line(message, ap2); + va_end(ap2); + } + while (status == 0); + + va_end(ap); + + if (job) + sd_journal_send("MESSAGE=%s", log_line, + "PRIORITY=%i", log_levels[level], + PWG_Event"=JobStateChanged", + PWG_ServiceURI"=%s", printer ? printer->uri : "", + PWG_JobID"=%d", job->id, + PWG_JobState"=%s", job->state_value < IPP_JSTATE_PENDING ? "" : job_states[job->state_value - IPP_JSTATE_PENDING], + PWG_JobImpressionsCompleted"=%d", ippGetInteger(job->impressions, 0), + NULL); + else + sd_journal_send("MESSAGE=%s", log_line, + "PRIORITY=%i", log_levels[level], + NULL); + + return (1); + } +#endif /* HAVE_ASL_H */ + /* * Format and write the log message... */ @@ -496,12 +712,13 @@ cupsdLogJob(cupsd_job_t *job, /* I - Job */ */ cupsd_joblog_t *temp; /* Copy of log message */ + size_t log_len = strlen(log_line); + /* Length of log message */ - - if ((temp = malloc(sizeof(cupsd_joblog_t) + strlen(log_line))) != NULL) + if ((temp = malloc(sizeof(cupsd_joblog_t) + log_len)) != NULL) { temp->time = time(NULL); - strcpy(temp->message, log_line); + memcpy(temp->message, log_line, log_len + 1); } if (!job->history) @@ -535,7 +752,7 @@ cupsdLogJob(cupsd_job_t *job, /* I - Job */ } else return (cupsdWriteErrorLog(CUPSD_LOG_ERROR, - "Unable to allocate memory for log line!")); + "Unable to allocate memory for log line.")); } @@ -559,12 +776,26 @@ cupsdLogMessage(int level, /* I - Log level */ if ((TestConfigFile || !ErrorLog) && level <= CUPSD_LOG_WARN) { va_start(ap, message); -#ifdef HAVE_VSYSLOG - vsyslog(LOG_LPR | syslevels[level], message, ap); + +#ifdef HAVE_ASL_H + asl_object_t m; /* Log message */ + + m = asl_new(ASL_TYPE_MSG); + asl_set(m, ASL_KEY_FACILITY, "org.cups.cupsd"); + asl_vlog(NULL, m, log_levels[level], message, ap); + asl_release(m); + +#elif defined(HAVE_SYSTEMD_SD_JOURNAL_H) + sd_journal_printv(log_levels[level], message, ap); + +#elif defined(HAVE_VSYSLOG) + vsyslog(LOG_LPR | log_levels[level], message, ap); + #else vfprintf(stderr, message, ap); putc('\n', stderr); #endif /* HAVE_VSYSLOG */ + va_end(ap); return (1); @@ -573,6 +804,32 @@ cupsdLogMessage(int level, /* I - Log level */ if (level > LogLevel || !ErrorLog) return (1); +#ifdef HAVE_ASL_H + if (!strcmp(ErrorLog, "syslog")) + { + asl_object_t m; /* Log message */ + + m = asl_new(ASL_TYPE_MSG); + asl_set(m, ASL_KEY_FACILITY, "org.cups.cupsd"); + + va_start(ap, message); + asl_vlog(NULL, m, log_levels[level], message, ap); + va_end(ap); + + asl_release(m); + return (1); + } + +#elif defined(HAVE_SYSTEMD_SD_JOURNAL_H) + if (!strcmp(ErrorLog, "syslog")) + { + va_start(ap, message); + sd_journal_printv(log_levels[level], message, ap); + va_end(ap); + return (1); + } +#endif /* HAVE_ASL_H */ + /* * Format and write the log message... */ @@ -623,7 +880,7 @@ cupsdLogPage(cupsd_job_t *job, /* I - Job being printed */ if (!PageLogFormat) return (1); - strcpy(number, "1"); + strlcpy(number, "1", sizeof(number)); copies = 1; sscanf(page, "%255s%d", number, &copies); @@ -641,53 +898,68 @@ cupsdLogPage(cupsd_job_t *job, /* I - Job being printed */ break; case 'p' : /* Printer name */ - strlcpy(bufptr, job->printer->name, - sizeof(buffer) - (bufptr - buffer)); + strlcpy(bufptr, job->dest, sizeof(buffer) - (size_t)(bufptr - buffer)); bufptr += strlen(bufptr); break; case 'j' : /* Job ID */ - snprintf(bufptr, sizeof(buffer) - (bufptr - buffer), "%d", job->id); + snprintf(bufptr, sizeof(buffer) - (size_t)(bufptr - buffer), "%d", job->id); bufptr += strlen(bufptr); break; case 'u' : /* Username */ - strlcpy(bufptr, job->username ? job->username : "-", - sizeof(buffer) - (bufptr - buffer)); + strlcpy(bufptr, job->username ? job->username : "-", sizeof(buffer) - (size_t)(bufptr - buffer)); bufptr += strlen(bufptr); break; case 'T' : /* Date and time */ - strlcpy(bufptr, cupsdGetDateTime(NULL, LogTimeFormat), - sizeof(buffer) - (bufptr - buffer)); + strlcpy(bufptr, cupsdGetDateTime(NULL, LogTimeFormat), sizeof(buffer) - (size_t)(bufptr - buffer)); bufptr += strlen(bufptr); break; case 'P' : /* Page number */ - strlcpy(bufptr, number, sizeof(buffer) - (bufptr - buffer)); + strlcpy(bufptr, number, sizeof(buffer) - (size_t)(bufptr - buffer)); bufptr += strlen(bufptr); break; case 'C' : /* Number of copies */ - snprintf(bufptr, sizeof(buffer) - (bufptr - buffer), "%d", copies); + snprintf(bufptr, sizeof(buffer) - (size_t)(bufptr - buffer), "%d", copies); bufptr += strlen(bufptr); break; case '{' : /* {attribute} */ - if ((nameend = strchr(format, '}')) != NULL && - (nameend - format - 2) < (sizeof(name) - 1)) + if ((nameend = strchr(format, '}')) != NULL && (size_t)(nameend - format - 2) < (sizeof(name) - 1)) { /* * Pull the name from inside the brackets... */ - memcpy(name, format + 1, nameend - format - 1); + memcpy(name, format + 1, (size_t)(nameend - format - 1)); name[nameend - format - 1] = '\0'; format = nameend; - if ((attr = ippFindAttribute(job->attrs, name, - IPP_TAG_ZERO)) != NULL) + attr = ippFindAttribute(job->attrs, name, IPP_TAG_ZERO); + if (!attr && !strcmp(name, "job-billing")) + { + /* + * Handle alias "job-account-id" (which was standardized after + * "job-billing" was defined for CUPS... + */ + + attr = ippFindAttribute(job->attrs, "job-account-id", IPP_TAG_ZERO); + } + else if (!attr && !strcmp(name, "media")) + { + /* + * Handle alias "media-col" which uses dimensions instead of + * names... + */ + + attr = ippFindAttribute(job->attrs, "media-col/media-size", IPP_TAG_BEGIN_COLLECTION); + } + + if (attr) { /* * Add the attribute value... @@ -705,14 +977,12 @@ cupsdLogPage(cupsd_job_t *job, /* I - Job being printed */ { case IPP_TAG_INTEGER : case IPP_TAG_ENUM : - snprintf(bufptr, sizeof(buffer) - (bufptr - buffer), - "%d", attr->values[i].integer); + snprintf(bufptr, sizeof(buffer) - (size_t)(bufptr - buffer), "%d", attr->values[i].integer); bufptr += strlen(bufptr); break; case IPP_TAG_BOOLEAN : - snprintf(bufptr, sizeof(buffer) - (bufptr - buffer), - "%d", attr->values[i].boolean); + snprintf(bufptr, sizeof(buffer) - (size_t)(bufptr - buffer), "%d", attr->values[i].boolean); bufptr += strlen(bufptr); break; @@ -726,14 +996,28 @@ cupsdLogPage(cupsd_job_t *job, /* I - Job being printed */ case IPP_TAG_CHARSET : case IPP_TAG_LANGUAGE : case IPP_TAG_MIMETYPE : - strlcpy(bufptr, attr->values[i].string.text, - sizeof(buffer) - (bufptr - buffer)); + strlcpy(bufptr, attr->values[i].string.text, sizeof(buffer) - (size_t)(bufptr - buffer)); bufptr += strlen(bufptr); break; + case IPP_TAG_BEGIN_COLLECTION : + if (!strcmp(attr->name, "media-size")) + { + ipp_attribute_t *x_dimension = ippFindAttribute(ippGetCollection(attr, 0), "x-dimension", IPP_TAG_INTEGER); + ipp_attribute_t *y_dimension = ippFindAttribute(ippGetCollection(attr, 0), "y-dimension", IPP_TAG_INTEGER); + /* Media dimensions */ + + if (x_dimension && y_dimension) + { + pwg_media_t *pwg = pwgMediaForSize(ippGetInteger(x_dimension, 0), ippGetInteger(y_dimension, 0)); + /* PWG media name */ + strlcpy(bufptr, pwg->pwg, sizeof(buffer) - (size_t)(bufptr - buffer)); + break; + } + } + default : - strlcpy(bufptr, "???", - sizeof(buffer) - (bufptr - buffer)); + strlcpy(bufptr, "???", sizeof(buffer) - (size_t)(bufptr - buffer)); bufptr += strlen(bufptr); break; } @@ -759,7 +1043,70 @@ cupsdLogPage(cupsd_job_t *job, /* I - Job being printed */ *bufptr = '\0'; -#ifdef HAVE_VSYSLOG +#ifdef HAVE_ASL_H + if (!strcmp(ErrorLog, "syslog")) + { + asl_object_t m; /* Log message */ + char job_id[32], /* job-id string */ + completed[32]; /* job-impressions-completed string */ + static const char * const job_states[] = + { /* job-state strings */ + "Pending", + "PendingHeld", + "Processing", + "ProcessingStopped", + "Canceled", + "Aborted", + "Completed" + }; + + snprintf(job_id, sizeof(job_id), "%d", job->id); + + m = asl_new(ASL_TYPE_MSG); + asl_set(m, ASL_KEY_FACILITY, "org.cups.cupsd"); + asl_set(m, PWG_Event, "JobStateChanged"); + asl_set(m, PWG_ServiceURI, job->printer->uri); + asl_set(m, PWG_JobID, job_id); + asl_set(m, PWG_JobState, job_states[job->state_value - IPP_JSTATE_PENDING]); + + if (job->impressions) + { + snprintf(completed, sizeof(completed), "%d", ippGetInteger(job->impressions, 0)); + asl_set(m, PWG_JobImpressionsCompleted, completed); + } + + asl_log(NULL, m, ASL_LEVEL_INFO, "%s", buffer); + + asl_release(m); + return (1); + } + +#elif defined(HAVE_SYSTEMD_SD_JOURNAL_H) + if (!strcmp(ErrorLog, "syslog")) + { + static const char * const job_states[] = + { /* job-state strings */ + "Pending", + "PendingHeld", + "Processing", + "ProcessingStopped", + "Canceled", + "Aborted", + "Completed" + }; + + sd_journal_send("MESSAGE=%s", buffer, + "PRIORITY=%i", LOG_INFO, + PWG_Event"=JobStateChanged", + PWG_ServiceURI"=%s", job->printer->uri, + PWG_JobID"=%d", job->id, + PWG_JobState"=%s", job_states[job->state_value - IPP_JSTATE_PENDING], + PWG_JobImpressionsCompleted"=%d", ippGetInteger(job->impressions, 0), + NULL); + return (1); + } + +#elif defined(HAVE_VSYSLOG) /* * See if we are logging pages via syslog... */ @@ -770,7 +1117,7 @@ cupsdLogPage(cupsd_job_t *job, /* I - Job being printed */ return (1); } -#endif /* HAVE_VSYSLOG */ +#endif /* HAVE_ASL_H */ /* * Not using syslog; check the log file... @@ -825,7 +1172,9 @@ cupsdLogRequest(cupsd_client_t *con, /* I - Request to log */ * Filter requests as needed... */ - if (AccessLogLevel < CUPSD_ACCESSLOG_ALL) + if (AccessLogLevel == CUPSD_ACCESSLOG_NONE) + return (1); + else if (AccessLogLevel < CUPSD_ACCESSLOG_ALL) { /* * Eliminate simple GET, POST, and PUT requests... @@ -929,7 +1278,36 @@ cupsdLogRequest(cupsd_client_t *con, /* I - Request to log */ } } -#ifdef HAVE_VSYSLOG +#ifdef HAVE_ASL_H + if (!strcmp(ErrorLog, "syslog")) + { + asl_object_t m; /* Log message */ + + m = asl_new(ASL_TYPE_MSG); + asl_set(m, ASL_KEY_FACILITY, "org.cups.cupsd"); + + asl_log(NULL, m, ASL_LEVEL_INFO, "REQUEST %s - %s \"%s %s HTTP/%d.%d\" %d " CUPS_LLFMT " %s %s\n", + con->http->hostname, con->username[0] != '\0' ? con->username : "-", + states[con->operation], _httpEncodeURI(temp, con->uri, sizeof(temp)), + con->http->version / 100, con->http->version % 100, + code, CUPS_LLCAST con->bytes, + con->request ? + ippOpString(con->request->request.op.operation_id) : "-", + con->response ? + ippErrorString(con->response->request.status.status_code) : "-"); + + asl_release(m); + return (1); + } + +#elif defined(HAVE_SYSTEMD_SD_JOURNAL_H) + if (!strcmp(ErrorLog, "syslog")) + { + sd_journal_print(LOG_INFO, "REQUEST %s - %s \"%s %s HTTP/%d.%d\" %d " CUPS_LLFMT " %s %s", con->http->hostname, con->username[0] != '\0' ? con->username : "-", states[con->operation], _httpEncodeURI(temp, con->uri, sizeof(temp)), con->http->version / 100, con->http->version % 100, code, CUPS_LLCAST con->bytes, con->request ? ippOpString(con->request->request.op.operation_id) : "-", con->response ? ippErrorString(con->response->request.status.status_code) : "-"); + return (1); + } + +#elif defined(HAVE_VSYSLOG) /* * See if we are logging accesses via syslog... */ @@ -938,9 +1316,9 @@ cupsdLogRequest(cupsd_client_t *con, /* I - Request to log */ { syslog(LOG_INFO, "REQUEST %s - %s \"%s %s HTTP/%d.%d\" %d " CUPS_LLFMT " %s %s\n", - con->http.hostname, con->username[0] != '\0' ? con->username : "-", + con->http->hostname, con->username[0] != '\0' ? con->username : "-", states[con->operation], _httpEncodeURI(temp, con->uri, sizeof(temp)), - con->http.version / 100, con->http.version % 100, + con->http->version / 100, con->http->version % 100, code, CUPS_LLCAST con->bytes, con->request ? ippOpString(con->request->request.op.operation_id) : "-", @@ -949,7 +1327,7 @@ cupsdLogRequest(cupsd_client_t *con, /* I - Request to log */ return (1); } -#endif /* HAVE_VSYSLOG */ +#endif /* HAVE_ASL_H */ /* * Not using syslog; check the log file... @@ -964,12 +1342,12 @@ cupsdLogRequest(cupsd_client_t *con, /* I - Request to log */ cupsFilePrintf(AccessFile, "%s - %s %s \"%s %s HTTP/%d.%d\" %d " CUPS_LLFMT " %s %s\n", - con->http.hostname, + con->http->hostname, con->username[0] != '\0' ? con->username : "-", cupsdGetDateTime(&(con->start), LogTimeFormat), states[con->operation], _httpEncodeURI(temp, con->uri, sizeof(temp)), - con->http.version / 100, con->http.version % 100, + con->http->version / 100, con->http->version % 100, code, CUPS_LLCAST con->bytes, con->request ? ippOpString(con->request->request.op.operation_id) : "-", @@ -991,6 +1369,7 @@ int /* O - 1 on success, 0 on failure */ cupsdWriteErrorLog(int level, /* I - Log level */ const char *message) /* I - Message string */ { + int ret = 1; /* Return value */ static const char levels[] = /* Log levels... */ { ' ', @@ -1006,34 +1385,62 @@ cupsdWriteErrorLog(int level, /* I - Log level */ }; -#ifdef HAVE_VSYSLOG +#ifdef HAVE_ASL_H + if (!strcmp(ErrorLog, "syslog")) + { + asl_object_t m; /* Log message */ + + m = asl_new(ASL_TYPE_MSG); + asl_set(m, ASL_KEY_FACILITY, "org.cups.cupsd"); + asl_log(NULL, m, ASL_LEVEL_INFO, "%s", message); + + asl_release(m); + return (1); + } + +#elif defined(HAVE_SYSTEMD_SD_JOURNAL_H) + if (!strcmp(ErrorLog, "syslog")) + { + sd_journal_print(log_levels[level], "%s", message); + return (1); + } + +#elif defined(HAVE_VSYSLOG) /* * See if we are logging errors via syslog... */ if (!strcmp(ErrorLog, "syslog")) { - syslog(syslevels[level], "%s", message); + syslog(log_levels[level], "%s", message); return (1); } -#endif /* HAVE_VSYSLOG */ +#endif /* HAVE_ASL_H */ /* * Not using syslog; check the log file... */ + _cupsMutexLock(&log_mutex); + if (!cupsdCheckLogFile(&ErrorFile, ErrorLog)) - return (0); + { + ret = 0; + } + else + { + /* + * Write the log message... + */ - /* - * Write the log message... - */ + cupsFilePrintf(ErrorFile, "%c %s %s\n", levels[level], + cupsdGetDateTime(NULL, LogTimeFormat), message); + cupsFileFlush(ErrorFile); + } - cupsFilePrintf(ErrorFile, "%c %s %s\n", levels[level], - cupsdGetDateTime(NULL, LogTimeFormat), message); - cupsFileFlush(ErrorFile); + _cupsMutexUnlock(&log_mutex); - return (1); + return (ret); } @@ -1049,7 +1456,7 @@ static int /* O - -1 for fatal, 0 for retry, 1 for success */ format_log_line(const char *message, /* I - Printf-style format string */ va_list ap) /* I - Argument list */ { - int len; /* Length of formatted line */ + ssize_t len; /* Length of formatted line */ /* @@ -1069,17 +1476,16 @@ format_log_line(const char *message, /* I - Printf-style format string */ * Format the log message... */ - len = vsnprintf(log_line, log_linesize, message, ap); + len = _cups_safe_vsnprintf(log_line, log_linesize, message, ap); /* * Resize the buffer as needed... */ - if (len >= log_linesize && log_linesize < 65536) + if ((size_t)len >= log_linesize && log_linesize < 65536) { char *temp; /* Temporary string pointer */ - len ++; if (len < 8192) @@ -1087,12 +1493,12 @@ format_log_line(const char *message, /* I - Printf-style format string */ else if (len > 65536) len = 65536; - temp = realloc(log_line, len); + temp = realloc(log_line, (size_t)len); if (temp) { log_line = temp; - log_linesize = len; + log_linesize = (size_t)len; return (0); } @@ -1103,5 +1509,5 @@ format_log_line(const char *message, /* I - Printf-style format string */ /* - * End of "$Id: log.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: log.c 12928 2015-10-23 21:31:58Z msweet $". */ diff --git a/scheduler/main.c b/scheduler/main.c index 11eae52..b1aa503 100644 --- a/scheduler/main.c +++ b/scheduler/main.c @@ -1,39 +1,16 @@ /* - * "$Id: main.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: main.c 12700 2015-06-08 18:32:35Z msweet $" * - * Main loop for the CUPS scheduler. + * Main loop for the CUPS scheduler. * - * Copyright 2007-2012 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. + * Copyright 2007-2015 by Apple Inc. + * Copyright 1997-2007 by Easy Software Products, all rights reserved. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * "LICENSE" which should have been included with this file. If this - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * main() - Main entry for the CUPS scheduler. - * cupsdAddString() - Copy and add a string to an array. - * cupsdCheckProcess() - Tell the main loop to check for dead children. - * cupsdClearString() - Clear a string. - * cupsdFreeStrings() - Free an array of strings. - * cupsdHoldSignals() - Hold child and termination signals. - * cupsdReleaseSignals() - Release signals for delivery. - * cupsdSetString() - Set a string value. - * cupsdSetStringf() - Set a formatted string value. - * launchd_checkin() - Check-in with launchd and collect the listening - * fds. - * launchd_checkout() - Update the launchd KeepAlive file as needed. - * parent_handler() - Catch USR1/CHLD signals... - * process_children() - Process all dead children... - * select_timeout() - Calculate the select timeout value. - * sigchld_handler() - Handle 'child' signals from old processes. - * sighup_handler() - Handle 'hangup' signals to reconfigure the - * scheduler. - * sigterm_handler() - Handle 'terminate' signals that stop the scheduler. - * usage() - Show scheduler usage. + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * "LICENSE" which should have been included with this file. If this + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -43,6 +20,12 @@ #define _MAIN_C_ #include "cupsd.h" #include <sys/resource.h> +#ifdef HAVE_ASL_H +# include <asl.h> +#elif defined(HAVE_SYSTEMD_SD_JOURNAL_H) +# define SD_JOURNAL_SUPPRESS_LOCATION +# include <systemd/sd-journal.h> +#endif /* HAVE_ASL_H */ #include <syslog.h> #include <grp.h> @@ -51,17 +34,18 @@ # include <libgen.h> # define CUPS_KEEPALIVE CUPS_CACHEDIR "/org.cups.cupsd" /* Name of the launchd KeepAlive file */ -# ifndef LAUNCH_JOBKEY_KEEPALIVE -# define LAUNCH_JOBKEY_KEEPALIVE "KeepAlive" -# endif /* !LAUNCH_JOBKEY_KEEPALIVE */ -# ifndef LAUNCH_JOBKEY_PATHSTATE -# define LAUNCH_JOBKEY_PATHSTATE "PathState" -# endif /* !LAUNCH_JOBKEY_PATHSTATE */ -# ifndef LAUNCH_JOBKEY_SERVICEIPC -# define LAUNCH_JOBKEY_SERVICEIPC "ServiceIPC" -# endif /* !LAUNCH_JOBKEY_SERVICEIPC */ +# ifdef HAVE_LAUNCH_ACTIVATE_SOCKET +/* Update when we have a public header we can include */ +extern int launch_activate_socket(const char *name, int **fds, size_t *cnt); +# endif /* HAVE_LAUNCH_ACTIVATE_SOCKET */ #endif /* HAVE_LAUNCH_H */ +#ifdef HAVE_SYSTEMD +# include <systemd/sd-daemon.h> +# define CUPS_KEEPALIVE CUPS_CACHEDIR "/org.cups.cupsd" + /* Name of the systemd path file */ +#endif /* HAVE_SYSTEMD */ + #if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO) # include <malloc.h> #endif /* HAVE_MALLOC_H && HAVE_MALLINFO */ @@ -70,6 +54,10 @@ # include <notify.h> #endif /* HAVE_NOTIFY_H */ +#ifdef HAVE_DBUS +# include <dbus/dbus.h> +#endif /* HAVE_DBUS */ + #ifdef HAVE_SYS_PARAM_H # include <sys/param.h> #endif /* HAVE_SYS_PARAM_H */ @@ -79,16 +67,16 @@ * Local functions... */ -#ifdef HAVE_LAUNCHD -static void launchd_checkin(void); -static void launchd_checkout(void); -#endif /* HAVE_LAUNCHD */ static void parent_handler(int sig); static void process_children(void); static void sigchld_handler(int sig); static void sighup_handler(int sig); static void sigterm_handler(int sig); static long select_timeout(int fds); +#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) +static void service_checkin(void); +static void service_checkout(void); +#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ static void usage(int status) __attribute__((noreturn)); @@ -118,7 +106,11 @@ main(int argc, /* I - Number of command-line args */ { int i; /* Looping var */ char *opt; /* Option character */ - int fg; /* Run in the foreground */ + int close_all = 1, /* Close all file descriptors? */ + disconnect = 1, /* Disconnect from controlling terminal? */ + fg = 0, /* Run in foreground? */ + run_as_child = 0; + /* Running as child process? */ int fds; /* Number of ready descriptors */ cupsd_client_t *con; /* Current client */ cupsd_job_t *job; /* Current job */ @@ -134,22 +126,15 @@ main(int argc, /* I - Number of command-line args */ #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) struct sigaction action; /* Actions for POSIX signals */ #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ -#ifdef __sgi - cups_file_t *fp; /* Fake lpsched lock file */ - struct stat statbuf; /* Needed for checking lpsched FIFO */ -#endif /* __sgi */ - int run_as_child = 0; - /* Needed for background fork/exec */ #ifdef __APPLE__ - int use_sysman = !getuid(); - /* Use system management functions? */ + int use_sysman = 1; /* Use system management functions? */ #else time_t netif_time = 0; /* Time since last network update */ #endif /* __APPLE__ */ -#if HAVE_LAUNCHD - int launchd_idle_exit; +#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) + int service_idle_exit; /* Idle exit on select timeout? */ -#endif /* HAVE_LAUNCHD */ +#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ #ifdef HAVE_GETEUID @@ -159,7 +144,7 @@ main(int argc, /* I - Number of command-line args */ if (getuid() != geteuid()) { - fputs("cupsd: Cannot run as a setuid program\n", stderr); + fputs("cupsd: Cannot run as a setuid program.\n", stderr); return (1); } #endif /* HAVE_GETEUID */ @@ -173,8 +158,10 @@ main(int argc, /* I - Number of command-line args */ #ifdef HAVE_LAUNCHD if (getenv("CUPSD_LAUNCHD")) { - Launchd = 1; - fg = 1; + OnDemand = 1; + fg = 1; + close_all = 0; + disconnect = 0; } #endif /* HAVE_LAUNCHD */ @@ -185,7 +172,8 @@ main(int argc, /* I - Number of command-line args */ { case 'C' : /* Run as child with config file */ run_as_child = 1; - fg = -1; + fg = 1; + close_all = 0; case 'c' : /* Configuration file */ i ++; @@ -240,26 +228,33 @@ main(int argc, /* I - Number of command-line args */ break; case 'f' : /* Run in foreground... */ - fg = 1; + fg = 1; + disconnect = 0; + close_all = 0; break; case 'F' : /* Run in foreground, but disconnect from terminal... */ - fg = -1; + fg = 1; + close_all = 0; break; case 'h' : /* Show usage/help */ usage(0); break; - case 'l' : /* Started by launchd... */ -#ifdef HAVE_LAUNCHD - Launchd = 1; - fg = 1; + case 'l' : /* Started by launchd/systemd... */ +#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) + OnDemand = 1; + fg = 1; + close_all = 0; + disconnect = 0; #else - _cupsLangPuts(stderr, _("cupsd: launchd(8) support not compiled " + _cupsLangPuts(stderr, _("cupsd: On-demand support not compiled " "in, running in normal mode.")); - fg = 0; -#endif /* HAVE_LAUNCHD */ + fg = 0; + disconnect = 1; + close_all = 1; +#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ break; case 'p' : /* Stop immediately for profiling */ @@ -267,12 +262,13 @@ main(int argc, /* I - Number of command-line args */ "use only!\n", stderr); stop_scheduler = 1; fg = 1; + disconnect = 0; + close_all = 0; break; case 'P' : /* Disable security profiles */ - fputs("cupsd: -P (disable security profiles) is for internal " - "testing use only!\n", stderr); - UseProfiles = 0; + fputs("cupsd: -P (disable sandboxing) is for internal testing use only.\n", stderr); + UseSandboxing = 0; break; case 's' : /* Set cups-files.conf location */ @@ -309,6 +305,8 @@ main(int argc, /* I - Number of command-line args */ case 't' : /* Test the cupsd.conf file... */ TestConfigFile = 1; fg = 1; + disconnect = 0; + close_all = 0; break; default : /* Unknown option */ @@ -325,10 +323,7 @@ main(int argc, /* I - Number of command-line args */ } if (!ConfigurationFile) - { cupsdSetString(&ConfigurationFile, CUPS_SERVERROOT "/cupsd.conf"); - cupsdSetString(&CupsFilesFile, CUPS_SERVERROOT "/cups-files.conf"); - } if (!CupsFilesFile) { @@ -354,13 +349,64 @@ main(int argc, /* I - Number of command-line args */ return (1); } - strlcpy(slash, "/cups-files.conf", len - (slash - filename)); + strlcpy(slash, "/cups-files.conf", len - (size_t)(slash - filename)); cupsdSetString(&CupsFilesFile, filename); free(filename); } + if (disconnect) + { + /* + * Make sure we aren't tying up any filesystems... + */ + + chdir("/"); + + /* + * Disconnect from the controlling terminal... + */ + + setsid(); + } + + if (close_all) + { + /* + * Close all open files... + */ + + getrlimit(RLIMIT_NOFILE, &limit); + + for (i = 0; i < (int)limit.rlim_cur && i < 1024; i ++) + close(i); + + /* + * Redirect stdin/out/err to /dev/null... + */ + + if ((i = open("/dev/null", O_RDONLY)) != 0) + { + dup2(i, 0); + close(i); + } + + if ((i = open("/dev/null", O_WRONLY)) != 1) + { + dup2(i, 1); + close(i); + } + + if ((i = open("/dev/null", O_WRONLY)) != 2) + { + dup2(i, 2); + close(i); + } + } + else + LogStderr = cupsFileStderr(); + /* - * If the user hasn't specified "-f", run in the background... + * Run in the background as needed... */ if (!fg) @@ -435,74 +481,17 @@ main(int argc, /* I - Number of command-line args */ #endif /* __OpenBSD__ && OpenBSD < 201211 */ /* - * Since CoreFoundation and DBUS both create fork-unsafe data on execution of - * a program, and since this kind of really unfriendly behavior seems to be - * more common these days in system libraries, we need to re-execute the - * background cupsd with the "-C" option to avoid problems. Unfortunately, - * we also have to assume that argv[0] contains the name of the cupsd - * executable - there is no portable way to get the real pathname... + * Since many system libraries create fork-unsafe data on execution of a + * program, we need to re-execute the background cupsd with the "-C" and "-s" + * options to avoid problems. Unfortunately, we also have to assume that + * argv[0] contains the name of the cupsd executable - there is no portable + * way to get the real pathname... */ - execlp(argv[0], argv[0], "-C", ConfigurationFile, (char *)0); + execlp(argv[0], argv[0], "-C", ConfigurationFile, "-s", CupsFilesFile, (char *)0); exit(errno); } - if (fg < 1) - { - /* - * Make sure we aren't tying up any filesystems... - */ - - chdir("/"); - -#ifndef DEBUG - /* - * Disable core dumps... - */ - - getrlimit(RLIMIT_CORE, &limit); - limit.rlim_cur = 0; - setrlimit(RLIMIT_CORE, &limit); - - /* - * Disconnect from the controlling terminal... - */ - - setsid(); - - /* - * Close all open files... - */ - - getrlimit(RLIMIT_NOFILE, &limit); - - for (i = 0; i < limit.rlim_cur && i < 1024; i ++) - close(i); - - /* - * Redirect stdin/out/err to /dev/null... - */ - - if ((i = open("/dev/null", O_RDONLY)) != 0) - { - dup2(i, 0); - close(i); - } - - if ((i = open("/dev/null", O_WRONLY)) != 1) - { - dup2(i, 1); - close(i); - } - - if ((i = open("/dev/null", O_WRONLY)) != 2) - { - dup2(i, 2); - close(i); - } -#endif /* DEBUG */ - } - /* * Set the timezone info... */ @@ -513,6 +502,14 @@ main(int argc, /* I - Number of command-line args */ setlocale(LC_TIME, ""); #endif /* LC_TIME */ +#ifdef HAVE_DBUS_THREADS_INIT + /* + * Enable threading support for D-BUS... + */ + + dbus_threads_init_default(); +#endif /* HAVE_DBUS_THREADS_INIT */ + /* * Set the maximum number of files... */ @@ -531,7 +528,7 @@ main(int argc, /* I - Number of command-line args */ #endif /* RLIM_INFINITY */ MaxFDs = limit.rlim_max; - limit.rlim_cur = MaxFDs; + limit.rlim_cur = (rlim_t)MaxFDs; setrlimit(RLIMIT_NOFILE, &limit); @@ -559,17 +556,18 @@ main(int argc, /* I - Number of command-line args */ cupsdCleanFiles(CacheDir, "*.ipp"); -#if HAVE_LAUNCHD - if (Launchd) +#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) + if (OnDemand) { /* - * If we were started by launchd get the listen sockets file descriptors... + * If we were started on demand by launchd or systemd get the listen sockets + * file descriptors... */ - launchd_checkin(); - launchd_checkout(); + service_checkin(); + service_checkout(); } -#endif /* HAVE_LAUNCHD */ +#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ /* * Startup the server... @@ -618,28 +616,6 @@ main(int argc, /* I - Number of command-line args */ signal(SIGTERM, sigterm_handler); #endif /* HAVE_SIGSET */ -#ifdef __sgi - /* - * Try to create a fake lpsched lock file if one is not already there. - * Some Adobe applications need it under IRIX in order to enable - * printing... - */ - - if ((fp = cupsFileOpen("/var/spool/lp/SCHEDLOCK", "w")) == NULL) - { - syslog(LOG_LPR, "Unable to create fake lpsched lock file " - "\"/var/spool/lp/SCHEDLOCK\"\' - %s!", - strerror(errno)); - } - else - { - fchmod(cupsFileNumber(fp), 0644); - fchown(cupsFileNumber(fp), User, Group); - - cupsFileClose(fp); - } -#endif /* __sgi */ - /* * Initialize authentication certificates... */ @@ -678,18 +654,15 @@ main(int argc, /* I - Number of command-line args */ * Send server-started event... */ -#ifdef HAVE_LAUNCHD - if (Launchd) - cupsdAddEvent(CUPSD_EVENT_SERVER_STARTED, NULL, NULL, - "Scheduler started via launchd."); +#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) + if (OnDemand) + cupsdAddEvent(CUPSD_EVENT_SERVER_STARTED, NULL, NULL, "Scheduler started on demand."); else -#endif /* HAVE_LAUNCHD */ +#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ if (fg) - cupsdAddEvent(CUPSD_EVENT_SERVER_STARTED, NULL, NULL, - "Scheduler started in foreground."); + cupsdAddEvent(CUPSD_EVENT_SERVER_STARTED, NULL, NULL, "Scheduler started in foreground."); else - cupsdAddEvent(CUPSD_EVENT_SERVER_STARTED, NULL, NULL, - "Scheduler started in background."); + cupsdAddEvent(CUPSD_EVENT_SERVER_STARTED, NULL, NULL, "Scheduler started in background."); /* * Start any pending print jobs... @@ -732,10 +705,10 @@ main(int argc, /* I - Number of command-line args */ for (con = (cupsd_client_t *)cupsArrayFirst(Clients); con; con = (cupsd_client_t *)cupsArrayNext(Clients)) - if (con->http.state == HTTP_WAITING) + if (httpGetState(con->http) == HTTP_WAITING) cupsdCloseClient(con); else - con->http.keep_alive = HTTP_KEEPALIVE_OFF; + con->http->keep_alive = HTTP_KEEPALIVE_OFF; cupsdPauseListening(); } @@ -763,23 +736,21 @@ main(int argc, /* I - Number of command-line args */ if (!cupsdReadConfiguration()) { - syslog(LOG_LPR, "Unable to read configuration file \'%s\' - exiting!", - ConfigurationFile); - break; - } - -#if HAVE_LAUNCHD - if (Launchd) - { - /* - * If we were started by launchd, get the listen socket file - * descriptors... - */ +#ifdef HAVE_ASL_H + asl_object_t m; /* Log message */ + + m = asl_new(ASL_TYPE_MSG); + asl_set(m, ASL_KEY_FACILITY, "org.cups.cupsd"); + asl_log(NULL, m, ASL_LEVEL_ERR, "Unable to read configuration file \"%s\" - exiting.", ConfigurationFile); + asl_release(m); +#elif defined(HAVE_SYSTEMD_SD_JOURNAL_H) + sd_journal_print(LOG_ERR, "Unable to read configuration file \"%s\" - exiting.", ConfigurationFile); +#else + syslog(LOG_LPR, "Unable to read configuration file \'%s\' - exiting.", ConfigurationFile); +#endif /* HAVE_ASL_H */ - launchd_checkin(); - launchd_checkout(); + break; } -#endif /* HAVE_LAUNCHD */ /* * Startup the server... @@ -810,23 +781,26 @@ main(int argc, /* I - Number of command-line args */ if ((timeout = select_timeout(fds)) > 1 && LastEvent) timeout = 1; -#if HAVE_LAUNCHD +#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) /* * If no other work is scheduled and we're being controlled by * launchd then timeout after 'LaunchdTimeout' seconds of * inactivity... */ - if (timeout == 86400 && Launchd && LaunchdTimeout && + if (timeout == 86400 && OnDemand && IdleExitTimeout && !cupsArrayCount(ActiveJobs) && +# ifdef HAVE_SYSTEMD + !WebInterface && +# endif /* HAVE_SYSTEMD */ (!Browsing || !BrowseLocalProtocols || !cupsArrayCount(Printers))) { - timeout = LaunchdTimeout; - launchd_idle_exit = 1; + timeout = IdleExitTimeout; + service_idle_exit = 1; } else - launchd_idle_exit = 0; -#endif /* HAVE_LAUNCHD */ + service_idle_exit = 0; +#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ if ((fds = cupsdDoSelect(timeout)) < 0) { @@ -854,7 +828,7 @@ main(int argc, /* I - Number of command-line args */ i ++, con = (cupsd_client_t *)cupsArrayNext(Clients)) cupsdLogMessage(CUPSD_LOG_EMERG, "Clients[%d] = %d, file = %d, state = %d", - i, con->http.fd, con->file, con->http.state); + i, con->number, con->file, httpGetState(con->http)); for (i = 0, lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); lis; @@ -923,13 +897,13 @@ main(int argc, /* I - Number of command-line args */ } #endif /* !__APPLE__ */ -#if HAVE_LAUNCHD +#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) /* * If no other work was scheduled and we're being controlled by launchd * then timeout after 'LaunchdTimeout' seconds of inactivity... */ - if (!fds && launchd_idle_exit) + if (!fds && service_idle_exit) { cupsdLogMessage(CUPSD_LOG_INFO, "Printer sharing is off and there are no jobs pending, " @@ -937,7 +911,7 @@ main(int argc, /* I - Number of command-line args */ stop_scheduler = 1; break; } -#endif /* HAVE_LAUNCHD */ +#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ /* * Resume listening for new connections as needed... @@ -991,7 +965,7 @@ main(int argc, /* I - Number of command-line args */ * Process pending data in the input buffer... */ - if (con->http.used) + if (httpGetReady(con->http)) { cupsdReadClient(con); continue; @@ -1002,11 +976,9 @@ main(int argc, /* I - Number of command-line args */ */ activity = current_time - Timeout; - if (con->http.activity < activity && !con->pipe_pid) + if (httpGetActivity(con->http) < activity && !con->pipe_pid) { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Closing client %d after %d seconds of inactivity...", - con->http.fd, Timeout); + cupsdLogMessage(CUPSD_LOG_DEBUG, "Closing client %d after %d seconds of inactivity.", con->number, Timeout); cupsdCloseClient(con); continue; @@ -1143,14 +1115,14 @@ main(int argc, /* I - Number of command-line args */ cupsdStopServer(); -#ifdef HAVE_LAUNCHD +#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) /* - * Update the launchd KeepAlive file as needed... + * Update the keep-alive file as needed... */ - if (Launchd) - launchd_checkout(); -#endif /* HAVE_LAUNCHD */ + if (OnDemand) + service_checkout(); +#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ /* * Stop all jobs... @@ -1167,18 +1139,6 @@ main(int argc, /* I - Number of command-line args */ cupsdStopSystemMonitor(); #endif /* __APPLE__ */ -#ifdef __sgi - /* - * Remove the fake IRIX lpsched lock file, but only if the existing - * file is not a FIFO which indicates that the real IRIX lpsched is - * running... - */ - - if (!stat("/var/spool/lp/FIFO", &statbuf)) - if (!S_ISFIFO(statbuf.st_mode)) - unlink("/var/spool/lp/SCHEDLOCK"); -#endif /* __sgi */ - cupsdStopSelect(); return (!stop_scheduler); @@ -1196,8 +1156,8 @@ cupsdAddString(cups_array_t **a, /* IO - String array */ if (!*a) *a = cupsArrayNew3((cups_array_func_t)strcmp, NULL, (cups_ahash_func_t)NULL, 0, - (cups_acopy_func_t)_cupsStrAlloc, - (cups_afree_func_t)_cupsStrFree); + (cups_acopy_func_t)strdup, + (cups_afree_func_t)free); return (cupsArrayAdd(*a, (char *)s)); } @@ -1227,7 +1187,7 @@ cupsdClearString(char **s) /* O - String value */ { if (s && *s) { - _cupsStrFree(*s); + free(*s); *s = NULL; } } @@ -1308,10 +1268,10 @@ cupsdSetString(char **s, /* O - New string */ return; if (*s) - _cupsStrFree(*s); + free(*s); if (v) - *s = _cupsStrAlloc(v); + *s = strdup(v); else *s = NULL; } @@ -1342,207 +1302,16 @@ cupsdSetStringf(char **s, /* O - New string */ vsnprintf(v, sizeof(v), f, ap); va_end(ap); - *s = _cupsStrAlloc(v); + *s = strdup(v); } else *s = NULL; if (olds) - _cupsStrFree(olds); + free(olds); } -#ifdef HAVE_LAUNCHD -/* - * 'launchd_checkin()' - Check-in with launchd and collect the listening fds. - */ - -static void -launchd_checkin(void) -{ - size_t i, /* Looping var */ - count; /* Number of listeners */ - launch_data_t ld_msg, /* Launch data message */ - ld_resp, /* Launch data response */ - ld_array, /* Launch data array */ - ld_sockets, /* Launch data sockets dictionary */ - tmp; /* Launch data */ - cupsd_listener_t *lis; /* Listeners array */ - http_addr_t addr; /* Address variable */ - socklen_t addrlen; /* Length of address */ - int fd; /* File descriptor */ - char s[256]; /* String addresss */ - - - cupsdLogMessage(CUPSD_LOG_DEBUG, "launchd_checkin: pid=%d", (int)getpid()); - - /* - * Check-in with launchd... - */ - - ld_msg = launch_data_new_string(LAUNCH_KEY_CHECKIN); - if ((ld_resp = launch_msg(ld_msg)) == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "launchd_checkin: launch_msg(\"" LAUNCH_KEY_CHECKIN - "\") IPC failure"); - exit(EXIT_FAILURE); - return; /* anti-compiler-warning */ - } - - if (launch_data_get_type(ld_resp) == LAUNCH_DATA_ERRNO) - { - errno = launch_data_get_errno(ld_resp); - cupsdLogMessage(CUPSD_LOG_ERROR, "launchd_checkin: Check-in failed: %s", - strerror(errno)); - exit(EXIT_FAILURE); - return; /* anti-compiler-warning */ - } - - /* - * Get the sockets dictionary... - */ - - if ((ld_sockets = launch_data_dict_lookup(ld_resp, LAUNCH_JOBKEY_SOCKETS)) - == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "launchd_checkin: No sockets found to answer requests on!"); - exit(EXIT_FAILURE); - return; /* anti-compiler-warning */ - } - - /* - * Get the array of listener sockets... - */ - - if ((ld_array = launch_data_dict_lookup(ld_sockets, "Listeners")) == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "launchd_checkin: No sockets found to answer requests on!"); - exit(EXIT_FAILURE); - return; /* anti-compiler-warning */ - } - - /* - * Add listening fd(s) to the Listener array... - */ - - if (launch_data_get_type(ld_array) == LAUNCH_DATA_ARRAY) - { - count = launch_data_array_get_count(ld_array); - - for (i = 0; i < count; i ++) - { - /* - * Get the launchd file descriptor and address... - */ - - if ((tmp = launch_data_array_get_index(ld_array, i)) != NULL) - { - fd = launch_data_get_fd(tmp); - addrlen = sizeof(addr); - - if (getsockname(fd, (struct sockaddr *)&addr, &addrlen)) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "launchd_checkin: Unable to get local address - %s", - strerror(errno)); - continue; - } - - /* - * Try to match the launchd socket address to one of the listeners... - */ - - for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); - lis; - lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) - if (httpAddrEqual(&lis->address, &addr)) - break; - - /* - * Add a new listener If there's no match... - */ - - if (lis) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "launchd_checkin: Matched existing listener %s with fd %d...", - httpAddrString(&(lis->address), s, sizeof(s)), fd); - } - else - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "launchd_checkin: Adding new listener %s with fd %d...", - httpAddrString(&addr, s, sizeof(s)), fd); - - if ((lis = calloc(1, sizeof(cupsd_listener_t))) == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "launchd_checkin: Unable to allocate listener - " - "%s.", strerror(errno)); - exit(EXIT_FAILURE); - } - - cupsArrayAdd(Listeners, lis); - - memcpy(&lis->address, &addr, sizeof(lis->address)); - } - - lis->fd = fd; - -# ifdef HAVE_SSL - if (_httpAddrPort(&(lis->address)) == 443) - lis->encryption = HTTP_ENCRYPT_ALWAYS; -# endif /* HAVE_SSL */ - } - } - } - - launch_data_free(ld_msg); - launch_data_free(ld_resp); -} - - -/* - * 'launchd_checkout()' - Update the launchd KeepAlive file as needed. - */ - -static void -launchd_checkout(void) -{ - int fd; /* File descriptor */ - - - /* - * Create or remove the launchd KeepAlive file based on whether - * there are active jobs, polling, browsing for remote printers or - * shared printers to advertise... - */ - - if (cupsArrayCount(ActiveJobs) || - (Browsing && BrowseLocalProtocols && cupsArrayCount(Printers))) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Creating launchd keepalive file \"" CUPS_KEEPALIVE - "\"..."); - - if ((fd = open(CUPS_KEEPALIVE, O_RDONLY | O_CREAT | O_EXCL, S_IRUSR)) >= 0) - close(fd); - } - else - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Removing launchd keepalive file \"" CUPS_KEEPALIVE - "\"..."); - - unlink(CUPS_KEEPALIVE); - } -} -#endif /* HAVE_LAUNCHD */ - - /* * 'parent_handler()' - Catch USR1/CHLD signals... */ @@ -1699,8 +1468,7 @@ process_children(void) } if (job->printer_message) - cupsdSetString(&(job->printer_message->values[0].string.text), - message); + ippSetString(job->attrs, &job->printer_message, 0, message); } } @@ -1820,7 +1588,7 @@ select_timeout(int fds) /* I - Number of descriptors returned */ for (con = (cupsd_client_t *)cupsArrayFirst(Clients); con; con = (cupsd_client_t *)cupsArrayNext(Clients)) - if (con->http.used > 0) + if (httpGetReady(con->http)) return (0); /* @@ -1874,9 +1642,9 @@ select_timeout(int fds) /* I - Number of descriptors returned */ for (con = (cupsd_client_t *)cupsArrayFirst(Clients); con; con = (cupsd_client_t *)cupsArrayNext(Clients)) - if ((con->http.activity + Timeout) < timeout) + if ((httpGetActivity(con->http) + Timeout) < timeout) { - timeout = con->http.activity + Timeout; + timeout = httpGetActivity(con->http) + Timeout; why = "timeout a client connection"; } @@ -2040,6 +1808,361 @@ sigterm_handler(int sig) /* I - Signal number */ } +#if defined(HAVE_LAUNCHD) || defined(HAVE_SYSTEMD) +/* + * 'service_checkin()' - Check-in with launchd and collect the listening fds. + */ + +static void +service_checkin(void) +{ +# ifdef HAVE_LAUNCH_ACTIVATE_SOCKET + int error; /* Check-in error, if any */ + size_t i, /* Looping var */ + count; /* Number of listeners */ + int *ld_sockets; /* Listener sockets */ + cupsd_listener_t *lis; /* Listeners array */ + http_addr_t addr; /* Address variable */ + socklen_t addrlen; /* Length of address */ + char s[256]; /* String addresss */ + + + cupsdLogMessage(CUPSD_LOG_DEBUG, "service_checkin: pid=%d", (int)getpid()); + + /* + * Check-in with launchd... + */ + + if ((error = launch_activate_socket("Listeners", &ld_sockets, &count)) != 0) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "service_checkin: Unable to get listener sockets: %s", strerror(error)); + exit(EXIT_FAILURE); + return; /* anti-compiler-warning */ + } + + /* + * Try to match the launchd sockets to the cupsd listeners... + */ + + cupsdLogMessage(CUPSD_LOG_DEBUG, "service_checkin: %d listeners.", (int)count); + + for (i = 0; i < count; i ++) + { + /* + * Get the launchd socket address... + */ + + addrlen = sizeof(addr); + + if (getsockname(ld_sockets[i], (struct sockaddr *)&addr, &addrlen)) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "service_checkin: Unable to get local address for listener #%d: %s", (int)i + 1, strerror(errno)); + continue; + } + + cupsdLogMessage(CUPSD_LOG_DEBUG, "service_checkin: Listener #%d at fd %d, \"%s\".", (int)i + 1, ld_sockets[i], httpAddrString(&addr, s, sizeof(s))); + + for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); + lis; + lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) + if (httpAddrEqual(&lis->address, &addr)) + break; + + /* + * Add a new listener if there's no match... + */ + + if (lis) + { + cupsdLogMessage(CUPSD_LOG_DEBUG, "service_checkin: Matched existing listener #%d to %s.", (int)i + 1, httpAddrString(&(lis->address), s, sizeof(s))); + } + else + { + cupsdLogMessage(CUPSD_LOG_DEBUG, "service_checkin: Adding new listener #%d for %s.", (int)i + 1, httpAddrString(&addr, s, sizeof(s))); + + if ((lis = calloc(1, sizeof(cupsd_listener_t))) == NULL) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "service_checkin: Unable to allocate listener: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + + cupsArrayAdd(Listeners, lis); + + memcpy(&lis->address, &addr, sizeof(lis->address)); + } + + lis->fd = ld_sockets[i]; + lis->on_demand = 1; + +# ifdef HAVE_SSL + if (httpAddrPort(&(lis->address)) == 443) + lis->encryption = HTTP_ENCRYPT_ALWAYS; +# endif /* HAVE_SSL */ + } + + free(ld_sockets); + +# elif defined(HAVE_LAUNCHD) + size_t i, /* Looping var */ + count; /* Number of listeners */ + launch_data_t ld_msg, /* Launch data message */ + ld_resp, /* Launch data response */ + ld_array, /* Launch data array */ + ld_sockets, /* Launch data sockets dictionary */ + tmp; /* Launch data */ + cupsd_listener_t *lis; /* Listeners array */ + http_addr_t addr; /* Address variable */ + socklen_t addrlen; /* Length of address */ + int fd; /* File descriptor */ + char s[256]; /* String addresss */ + + + cupsdLogMessage(CUPSD_LOG_DEBUG, "service_checkin: pid=%d", (int)getpid()); + + /* + * Check-in with launchd... + */ + + ld_msg = launch_data_new_string(LAUNCH_KEY_CHECKIN); + if ((ld_resp = launch_msg(ld_msg)) == NULL) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "service_checkin: launch_msg(\"" LAUNCH_KEY_CHECKIN + "\") IPC failure"); + exit(EXIT_FAILURE); + return; /* anti-compiler-warning */ + } + + if (launch_data_get_type(ld_resp) == LAUNCH_DATA_ERRNO) + { + errno = launch_data_get_errno(ld_resp); + cupsdLogMessage(CUPSD_LOG_ERROR, "service_checkin: Check-in failed: %s", + strerror(errno)); + exit(EXIT_FAILURE); + return; /* anti-compiler-warning */ + } + + /* + * Get the sockets dictionary... + */ + + if ((ld_sockets = launch_data_dict_lookup(ld_resp, LAUNCH_JOBKEY_SOCKETS)) + == NULL) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "service_checkin: No sockets found to answer requests on."); + exit(EXIT_FAILURE); + return; /* anti-compiler-warning */ + } + + /* + * Get the array of listener sockets... + */ + + if ((ld_array = launch_data_dict_lookup(ld_sockets, "Listeners")) == NULL) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "service_checkin: No sockets found to answer requests on."); + exit(EXIT_FAILURE); + return; /* anti-compiler-warning */ + } + + /* + * Add listening fd(s) to the Listener array... + */ + + if (launch_data_get_type(ld_array) == LAUNCH_DATA_ARRAY) + { + count = launch_data_array_get_count(ld_array); + + cupsdLogMessage(CUPSD_LOG_DEBUG, "service_checkin: %d listeners.", (int)count); + + for (i = 0; i < count; i ++) + { + /* + * Get the launchd file descriptor and address... + */ + + if ((tmp = launch_data_array_get_index(ld_array, i)) != NULL) + { + fd = launch_data_get_fd(tmp); + addrlen = sizeof(addr); + + if (getsockname(fd, (struct sockaddr *)&addr, &addrlen)) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "service_checkin: Unable to get local address for listener #%d: %s", (int)i + 1, strerror(errno)); + continue; + } + + cupsdLogMessage(CUPSD_LOG_DEBUG, "service_checkin: Listener #%d at fd %d, \"%s\".", (int)i + 1, fd, httpAddrString(&addr, s, sizeof(s))); + + /* + * Try to match the launchd socket address to one of the listeners... + */ + + for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); + lis; + lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) + if (httpAddrEqual(&lis->address, &addr)) + break; + + /* + * Add a new listener If there's no match... + */ + + if (lis) + { + cupsdLogMessage(CUPSD_LOG_DEBUG, "service_checkin: Matched existing listener #%d to %s.", (int)i + 1, httpAddrString(&(lis->address), s, sizeof(s))); + } + else + { + cupsdLogMessage(CUPSD_LOG_DEBUG, "service_checkin: Adding new listener #%d for %s.", (int)i + 1, httpAddrString(&addr, s, sizeof(s))); + + if ((lis = calloc(1, sizeof(cupsd_listener_t))) == NULL) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "service_checkin: Unable to allocate listener: %s.", strerror(errno)); + exit(EXIT_FAILURE); + } + + cupsArrayAdd(Listeners, lis); + + memcpy(&lis->address, &addr, sizeof(lis->address)); + } + + lis->fd = fd; + lis->on_demand = 1; + +# ifdef HAVE_SSL + if (httpAddrPort(&(lis->address)) == 443) + lis->encryption = HTTP_ENCRYPT_ALWAYS; +# endif /* HAVE_SSL */ + } + } + } + + launch_data_free(ld_msg); + launch_data_free(ld_resp); + +# else /* HAVE_SYSTEMD */ + int i, /* Looping var */ + count; /* Number of listeners */ + cupsd_listener_t *lis; /* Listeners array */ + http_addr_t addr; /* Address variable */ + socklen_t addrlen; /* Length of address */ + char s[256]; /* String addresss */ + + + cupsdLogMessage(CUPSD_LOG_DEBUG, "service_checkin: pid=%d", (int)getpid()); + + /* + * Check-in with systemd... + */ + + if ((count = sd_listen_fds(0)) < 0) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "service_checkin: Unable to get listener sockets: %s", strerror(-count)); + exit(EXIT_FAILURE); + return; /* anti-compiler-warning */ + } + + /* + * Try to match the systemd sockets to the cupsd listeners... + */ + + cupsdLogMessage(CUPSD_LOG_DEBUG, "service_checkin: %d listeners.", count); + + for (i = 0; i < count; i ++) + { + /* + * Get the launchd socket address... + */ + + addrlen = sizeof(addr); + + if (getsockname(SD_LISTEN_FDS_START + i, (struct sockaddr *)&addr, &addrlen)) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "service_checkin: Unable to get local address for listener #%d: %s", (int)i + 1, strerror(errno)); + continue; + } + + cupsdLogMessage(CUPSD_LOG_DEBUG, "service_checkin: Listener #%d at fd %d, \"%s\".", (int)i + 1, SD_LISTEN_FDS_START + i, httpAddrString(&addr, s, sizeof(s))); + + for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); + lis; + lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) + if (httpAddrEqual(&lis->address, &addr)) + break; + + /* + * Add a new listener if there's no match... + */ + + if (lis) + { + cupsdLogMessage(CUPSD_LOG_DEBUG, "service_checkin: Matched existing listener #%d to %s.", (int)i + 1, httpAddrString(&(lis->address), s, sizeof(s))); + } + else + { + cupsdLogMessage(CUPSD_LOG_DEBUG, "service_checkin: Adding new listener #%d for %s.", (int)i + 1, httpAddrString(&addr, s, sizeof(s))); + + if ((lis = calloc(1, sizeof(cupsd_listener_t))) == NULL) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "service_checkin: Unable to allocate listener: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + + cupsArrayAdd(Listeners, lis); + + memcpy(&lis->address, &addr, sizeof(lis->address)); + } + + lis->fd = SD_LISTEN_FDS_START + i; + lis->on_demand = 1; + +# ifdef HAVE_SSL + if (httpAddrPort(&(lis->address)) == 443) + lis->encryption = HTTP_ENCRYPT_ALWAYS; +# endif /* HAVE_SSL */ + } +# endif /* HAVE_LAUNCH_ACTIVATE_SOCKET */ +} + + +/* + * 'service_checkout()' - Update the CUPS_KEEPALIVE file as needed. + */ + +static void +service_checkout(void) +{ + int fd; /* File descriptor */ + + + /* + * Create or remove the "keep-alive" file based on whether there are active + * jobs or shared printers to advertise... + */ + + if (cupsArrayCount(ActiveJobs) || /* Active jobs */ + WebInterface || /* Web interface enabled */ + (Browsing && BrowseLocalProtocols && cupsArrayCount(Printers))) + /* Printers being shared */ + { + cupsdLogMessage(CUPSD_LOG_DEBUG, "Creating keep-alive file \"" CUPS_KEEPALIVE "\"."); + + if ((fd = open(CUPS_KEEPALIVE, O_RDONLY | O_CREAT | O_EXCL, S_IRUSR)) >= 0) + close(fd); + } + else + { + cupsdLogMessage(CUPSD_LOG_DEBUG, "Removing keep-alive file \"" CUPS_KEEPALIVE "\"."); + + unlink(CUPS_KEEPALIVE); + } +} +#endif /* HAVE_LAUNCHD || HAVE_SYSTEMD */ + + /* * 'usage()' - Show scheduler usage. */ @@ -2057,7 +2180,7 @@ usage(int status) /* O - Exit status */ _cupsLangPuts(fp, _(" -F Run in the foreground but " "detach from console.")); _cupsLangPuts(fp, _(" -h Show this usage message.")); - _cupsLangPuts(fp, _(" -l Run cupsd from launchd(8).")); + _cupsLangPuts(fp, _(" -l Run cupsd on demand.")); _cupsLangPuts(fp, _(" -t Test the configuration " "file.")); @@ -2066,5 +2189,5 @@ usage(int status) /* O - Exit status */ /* - * End of "$Id: main.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: main.c 12700 2015-06-08 18:32:35Z msweet $". */ diff --git a/scheduler/mime-private.h b/scheduler/mime-private.h index f984548..078953d 100644 --- a/scheduler/mime-private.h +++ b/scheduler/mime-private.h @@ -1,5 +1,5 @@ /* - * "$Id: mime-private.h 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: mime-private.h 3411 2011-09-07 22:31:27Z msweet $" * * Private MIME type/conversion database definitions for CUPS. * @@ -41,5 +41,5 @@ extern void _mimeError(mime_t *mime, const char *format, ...) #endif /* !_CUPS_MIME_PRIVATE_H_ */ /* - * End of "$Id: mime-private.h 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: mime-private.h 3411 2011-09-07 22:31:27Z msweet $". */ diff --git a/scheduler/mime.c b/scheduler/mime.c index 412c9e0..29d3ebc 100644 --- a/scheduler/mime.c +++ b/scheduler/mime.c @@ -1,40 +1,16 @@ /* - * "$Id: mime.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: mime.c 11558 2014-02-06 18:33:34Z msweet $" * - * MIME database file routines for CUPS. + * MIME database file routines for CUPS. * - * Copyright 2007-2011 by Apple Inc. - * Copyright 1997-2006 by Easy Software Products, all rights reserved. + * Copyright 2007-2014 by Apple Inc. + * Copyright 1997-2006 by Easy Software Products, all rights reserved. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * mimeDelete() - Delete (free) a MIME database. - * mimeDeleteFilter() - Delete a filter from the MIME database. - * mimeDeleteType() - Delete a type from the MIME database. - * _mimeError() - Show an error message. - * mimeFirstFilter() - Get the first filter in the MIME database. - * mimeFirstType() - Get the first type in the MIME database. - * mimeLoad() - Create a new MIME database from disk. - * mimeLoadFilters() - Load filter definitions from disk. - * mimeLoadTypes() - Load type definitions from disk. - * mimeNew() - Create a new, empty MIME database. - * mimeNextFilter() - Get the next filter in the MIME database. - * mimeNextType() - Get the next type in the MIME database. - * mimeNumFilters() - Get the number of filters in a MIME database. - * mimeNumTypes() - Get the number of types in a MIME database. - * mimeSetErrorCallback() - Set the callback for error messages. - * mime_add_fcache() - Add a filter to the filter cache. - * mime_compare_fcache() - Compare two filter cache entries. - * mime_delete_fcache() - Free all memory used by the filter cache. - * mime_delete_rules() - Free all memory for the given rule tree. - * mime_load_convs() - Load a xyz.convs file. - * mime_load_types() - Load a xyz.types file. + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -134,7 +110,7 @@ mimeDeleteFilter(mime_t *mime, /* I - MIME database */ filter ? filter->dst->super : "???", filter ? filter->cost : -1, filter ? CUPS_LLCAST filter->maxsize : CUPS_LLCAST -1)); - + if (!mime || !filter) return; @@ -659,6 +635,9 @@ mime_delete_rules(mime_magic_t *rules) /* I - Rules to free */ if (rules->child != NULL) mime_delete_rules(rules->child); + if (rules->op == MIME_MAGIC_REGEX) + regfree(&(rules->value.rev)); + free(rules); rules = next; } @@ -741,7 +720,7 @@ mime_load_convs( while (*lineptr != '/' && *lineptr != '\n' && *lineptr != '\0' && (temp - super + 1) < MIME_MAX_SUPER) - *temp++ = tolower(*lineptr++ & 255); + *temp++ = (char)tolower(*lineptr++ & 255); *temp = '\0'; @@ -753,7 +732,7 @@ mime_load_convs( while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\n' && *lineptr != '\0' && (temp - type + 1) < MIME_MAX_TYPE) - *temp++ = tolower(*lineptr++ & 255); + *temp++ = (char)tolower(*lineptr++ & 255); *temp = '\0'; @@ -798,7 +777,7 @@ mime_load_convs( if (!mime_add_fcache(filtercache, filter, filterpath)) { DEBUG_printf(("mime_load_convs: Filter %s not found in %s.", filter, - filterpath)); + filterpath)); _mimeError(mime, "Filter \"%s\" not found.", filter); continue; } @@ -814,7 +793,7 @@ mime_load_convs( while (*lineptr != '/' && *lineptr != '\n' && *lineptr != '\0' && (temp - super + 1) < MIME_MAX_SUPER) - *temp++ = tolower(*lineptr++ & 255); + *temp++ = (char)tolower(*lineptr++ & 255); *temp = '\0'; @@ -826,7 +805,7 @@ mime_load_convs( while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\n' && *lineptr != '\0' && (temp - type + 1) < MIME_MAX_TYPE) - *temp++ = tolower(*lineptr++ & 255); + *temp++ = (char)tolower(*lineptr++ & 255); *temp = '\0'; @@ -836,8 +815,8 @@ mime_load_convs( * Force * / * to be "application/octet-stream"... */ - strcpy(super, "application"); - strcpy(type, "octet-stream"); + strlcpy(super, "application", sizeof(super)); + strlcpy(type, "octet-stream", sizeof(type)); } /* @@ -865,7 +844,7 @@ mime_load_types(mime_t *mime, /* I - MIME database */ const char *filename) /* I - Types file to load */ { cups_file_t *fp; /* Types file */ - int linelen; /* Length of line */ + size_t linelen; /* Length of line */ char line[32768], /* Input line from file */ *lineptr, /* Current position in line */ super[MIME_MAX_SUPER], /* Super-type name */ @@ -927,7 +906,7 @@ mime_load_types(mime_t *mime, /* I - MIME database */ while (*lineptr != '/' && *lineptr != '\n' && *lineptr != '\0' && (temp - super + 1) < MIME_MAX_SUPER) - *temp++ = tolower(*lineptr++ & 255); + *temp++ = (char)tolower(*lineptr++ & 255); *temp = '\0'; @@ -939,7 +918,7 @@ mime_load_types(mime_t *mime, /* I - MIME database */ while (*lineptr != ' ' && *lineptr != '\t' && *lineptr != '\n' && *lineptr != '\0' && (temp - type + 1) < MIME_MAX_TYPE) - *temp++ = tolower(*lineptr++ & 255); + *temp++ = (char)tolower(*lineptr++ & 255); *temp = '\0'; @@ -956,5 +935,5 @@ mime_load_types(mime_t *mime, /* I - MIME database */ /* - * End of "$Id: mime.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: mime.c 11558 2014-02-06 18:33:34Z msweet $". */ diff --git a/scheduler/mime.h b/scheduler/mime.h index 51d7a29..ddd3283 100644 --- a/scheduler/mime.h +++ b/scheduler/mime.h @@ -1,9 +1,9 @@ /* - * "$Id: mime.h 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: mime.h 11272 2013-09-10 19:15:36Z msweet $" * * MIME type/conversion database definitions for CUPS. * - * Copyright 2007-2011 by Apple Inc. + * Copyright 2007-2013 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -19,6 +19,7 @@ # include <cups/array.h> # include <cups/ipp.h> # include <cups/file.h> +# include <regex.h> /* @@ -58,7 +59,8 @@ typedef enum MIME_MAGIC_INT, /* Integer/32-bit word matches */ MIME_MAGIC_LOCALE, /* Current locale matches string */ MIME_MAGIC_CONTAINS, /* File contains a string */ - MIME_MAGIC_ISTRING /* Case-insensitive string matches */ + MIME_MAGIC_ISTRING, /* Case-insensitive string matches */ + MIME_MAGIC_REGEX /* Regular expression matches */ } mime_op_t; typedef struct _mime_magic_s /**** MIME Magic Data ****/ @@ -80,6 +82,7 @@ typedef struct _mime_magic_s /**** MIME Magic Data ****/ unsigned char charv; /* Byte value */ unsigned short shortv; /* Short value */ unsigned intv; /* Integer value */ + regex_t rev; /* Regular expression value */ } value; } mime_magic_t; @@ -158,5 +161,5 @@ extern void mimeSetErrorCallback(mime_t *mime, mime_error_cb_t cb, #endif /* !_CUPS_MIME_H_ */ /* - * End of "$Id: mime.h 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: mime.h 11272 2013-09-10 19:15:36Z msweet $". */ diff --git a/scheduler/network.c b/scheduler/network.c index 07b5265..18f9b7c 100644 --- a/scheduler/network.c +++ b/scheduler/network.c @@ -1,23 +1,16 @@ /* - * "$Id: network.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: network.c 11497 2014-01-06 21:59:35Z msweet $" * - * Network interface functions for the CUPS scheduler. + * Network interface functions for the CUPS scheduler. * - * Copyright 2007-2012 by Apple Inc. - * Copyright 1997-2006 by Easy Software Products, all rights reserved. + * Copyright 2007-2014 by Apple Inc. + * Copyright 1997-2006 by Easy Software Products, all rights reserved. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * "LICENSE" which should have been included with this file. If this - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * cupsdNetIFFind() - Find a network interface. - * cupsdNetIFFree() - Free the current network interface list. - * cupsdNetIFUpdate() - Update the network interface list as needed... - * compare_netif() - Compare two network interfaces. + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * "LICENSE" which should have been included with this file. If this + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -133,7 +126,10 @@ cupsdNetIFUpdate(void) */ if (getifaddrs(&addrs) < 0) + { + cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdNetIFUpdate: Unable to get interface list - %s", strerror(errno)); return; + } for (addr = addrs; addr != NULL; addr = addr->ifa_next) { @@ -148,7 +144,10 @@ cupsdNetIFUpdate(void) #endif ) || addr->ifa_netmask == NULL || addr->ifa_name == NULL) + { + cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdNetIFUpdate: Ignoring \"%s\".", addr->ifa_name); continue; + } /* * Try looking up the hostname for the address as needed... @@ -178,7 +177,10 @@ cupsdNetIFUpdate(void) hostlen = strlen(hostname); if ((temp = calloc(1, sizeof(cupsd_netif_t) + hostlen)) == NULL) + { + cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdNetIFUpdate: Unable to allocate memory for interface."); break; + } /* * Copy all of the information... @@ -264,7 +266,7 @@ cupsdNetIFUpdate(void) if (match) { - temp->port = _httpAddrPort(&(lis->address)); + temp->port = httpAddrPort(&(lis->address)); break; } } @@ -296,5 +298,5 @@ compare_netif(cupsd_netif_t *a, /* I - First network interface */ /* - * End of "$Id: network.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: network.c 11497 2014-01-06 21:59:35Z msweet $". */ diff --git a/scheduler/network.h b/scheduler/network.h index 0570975..411a6d2 100644 --- a/scheduler/network.h +++ b/scheduler/network.h @@ -1,5 +1,5 @@ /* - * "$Id: network.h 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: network.h 10996 2013-05-29 11:51:34Z msweet $" * * Network interface definitions for the CUPS scheduler. * @@ -48,5 +48,5 @@ extern void cupsdNetIFUpdate(void); /* - * End of "$Id: network.h 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: network.h 10996 2013-05-29 11:51:34Z msweet $". */ diff --git a/scheduler/org.cups.cups-lpd.plist.in b/scheduler/org.cups.cups-lpd.plist.in index 32067ef..76eb2ee 100644 --- a/scheduler/org.cups.cups-lpd.plist.in +++ b/scheduler/org.cups.cups-lpd.plist.in @@ -6,6 +6,12 @@ <true/> <key>Label</key> <string>org.cups.cups-lpd</string> + <key>ProcessType</key> + <string>Background</string> + <key>EnableTransactions</key> + <true/> + <key>EnablePressuredExit</key> + <true/> <key>ProgramArguments</key> <array> <string>/usr/libexec/cups/daemon/cups-lpd</string> diff --git a/scheduler/org.cups.cups-lpd.socket b/scheduler/org.cups.cups-lpd.socket new file mode 100644 index 0000000..dd5288c --- /dev/null +++ b/scheduler/org.cups.cups-lpd.socket @@ -0,0 +1,9 @@ +[Unit] +Description=CUPS LPD Server Socket + +[Socket] +ListenStream=515 +Accept=yes + +[Install] +WantedBy=sockets.target diff --git a/scheduler/org.cups.cups-lpdAT.service.in b/scheduler/org.cups.cups-lpdAT.service.in new file mode 100644 index 0000000..5c78273 --- /dev/null +++ b/scheduler/org.cups.cups-lpdAT.service.in @@ -0,0 +1,9 @@ +[Unit] +Description=CUPS LPD server +Documentation=man:cups-lpd(8) + +[Service] +ExecStart=-@CUPS_SERVERBIN@/daemon/cups-lpd +StandardInput=socket +User=@CUPS_USER@ + diff --git a/scheduler/org.cups.cupsd.path.in b/scheduler/org.cups.cupsd.path.in new file mode 100644 index 0000000..1bccc6f --- /dev/null +++ b/scheduler/org.cups.cupsd.path.in @@ -0,0 +1,8 @@ +[Unit] +Description=CUPS Scheduler + +[Path] +PathExists=@CUPS_CACHEDIR@/org.cups.cupsd + +[Install] +WantedBy=multi-user.target diff --git a/scheduler/org.cups.cupsd.plist b/scheduler/org.cups.cupsd.plist index ccc861d..c0755c4 100644 --- a/scheduler/org.cups.cupsd.plist +++ b/scheduler/org.cups.cupsd.plist @@ -4,8 +4,12 @@ <dict> <key>Label</key> <string>org.cups.cupsd</string> + <key>ProcessType</key> + <string>Background</string> <key>EnableTransactions</key> <true/> + <key>EnablePressuredExit</key> + <true/> <key>ExitTimeOut</key> <integer>60</integer> <key>KeepAlive</key> @@ -21,8 +25,7 @@ <string>/usr/sbin/cupsd</string> <string>-l</string> </array> - <!-- These environment variables are only used when CUPS is compiled - with --enable-debug-printfs --> + <!-- These environment variables are only used when CUPS is compiled with debug-printfs support --> <key>EnvironmentVariables</key> <dict> <key>CUPS_DEBUG_LOG</key> @@ -30,27 +33,13 @@ <key>CUPS_DEBUG_LEVEL</key> <string>3</string> <key>CUPS_DEBUG_FILTER</key> - <string>^(http|_http|ipp|_ipp|mime).*</string> + <string>^(cupsDo|cupsGet|cupsMake|cupsSet|http|_http|ipp|_ipp|mime).*</string> </dict> - <key>ServiceIPC</key> - <true/> <key>Sockets</key> <dict> <key>Listeners</key> <array> <dict> - <key>SockNodeName</key> - <string>::1</string> - <key>SockServiceName</key> - <string>ipp</string> - </dict> - <dict> - <key>SockNodeName</key> - <string>127.0.0.1</string> - <key>SockServiceName</key> - <string>ipp</string> - </dict> - <dict> <key>SockPathMode</key> <integer>49663</integer> <key>SockPathName</key> diff --git a/scheduler/org.cups.cupsd.service.in b/scheduler/org.cups.cupsd.service.in new file mode 100644 index 0000000..0a27c76 --- /dev/null +++ b/scheduler/org.cups.cupsd.service.in @@ -0,0 +1,11 @@ +[Unit] +Description=CUPS Scheduler +Documentation=man:cupsd(8) + +[Service] +ExecStart=@sbindir@/cupsd -l +Type=simple + +[Install] +Also=org.cups.cupsd.socket org.cups.cupsd.path +WantedBy=printer.target diff --git a/scheduler/org.cups.cupsd.socket.in b/scheduler/org.cups.cupsd.socket.in new file mode 100644 index 0000000..b0928c5 --- /dev/null +++ b/scheduler/org.cups.cupsd.socket.in @@ -0,0 +1,8 @@ +[Unit] +Description=CUPS Scheduler + +[Socket] +ListenStream=@CUPS_DEFAULT_DOMAINSOCKET@ + +[Install] +WantedBy=sockets.target diff --git a/scheduler/policy.c b/scheduler/policy.c index 75b5983..b9883d4 100644 --- a/scheduler/policy.c +++ b/scheduler/policy.c @@ -1,32 +1,16 @@ /* - * "$Id: policy.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: policy.c 11681 2014-03-05 19:07:24Z msweet $" * - * Policy routines for the CUPS scheduler. + * Policy routines for the CUPS scheduler. * - * Copyright 2007-2011 by Apple Inc. - * Copyright 1997-2006 by Easy Software Products, all rights reserved. + * Copyright 2007-2011, 2014 by Apple Inc. + * Copyright 1997-2006 by Easy Software Products, all rights reserved. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * AddPolicy() - Add a policy to the system. - * cupsdAddPolicyOp() - Add an operation to a policy. - * cupsdCheckPolicy() - Check the IPP operation and username against a - * policy. - * cupsdDeleteAllPolicies() - Delete all policies in memory. - * cupsdFindPolicy() - Find a named policy. - * cupsdFindPolicyOp() - Find a policy operation. - * cupsdGetPrivateAttrs() - Get the private attributes for the current - * request. - * compare_ops() - Compare two operations. - * compare_policies() - Compare two policies. - * free_policy() - Free the memory used by a policy. - * hash_op() - Generate a lookup hash for the operation. + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -48,7 +32,7 @@ static int hash_op(cupsd_location_t *op); /* - * 'AddPolicy()' - Add a policy to the system. + * 'cupsdAddPolicy()' - Add a policy to the system. */ cupsd_policy_t * /* O - Policy */ @@ -136,7 +120,7 @@ cupsdCheckPolicy(cupsd_policy_t *p, /* I - Policy */ if (!p || !con) { - cupsdLogMessage(CUPSD_LOG_CRIT, "cupsdCheckPolicy: p=%p, con=%p!", p, con); + cupsdLogMessage(CUPSD_LOG_CRIT, "cupsdCheckPolicy: p=%p, con=%p.", p, con); return ((http_status_t)0); } @@ -147,7 +131,7 @@ cupsdCheckPolicy(cupsd_policy_t *p, /* I - Policy */ if ((po = cupsdFindPolicyOp(p, con->request->request.op.operation_id)) == NULL) { - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCheckPolicy: No matching operation, returning 0!"); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCheckPolicy: No matching operation, returning 0."); return ((http_status_t)0); } @@ -263,7 +247,7 @@ cupsdFindPolicyOp(cupsd_policy_t *p, /* I - Policy */ return (po); } - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFindPolicyOp: No match found!"); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFindPolicyOp: No match found."); return (NULL); } @@ -293,9 +277,15 @@ cupsdGetPrivateAttrs( cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdGetPrivateAttrs(policy=%p(%s), con=%p(%d), " "printer=%p(%s), owner=\"%s\")", policy, policy->name, con, - con->http.fd, printer, printer ? printer->name : "", owner); + con->number, printer, printer ? printer->name : "", owner); #endif /* DEBUG */ + if (!policy) + { + cupsdLogMessage(CUPSD_LOG_CRIT, "cupsdGetPrivateAttrs: policy=%p, con=%p, printer=%p, owner=\"%s\", DefaultPolicyPtr=%p: This should never happen, please report a bug.", policy, con, printer, owner, DefaultPolicyPtr); + policy = DefaultPolicyPtr; + } + /* * Get the access and attributes lists that correspond to the request... */ @@ -513,5 +503,5 @@ hash_op(cupsd_location_t *op) /* I - Operation */ /* - * End of "$Id: policy.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: policy.c 11681 2014-03-05 19:07:24Z msweet $". */ diff --git a/scheduler/policy.h b/scheduler/policy.h index df17a11..8af88f5 100644 --- a/scheduler/policy.h +++ b/scheduler/policy.h @@ -1,5 +1,5 @@ /* - * "$Id: policy.h 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: policy.h 10996 2013-05-29 11:51:34Z msweet $" * * Policy definitions for the CUPS scheduler. * @@ -59,5 +59,5 @@ extern cups_array_t *cupsdGetPrivateAttrs(cupsd_policy_t *p, /* - * End of "$Id: policy.h 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: policy.h 10996 2013-05-29 11:51:34Z msweet $". */ diff --git a/scheduler/printers.c b/scheduler/printers.c index 48c4a82..61956b7 100644 --- a/scheduler/printers.c +++ b/scheduler/printers.c @@ -1,59 +1,16 @@ /* - * "$Id: printers.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: printers.c 12733 2015-06-12 01:21:05Z msweet $" * - * Printer routines for the CUPS scheduler. + * Printer routines for the CUPS scheduler. * - * Copyright 2007-2012 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. + * Copyright 2007-2015 by Apple Inc. + * Copyright 1997-2007 by Easy Software Products, all rights reserved. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * cupsdAddPrinter() - Add a printer to the system. - * cupsdCreateCommonData() - Create the common printer data. - * cupsdDeleteAllPrinters() - Delete all printers from the system. - * cupsdDeletePrinter() - Delete a printer from the system. - * cupsdFindDest() - Find a destination in the list. - * cupsdFindPrinter() - Find a printer in the list. - * cupsdLoadAllPrinters() - Load printers from the printers.conf file. - * cupsdRenamePrinter() - Rename a printer. - * cupsdSaveAllPrinters() - Save all printer definitions to the - * printers.conf file. - * cupsdSetAuthInfoRequired() - Set the required authentication info. - * cupsdSetDeviceURI() - Set the device URI for a printer. - * cupsdSetPrinterAttr() - Set a printer attribute. - * cupsdSetPrinterAttrs() - Set printer attributes based upon the PPD - * file. - * cupsdSetPrinterReasons() - Set/update the reasons strings. - * cupsdSetPrinterState() - Update the current state of a printer. - * cupsdStopPrinter() - Stop a printer from printing any jobs... - * cupsdUpdatePrinterPPD() - Update keywords in a printer's PPD file. - * cupsdUpdatePrinters() - Update printers after a partial reload. - * cupsdValidateDest() - Validate a printer/class destination. - * cupsdWritePrintcap() - Write a pseudo-printcap file for older - * applications that need it... - * add_printer_defaults() - Add name-default attributes to the printer - * attributes. - * add_printer_filter() - Add a MIME filter for a printer. - * add_printer_formats() - Add document-format-supported values for a - * printer. - * compare_printers() - Compare two printers. - * delete_printer_filters() - Delete all MIME filters for a printer. - * dirty_printer() - Mark config and state files dirty for the - * specified printer. - * load_ppd() - Load a cached PPD file, updating the cache as - * needed. - * new_media_col() - Create a media-col collection value. - * write_irix_config() - Update the config files used by the IRIX - * desktop tools. - * write_irix_state() - Update the status files used by IRIX printing - * desktop tools. - * write_xml_string() - Write a string with XML escaping. + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -93,13 +50,8 @@ static int compare_printers(void *first, void *second, void *data); static void delete_printer_filters(cupsd_printer_t *p); static void dirty_printer(cupsd_printer_t *p); static void load_ppd(cupsd_printer_t *p); -static void log_ipp_conformance(cupsd_printer_t *p, const char *reason); static ipp_t *new_media_col(_pwg_size_t *size, const char *source, const char *type); -#ifdef __sgi -static void write_irix_config(cupsd_printer_t *p); -static void write_irix_state(cupsd_printer_t *p); -#endif /* __sgi */ static void write_xml_string(cups_file_t *fp, const char *s); @@ -139,15 +91,16 @@ cupsdAddPrinter(const char *name) /* I - Name of printer */ httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, ServerName, RemotePort, "/printers/%s", name); cupsdSetString(&p->uri, uri); - cupsdSetString(&p->uuid, _httpAssembleUUID(ServerName, RemotePort, name, 0, - uuid, sizeof(uuid))); + cupsdSetString(&p->uuid, httpAssembleUUID(ServerName, RemotePort, name, 0, + uuid, sizeof(uuid))); cupsdSetDeviceURI(p, "file:///dev/null"); - p->state = IPP_PRINTER_STOPPED; - p->state_time = time(NULL); - p->accepting = 0; - p->shared = DefaultShared; - p->filetype = mimeAddType(MimeDatabase, "printer", name); + p->config_time = time(NULL); + p->state = IPP_PRINTER_STOPPED; + p->state_time = time(NULL); + p->accepting = 0; + p->shared = DefaultShared; + p->filetype = mimeAddType(MimeDatabase, "printer", name); cupsdSetString(&p->job_sheets[0], "none"); cupsdSetString(&p->job_sheets[1], "none"); @@ -219,6 +172,10 @@ cupsdCreateCommonData(void) "third-shift", "weekend" }; + static const char * const features[] =/* ipp-features-supported values */ + { + "subscription-object" + }; static const char * const versions[] =/* ipp-versions-supported values */ { "1.0", @@ -228,54 +185,53 @@ cupsdCreateCommonData(void) }; static const int ops[] = /* operations-supported values */ { - IPP_PRINT_JOB, - IPP_VALIDATE_JOB, - IPP_CREATE_JOB, - IPP_SEND_DOCUMENT, - IPP_CANCEL_JOB, - IPP_GET_JOB_ATTRIBUTES, - IPP_GET_JOBS, - IPP_GET_PRINTER_ATTRIBUTES, - IPP_HOLD_JOB, - IPP_RELEASE_JOB, - IPP_RESTART_JOB, - IPP_PAUSE_PRINTER, - IPP_RESUME_PRINTER, - IPP_PURGE_JOBS, - IPP_SET_PRINTER_ATTRIBUTES, - IPP_SET_JOB_ATTRIBUTES, - IPP_GET_PRINTER_SUPPORTED_VALUES, - IPP_CREATE_PRINTER_SUBSCRIPTION, - IPP_CREATE_JOB_SUBSCRIPTION, - IPP_GET_SUBSCRIPTION_ATTRIBUTES, - IPP_GET_SUBSCRIPTIONS, - IPP_RENEW_SUBSCRIPTION, - IPP_CANCEL_SUBSCRIPTION, - IPP_GET_NOTIFICATIONS, - IPP_ENABLE_PRINTER, - IPP_DISABLE_PRINTER, - IPP_HOLD_NEW_JOBS, - IPP_RELEASE_HELD_NEW_JOBS, - IPP_CANCEL_JOBS, - IPP_CANCEL_MY_JOBS, - IPP_CLOSE_JOB, - CUPS_GET_DEFAULT, - CUPS_GET_PRINTERS, - CUPS_ADD_PRINTER, - CUPS_DELETE_PRINTER, - CUPS_GET_CLASSES, - CUPS_ADD_CLASS, - CUPS_DELETE_CLASS, - CUPS_ACCEPT_JOBS, - CUPS_REJECT_JOBS, - CUPS_SET_DEFAULT, - CUPS_GET_DEVICES, - CUPS_GET_PPDS, - CUPS_MOVE_JOB, - CUPS_AUTHENTICATE_JOB, - CUPS_GET_PPD, - CUPS_GET_DOCUMENT, - IPP_RESTART_JOB + IPP_OP_PRINT_JOB, + IPP_OP_VALIDATE_JOB, + IPP_OP_CREATE_JOB, + IPP_OP_SEND_DOCUMENT, + IPP_OP_CANCEL_JOB, + IPP_OP_GET_JOB_ATTRIBUTES, + IPP_OP_GET_JOBS, + IPP_OP_GET_PRINTER_ATTRIBUTES, + IPP_OP_HOLD_JOB, + IPP_OP_RELEASE_JOB, + IPP_OP_PAUSE_PRINTER, + IPP_OP_RESUME_PRINTER, + IPP_OP_PURGE_JOBS, + IPP_OP_SET_PRINTER_ATTRIBUTES, + IPP_OP_SET_JOB_ATTRIBUTES, + IPP_OP_GET_PRINTER_SUPPORTED_VALUES, + IPP_OP_CREATE_PRINTER_SUBSCRIPTIONS, + IPP_OP_CREATE_JOB_SUBSCRIPTIONS, + IPP_OP_GET_SUBSCRIPTION_ATTRIBUTES, + IPP_OP_GET_SUBSCRIPTIONS, + IPP_OP_RENEW_SUBSCRIPTION, + IPP_OP_CANCEL_SUBSCRIPTION, + IPP_OP_GET_NOTIFICATIONS, + IPP_OP_ENABLE_PRINTER, + IPP_OP_DISABLE_PRINTER, + IPP_OP_HOLD_NEW_JOBS, + IPP_OP_RELEASE_HELD_NEW_JOBS, + IPP_OP_CANCEL_JOBS, + IPP_OP_CANCEL_MY_JOBS, + IPP_OP_CLOSE_JOB, + IPP_OP_CUPS_GET_DEFAULT, + IPP_OP_CUPS_GET_PRINTERS, + IPP_OP_CUPS_ADD_MODIFY_PRINTER, + IPP_OP_CUPS_DELETE_PRINTER, + IPP_OP_CUPS_GET_CLASSES, + IPP_OP_CUPS_ADD_MODIFY_CLASS, + IPP_OP_CUPS_DELETE_CLASS, + IPP_OP_CUPS_ACCEPT_JOBS, + IPP_OP_CUPS_REJECT_JOBS, + IPP_OP_CUPS_SET_DEFAULT, + IPP_OP_CUPS_GET_DEVICES, + IPP_OP_CUPS_GET_PPDS, + IPP_OP_CUPS_MOVE_JOB, + IPP_OP_CUPS_AUTHENTICATE_JOB, + IPP_OP_CUPS_GET_PPD, + IPP_OP_CUPS_GET_DOCUMENT, + IPP_OP_RESTART_JOB }; static const char * const charsets[] =/* charset-supported values */ { @@ -348,9 +304,9 @@ cupsdCreateCommonData(void) "multiple-document-handling", "number-up", "output-bin", - "output-mode", "orientation-requested", "page-ranges", + "print-color-mode", "print-quality", "printer-resolution", "sides" @@ -367,9 +323,9 @@ cupsdCreateCommonData(void) "multiple-document-handling", "number-up", "output-bin", - "output-mode", "orientation-requested", "page-ranges", + "print-color-mode", "print-quality", "printer-resolution", "sides" @@ -388,8 +344,11 @@ cupsdCreateCommonData(void) }; static const char * const printer_settable[] = { /* printer-settable-attributes-supported */ + "printer-geo-location", "printer-info", - "printer-location" + "printer-location", + "printer-organization", + "printer-organizational-unit" }; static const char * const which_jobs[] = { /* which-jobs-supported values */ @@ -469,6 +428,9 @@ cupsdCreateCommonData(void) ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE, "generated-natural-language-supported", NULL, DefaultLanguage); + /* ipp-features-supported */ + ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "ipp-features-supported", sizeof(features) / sizeof(features[0]), NULL, features); + /* ipp-versions-supported */ ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, "ipp-versions-supported", sizeof(versions) / sizeof(versions[0]), @@ -478,6 +440,10 @@ cupsdCreateCommonData(void) ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "ippget-event-life", 15); + /* job-cancel-after-supported */ + ippAddRange(CommonData, IPP_TAG_PRINTER, "job-cancel-after-supported", + 0, INT_MAX); + /* job-creation-attributes-supported */ ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, "job-creation-attributes-supported", @@ -578,6 +544,9 @@ cupsdCreateCommonData(void) ippAddInteger(CommonData, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "multiple-operation-time-out", MultipleOperationTimeout); + /* multiple-operation-time-out-action */ + ippAddString(CommonData, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "multiple-operation-time-out-action", NULL, "process-job"); + /* natural-language-configured (no IPP_TAG_COPY) */ ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE, "natural-language-configured", NULL, DefaultLanguage); @@ -663,6 +632,9 @@ cupsdCreateCommonData(void) ippAddString(CommonData, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, "pdl-override-supported", NULL, "attempted"); + /* printer-get-attributes-supported */ + ippAddString(CommonData, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "printer-get-attributes-supported", NULL, "document-format"); + /* printer-op-policy-supported */ attr = ippAddStrings(CommonData, IPP_TAG_PRINTER, IPP_TAG_NAME | IPP_TAG_COPY, "printer-op-policy-supported", cupsArrayCount(Policies), @@ -720,9 +692,6 @@ cupsdDeletePrinter( { int i, /* Looping var */ changed = 0; /* Class changed? */ -#ifdef __sgi - char filename[1024]; /* Interface script filename */ -#endif /* __sgi */ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDeletePrinter(p=%p(%s), update=%d)", @@ -756,31 +725,6 @@ cupsdDeletePrinter( cupsArrayRemove(Printers, p); /* - * Remove the dummy interface/icon/option files under IRIX... - */ - -#ifdef __sgi - snprintf(filename, sizeof(filename), "/var/spool/lp/interface/%s", p->name); - unlink(filename); - - snprintf(filename, sizeof(filename), "/var/spool/lp/gui_interface/ELF/%s.gui", - p->name); - unlink(filename); - - snprintf(filename, sizeof(filename), "/var/spool/lp/activeicons/%s", p->name); - unlink(filename); - - snprintf(filename, sizeof(filename), "/var/spool/lp/pod/%s.config", p->name); - unlink(filename); - - snprintf(filename, sizeof(filename), "/var/spool/lp/pod/%s.status", p->name); - unlink(filename); - - snprintf(filename, sizeof(filename), "/var/spool/lp/member/%s", p->name); - unlink(filename); -#endif /* __sgi */ - - /* * If p is the default printer, assign a different one... */ @@ -824,6 +768,7 @@ cupsdDeletePrinter( cupsdClearString(&p->hostname); cupsdClearString(&p->name); cupsdClearString(&p->location); + cupsdClearString(&p->geo_location); cupsdClearString(&p->make_model); cupsdClearString(&p->info); cupsdClearString(&p->job_sheets[0]); @@ -957,7 +902,7 @@ cupsdLoadAllPrinters(void) cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); } - else if (!_cups_strcasecmp(line, "</Printer>")) + else if (!_cups_strcasecmp(line, "</Printer>") || !_cups_strcasecmp(line, "</DefaultPrinter>")) { if (p != NULL) { @@ -1033,6 +978,21 @@ cupsdLoadAllPrinters(void) if (value) cupsdSetString(&p->location, value); } + else if (!_cups_strcasecmp(line, "GeoLocation")) + { + if (value) + cupsdSetString(&p->geo_location, value); + } + else if (!_cups_strcasecmp(line, "Organization")) + { + if (value) + cupsdSetString(&p->organization, value); + } + else if (!_cups_strcasecmp(line, "OrganizationalUnit")) + { + if (value) + cupsdSetString(&p->organizational_unit, value); + } else if (!_cups_strcasecmp(line, "DeviceURI")) { if (value) @@ -1137,6 +1097,15 @@ cupsdLoadAllPrinters(void) if (value) p->state_time = atoi(value); } + else if (!_cups_strcasecmp(line, "ConfigTime")) + { + /* + * Set the config time... + */ + + if (value) + p->config_time = atoi(value); + } else if (!_cups_strcasecmp(line, "Accepting")) { /* @@ -1160,7 +1129,7 @@ cupsdLoadAllPrinters(void) else if (!_cups_strcasecmp(line, "Type")) { if (value) - p->type = atoi(value); + p->type = (cups_ptype_t)atoi(value); else cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); @@ -1287,10 +1256,17 @@ cupsdLoadAllPrinters(void) else if (!_cups_strcasecmp(line, "ErrorPolicy")) { if (value) - cupsdSetString(&p->error_policy, value); + { + if (strcmp(value, "retry-current-job") && + strcmp(value, "abort-job") && + strcmp(value, "retry-job") && + strcmp(value, "stop-printer")) + cupsdLogMessage(CUPSD_LOG_ALERT, "Invalid ErrorPolicy \"%s\" on line %d or printers.conf.", ErrorPolicy, linenum); + else + cupsdSetString(&p->error_policy, value); + } else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of printers.conf.", linenum); + cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); } else if (!_cups_strcasecmp(line, "Attribute") && value) { @@ -1486,9 +1462,18 @@ cupsdSaveAllPrinters(void) if (printer->location) cupsFilePutConf(fp, "Location", printer->location); + if (printer->geo_location) + cupsFilePutConf(fp, "GeoLocation", printer->geo_location); + if (printer->make_model) cupsFilePutConf(fp, "MakeModel", printer->make_model); + if (printer->organization) + cupsFilePutConf(fp, "Organization", printer->organization); + + if (printer->organizational_unit) + cupsFilePutConf(fp, "OrganizationalUnit", printer->organizational_unit); + cupsFilePutConf(fp, "DeviceURI", printer->device_uri); if (printer->port_monitor) @@ -1498,13 +1483,14 @@ cupsdSaveAllPrinters(void) { cupsFilePuts(fp, "State Stopped\n"); - if (printer->state_message) + if (printer->state_message[0]) cupsFilePutConf(fp, "StateMessage", printer->state_message); } else cupsFilePuts(fp, "State Idle\n"); cupsFilePrintf(fp, "StateTime %d\n", (int)printer->state_time); + cupsFilePrintf(fp, "ConfigTime %d\n", (int)printer->config_time); for (i = 0; i < printer->num_reasons; i ++) if (strcmp(printer->reasons[i], "connecting-to-device") && @@ -1562,8 +1548,7 @@ cupsdSaveAllPrinters(void) if (i) *ptr++ = ','; - strlcpy(ptr, marker->values[i].string.text, - value + sizeof(value) - ptr); + strlcpy(ptr, marker->values[i].string.text, (size_t)(value + sizeof(value) - ptr)); ptr += strlen(ptr); } @@ -1622,8 +1607,7 @@ cupsdSaveAllPrinters(void) if (i) *ptr++ = ','; - strlcpy(ptr, marker->values[i].string.text, - value + sizeof(value) - ptr); + strlcpy(ptr, marker->values[i].string.text, (size_t)(value + sizeof(value) - ptr)); ptr += strlen(ptr); } @@ -1643,8 +1627,7 @@ cupsdSaveAllPrinters(void) if (i) *ptr++ = ','; - strlcpy(ptr, marker->values[i].string.text, - value + sizeof(value) - ptr); + strlcpy(ptr, marker->values[i].string.text, (size_t)(value + sizeof(value) - ptr)); ptr += strlen(ptr); } @@ -1656,15 +1639,10 @@ cupsdSaveAllPrinters(void) cupsFilePrintf(fp, "Attribute marker-change-time %ld\n", (long)printer->marker_time); - cupsFilePuts(fp, "</Printer>\n"); - -#ifdef __sgi - /* - * Make IRIX desktop & printer status happy - */ - - write_irix_state(printer); -#endif /* __sgi */ + if (printer == DefaultPrinter) + cupsFilePuts(fp, "</DefaultPrinter>\n"); + else + cupsFilePuts(fp, "</Printer>\n"); } cupsdCloseCreatedConfFile(fp, filename); @@ -1767,7 +1745,7 @@ cupsdSetAuthInfoRequired( strcmp(p->auth_info_required[0], "none")) p->type |= CUPS_PRINTER_AUTHENTICATED; else - p->type &= ~CUPS_PRINTER_AUTHENTICATED; + p->type &= (cups_ptype_t)~CUPS_PRINTER_AUTHENTICATED; return (1); } @@ -1910,12 +1888,13 @@ void cupsdSetPrinterAttr( cupsd_printer_t *p, /* I - Printer */ const char *name, /* I - Attribute name */ - char *value) /* I - Attribute value string */ + const char *value) /* I - Attribute value string */ { ipp_attribute_t *attr; /* Attribute */ int i, /* Looping var */ count; /* Number of values */ - char *ptr, /* Pointer into value */ + char *temp, /* Temporary copy of value string */ + *ptr, /* Pointer into value */ *start, /* Start of value */ quote; /* Quote character */ ipp_tag_t value_tag; /* Value tag for this attribute */ @@ -1932,10 +1911,21 @@ cupsdSetPrinterAttr( } /* + * Copy the value string so we can do what we want with it... + */ + + if ((temp = strdup(value)) == NULL) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Unable to duplicate value for \"%s\" attribute.", name); + return; + } + + /* * Count the number of values... */ - for (count = 1, quote = '\0', ptr = value; + for (count = 1, quote = '\0', ptr = temp; *ptr; ptr ++) { @@ -1977,21 +1967,22 @@ cupsdSetPrinterAttr( if (!attr) { + free(temp); cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to allocate memory for printer attribute " "(%d values)", count); return; } - for (i = 0; i < count; i ++) + for (i = 0, start = temp; i < count; i ++) { - if ((ptr = strchr(value, ',')) != NULL) + if ((ptr = strchr(start, ',')) != NULL) *ptr++ = '\0'; - attr->values[i].integer = strtol(value, NULL, 10); + attr->values[i].integer = strtol(start, NULL, 10); if (ptr) - value = ptr; + start = ptr; } } else @@ -2027,13 +2018,14 @@ cupsdSetPrinterAttr( if (!attr) { + free(temp); cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to allocate memory for printer attribute " "(%d values)", count); return; } - for (i = 0, quote = '\0', ptr = value; i < count; i ++) + for (i = 0, quote = '\0', ptr = temp; i < count; i ++) { for (start = ptr; *ptr; ptr ++) { @@ -2062,6 +2054,79 @@ cupsdSetPrinterAttr( attr->values[i].string.text = _cupsStrAlloc(start); } } + + free(temp); + + /* + * Update the printer-supply and printer-supply-description, as needed... + */ + + if (!strcmp(name, "marker-names")) + { + ipp_attribute_t *supply_desc = ippFindAttribute(p->attrs, "printer-supply-description", IPP_TAG_TEXT); + /* printer-supply-description attribute */ + + if (supply_desc != NULL) + ippDeleteAttribute(p->attrs, supply_desc); + + supply_desc = ippCopyAttribute(p->attrs, attr, 0); + ippSetName(p->attrs, &supply_desc, "printer-supply-description"); + ippSetValueTag(p->attrs, &supply_desc, IPP_TAG_TEXT); + } + else if (!strcmp(name, "marker-colors") || !strcmp(name, "marker-levels") || !strcmp(name, "marker-types")) + { + char buffer[256], /* printer-supply values */ + pstype[64], /* printer-supply type value */ + *psptr; /* Pointer into type */ + const char *color, /* marker-colors value */ + *type; /* marker-types value */ + int level; /* marker-levels value */ + ipp_attribute_t *colors = ippFindAttribute(p->attrs, "marker-colors", IPP_TAG_NAME); + /* marker-colors attribute */ + ipp_attribute_t *levels = ippFindAttribute(p->attrs, "marker-levels", IPP_TAG_INTEGER); + /* marker-levels attribute */ + ipp_attribute_t *types = ippFindAttribute(p->attrs, "marker-types", IPP_TAG_KEYWORD); + /* marker-types attribute */ + ipp_attribute_t *supply = ippFindAttribute(p->attrs, "printer-supply", IPP_TAG_STRING); + /* printer-supply attribute */ + + if (supply != NULL) + { + ippDeleteAttribute(p->attrs, supply); + supply = NULL; + } + + if (!colors || !levels || !types) + return; + + count = ippGetCount(colors); + if (count != ippGetCount(levels) || count != ippGetCount(types)) + return; + + for (i = 0; i < count; i ++) + { + color = ippGetString(colors, i, NULL); + level = ippGetInteger(levels, i); + type = ippGetString(types, i, NULL); + + for (psptr = pstype; *type && psptr < (pstype + sizeof(pstype) - 1); type ++) + if (*type == '-') + { + type ++; + *psptr++ = (char)toupper(*type & 255); + } + else + *psptr++ = *type; + *psptr = '\0'; + + snprintf(buffer, sizeof(buffer), "index=%d;class=%s;type=%s;unit=percent;maxcapacity=100;level=%d;colorantname=%s;", i + 1, strncmp(pstype, "waste", 5) ? "supplyThatIsConsumed" : "receptacleThatIsFilled", pstype, level, color); + + if (!i) + supply = ippAddOctetString(p->attrs, IPP_TAG_PRINTER, "printer-supply", buffer, (int)strlen(buffer)); + else + ippSetOctetString(p->attrs, &supply, i, buffer, (int)strlen(buffer)); + } + } } @@ -2121,10 +2186,8 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ if ((auth_type = auth->type) == CUPSD_AUTH_DEFAULT) auth_type = cupsdDefaultAuthType(); - if (auth_type == CUPSD_AUTH_BASIC || auth_type == CUPSD_AUTH_BASICDIGEST) + if (auth_type == CUPSD_AUTH_BASIC) auth_supported = "basic"; - else if (auth_type == CUPSD_AUTH_DIGEST) - auth_supported = "digest"; #ifdef HAVE_GSSAPI else if (auth_type == CUPSD_AUTH_NEGOTIATE) auth_supported = "negotiate"; @@ -2133,10 +2196,10 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ if (auth_type != CUPSD_AUTH_NONE) p->type |= CUPS_PRINTER_AUTHENTICATED; else - p->type &= ~CUPS_PRINTER_AUTHENTICATED; + p->type &= (cups_ptype_t)~CUPS_PRINTER_AUTHENTICATED; } else - p->type &= ~CUPS_PRINTER_AUTHENTICATED; + p->type &= (cups_ptype_t)~CUPS_PRINTER_AUTHENTICATED; /* * Create the required IPP attributes for a printer... @@ -2153,10 +2216,15 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ p->name); ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-location", NULL, p->location ? p->location : ""); + if (p->geo_location) + ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-geo-location", NULL, p->geo_location); + else + ippAddOutOfBand(p->attrs, IPP_TAG_PRINTER, IPP_TAG_UNKNOWN, "printer-geo-location"); ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info", NULL, p->info ? p->info : ""); - ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-uuid", NULL, - p->uuid); + ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-organization", NULL, p->organization ? p->organization : ""); + ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-organizational-unit", NULL, p->organizational_unit ? p->organizational_unit : ""); + ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-uuid", NULL, p->uuid); if (cupsArrayCount(p->users) > 0) { @@ -2172,7 +2240,7 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ for (i = 0, name = (char *)cupsArrayFirst(p->users); name; i ++, name = (char *)cupsArrayNext(p->users)) - attr->values[i].string.text = _cupsStrRetain(name); + attr->values[i].string.text = _cupsStrAlloc(name); } ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, @@ -2215,7 +2283,7 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ if (p->type & CUPS_PRINTER_CLASS) { p->raw = 1; - p->type &= ~CUPS_PRINTER_OPTIONS; + p->type &= (cups_ptype_t)~CUPS_PRINTER_OPTIONS; /* * Add class-specific attributes... @@ -2239,9 +2307,9 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ for (i = 0; i < p->num_printers; i ++) { if (attr != NULL) - attr->values[i].string.text = _cupsStrRetain(p->printers[i]->name); + attr->values[i].string.text = _cupsStrAlloc(p->printers[i]->name); - p->type &= ~CUPS_PRINTER_OPTIONS | p->printers[i]->type; + p->type &= (cups_ptype_t)~CUPS_PRINTER_OPTIONS | p->printers[i]->type; } } } @@ -2339,7 +2407,7 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ { for (i = 0; i < oldattr->num_values; i ++) attr->values[i].string.text = - _cupsStrRetain(oldattr->values[i].string.text); + _cupsStrAlloc(oldattr->values[i].string.text); } } @@ -2393,7 +2461,7 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ { for (i = 0; i < oldattr->num_values; i ++) attr->values[i].string.text = - _cupsStrRetain(oldattr->values[i].string.text); + _cupsStrAlloc(oldattr->values[i].string.text); } } @@ -2406,7 +2474,7 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ { for (i = 0; i < oldattr->num_values; i ++) attr->values[i].string.text = - _cupsStrRetain(oldattr->values[i].string.text); + _cupsStrAlloc(oldattr->values[i].string.text); } } @@ -2435,15 +2503,6 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ add_printer_defaults(p); -#ifdef __sgi - /* - * Write the IRIX printer config and status files... - */ - - write_irix_config(p); - write_irix_state(p); -#endif /* __sgi */ - /* * Let the browse protocols reflect the change */ @@ -2539,14 +2598,17 @@ cupsdSetPrinterReasons( _cupsStrFree(p->reasons[i]); if (i < p->num_reasons) - memmove(p->reasons + i, p->reasons + i + 1, - (p->num_reasons - i) * sizeof(char *)); + memmove(p->reasons + i, p->reasons + i + 1, (size_t)(p->num_reasons - i) * sizeof(char *)); if (!strcmp(reason, "paused") && p->state == IPP_PRINTER_STOPPED) cupsdSetPrinterState(p, IPP_PRINTER_IDLE, 1); + if (!strcmp(reason, "cups-waiting-for-job-completed") && p->job) + p->job->completed = 0; + if (strcmp(reason, "connecting-to-device")) dirty_printer(p); + break; } } @@ -2562,10 +2624,6 @@ cupsdSetPrinterReasons( if (i >= p->num_reasons) { - if (!strncmp(reason, "cups-ipp-missing-", 17) || - !strncmp(reason, "cups-ipp-wrong-", 15)) - log_ipp_conformance(p, reason); - if (i >= (int)(sizeof(p->reasons) / sizeof(p->reasons[0]))) { cupsdLogMessage(CUPSD_LOG_ALERT, @@ -2581,6 +2639,9 @@ cupsdSetPrinterReasons( if (!strcmp(reason, "paused") && p->state != IPP_PRINTER_STOPPED) cupsdSetPrinterState(p, IPP_PRINTER_STOPPED, 1); + if (!strcmp(reason, "cups-waiting-for-job-completed") && p->job) + p->job->completed = 1; + if (strcmp(reason, "connecting-to-device")) dirty_printer(p); } @@ -2631,10 +2692,6 @@ cupsdSetPrinterState( */ p->state_time = time(NULL); - -#ifdef __sgi - write_irix_state(p); -#endif /* __sgi */ } /* @@ -3023,16 +3080,6 @@ cupsdWritePrintcap(void) cupsd_printer_t *p; /* Current printer */ -#ifdef __sgi - /* - * Update the IRIX printer state for the default printer; if - * no printers remain, then the default printer file will be - * removed... - */ - - write_irix_state(DefaultPrinter); -#endif /* __sgi */ - /* * See if we have a printcap file; if not, don't bother writing it. */ @@ -3226,6 +3273,10 @@ add_printer_defaults(cupsd_printer_t *p)/* I - Printer */ cupsArrayAdd(CommonDefaults, _cupsStrAlloc("copies-default")); cupsArrayAdd(CommonDefaults, _cupsStrAlloc("document-format-default")); cupsArrayAdd(CommonDefaults, _cupsStrAlloc("finishings-default")); + cupsArrayAdd(CommonDefaults, _cupsStrAlloc("job-account-id-default")); + cupsArrayAdd(CommonDefaults, + _cupsStrAlloc("job-accounting-user-id-default")); + cupsArrayAdd(CommonDefaults, _cupsStrAlloc("job-cancel-after-default")); cupsArrayAdd(CommonDefaults, _cupsStrAlloc("job-hold-until-default")); cupsArrayAdd(CommonDefaults, _cupsStrAlloc("job-priority-default")); cupsArrayAdd(CommonDefaults, _cupsStrAlloc("job-sheets-default")); @@ -3274,6 +3325,10 @@ add_printer_defaults(cupsd_printer_t *p)/* I - Printer */ ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_MIMETYPE, "document-format-default", NULL, "application/octet-stream"); + if (!cupsGetOption("job-cancel-after", p->num_options, p->options)) + ippAddInteger(p->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, + "job-cancel-after-default", MaxJobTime); + if (!cupsGetOption("job-hold-until", p->num_options, p->options)) ippAddString(p->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "job-hold-until-default", NULL, "no-hold"); @@ -3377,7 +3432,7 @@ add_printer_filter( { char *ptr; /* Pointer into maxsize(nnnn) program */ - maxsize = strtoll(program + 8, &ptr, 10); + maxsize = (size_t)strtoll(program + 8, &ptr, 10); if (*ptr != ')') { @@ -3565,8 +3620,7 @@ add_printer_formats(cupsd_printer_t *p) /* I - Printer */ filter; filter = (mime_filter_t *)cupsArrayNext(MimeDatabase->filters)) { - if (filter->dst == p->filetype && filter->filter && - strstr(filter->filter, "PrintJobMgr")) + if (filter->dst == p->filetype && strstr(filter->filter, "PrintJobMgr")) break; } @@ -3731,7 +3785,8 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ qualities[3]; /* print-quality values */ int num_margins, /* Number of media-*-margin-supported values */ margins[16]; /* media-*-margin-supported values */ - const char *filter; /* Current filter */ + const char *filter, /* Current filter */ + *mandatory; /* Current mandatory attribute */ static const char * const sides[3] = /* sides-supported values */ { "one-sided", @@ -3787,7 +3842,9 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ cupsdLogMessage(CUPSD_LOG_DEBUG, "load_ppd: Loading %s...", ppd_name); - p->type &= ~CUPS_PRINTER_OPTIONS; + cupsdClearString(&(p->make_model)); + + p->type &= (cups_ptype_t)~CUPS_PRINTER_OPTIONS; p->type |= CUPS_PRINTER_BW; finishings[0] = IPP_FINISHINGS_NONE; @@ -3803,6 +3860,10 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ p->pc = _ppdCacheCreateWithPPD(ppd); + if (!p->pc) + cupsdLogMessage(CUPSD_LOG_WARN, "Unable to create cache of \"%s\": %s", + ppd_name, cupsLastErrorString()); + ppdMarkDefaults(ppd); if (ppd->color_device) @@ -3815,8 +3876,28 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ if (ppd_attr->value && !_cups_strcasecmp(ppd_attr->value, "true")) p->type |= CUPS_PRINTER_FAX; - ippAddBoolean(p->ppd_attrs, IPP_TAG_PRINTER, "color-supported", - ppd->color_device); + ippAddBoolean(p->ppd_attrs, IPP_TAG_PRINTER, "color-supported", (char)ppd->color_device); + + if (p->pc && p->pc->charge_info_uri) + ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_URI, + "printer-charge-info-uri", NULL, p->pc->charge_info_uri); + + if (p->pc && p->pc->account_id) + ippAddBoolean(p->ppd_attrs, IPP_TAG_PRINTER, "job-account-id-supported", + 1); + + if (p->pc && p->pc->accounting_user_id) + ippAddBoolean(p->ppd_attrs, IPP_TAG_PRINTER, + "job-accounting-user-id-supported", 1); + + if (p->pc && p->pc->password) + { + ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, + "job-password-encryption-supported", NULL, "none"); + ippAddInteger(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, + "job-password-supported", (int)strlen(p->pc->password)); + } + if (ppd->throughput) { ippAddInteger(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, @@ -3838,6 +3919,9 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ "pages-per-minute-color", 1); } + if ((ppd_attr = ppdFindAttr(ppd, "1284DeviceId", NULL)) != NULL) + ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-device-id", NULL, ppd_attr->value); + num_qualities = 0; if ((output_mode = ppdFindOption(ppd, "OutputMode")) != NULL) @@ -3906,10 +3990,10 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ if (ppd->num_sizes == 0 || !p->pc) { - if (!ppdFindAttr(ppd, "APScannerOnly", NULL)) + if (!ppdFindAttr(ppd, "APScannerOnly", NULL) && !ppdFindAttr(ppd, "cups3D", NULL)) cupsdLogMessage(CUPSD_LOG_CRIT, "The PPD file for printer %s contains no media " - "options and is therefore invalid!", p->name); + "options and is therefore invalid.", p->name); ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default", NULL, "unknown"); @@ -3973,13 +4057,13 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ for (i = p->pc->num_sizes, pwgsize = p->pc->sizes; i > 0; i --, pwgsize ++, val ++) - val->string.text = _cupsStrRetain(pwgsize->map.pwg); + val->string.text = _cupsStrAlloc(pwgsize->map.pwg); if (p->pc->custom_min_keyword) { - val->string.text = _cupsStrRetain(p->pc->custom_min_keyword); + val->string.text = _cupsStrAlloc(p->pc->custom_min_keyword); val ++; - val->string.text = _cupsStrRetain(p->pc->custom_max_keyword); + val->string.text = _cupsStrAlloc(p->pc->custom_max_keyword); } } @@ -4031,7 +4115,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ val = attr->values; i > 0; i --, pwgsource ++, val ++) - val->string.text = _cupsStrRetain(pwgsource->pwg); + val->string.text = _cupsStrAlloc(pwgsource->pwg); } /* @@ -4047,7 +4131,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ val = attr->values; i > 0; i --, pwgtype ++, val ++) - val->string.text = _cupsStrRetain(pwgtype->pwg); + val->string.text = _cupsStrAlloc(pwgtype->pwg); } /* @@ -4292,41 +4376,51 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ } /* - * output-mode and print-color-mode... + * print-color-mode... */ if (ppd->color_device) { - static const char * const output_modes[] = + static const char * const color_modes[] = { "monochrome", "color" }; ippAddStrings(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "output-mode-supported", 2, NULL, output_modes); - ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "output-mode-default", NULL, "color"); - - ippAddStrings(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "print-color-mode-supported", 2, NULL, output_modes); + "print-color-mode-supported", 2, NULL, color_modes); ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "print-color-mode-default", NULL, "color"); } else { ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "output-mode-supported", NULL, "monochrome"); - ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "output-mode-default", NULL, "monochrome"); - - ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "print-color-mode-supported", NULL, "monochrome"); ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "print-color-mode-default", NULL, "monochrome"); } /* + * Mandatory job attributes, if any... + */ + + if (p->pc && cupsArrayCount(p->pc->mandatory) > 0) + { + int count = cupsArrayCount(p->pc->mandatory); + /* Number of mandatory attributes */ + + attr = ippAddStrings(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, + "printer-mandatory-job-attributes", count, NULL, + NULL); + + for (val = attr->values, + mandatory = (char *)cupsArrayFirst(p->pc->mandatory); + mandatory; + val ++, mandatory = (char *)cupsArrayNext(p->pc->mandatory)) + val->string.text = _cupsStrAlloc(mandatory); + } + + /* * Printer resolutions... */ @@ -4589,6 +4683,13 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ } /* + * 3D printer support... + */ + + if (ppdFindAttr(ppd, "cups3D", NULL)) + p->type |= CUPS_PRINTER_3D; + + /* * Show current and available port monitors for this printer... */ @@ -4654,22 +4755,16 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ CGContextRef context; /* The CG context used for resizing */ snprintf(outPath, sizeof(outPath), "%s/%s.png", CacheDir, p->name); - outUrl = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, - (UInt8 *)outPath, - strlen(outPath), - FALSE); - icnsFileUrl = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, - (UInt8 *)ppd_attr->value, - strlen(ppd_attr->value), - FALSE); + outUrl = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (UInt8 *)outPath, (CFIndex)strlen(outPath), FALSE); + icnsFileUrl = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (UInt8 *)ppd_attr->value, (CFIndex)strlen(ppd_attr->value), FALSE); if (outUrl && icnsFileUrl) { sourceRef = CGImageSourceCreateWithURL(icnsFileUrl, NULL); if (sourceRef) { - for (i = 0; i < CGImageSourceGetCount(sourceRef); i ++) + for (i = 0; i < (int)CGImageSourceGetCount(sourceRef); i ++) { - imageRef = CGImageSourceCreateImageAtIndex(sourceRef, i, NULL); + imageRef = CGImageSourceCreateImageAtIndex(sourceRef, (size_t)i, NULL); if (!imageRef) continue; @@ -4773,14 +4868,12 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ pstatus = ppdLastError(&pline); - cupsdLogMessage(CUPSD_LOG_ERROR, "PPD file for %s cannot be loaded!", - p->name); + cupsdLogMessage(CUPSD_LOG_ERROR, "PPD file for %s cannot be loaded.", p->name); if (pstatus <= PPD_ALLOC_ERROR) - cupsdLogMessage(CUPSD_LOG_ERROR, "%s", strerror(errno)); + cupsdLogMessage(CUPSD_LOG_ERROR, "%s: %s", ppd_name, strerror(errno)); else - cupsdLogMessage(CUPSD_LOG_ERROR, "%s on line %d.", - ppdErrorString(pstatus), pline); + cupsdLogMessage(CUPSD_LOG_ERROR, "%s on line %d of %s.", ppdErrorString(pstatus), pline, ppd_name); cupsdLogMessage(CUPSD_LOG_INFO, "Hint: Run \"cupstestppd %s\" and fix any errors.", @@ -4902,83 +4995,6 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ /* - * 'log_ipp_conformance()' - Log an IPP conformance issue with a printer. - */ - -static void -log_ipp_conformance( - cupsd_printer_t *p, /* I - Printer */ - const char *reason) /* I - Printer state reason */ -{ - const char *message; /* Message to log */ -#ifdef __APPLE__ - aslmsg aslm; /* Apple System Log message */ -#endif /* __APPLE__ */ - - - /* - * Strip the leading "cups-ipp-" from the reason and create a log message for - * it... - */ - - reason += 9; - if (!strcmp(reason, "missing-cancel-job")) - message = "Printer does not support REQUIRED Cancel-Job operation."; - else if (!strcmp(reason, "missing-get-job-attributes")) - message = "Printer does not support REQUIRED Get-Job-Attributes operation."; - else if (!strcmp(reason, "missing-print-job")) - message = "Printer does not support REQUIRED Print-Job operation."; - else if (!strcmp(reason, "missing-validate-job")) - message = "Printer does not support REQUIRED Validate-Job operation."; - else if (!strcmp(reason, "missing-get-printer-attributes")) - message = "Printer does not support REQUIRED Get-Printer-Attributes operation."; - else if (!strcmp(reason, "missing-send-document")) - message = "Printer supports Create-Job but not Send-Document operation."; - else if (!strcmp(reason, "missing-job-history")) - message = "Printer does not provide REQUIRED job history."; - else if (!strcmp(reason, "missing-job-id")) - message = "Printer does not provide REQUIRED job-id attribute."; - else if (!strcmp(reason, "missing-job-state")) - message = "Printer does not provide REQUIRED job-state attribute."; - else if (!strcmp(reason, "missing-operations-supported")) - message = "Printer does not provide REQUIRED operations-supported " - "attribute."; - else if (!strcmp(reason, "missing-printer-is-accepting-jobs")) - message = "Printer does not provide REQUIRED printer-is-accepting-jobs " - "attribute."; - else if (!strcmp(reason, "missing-printer-state-reasons")) - message = "Printer does not provide REQUIRED printer-state-reasons " - "attribute."; - else if (!strcmp(reason, "wrong-http-version")) - message = "Printer does not use REQUIRED HTTP/1.1 transport."; - else - message = "Unknown IPP conformance failure."; - - cupsdLogMessage(CUPSD_LOG_WARN, "%s: %s", p->name, message); - -#ifdef __APPLE__ - /* - * Report the failure information to Apple if the user opts into providing - * feedback to Apple... - */ - - aslm = asl_new(ASL_TYPE_MSG); - if (aslm) - { - asl_set(aslm, "com.apple.message.domain", "com.apple.printing.ipp.conformance"); - asl_set(aslm, "com.apple.message.domain_scope", "com.apple.printing.ipp.conformance"); - asl_set(aslm, "com.apple.message.signature", reason); - asl_set(aslm, "com.apple.message.signature2", - p->make_model ? p->make_model : "Unknown"); - asl_log(NULL, aslm, ASL_LEVEL_NOTICE, "%s: %s", - p->make_model ? p->make_model : "Unknown", message); - asl_free(aslm); - } -#endif /* __APPLE__ */ -} - - -/* * 'new_media_col()' - Create a media-col collection value. */ @@ -5022,261 +5038,6 @@ new_media_col(_pwg_size_t *size, /* I - media-size/margin values */ } -#ifdef __sgi -/* - * 'write_irix_config()' - Update the config files used by the IRIX - * desktop tools. - */ - -static void -write_irix_config(cupsd_printer_t *p) /* I - Printer to update */ -{ - char filename[1024]; /* Interface script filename */ - cups_file_t *fp; /* Interface script file */ - ipp_attribute_t *attr; /* Attribute data */ - - - /* - * Add dummy interface and GUI scripts to fool SGI's "challenged" printing - * tools. First the interface script that tells the tools what kind of - * printer we have... - */ - - snprintf(filename, sizeof(filename), "/var/spool/lp/interface/%s", p->name); - - if (p->type & CUPS_PRINTER_CLASS) - unlink(filename); - else if ((fp = cupsFileOpen(filename, "w")) != NULL) - { - cupsFilePuts(fp, "#!/bin/sh\n"); - - if ((attr = ippFindAttribute(p->attrs, "printer-make-and-model", - IPP_TAG_TEXT)) != NULL) - cupsFilePrintf(fp, "NAME=\"%s\"\n", attr->values[0].string.text); - else if (p->type & CUPS_PRINTER_CLASS) - cupsFilePuts(fp, "NAME=\"Printer Class\"\n"); - else - cupsFilePuts(fp, "NAME=\"Remote Destination\"\n"); - - if (p->type & CUPS_PRINTER_COLOR) - cupsFilePuts(fp, "TYPE=ColorPostScript\n"); - else - cupsFilePuts(fp, "TYPE=MonoPostScript\n"); - - cupsFilePrintf(fp, "HOSTNAME=%s\n", ServerName); - cupsFilePrintf(fp, "HOSTPRINTER=%s\n", p->name); - - cupsFileClose(fp); - - chmod(filename, 0755); - chown(filename, User, Group); - } - - /* - * Then the member file that tells which device file the queue is connected - * to... Networked printers use "/dev/null" in this file, so that's what - * we use (the actual device URI can confuse some apps...) - */ - - snprintf(filename, sizeof(filename), "/var/spool/lp/member/%s", p->name); - - if (p->type & CUPS_PRINTER_CLASS) - unlink(filename); - else if ((fp = cupsFileOpen(filename, "w")) != NULL) - { - cupsFilePuts(fp, "/dev/null\n"); - - cupsFileClose(fp); - - chmod(filename, 0644); - chown(filename, User, Group); - } - - /* - * The gui_interface file is a script or program that launches a GUI - * option panel for the printer, using options specified on the - * command-line in the third argument. The option panel must send - * any printing options to stdout on a single line when the user - * accepts them, or nothing if the user cancels the dialog. - * - * The default options panel program is /usr/bin/glpoptions, from - * the ESP Print Pro software. You can select another using the - * PrintcapGUI option. - */ - - snprintf(filename, sizeof(filename), "/var/spool/lp/gui_interface/ELF/%s.gui", p->name); - - if (p->type & CUPS_PRINTER_CLASS) - unlink(filename); - else if ((fp = cupsFileOpen(filename, "w")) != NULL) - { - cupsFilePuts(fp, "#!/bin/sh\n"); - cupsFilePrintf(fp, "%s -d %s -o \"$3\"\n", PrintcapGUI, p->name); - - cupsFileClose(fp); - - chmod(filename, 0755); - chown(filename, User, Group); - } - - /* - * The POD config file is needed by the printstatus command to show - * the printer location and device. - */ - - snprintf(filename, sizeof(filename), "/var/spool/lp/pod/%s.config", p->name); - - if (p->type & CUPS_PRINTER_CLASS) - unlink(filename); - else if ((fp = cupsFileOpen(filename, "w")) != NULL) - { - cupsFilePrintf(fp, "Printer Class | %s\n", - (p->type & CUPS_PRINTER_COLOR) ? "ColorPostScript" : "MonoPostScript"); - cupsFilePrintf(fp, "Printer Model | %s\n", p->make_model ? p->make_model : ""); - cupsFilePrintf(fp, "Location Code | %s\n", p->location ? p->location : ""); - cupsFilePrintf(fp, "Physical Location | %s\n", p->info ? p->info : ""); - cupsFilePrintf(fp, "Port Path | %s\n", p->device_uri); - cupsFilePrintf(fp, "Config Path | /var/spool/lp/pod/%s.config\n", p->name); - cupsFilePrintf(fp, "Active Status Path | /var/spool/lp/pod/%s.status\n", p->name); - cupsFilePuts(fp, "Status Update Wait | 10 seconds\n"); - - cupsFileClose(fp); - - chmod(filename, 0664); - chown(filename, User, Group); - } -} - - -/* - * 'write_irix_state()' - Update the status files used by IRIX printing - * desktop tools. - */ - -static void -write_irix_state(cupsd_printer_t *p) /* I - Printer to update */ -{ - char filename[1024]; /* Interface script filename */ - cups_file_t *fp; /* Interface script file */ - int tag; /* Status tag value */ - - - if (p) - { - /* - * The POD status file is needed for the printstatus window to - * provide the current status of the printer. - */ - - snprintf(filename, sizeof(filename), "/var/spool/lp/pod/%s.status", p->name); - - if (p->type & CUPS_PRINTER_CLASS) - unlink(filename); - else if ((fp = cupsFileOpen(filename, "w")) != NULL) - { - cupsFilePrintf(fp, "Operational Status | %s\n", - (p->state == IPP_PRINTER_IDLE) ? "Idle" : - (p->state == IPP_PRINTER_PROCESSING) ? "Busy" : - "Faulted"); - cupsFilePrintf(fp, "Information | 01 00 00 | %s\n", CUPS_SVERSION); - cupsFilePrintf(fp, "Information | 02 00 00 | Device URI: %s\n", - p->device_uri); - cupsFilePrintf(fp, "Information | 03 00 00 | %s jobs\n", - p->accepting ? "Accepting" : "Not accepting"); - cupsFilePrintf(fp, "Information | 04 00 00 | %s\n", p->state_message); - - cupsFileClose(fp); - - chmod(filename, 0664); - chown(filename, User, Group); - } - - /* - * The activeicons file is needed to provide desktop icons for printers: - * - * [ quoted from /usr/lib/print/tagit ] - * - * --- Type of printer tags (base values) - * - * Dumb=66048 # 0x10200 - * DumbColor=66080 # 0x10220 - * Raster=66112 # 0x10240 - * ColorRaster=66144 # 0x10260 - * Plotter=66176 # 0x10280 - * PostScript=66208 # 0x102A0 - * ColorPostScript=66240 # 0x102C0 - * MonoPostScript=66272 # 0x102E0 - * - * --- Printer state modifiers for local printers - * - * Idle=0 # 0x0 - * Busy=1 # 0x1 - * Faulted=2 # 0x2 - * Unknown=3 # 0x3 (Faulted due to unknown reason) - * - * --- Printer state modifiers for network printers - * - * NetIdle=8 # 0x8 - * NetBusy=9 # 0x9 - * NetFaulted=10 # 0xA - * NetUnknown=11 # 0xB (Faulted due to unknown reason) - */ - - snprintf(filename, sizeof(filename), "/var/spool/lp/activeicons/%s", p->name); - - if (p->type & CUPS_PRINTER_CLASS) - unlink(filename); - else if ((fp = cupsFileOpen(filename, "w")) != NULL) - { - if (p->type & CUPS_PRINTER_COLOR) - tag = 66240; - else - tag = 66272; - - if (p->type & CUPS_PRINTER_REMOTE) - tag |= 8; - - if (p->state == IPP_PRINTER_PROCESSING) - tag |= 1; - - else if (p->state == IPP_PRINTER_STOPPED) - tag |= 2; - - cupsFilePuts(fp, "#!/bin/sh\n"); - cupsFilePrintf(fp, "#Tag %d\n", tag); - - cupsFileClose(fp); - - chmod(filename, 0755); - chown(filename, User, Group); - } - } - - /* - * The default file is needed by the printers window to show - * the default printer. - */ - - snprintf(filename, sizeof(filename), "/var/spool/lp/default"); - - if (DefaultPrinter != NULL) - { - if ((fp = cupsFileOpen(filename, "w")) != NULL) - { - cupsFilePrintf(fp, "%s\n", DefaultPrinter->name); - - cupsFileClose(fp); - - chmod(filename, 0644); - chown(filename, User, Group); - } - } - else - unlink(filename); -} -#endif /* __sgi */ - - /* * 'write_xml_string()' - Write a string with XML escaping. */ @@ -5296,7 +5057,7 @@ write_xml_string(cups_file_t *fp, /* I - File to write to */ if (*s == '&') { if (s > start) - cupsFileWrite(fp, start, s - start); + cupsFileWrite(fp, start, (size_t)(s - start)); cupsFilePuts(fp, "&"); start = s + 1; @@ -5304,7 +5065,7 @@ write_xml_string(cups_file_t *fp, /* I - File to write to */ else if (*s == '<') { if (s > start) - cupsFileWrite(fp, start, s - start); + cupsFileWrite(fp, start, (size_t)(s - start)); cupsFilePuts(fp, "<"); start = s + 1; @@ -5317,5 +5078,5 @@ write_xml_string(cups_file_t *fp, /* I - File to write to */ /* - * End of "$Id: printers.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: printers.c 12733 2015-06-12 01:21:05Z msweet $". */ diff --git a/scheduler/printers.h b/scheduler/printers.h index ad89d70..27db750 100644 --- a/scheduler/printers.h +++ b/scheduler/printers.h @@ -1,16 +1,16 @@ /* - * "$Id: printers.h 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: printers.h 12666 2015-05-25 19:38:09Z msweet $" * - * Printer definitions for the CUPS scheduler. + * Printer definitions for the CUPS scheduler. * - * Copyright 2007-2012 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. + * Copyright 2007-2013 by Apple Inc. + * Copyright 1997-2007 by Easy Software Products, all rights reserved. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ #ifdef HAVE_DNSSD @@ -63,9 +63,12 @@ struct cupsd_printer_s *uuid, /* Printer UUID */ *hostname, /* Host printer resides on */ *name, /* Printer name */ - *location, /* Location code */ + *location, /* Location string */ + *geo_location, /* Geographic location URI */ *make_model, /* Make and model */ *info, /* Description */ + *organization, /* Organization name */ + *organizational_unit, /* Organizational unit (department, etc.) */ *op_policy, /* Operation policy name */ *error_policy; /* Error policy */ cupsd_policy_t *op_policy_ptr; /* Pointer to operation policy */ @@ -77,7 +80,8 @@ struct cupsd_printer_s char state_message[1024]; /* Printer state message */ int num_reasons; /* Number of printer-state-reasons */ char *reasons[64]; /* printer-state-reasons strings */ - time_t state_time; /* Time at this state */ + time_t config_time, /* Time at this configuration */ + state_time; /* Time at this state */ char *job_sheets[2]; /* Banners/job sheets */ cups_ptype_t type; /* Printer type (color, small, etc.) */ char *device_uri; /* Device URI */ @@ -166,7 +170,8 @@ extern int cupsdSetAuthInfoRequired(cupsd_printer_t *p, ipp_attribute_t *attr); extern void cupsdSetDeviceURI(cupsd_printer_t *p, const char *uri); extern void cupsdSetPrinterAttr(cupsd_printer_t *p, - const char *name, char *value); + const char *name, + const char *value); extern void cupsdSetPrinterAttrs(cupsd_printer_t *p); extern int cupsdSetPrinterReasons(cupsd_printer_t *p, const char *s); @@ -189,5 +194,5 @@ extern void cupsdWritePrintcap(void); /* - * End of "$Id: printers.h 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: printers.h 12666 2015-05-25 19:38:09Z msweet $". */ diff --git a/scheduler/process.c b/scheduler/process.c index a706ac2..19c7472 100644 --- a/scheduler/process.c +++ b/scheduler/process.c @@ -1,26 +1,16 @@ /* - * "$Id: process.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: process.c 12521 2015-02-17 20:00:17Z msweet $" * - * Process management routines for the CUPS scheduler. + * Process management routines for the CUPS scheduler. * - * Copyright 2007-2012 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. + * Copyright 2007-2015 by Apple Inc. + * Copyright 1997-2007 by Easy Software Products, all rights reserved. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * cupsdCreateProfile() - Create an execution profile for a subprocess. - * cupsdDestroyProfile() - Delete an execution profile. - * cupsdEndProcess() - End a process. - * cupsdFinishProcess() - Finish a process and get its name. - * cupsdStartProcess() - Start a process. - * compare_procs() - Compare two processes. - * cupsd_requote() - Make a regular-expression version of a string. + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -32,6 +22,19 @@ #ifdef __APPLE__ # include <libgen.h> #endif /* __APPLE__ */ +#ifdef HAVE_POSIX_SPAWN +# include <spawn.h> +extern char **environ; +#endif /* HAVE_POSIX_SPAWN */ +#ifdef HAVE_POSIX_SPAWN +# if !defined(__OpenBSD__) || OpenBSD >= 201505 +# define USE_POSIX_SPAWN 1 +# else +# define USE_POSIX_SPAWN 0 +# endif /* !__OpenBSD__ || */ +#else +# define USE_POSIX_SPAWN 0 +#endif /* HAVE_POSIX_SPAWN */ /* @@ -68,34 +71,37 @@ static char *cupsd_requote(char *dst, const char *src, size_t dstsize); */ void * /* O - Profile or NULL on error */ -cupsdCreateProfile(int job_id) /* I - Job ID or 0 for none */ +cupsdCreateProfile(int job_id, /* I - Job ID or 0 for none */ + int allow_networking)/* I - Allow networking off machine? */ { #ifdef HAVE_SANDBOX_H - cups_file_t *fp; /* File pointer */ - char profile[1024], /* File containing the profile */ - cache[1024], /* Quoted CacheDir */ - request[1024], /* Quoted RequestRoot */ - root[1024], /* Quoted ServerRoot */ - temp[1024]; /* Quoted TempDir */ - const char *nodebug; /* " (with no-log)" for no debug */ - - - if (!UseProfiles) + cups_file_t *fp; /* File pointer */ + char profile[1024], /* File containing the profile */ + bin[1024], /* Quoted ServerBin */ + cache[1024], /* Quoted CacheDir */ + domain[1024], /* Domain socket, if any */ + request[1024], /* Quoted RequestRoot */ + root[1024], /* Quoted ServerRoot */ + state[1024], /* Quoted StateDir */ + temp[1024]; /* Quoted TempDir */ + const char *nodebug; /* " (with no-log)" for no debug */ + cupsd_listener_t *lis; /* Current listening socket */ + + + if (!UseSandboxing || Sandboxing == CUPSD_SANDBOXING_OFF) { /* * Only use sandbox profiles as root... */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCreateProfile(job_id=%d) = NULL", - job_id); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCreateProfile(job_id=%d, allow_networking=%d) = NULL", job_id, allow_networking); return (NULL); } if ((fp = cupsTempFile2(profile, sizeof(profile))) == NULL) { - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCreateProfile(job_id=%d) = NULL", - job_id); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCreateProfile(job_id=%d, allow_networking=%d) = NULL", job_id, allow_networking); cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create security profile: %s", strerror(errno)); return (NULL); @@ -104,22 +110,29 @@ cupsdCreateProfile(int job_id) /* I - Job ID or 0 for none */ fchown(cupsFileNumber(fp), RunUser, Group); fchmod(cupsFileNumber(fp), 0640); + cupsd_requote(bin, ServerBin, sizeof(bin)); cupsd_requote(cache, CacheDir, sizeof(cache)); cupsd_requote(request, RequestRoot, sizeof(request)); cupsd_requote(root, ServerRoot, sizeof(root)); + cupsd_requote(state, StateDir, sizeof(state)); cupsd_requote(temp, TempDir, sizeof(temp)); nodebug = LogLevel < CUPSD_LOG_DEBUG ? " (with no-log)" : ""; cupsFilePuts(fp, "(version 1)\n"); - cupsFilePuts(fp, "(allow default)\n"); - cupsFilePrintf(fp, - "(deny file-write* file-read-data file-read-metadata\n" - " (regex" - " #\"^%s$\"" /* RequestRoot */ - " #\"^%s/\"" /* RequestRoot/... */ - ")%s)\n", - request, request, nodebug); + if (Sandboxing == CUPSD_SANDBOXING_STRICT) + cupsFilePuts(fp, "(deny default)\n"); + else + cupsFilePuts(fp, "(allow default)\n"); + if (LogLevel >= CUPSD_LOG_DEBUG) + cupsFilePuts(fp, "(debug deny)\n"); + cupsFilePuts(fp, "(import \"system.sb\")\n"); + cupsFilePuts(fp, "(system-network)\n"); + cupsFilePuts(fp, "(allow mach-per-user-lookup)\n"); + cupsFilePuts(fp, "(allow ipc-posix-sem)\n"); + cupsFilePuts(fp, "(allow ipc-posix-shm)\n"); + cupsFilePuts(fp, "(allow ipc-sysv-shm)\n"); + cupsFilePuts(fp, "(allow mach-lookup)\n"); if (!RunUser) cupsFilePrintf(fp, "(deny file-write* file-read-data file-read-metadata\n" @@ -142,13 +155,43 @@ cupsdCreateProfile(int job_id) /* I - Job ID or 0 for none */ " #\"^/System/\"" ")%s)\n", root, root, nodebug); - /* Specifically allow applications to stat RequestRoot */ + /* Specifically allow applications to stat RequestRoot and some other system folders */ cupsFilePrintf(fp, "(allow file-read-metadata\n" " (regex" + " #\"^/$\"" /* / */ + " #\"^/usr$\"" /* /usr */ + " #\"^/Library$\"" /* /Library */ + " #\"^/Library/Printers$\"" /* /Library/Printers */ " #\"^%s$\"" /* RequestRoot */ "))\n", request); + /* Read and write TempDir, CacheDir, and other common folders */ + cupsFilePuts(fp, + "(allow file-write* file-read-data file-read-metadata\n" + " (regex" + " #\"^/private/var/db/\"" + " #\"^/private/var/folders/\"" + " #\"^/private/var/lib/\"" + " #\"^/private/var/log/\"" + " #\"^/private/var/mysql/\"" + " #\"^/private/var/run/\"" + " #\"^/private/var/spool/\"" + " #\"^/Library/Application Support/\"" + " #\"^/Library/Caches/\"" + " #\"^/Library/Logs/\"" + " #\"^/Library/Preferences/\"" + " #\"^/Library/WebServer/\"" + " #\"^/Users/Shared/\"" + "))\n"); + cupsFilePrintf(fp, + "(deny file-write*\n" + " (regex #\"^%s$\")%s)\n", + request, nodebug); + cupsFilePrintf(fp, + "(deny file-write* file-read-data file-read-metadata\n" + " (regex #\"^%s/\")%s)\n", + request, nodebug); cupsFilePrintf(fp, "(allow file-write* file-read-data file-read-metadata\n" " (regex" @@ -156,56 +199,160 @@ cupsdCreateProfile(int job_id) /* I - Job ID or 0 for none */ " #\"^%s/\"" /* TempDir/... */ " #\"^%s$\"" /* CacheDir */ " #\"^%s/\"" /* CacheDir/... */ + " #\"^%s$\"" /* StateDir */ + " #\"^%s/\"" /* StateDir/... */ + "))\n", + temp, temp, cache, cache, state, state); + /* Read common folders */ + cupsFilePrintf(fp, + "(allow file-read-data file-read-metadata\n" + " (regex" + " #\"^/AppleInternal$\"" + " #\"^/AppleInternal/\"" + " #\"^/bin$\"" /* /bin */ + " #\"^/bin/\"" /* /bin/... */ + " #\"^/private$\"" + " #\"^/private/etc$\"" + " #\"^/private/etc/\"" + " #\"^/private/tmp$\"" + " #\"^/private/tmp/\"" + " #\"^/private/var$\"" + " #\"^/private/var/db$\"" + " #\"^/private/var/folders$\"" + " #\"^/private/var/lib$\"" + " #\"^/private/var/log$\"" + " #\"^/private/var/mysql$\"" + " #\"^/private/var/run$\"" + " #\"^/private/var/spool$\"" + " #\"^/private/var/tmp$\"" + " #\"^/private/var/tmp/\"" + " #\"^/usr/bin$\"" /* /usr/bin */ + " #\"^/usr/bin/\"" /* /usr/bin/... */ + " #\"^/usr/libexec/cups$\"" /* /usr/libexec/cups */ + " #\"^/usr/libexec/cups/\"" /* /usr/libexec/cups/... */ + " #\"^/usr/libexec/fax$\"" /* /usr/libexec/fax */ + " #\"^/usr/libexec/fax/\"" /* /usr/libexec/fax/... */ + " #\"^/usr/sbin$\"" /* /usr/sbin */ + " #\"^/usr/sbin/\"" /* /usr/sbin/... */ + " #\"^/Library$\"" /* /Library */ + " #\"^/Library/\"" /* /Library/... */ + " #\"^/System$\"" /* /System */ + " #\"^/System/\"" /* /System/... */ " #\"^%s/Library$\"" /* RequestRoot/Library */ " #\"^%s/Library/\"" /* RequestRoot/Library/... */ - " #\"^/Library/Application Support/\"" - " #\"^/Library/Caches/\"" - " #\"^/Library/Preferences/\"" - " #\"^/Library/Printers/.*/\"" - " #\"^/Users/Shared/\"" + " #\"^%s$\"" /* ServerBin */ + " #\"^%s/\"" /* ServerBin/... */ + " #\"^%s$\"" /* ServerRoot */ + " #\"^%s/\"" /* ServerRoot/... */ "))\n", - temp, temp, cache, cache, request, request); - cupsFilePrintf(fp, - "(deny file-write*\n" + request, request, bin, bin, root, root); + if (Sandboxing == CUPSD_SANDBOXING_RELAXED) + { + /* Limited write access to /Library/Printers/... */ + cupsFilePuts(fp, + "(allow file-write*\n" " (regex" - " #\"^/Library/Printers/PPDs$\"" - " #\"^/Library/Printers/PPDs/\"" - " #\"^/Library/Printers/PPD Plugins$\"" - " #\"^/Library/Printers/PPD Plugins/\"" - ")%s)\n", nodebug); - if (job_id) + " #\"^/Library/Printers/.*/\"" + "))\n"); + cupsFilePrintf(fp, + "(deny file-write*\n" + " (regex" + " #\"^/Library/Printers/PPDs$\"" + " #\"^/Library/Printers/PPDs/\"" + " #\"^/Library/Printers/PPD Plugins$\"" + " #\"^/Library/Printers/PPD Plugins/\"" + ")%s)\n", nodebug); + } + /* Allow execution of child processes as long as the programs are not in a user directory */ + cupsFilePuts(fp, "(allow process*)\n"); + cupsFilePuts(fp, "(deny process-exec (regex #\"^/Users/\"))\n"); + if (RunUser && getenv("CUPS_TESTROOT")) { - /* - * Allow job filters to read the spool file(s)... - */ + /* Allow source directory access in "make test" environment */ + char testroot[1024]; /* Root directory of test files */ + + cupsd_requote(testroot, getenv("CUPS_TESTROOT"), sizeof(testroot)); cupsFilePrintf(fp, + "(allow file-write* file-read-data file-read-metadata\n" + " (regex" + " #\"^%s$\"" /* CUPS_TESTROOT */ + " #\"^%s/\"" /* CUPS_TESTROOT/... */ + "))\n", + testroot, testroot); + cupsFilePrintf(fp, + "(allow process-exec\n" + " (regex" + " #\"^%s/\"" /* CUPS_TESTROOT/... */ + "))\n", + testroot); + cupsFilePrintf(fp, "(allow sysctl*)\n"); + } + if (job_id) + { + /* Allow job filters to read the current job files... */ + cupsFilePrintf(fp, "(allow file-read-data file-read-metadata\n" - " (regex #\"^%s/([ac]%05d|d%05d-[0-9][0-9][0-9])$\"))\n", + " (regex #\"^%s/([ac]%05d|d%05d-[0-9][0-9][0-9])$\"))\n", request, job_id, job_id); } else { - /* - * Allow email notifications from notifiers... - */ - + /* Allow email notifications from notifiers... */ cupsFilePuts(fp, "(allow process-exec\n" " (literal \"/usr/sbin/sendmail\")\n" - " (with no-sandbox)\n" - ")\n"); + " (with no-sandbox))\n"); + } + /* Allow access to Bluetooth, USB, and notify_post. */ + cupsFilePuts(fp, "(allow iokit*)\n"); + cupsFilePuts(fp, "(allow distributed-notification-post)\n"); + /* Allow outbound networking to local services */ + cupsFilePuts(fp, "(allow network-outbound" + "\n (regex #\"^/private/var/run/\" #\"^/private/tmp/\" #\"^/private/var/tmp/\")"); + for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); + lis; + lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) + { + if (httpAddrFamily(&(lis->address)) == AF_LOCAL) + { + httpAddrString(&(lis->address), domain, sizeof(domain)); + cupsFilePrintf(fp, "\n (literal \"%s\")", domain); + } + } + if (allow_networking) + { + /* Allow TCP and UDP networking off the machine... */ + cupsFilePuts(fp, "\n (remote tcp))\n"); + cupsFilePuts(fp, "(allow network-bind)\n"); /* for LPD resvport */ + cupsFilePuts(fp, "(allow network*\n" + " (local udp \"*:*\")\n" + " (remote udp \"*:*\"))\n"); + + /* Also allow access to device files... */ + cupsFilePuts(fp, "(allow file-write* file-read-data file-read-metadata file-ioctl\n" + " (regex #\"^/dev/\"))\n"); + + /* And allow kernel extensions to be loaded, e.g., SMB */ + cupsFilePuts(fp, "(allow system-kext-load)\n"); + } + else + { + /* Only allow SNMP (UDP) and LPD (TCP) off the machine... */ + cupsFilePuts(fp, ")\n"); + cupsFilePuts(fp, "(allow network-outbound\n" + " (remote udp \"*:161\")" + " (remote tcp \"*:515\"))\n"); + cupsFilePuts(fp, "(allow network-inbound\n" + " (local udp \"localhost:*\"))\n"); } - cupsFileClose(fp); - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCreateProfile(job_id=%d) = \"%s\"", - job_id, profile); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCreateProfile(job_id=%d,allow_networking=%d) = \"%s\"", job_id, allow_networking, profile); return ((void *)strdup(profile)); #else - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCreateProfile(job_id=%d) = NULL", - job_id); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCreateProfile(job_id=%d, allow_networking=%d) = NULL", job_id, allow_networking); return (NULL); #endif /* HAVE_SANDBOX_H */ @@ -268,10 +415,10 @@ cupsdEndProcess(int pid, /* I - Process ID */ */ const char * /* O - Process name */ -cupsdFinishProcess(int pid, /* I - Process ID */ - char *name, /* I - Name buffer */ - int namelen, /* I - Size of name buffer */ - int *job_id) /* O - Job ID pointer or NULL */ +cupsdFinishProcess(int pid, /* I - Process ID */ + char *name, /* I - Name buffer */ + size_t namelen, /* I - Size of name buffer */ + int *job_id) /* O - Job ID pointer or NULL */ { cupsd_proc_t key, /* Search key */ *proc; /* Matching process */ @@ -296,10 +443,7 @@ cupsdFinishProcess(int pid, /* I - Process ID */ strlcpy(name, "unknown", namelen); } - cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdFinishProcess(pid=%d, name=%p, namelen=%d, " - "job_id=%p(%d)) = \"%s\"", pid, name, namelen, job_id, - job_id ? *job_id : 0, name); + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFinishProcess(pid=%d, name=%p, namelen=" CUPS_LLFMT ", job_id=%p(%d)) = \"%s\"", pid, name, CUPS_LLCAST namelen, job_id, job_id ? *job_id : 0, name); return (name); } @@ -326,13 +470,20 @@ cupsdStartProcess( { int i; /* Looping var */ const char *exec_path = command; /* Command to be exec'd */ - char *real_argv[103], /* Real command-line arguments */ - cups_exec[1024]; /* Path to "cups-exec" program */ - int user; /* Command UID */ + char *real_argv[110], /* Real command-line arguments */ + cups_exec[1024], /* Path to "cups-exec" program */ + user_str[16], /* User string */ + group_str[16], /* Group string */ + nice_str[16]; /* FilterNice string */ + uid_t user; /* Command UID */ cupsd_proc_t *proc; /* New process record */ -#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) +#if USE_POSIX_SPAWN + posix_spawn_file_actions_t actions; /* Spawn file actions */ + posix_spawnattr_t attrs; /* Spawn attributes */ + sigset_t defsignals; /* Default signals */ +#elif defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) struct sigaction action; /* POSIX signal handler */ -#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ +#endif /* USE_POSIX_SPAWN */ #if defined(__APPLE__) char processPath[1024], /* CFProcessPath environment variable */ linkpath[1024]; /* Link path for symlinks... */ @@ -396,25 +547,107 @@ cupsdStartProcess( * Use helper program when we have a sandbox profile... */ +#if !USE_POSIX_SPAWN if (profile) +#endif /* !USE_POSIX_SPAWN */ { snprintf(cups_exec, sizeof(cups_exec), "%s/daemon/cups-exec", ServerBin); + snprintf(user_str, sizeof(user_str), "%d", user); + snprintf(group_str, sizeof(group_str), "%d", Group); + snprintf(nice_str, sizeof(nice_str), "%d", FilterNice); real_argv[0] = cups_exec; - real_argv[1] = profile; - real_argv[2] = (char *)command; + real_argv[1] = (char *)"-g"; + real_argv[2] = group_str; + real_argv[3] = (char *)"-n"; + real_argv[4] = nice_str; + real_argv[5] = (char *)"-u"; + real_argv[6] = user_str; + real_argv[7] = profile ? profile : "none"; + real_argv[8] = (char *)command; for (i = 0; - i < (int)(sizeof(real_argv) / sizeof(real_argv[0]) - 4) && argv[i]; + i < (int)(sizeof(real_argv) / sizeof(real_argv[0]) - 10) && argv[i]; i ++) - real_argv[i + 3] = argv[i]; + real_argv[i + 9] = argv[i]; - real_argv[i + 3] = NULL; + real_argv[i + 9] = NULL; argv = real_argv; exec_path = cups_exec; } + if (LogLevel == CUPSD_LOG_DEBUG2) + { + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess: Preparing to start \"%s\", arguments:", command); + + for (i = 0; argv[i]; i ++) + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess: argv[%d] = \"%s\"", i, argv[i]); + } + +#if USE_POSIX_SPAWN + /* + * Setup attributes and file actions for the spawn... + */ + + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess: Setting spawn attributes."); + sigemptyset(&defsignals); + sigaddset(&defsignals, SIGTERM); + sigaddset(&defsignals, SIGCHLD); + sigaddset(&defsignals, SIGPIPE); + + posix_spawnattr_init(&attrs); + posix_spawnattr_setflags(&attrs, POSIX_SPAWN_SETPGROUP | POSIX_SPAWN_SETSIGDEF); + posix_spawnattr_setpgroup(&attrs, 0); + posix_spawnattr_setsigdefault(&attrs, &defsignals); + + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess: Setting file actions."); + posix_spawn_file_actions_init(&actions); + if (infd != 0) + { + if (infd < 0) + posix_spawn_file_actions_addopen(&actions, 0, "/dev/null", O_RDONLY, 0); + else + posix_spawn_file_actions_adddup2(&actions, infd, 0); + } + + if (outfd != 1) + { + if (outfd < 0) + posix_spawn_file_actions_addopen(&actions, 1, "/dev/null", O_WRONLY, 0); + else + posix_spawn_file_actions_adddup2(&actions, outfd, 1); + } + + if (errfd != 2) + { + if (errfd < 0) + posix_spawn_file_actions_addopen(&actions, 2, "/dev/null", O_WRONLY, 0); + else + posix_spawn_file_actions_adddup2(&actions, errfd, 2); + } + + if (backfd != 3 && backfd >= 0) + posix_spawn_file_actions_adddup2(&actions, backfd, 3); + + if (sidefd != 4 && sidefd >= 0) + posix_spawn_file_actions_adddup2(&actions, sidefd, 4); + + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess: Calling posix_spawn."); + + if (posix_spawn(pid, exec_path, &actions, &attrs, argv, envp ? envp : environ)) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to fork %s - %s.", command, strerror(errno)); + + *pid = 0; + } + else + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess: pid=%d", (int)*pid); + + posix_spawn_file_actions_destroy(&actions); + posix_spawnattr_destroy(&attrs); + +#else /* * Block signals before forking... */ @@ -444,13 +677,13 @@ cupsdStartProcess( * processes it creates. */ -#ifdef HAVE_SETPGID +# ifdef HAVE_SETPGID if (!RunUser && setpgid(0, 0)) exit(errno + 100); -#else +# else if (!RunUser && setpgrp()) exit(errno + 100); -#endif /* HAVE_SETPGID */ +# endif /* HAVE_SETPGID */ /* * Update the remaining file descriptors as needed... @@ -529,11 +762,11 @@ cupsdStartProcess( * Unblock signals before doing the exec... */ -#ifdef HAVE_SIGSET +# ifdef HAVE_SIGSET sigset(SIGTERM, SIG_DFL); sigset(SIGCHLD, SIG_DFL); sigset(SIGPIPE, SIG_DFL); -#elif defined(HAVE_SIGACTION) +# elif defined(HAVE_SIGACTION) memset(&action, 0, sizeof(action)); sigemptyset(&action.sa_mask); @@ -542,11 +775,11 @@ cupsdStartProcess( sigaction(SIGTERM, &action, NULL); sigaction(SIGCHLD, &action, NULL); sigaction(SIGPIPE, &action, NULL); -#else +# else signal(SIGTERM, SIG_DFL); signal(SIGCHLD, SIG_DFL); signal(SIGPIPE, SIG_DFL); -#endif /* HAVE_SIGSET */ +# endif /* HAVE_SIGSET */ cupsdReleaseSignals(); @@ -573,7 +806,11 @@ cupsdStartProcess( *pid = 0; } - else + + cupsdReleaseSignals(); +#endif /* USE_POSIX_SPAWN */ + + if (*pid) { if (!process_array) process_array = cupsArrayNew((cups_array_func_t)compare_procs, NULL); @@ -591,8 +828,6 @@ cupsdStartProcess( } } - cupsdReleaseSignals(); - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess(command=\"%s\", argv=%p, envp=%p, " "infd=%d, outfd=%d, errfd=%d, backfd=%d, sidefd=%d, root=%d, " @@ -638,10 +873,13 @@ cupsd_requote(char *dst, /* I - Destination buffer */ { ch = *src++; + if (ch == '/' && !*src) + break; /* Don't add trailing slash */ + if (strchr(".?*()[]^$\\", ch)) *dstptr++ = '\\'; - *dstptr++ = ch; + *dstptr++ = (char)ch; } *dstptr = '\0'; @@ -652,5 +890,5 @@ cupsd_requote(char *dst, /* I - Destination buffer */ /* - * End of "$Id: process.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: process.c 12521 2015-02-17 20:00:17Z msweet $". */ diff --git a/scheduler/quotas.c b/scheduler/quotas.c index 3ebfd8d..ae8b88f 100644 --- a/scheduler/quotas.c +++ b/scheduler/quotas.c @@ -1,5 +1,5 @@ /* - * "$Id: quotas.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: quotas.c 10996 2013-05-29 11:51:34Z msweet $" * * Quota routines for the CUPS scheduler. * @@ -240,5 +240,5 @@ compare_quotas(const cupsd_quota_t *q1, /* I - First quota record */ /* - * End of "$Id: quotas.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: quotas.c 10996 2013-05-29 11:51:34Z msweet $". */ diff --git a/scheduler/select.c b/scheduler/select.c index e2f40d8..357cc40 100644 --- a/scheduler/select.c +++ b/scheduler/select.c @@ -1,28 +1,16 @@ /* - * "$Id: select.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: select.c 11594 2014-02-14 20:09:01Z msweet $" * - * Select abstraction functions for the CUPS scheduler. + * Select abstraction functions for the CUPS scheduler. * - * Copyright 2007-2010 by Apple Inc. - * Copyright 2006-2007 by Easy Software Products. + * Copyright 2007-2014 by Apple Inc. + * Copyright 2006-2007 by Easy Software Products. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * cupsdAddSelect() - Add a file descriptor to the list. - * cupsdDoSelect() - Do a select-like operation. - * cupsdIsSelecting() - Determine whether we are monitoring a file - * descriptor. - * cupsdRemoveSelect() - Remove a file descriptor from the list. - * cupsdStartSelect() - Initialize the file polling engine. - * cupsdStopSelect() - Shutdown the file polling engine. - * compare_fds() - Compare file descriptors. - * find_fd() - Find an existing file descriptor record. + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -39,8 +27,6 @@ # include <sys/time.h> #elif defined(HAVE_POLL) # include <poll.h> -#elif defined(__hpux) -# include <sys/time.h> #else # include <sys/select.h> #endif /* HAVE_EPOLL */ @@ -49,15 +35,14 @@ /* * Design Notes for Poll/Select API in CUPSD * ----------------------------------------- - * + * * SUPPORTED APIS - * + * * OS select poll epoll kqueue /dev/poll * -------------- ------ ------ ------ ------ --------- * AIX YES YES NO NO NO * FreeBSD YES YES NO YES NO * HP-UX YES YES NO NO NO - * IRIX YES YES NO NO NO * Linux YES YES YES NO NO * MacOS X YES YES NO YES NO * NetBSD YES YES NO YES NO @@ -65,22 +50,22 @@ * Solaris YES YES NO NO YES * Tru64 YES YES NO NO NO * Windows YES NO NO NO NO - * - * + * + * * HIGH-LEVEL API - * + * * typedef void (*cupsd_selfunc_t)(void *data); - * + * * void cupsdStartSelect(void); * void cupsdStopSelect(void); * void cupsdAddSelect(int fd, cupsd_selfunc_t read_cb, * cupsd_selfunc_t write_cb, void *data); * void cupsdRemoveSelect(int fd); * int cupsdDoSelect(int timeout); - * - * + * + * * IMPLEMENTATION STRATEGY - * + * * 0. Common Stuff * a. CUPS array of file descriptor to callback functions * and data + temporary array of removed fd's. @@ -103,7 +88,7 @@ * working sets. * d. cupsdStopSelect() frees all of the memory used by the * CUPS array and fd_set's. - * + * * 2. poll() - O(n log n) * a. Regular array of pollfd, sorted the same as the CUPS * array. @@ -117,7 +102,7 @@ * e. cupsdRemoveSelect() flags the pollfd array as invalid. * f. cupsdStopSelect() frees all of the memory used by the * CUPS array and pollfd array. - * + * * 3. epoll() - O(n) * a. cupsdStartSelect() creates epoll file descriptor using * epoll_create() with the maximum fd count, and @@ -133,7 +118,7 @@ * the callback record. * d. cupsdStopSelect() closes the epoll file descriptor and * frees all of the memory used by the event buffer. - * + * * 4. kqueue() - O(n) * b. cupsdStartSelect() creates kqueue file descriptor * using kqueue() function and allocates a global event @@ -146,7 +131,7 @@ * find the callback record. * e. cupsdStopSelect() closes the kqueue() file descriptor * and frees all of the memory used by the event buffer. - * + * * 5. /dev/poll - O(n log n) - NOT YET IMPLEMENTED * a. cupsdStartSelect() opens /dev/poll and allocates an * array of pollfd structs; on failure to open /dev/poll, @@ -533,15 +518,13 @@ cupsdDoSelect(long timeout) /* I - Timeout in seconds */ if (cupsd_pollfds) - pfd = realloc(cupsd_pollfds, allocfds * sizeof(struct pollfd)); + pfd = realloc(cupsd_pollfds, (size_t)allocfds * sizeof(struct pollfd)); else - pfd = malloc(allocfds * sizeof(struct pollfd)); + pfd = malloc((size_t)allocfds * sizeof(struct pollfd)); if (!pfd) { - cupsdLogMessage(CUPSD_LOG_EMERG, - "Unable to allocate %d bytes for polling!", - (int)(allocfds * sizeof(struct pollfd))); + cupsdLogMessage(CUPSD_LOG_EMERG, "Unable to allocate %d bytes for polling.", (int)((size_t)allocfds * sizeof(struct pollfd))); return (-1); } @@ -570,9 +553,9 @@ cupsdDoSelect(long timeout) /* I - Timeout in seconds */ } if (timeout >= 0 && timeout < 86400) - nfds = poll(cupsd_pollfds, count, timeout * 1000); + nfds = poll(cupsd_pollfds, (nfds_t)count, timeout * 1000); else - nfds = poll(cupsd_pollfds, count, -1); + nfds = poll(cupsd_pollfds, (nfds_t)count, -1); if (nfds > 0) { @@ -813,7 +796,7 @@ cupsdRemoveSelect(int fd) /* I - File descriptor */ void cupsdStartSelect(void) { - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartSelect()"); + cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdStartSelect()"); cupsd_fds = cupsArrayNew((cups_array_func_t)compare_fds, NULL); @@ -823,13 +806,13 @@ cupsdStartSelect(void) #ifdef HAVE_EPOLL cupsd_epoll_fd = epoll_create(MaxFDs); - cupsd_epoll_events = calloc(MaxFDs, sizeof(struct epoll_event)); + cupsd_epoll_events = calloc((size_t)MaxFDs, sizeof(struct epoll_event)); cupsd_update_pollfds = 0; #elif defined(HAVE_KQUEUE) cupsd_kqueue_fd = kqueue(); cupsd_kqueue_changes = 0; - cupsd_kqueue_events = calloc(MaxFDs, sizeof(struct kevent)); + cupsd_kqueue_events = calloc((size_t)MaxFDs, sizeof(struct kevent)); #elif defined(HAVE_POLL) cupsd_update_pollfds = 0; @@ -851,7 +834,7 @@ cupsdStopSelect(void) _cupsd_fd_t *fdptr; /* Current file descriptor */ - cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStopSelect()"); + cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdStopSelect()"); for (fdptr = (_cupsd_fd_t *)cupsArrayFirst(cupsd_fds); fdptr; @@ -947,5 +930,5 @@ find_fd(int fd) /* I - File descriptor */ /* - * End of "$Id: select.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: select.c 11594 2014-02-14 20:09:01Z msweet $". */ diff --git a/scheduler/server.c b/scheduler/server.c index 7e511c4..37001de 100644 --- a/scheduler/server.c +++ b/scheduler/server.c @@ -1,5 +1,5 @@ /* - * "$Id: server.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: server.c 12689 2015-06-03 19:49:54Z msweet $" * * Server start/stop routines for the CUPS scheduler. * @@ -54,7 +54,7 @@ cupsdStartServer(void) * Create the default security profile... */ - DefaultProfile = cupsdCreateProfile(0); + DefaultProfile = cupsdCreateProfile(0, 1); /* * Startup all the networking stuff... @@ -142,21 +142,24 @@ cupsdStopServer(void) if (AccessFile != NULL) { - cupsFileClose(AccessFile); + if (AccessFile != LogStderr) + cupsFileClose(AccessFile); AccessFile = NULL; } if (ErrorFile != NULL) { - cupsFileClose(ErrorFile); + if (ErrorFile != LogStderr) + cupsFileClose(ErrorFile); ErrorFile = NULL; } if (PageFile != NULL) { - cupsFileClose(PageFile); + if (PageFile != LogStderr) + cupsFileClose(PageFile); PageFile = NULL; } @@ -180,5 +183,5 @@ cupsdStopServer(void) /* - * End of "$Id: server.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: server.c 12689 2015-06-03 19:49:54Z msweet $". */ diff --git a/scheduler/statbuf.c b/scheduler/statbuf.c index 7f99149..b608b15 100644 --- a/scheduler/statbuf.c +++ b/scheduler/statbuf.c @@ -1,22 +1,16 @@ /* - * "$Id: statbuf.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: statbuf.c 11594 2014-02-14 20:09:01Z msweet $" * - * Status buffer routines for the CUPS scheduler. + * Status buffer routines for the CUPS scheduler. * - * Copyright 2007-2010 by Apple Inc. - * Copyright 1997-2006 by Easy Software Products, all rights reserved. + * Copyright 2007-2014 by Apple Inc. + * Copyright 1997-2006 by Easy Software Products, all rights reserved. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * cupsdStatBufDelete() - Destroy a status buffer. - * cupsdStatBufNew() - Create a new status buffer. - * cupsdStatBufUpdate() - Update the status buffer. + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -119,7 +113,7 @@ cupsdStatBufNew(int fd, /* I - File descriptor of pipe */ char * /* O - Line from buffer, "", or NULL */ cupsdStatBufUpdate( cupsd_statbuf_t *sb, /* I - Status buffer */ - int *loglevel, /* O - Log level */ + int *loglevel, /* O - Log level */ char *line, /* I - Line buffer */ int linelen) /* I - Size of line buffer */ { @@ -138,8 +132,7 @@ cupsdStatBufUpdate( * No, read more data... */ - if ((bytes = read(sb->fd, sb->buffer + sb->bufused, - CUPSD_SB_BUFFER_SIZE - sb->bufused - 1)) > 0) + if ((bytes = read(sb->fd, sb->buffer + sb->bufused, (size_t)(CUPSD_SB_BUFFER_SIZE - sb->bufused - 1))) > 0) { sb->bufused += bytes; sb->buffer[sb->bufused] = '\0'; @@ -258,6 +251,11 @@ cupsdStatBufUpdate( *loglevel = CUPSD_LOG_STATE; message = sb->buffer + 6; } + else if (!strncmp(sb->buffer, "JOBSTATE:", 9)) + { + *loglevel = CUPSD_LOG_JOBSTATE; + message = sb->buffer + 9; + } else if (!strncmp(sb->buffer, "ATTR:", 5)) { *loglevel = CUPSD_LOG_ATTR; @@ -307,7 +305,7 @@ cupsdStatBufUpdate( * Copy the message to the line buffer... */ - strlcpy(line, message, linelen); + strlcpy(line, message, (size_t)linelen); /* * Copy over the buffer data we've used up... @@ -326,5 +324,5 @@ cupsdStatBufUpdate( /* - * End of "$Id: statbuf.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: statbuf.c 11594 2014-02-14 20:09:01Z msweet $". */ diff --git a/scheduler/statbuf.h b/scheduler/statbuf.h index 91564d0..68bf206 100644 --- a/scheduler/statbuf.h +++ b/scheduler/statbuf.h @@ -1,5 +1,5 @@ /* - * "$Id: statbuf.h 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: statbuf.h 10996 2013-05-29 11:51:34Z msweet $" * * Status buffer definitions for the CUPS scheduler. * @@ -45,5 +45,5 @@ extern char *cupsdStatBufUpdate(cupsd_statbuf_t *sb, int *loglevel, /* - * End of "$Id: statbuf.h 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: statbuf.h 10996 2013-05-29 11:51:34Z msweet $". */ diff --git a/scheduler/subscriptions.c b/scheduler/subscriptions.c index 0b9c452..5d0e822 100644 --- a/scheduler/subscriptions.c +++ b/scheduler/subscriptions.c @@ -1,37 +1,16 @@ /* - * "$Id: subscriptions.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: subscriptions.c 12978 2015-11-17 19:29:52Z msweet $" * - * Subscription routines for the CUPS scheduler. + * Subscription routines for the CUPS scheduler. * - * Copyright 2007-2011 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. + * Copyright 2007-2014 by Apple Inc. + * Copyright 1997-2007 by Easy Software Products, all rights reserved. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * cupsdAddEvent() - Add an event to the global event cache. - * cupsdAddSubscription() - Add a new subscription object. - * cupsdDeleteAllSubscriptions() - Delete all subscriptions. - * cupsdDeleteSubscription() - Delete a subscription object. - * cupsdEventName() - Return a single event name. - * cupsdEventValue() - Return the event mask value for a name. - * cupsdExpireSubscriptions() - Expire old subscription objects. - * cupsdFindSubscription() - Find a subscription by ID. - * cupsdLoadAllSubscriptions() - Load all subscriptions from the .conf file. - * cupsdSaveAllSubscriptions() - Save all subscriptions to the .conf file. - * cupsdStopAllNotifiers() - Stop all notifier processes. - * cupsd_compare_subscriptions() - Compare two subscriptions. - * cupsd_delete_event() - Delete a single event... - * cupsd_send_dbus() - Send a DBUS notification... - * cupsd_send_notification() - Send a notification for the specified - * event. - * cupsd_start_notifier() - Start a notifier subprocess... - * cupsd_update_notifier() - Read messages from notifiers. + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -126,9 +105,7 @@ cupsdAddEvent( * Check if this subscription requires this event... */ - if ((sub->mask & event) != 0 && - (sub->dest == dest || !sub->dest) && - (sub->job == job || !sub->job)) + if ((sub->mask & event) != 0 && (sub->dest == dest || !sub->dest || sub->job == job)) { /* * Need this event, so create a new event record... @@ -212,7 +189,7 @@ cupsdAddEvent( (const char * const *)dest->reasons); ippAddBoolean(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, - "printer-is-accepting-jobs", dest->accepting); + "printer-is-accepting-jobs", (char)dest->accepting); } if (job) @@ -945,9 +922,9 @@ cupsdLoadAllSubscriptions(void) if (isxdigit(valueptr[0]) && isxdigit(valueptr[1])) { if (isdigit(valueptr[0])) - sub->user_data[i] = (valueptr[0] - '0') << 4; + sub->user_data[i] = (unsigned char)((valueptr[0] - '0') << 4); else - sub->user_data[i] = (tolower(valueptr[0]) - 'a' + 10) << 4; + sub->user_data[i] = (unsigned char)((tolower(valueptr[0]) - 'a' + 10) << 4); if (isdigit(valueptr[1])) sub->user_data[i] |= valueptr[1] - '0'; @@ -966,7 +943,7 @@ cupsdLoadAllSubscriptions(void) break; } else - sub->user_data[i] = *valueptr++; + sub->user_data[i] = (unsigned char)*valueptr++; } if (*valueptr) @@ -1638,5 +1615,5 @@ cupsd_update_notifier(void) /* - * End of "$Id: subscriptions.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: subscriptions.c 12978 2015-11-17 19:29:52Z msweet $". */ diff --git a/scheduler/subscriptions.h b/scheduler/subscriptions.h index 1a786ae..867a1c6 100644 --- a/scheduler/subscriptions.h +++ b/scheduler/subscriptions.h @@ -1,5 +1,5 @@ /* - * "$Id: subscriptions.h 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: subscriptions.h 10996 2013-05-29 11:51:34Z msweet $" * * Subscription definitions for the CUPS scheduler. * @@ -162,5 +162,5 @@ extern void cupsdStopAllNotifiers(void); /* - * End of "$Id: subscriptions.h 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: subscriptions.h 10996 2013-05-29 11:51:34Z msweet $". */ diff --git a/scheduler/sysman.c b/scheduler/sysman.c index d5f82c1..63b51a9 100644 --- a/scheduler/sysman.c +++ b/scheduler/sysman.c @@ -1,34 +1,16 @@ /* - * "$Id: sysman.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: sysman.c 12236 2014-11-03 04:08:41Z msweet $" * - * System management functions for the CUPS scheduler. + * System management functions for the CUPS scheduler. * - * Copyright 2007-2011 by Apple Inc. - * Copyright 2006 by Easy Software Products. + * Copyright 2007-2014 by Apple Inc. + * Copyright 2006 by Easy Software Products. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * cupsdCleanDirty() - Write dirty config and state files. - * cupsdMarkDirty() - Mark config or state files as needing a - * write. - * cupsdSetBusyState() - Let the system know when we are busy - * doing something. - * cupsdAllowSleep() - Tell the OS it is now OK to sleep. - * cupsdStartSystemMonitor() - Start monitoring for system change. - * cupsdStopSystemMonitor() - Stop monitoring for system change. - * sysEventThreadEntry() - A thread to receive power and computer - * name change notifications. - * sysEventPowerNotifier() - Handle power notification events. - * sysEventConfigurationNotifier() - Computer name changed notification - * callback. - * sysEventTimerNotifier() - Handle delayed event notifications. - * sysUpdate() - Update the current system state. + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ @@ -37,42 +19,28 @@ */ #include "cupsd.h" -#ifdef HAVE_VPROC_TRANSACTION_BEGIN -# include <vproc.h> -#endif /* HAVE_VPROC_TRANSACTION_BEGIN */ #ifdef __APPLE__ +# include <vproc.h> # include <IOKit/pwr_mgt/IOPMLib.h> -# ifdef HAVE_IOKIT_PWR_MGT_IOPMLIBPRIVATE_H -# include <IOKit/pwr_mgt/IOPMLibPrivate.h> -# endif /* HAVE_IOKIT_PWR_MGT_IOPMLIBPRIVATE_H */ #endif /* __APPLE__ */ /* * The system management functions cover disk and power management which - * are primarily used on portable computers. + * are primarily used for portable computers. * * Disk management involves delaying the write of certain configuration * and state files to minimize the number of times the disk has to spin - * up. + * up or flash to be written to. * - * Power management support is currently only implemented on MacOS X, but + * Power management support is currently only implemented on OS X, but * essentially we use four functions to let the OS know when it is OK to * put the system to sleep, typically when we are not in the middle of - * printing a job. - * - * Once put to sleep, we invalidate all remote printers since it is common - * to wake up in a new location/on a new wireless network. + * printing a job. And on OS X we can also "sleep print" - basically the + * system only wakes up long enough to service network requests and process + * print jobs. */ -/* - * Local globals... - */ - -#ifdef kIOPMAssertionTypeDenySystemSleep -static IOPMAssertionID dark_wake = 0; /* "Dark wake" assertion for sharing */ -#endif /* kIOPMAssertionTypeDenySystemSleep */ - /* * 'cupsdCleanDirty()' - Write dirty config and state files. @@ -162,9 +130,10 @@ cupsdSetBusyState(void) "Active clients and printing jobs", "Active clients, printing jobs, and dirty files" }; -#ifdef HAVE_VPROC_TRANSACTION_BEGIN +#ifdef __APPLE__ static vproc_transaction_t vtran = 0; /* Current busy transaction */ -#endif /* HAVE_VPROC_TRANSACTION_BEGIN */ + static IOPMAssertionID keep_awake = 0;/* Keep the system awake while printing */ +#endif /* __APPLE__ */ /* @@ -204,7 +173,7 @@ cupsdSetBusyState(void) { busy = newbusy; -#ifdef HAVE_VPROC_TRANSACTION_BEGIN +#ifdef __APPLE__ if (busy && !vtran) vtran = vproc_transaction_begin(NULL); else if (!busy && vtran) @@ -212,24 +181,25 @@ cupsdSetBusyState(void) vproc_transaction_end(NULL, vtran); vtran = 0; } -#endif /* HAVE_VPROC_TRANSACTION_BEGIN */ +#endif /* __APPLE__ */ } -#ifdef kIOPMAssertionTypeDenySystemSleep - if (cupsArrayCount(PrintingJobs) > 0 && !dark_wake) +#ifdef __APPLE__ + if (cupsArrayCount(PrintingJobs) > 0 && !keep_awake) { - cupsdLogMessage(CUPSD_LOG_DEBUG, "Asserting dark wake."); - IOPMAssertionCreateWithName(kIOPMAssertionTypeDenySystemSleep, + cupsdLogMessage(CUPSD_LOG_DEBUG, "Asserting NetworkClientActive."); + + IOPMAssertionCreateWithName(kIOPMAssertNetworkClientActive, kIOPMAssertionLevelOn, - CFSTR("org.cups.cupsd"), &dark_wake); + CFSTR("org.cups.cupsd"), &keep_awake); } - else if (cupsArrayCount(PrintingJobs) == 0 && dark_wake) + else if (cupsArrayCount(PrintingJobs) == 0 && keep_awake) { - cupsdLogMessage(CUPSD_LOG_DEBUG, "Releasing dark wake assertion."); - IOPMAssertionRelease(dark_wake); - dark_wake = 0; + cupsdLogMessage(CUPSD_LOG_DEBUG, "Releasing power assertion."); + IOPMAssertionRelease(keep_awake); + keep_awake = 0; } -#endif /* kIOPMAssertionTypeDenySystemSleep */ +#endif /* __APPLE__ */ } @@ -244,8 +214,10 @@ cupsdSetBusyState(void) * Include MacOS-specific headers... */ +# include <notify.h> # include <IOKit/IOKitLib.h> # include <IOKit/IOMessage.h> +# include <IOKit/ps/IOPowerSources.h> # include <IOKit/pwr_mgt/IOPMLib.h> # include <SystemConfiguration/SystemConfiguration.h> # include <pthread.h> @@ -310,6 +282,8 @@ static CFStringRef ComputerNameKey = NULL, NetworkInterfaceKeyIPv6 = NULL; /* Netowrk interface key */ static cupsd_sysevent_t LastSysEvent; /* Last system event (for delayed sleep) */ +static int NameChanged = 0;/* Did we get a 'name changed' event during sleep? */ +static int PSToken = 0; /* Power source notifications */ /* @@ -325,6 +299,7 @@ static void sysEventConfigurationNotifier(SCDynamicStoreRef store, void *context); static void sysEventTimerNotifier(CFRunLoopTimerRef timer, void *context); static void sysUpdate(void); +static void sysUpdateNames(void); /* @@ -336,6 +311,7 @@ cupsdAllowSleep(void) { cupsdCleanDirty(); + cupsdLogMessage(CUPSD_LOG_DEBUG, "Allowing system sleep."); IOAllowPowerChange(LastSysEvent.powerKernelPort, LastSysEvent.powerNotificationID); } @@ -351,6 +327,8 @@ cupsdStartSystemMonitor(void) int flags; /* fcntl flags on pipe */ + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartSystemMonitor()"); + if (cupsdOpenPipe(SysEventPipes)) { cupsdLogMessage(CUPSD_LOG_ERROR, "System event monitor pipe() failed - %s!", @@ -375,6 +353,15 @@ cupsdStartSystemMonitor(void) pthread_mutex_init(&SysEventThreadMutex, NULL); pthread_cond_init(&SysEventThreadCond, NULL); pthread_create(&SysEventThread, NULL, (void *(*)())sysEventThreadEntry, NULL); + + /* + * Monitor for power source changes via dispatch queue... + */ + + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartSystemMonitor: IOPSGetTimeRemainingEstimate=%f", IOPSGetTimeRemainingEstimate()); + ACPower = IOPSGetTimeRemainingEstimate() == kIOPSTimeRemainingUnlimited; + notify_register_dispatch(kIOPSNotifyPowerSource, &PSToken, dispatch_get_main_queue(), ^(int t) { (void)t; + ACPower = IOPSGetTimeRemainingEstimate() == kIOPSTimeRemainingUnlimited; }); } @@ -388,6 +375,8 @@ cupsdStopSystemMonitor(void) CFRunLoopRef rl; /* The event handler runloop */ + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStopSystemMonitor()"); + if (SysEventThread) { /* @@ -418,6 +407,12 @@ cupsdStopSystemMonitor(void) cupsdRemoveSelect(SysEventPipes[0]); cupsdClosePipe(SysEventPipes); } + + if (PSToken != 0) + { + notify_cancel(PSToken); + PSToken = 0; + } } @@ -658,18 +653,19 @@ sysEventPowerNotifier( switch (messageType) { - case kIOMessageCanSystemPowerOff: - case kIOMessageCanSystemSleep: + case kIOMessageCanSystemPowerOff : + case kIOMessageCanSystemSleep : threadData->sysevent.event |= SYSEVENT_CANSLEEP; break; - case kIOMessageSystemWillRestart: - case kIOMessageSystemWillPowerOff: - case kIOMessageSystemWillSleep: + case kIOMessageSystemWillRestart : + case kIOMessageSystemWillPowerOff : + case kIOMessageSystemWillSleep : threadData->sysevent.event |= SYSEVENT_WILLSLEEP; + threadData->sysevent.event &= ~SYSEVENT_WOKE; break; - case kIOMessageSystemHasPoweredOn: + case kIOMessageSystemHasPoweredOn : /* * Because powered on is followed by a net-changed event, delay * before sending it. @@ -679,16 +675,62 @@ sysEventPowerNotifier( threadData->sysevent.event |= SYSEVENT_WOKE; break; - case kIOMessageSystemWillNotPowerOff: - case kIOMessageSystemWillNotSleep: + case kIOMessageSystemWillNotPowerOff : + case kIOMessageSystemWillNotSleep : # ifdef kIOMessageSystemWillPowerOn - case kIOMessageSystemWillPowerOn: + case kIOMessageSystemWillPowerOn : # endif /* kIOMessageSystemWillPowerOn */ default: sendit = 0; break; } + switch (messageType) + { + case kIOMessageCanSystemPowerOff : + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Got kIOMessageCanSystemPowerOff message."); + break; + case kIOMessageCanSystemSleep : + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Got kIOMessageCannSystemSleep message."); + break; + case kIOMessageSystemWillRestart : + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Got kIOMessageSystemWillRestart message."); + break; + case kIOMessageSystemWillPowerOff : + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Got kIOMessageSystemWillPowerOff message."); + break; + case kIOMessageSystemWillSleep : + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Got kIOMessageSystemWillSleep message."); + break; + case kIOMessageSystemHasPoweredOn : + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Got kIOMessageSystemHasPoweredOn message."); + break; + case kIOMessageSystemWillNotPowerOff : + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Got kIOMessageSystemWillNotPowerOff message."); + break; + case kIOMessageSystemWillNotSleep : + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Got kIOMessageSystemWillNotSleep message."); + break; +# ifdef kIOMessageSystemWillPowerOn + case kIOMessageSystemWillPowerOn : + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Got kIOMessageSystemWillPowerOn message."); + break; +# endif /* kIOMessageSystemWillPowerOn */ + default: + cupsdLogMessage(CUPSD_LOG_DEBUG, "Got unknown power message %d.", + (int)messageType); + break; + } + if (sendit == 0) IOAllowPowerChange(threadData->sysevent.powerKernelPort, (long)messageArgument); @@ -816,8 +858,9 @@ sysUpdate(void) { /* * If there are active printers that don't have the connecting-to-device - * printer-state-reason then cancel the sleep request (i.e. this reason - * indicates a job that is not yet connected to the printer)... + * or cups-waiting-for-job-completed printer-state-reason then cancel the + * sleep request, i.e., these reasons indicate a job that is not actively + * doing anything... */ for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); @@ -827,7 +870,8 @@ sysUpdate(void) if (p->job) { for (i = 0; i < p->num_reasons; i ++) - if (!strcmp(p->reasons[i], "connecting-to-device")) + if (!strcmp(p->reasons[i], "connecting-to-device") || + !strcmp(p->reasons[i], "cups-waiting-for-job-completed")) break; if (!p->num_reasons || i >= p->num_reasons) @@ -838,14 +882,14 @@ sysUpdate(void) if (p) { cupsdLogMessage(CUPSD_LOG_INFO, - "System sleep canceled because printer %s is active", + "System sleep canceled because printer %s is active.", p->name); IOCancelPowerChange(sysevent.powerKernelPort, sysevent.powerNotificationID); } else { - cupsdLogMessage(CUPSD_LOG_DEBUG, "System wants to sleep"); + cupsdLogMessage(CUPSD_LOG_DEBUG, "System wants to sleep."); IOAllowPowerChange(sysevent.powerKernelPort, sysevent.powerNotificationID); } @@ -853,50 +897,30 @@ sysUpdate(void) if (sysevent.event & SYSEVENT_WILLSLEEP) { - cupsdLogMessage(CUPSD_LOG_DEBUG, "System going to sleep"); + cupsdLogMessage(CUPSD_LOG_DEBUG, "System going to sleep."); Sleeping = 1; - for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); - p; - p = (cupsd_printer_t *)cupsArrayNext(Printers)) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Deregistering local printer \"%s\"", p->name); - cupsdDeregisterPrinter(p, 0); - } - cupsdCleanDirty(); -#ifdef kIOPMAssertionTypeDenySystemSleep - /* - * Remove our assertion as needed since the user wants the system to - * sleep (different than idle sleep)... - */ - - if (dark_wake) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, "Releasing dark wake assertion."); - IOPMAssertionRelease(dark_wake); - dark_wake = 0; - } -#endif /* kIOPMAssertionTypeDenySystemSleep */ - /* * If we have no printing jobs, allow the power change immediately. - * Otherwise set the SleepJobs time to 15 seconds in the future when + * Otherwise set the SleepJobs time to 10 seconds in the future when * we'll take more drastic measures... */ if (cupsArrayCount(PrintingJobs) == 0) + { + cupsdLogMessage(CUPSD_LOG_DEBUG, "Allowing system sleep."); IOAllowPowerChange(sysevent.powerKernelPort, sysevent.powerNotificationID); + } else { /* * If there are active printers that don't have the connecting-to-device - * printer-state-reason then delay the sleep request (i.e. this reason - * indicates a job that is not yet connected to the printer)... + * or cups-waiting-for-job-completed printer-state-reasons then delay the + * sleep request, i.e., these reasons indicate a job is active... */ for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); @@ -906,7 +930,8 @@ sysUpdate(void) if (p->job) { for (i = 0; i < p->num_reasons; i ++) - if (!strcmp(p->reasons[i], "connecting-to-device")) + if (!strcmp(p->reasons[i], "connecting-to-device") || + !strcmp(p->reasons[i], "cups-waiting-for-job-completed")) break; if (!p->num_reasons || i >= p->num_reasons) @@ -916,11 +941,16 @@ sysUpdate(void) if (p) { + cupsdLogMessage(CUPSD_LOG_INFO, + "System sleep delayed because printer %s is active.", + p->name); + LastSysEvent = sysevent; SleepJobs = time(NULL) + 10; } else { + cupsdLogMessage(CUPSD_LOG_DEBUG, "Allowing system sleep."); IOAllowPowerChange(sysevent.powerKernelPort, sysevent.powerNotificationID); } @@ -929,78 +959,118 @@ sysUpdate(void) if (sysevent.event & SYSEVENT_WOKE) { - cupsdLogMessage(CUPSD_LOG_DEBUG, "System woke from sleep"); + cupsdLogMessage(CUPSD_LOG_DEBUG, "System woke from sleep."); IOAllowPowerChange(sysevent.powerKernelPort, sysevent.powerNotificationID); Sleeping = 0; -#ifdef kIOPMAssertionTypeDenySystemSleep - if (cupsArrayCount(PrintingJobs) > 0 && !dark_wake) + /* + * Make sure jobs that were queued prior to the system going to sleep don't + * get canceled right away... + */ + + if (MaxJobTime > 0) { - cupsdLogMessage(CUPSD_LOG_DEBUG, "Asserting dark wake."); - IOPMAssertionCreateWithName(kIOPMAssertionTypeDenySystemSleep, - kIOPMAssertionLevelOn, - CFSTR("org.cups.cupsd"), &dark_wake); + cupsd_job_t *job; /* Current job */ + + for (job = (cupsd_job_t *)cupsArrayFirst(ActiveJobs); + job; + job = (cupsd_job_t *)cupsArrayNext(ActiveJobs)) + { + if (job->cancel_time) + { + ipp_attribute_t *cancel_after = ippFindAttribute(job->attrs, + "job-cancel-after", + IPP_TAG_INTEGER); + + if (cancel_after) + job->cancel_time = time(NULL) + ippGetInteger(cancel_after, 0); + else + job->cancel_time = time(NULL) + MaxJobTime; + } + } } -#endif /* kIOPMAssertionTypeDenySystemSleep */ + + if (NameChanged) + sysUpdateNames(); cupsdCheckJobs(); } if (sysevent.event & SYSEVENT_NETCHANGED) { - if (!Sleeping) + if (Sleeping) cupsdLogMessage(CUPSD_LOG_DEBUG, - "System network configuration changed"); + "System network configuration changed - " + "ignored while sleeping."); else cupsdLogMessage(CUPSD_LOG_DEBUG, - "System network configuration changed; " - "ignored while sleeping"); + "System network configuration changed."); } if (sysevent.event & SYSEVENT_NAMECHANGED) { - if (!Sleeping) + if (Sleeping) + { + NameChanged = 1; + + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Computer name or BTMM domains changed - ignored while " + "sleeping."); + } + else { cupsdLogMessage(CUPSD_LOG_DEBUG, - "Computer name or BTMM domains changed"); + "Computer name or BTMM domains changed."); - /* - * De-register the individual printers... - */ + sysUpdateNames(); + } + } + } +} - for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); - p; - p = (cupsd_printer_t *)cupsArrayNext(Printers)) - cupsdDeregisterPrinter(p, 1); + +/* + * 'sysUpdateNames()' - Update computer and/or BTMM domains. + */ + +static void +sysUpdateNames(void) +{ + cupsd_printer_t *p; /* Current printer */ + + + NameChanged = 0; + + /* + * De-register the individual printers... + */ + + for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); + p; + p = (cupsd_printer_t *)cupsArrayNext(Printers)) + cupsdDeregisterPrinter(p, 1); # if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) - /* - * Update the computer name and BTMM domain list... - */ + /* + * Update the computer name and BTMM domain list... + */ - cupsdUpdateDNSSDName(); + cupsdUpdateDNSSDName(); # endif /* HAVE_DNSSD || HAVE_AVAHI */ - /* - * Now re-register them... - */ + /* + * Now re-register them... + */ - for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); - p; - p = (cupsd_printer_t *)cupsArrayNext(Printers)) - cupsdRegisterPrinter(p); - } - else - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Computer name or BTMM domains changed; ignored while " - "sleeping"); - } - } + for (p = (cupsd_printer_t *)cupsArrayFirst(Printers); + p; + p = (cupsd_printer_t *)cupsArrayNext(Printers)) + cupsdRegisterPrinter(p); } #endif /* __APPLE__ */ /* - * End of "$Id: sysman.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: sysman.c 12236 2014-11-03 04:08:41Z msweet $". */ diff --git a/scheduler/sysman.h b/scheduler/sysman.h index d603178..9da386d 100644 --- a/scheduler/sysman.h +++ b/scheduler/sysman.h @@ -1,16 +1,16 @@ /* - * "$Id: sysman.h 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: sysman.h 12140 2014-08-30 01:51:22Z msweet $" * - * System management definitions for the CUPS scheduler. + * System management definitions for the CUPS scheduler. * - * Copyright 2007-2011 by Apple Inc. - * Copyright 2006 by Easy Software Products. + * Copyright 2007-2014 by Apple Inc. + * Copyright 2006 by Easy Software Products. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -35,7 +35,9 @@ VAR int DirtyFiles VALUE(CUPSD_DIRTY_NONE), /* How often do we write dirty files? */ VAR time_t DirtyCleanTime VALUE(0); /* When to clean dirty files next */ -VAR int Sleeping VALUE(0); +VAR int ACPower VALUE(-1), + /* Is the system on AC power? */ + Sleeping VALUE(0); /* Non-zero if machine is entering or * * in a sleep state... */ VAR time_t SleepJobs VALUE(0); @@ -60,5 +62,5 @@ extern void cupsdStopSystemMonitor(void); /* - * End of "$Id: sysman.h 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: sysman.h 12140 2014-08-30 01:51:22Z msweet $". */ diff --git a/scheduler/testlpd.c b/scheduler/testlpd.c index 3ff483e..a614ec4 100644 --- a/scheduler/testlpd.c +++ b/scheduler/testlpd.c @@ -1,27 +1,16 @@ /* - * "$Id: testlpd.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: testlpd.c 12644 2015-05-19 21:22:35Z msweet $" * - * cups-lpd test program for CUPS. + * cups-lpd test program for CUPS. * - * Copyright 2007-2010 by Apple Inc. - * Copyright 2006 by Easy Software Products, all rights reserved. + * Copyright 2007-2015 by Apple Inc. + * Copyright 2006 by Easy Software Products, all rights reserved. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * main() - Simulate an LPD client. - * do_command() - Send the LPD command and wait for a response. - * print_job() - Submit a file for printing. - * print_waiting() - Print waiting jobs. - * remove_job() - Cancel a print job. - * status_long() - Show the long printer status. - * status_short() - Show the short printer status. - * usage() - Show program usage... + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -42,11 +31,11 @@ */ static int do_command(int outfd, int infd, const char *command); -static int print_job(int outfd, int infd, char *dest, char **args); +static int print_job(int outfd, int infd, char *dest, char **args) __attribute__((nonnull(4))); static int print_waiting(int outfd, int infd, char *dest); -static int remove_job(int outfd, int infd, char *dest, char **args); -static int status_long(int outfd, int infd, char *dest, char **args); -static int status_short(int outfd, int infd, char *dest, char **args); +static int remove_job(int outfd, int infd, char *dest, char **args) __attribute__((nonnull(4))); +static int status_long(int outfd, int infd, char *dest, char **args) __attribute__((nonnull(4))); +static int status_short(int outfd, int infd, char *dest, char **args) __attribute__((nonnull(4))); static void usage(void) __attribute__((noreturn)); @@ -76,7 +65,7 @@ main(int argc, /* I - Number of command-line arguments */ */ op = NULL; - opargs = NULL; + opargs = argv + argc; dest = NULL; cupslpd_argc = 1; cupslpd_argv[0] = (char *)"cups-lpd"; @@ -210,15 +199,15 @@ do_command(int outfd, /* I - Command file descriptor */ int infd, /* I - Response file descriptor */ const char *command) /* I - Command line to send */ { - int len; /* Length of command line */ - char status; /* Status byte */ + size_t len; /* Length of command line */ + char status; /* Status byte */ printf("COMMAND: %02X %s", command[0], command + 1); len = strlen(command); - if (write(outfd, command, len) < len) + if ((size_t)write(outfd, command, len) < len) { puts(" Write failed!"); return (-1); @@ -251,7 +240,7 @@ print_job(int outfd, /* I - Command file descriptor */ struct stat fileinfo; /* File information */ char *jobname; /* Job name */ int sequence; /* Sequence number */ - int bytes; /* Bytes read/written */ + ssize_t bytes; /* Bytes read/written */ /* @@ -305,10 +294,10 @@ print_job(int outfd, /* I - Command file descriptor */ * Send the control file... */ - bytes = strlen(control); + bytes = (ssize_t)strlen(control); snprintf(command, sizeof(command), "\002%d cfA%03dlocalhost\n", - bytes, sequence); + (int)bytes, sequence); if ((status = do_command(outfd, infd, command)) != 0) { @@ -318,14 +307,14 @@ print_job(int outfd, /* I - Command file descriptor */ bytes ++; - if (write(outfd, control, bytes) < bytes) + if (write(outfd, control, (size_t)bytes) < bytes) { - printf("CONTROL: Unable to write %d bytes!\n", bytes); + printf("CONTROL: Unable to write %d bytes!\n", (int)bytes); close(fd); return (-1); } - printf("CONTROL: Wrote %d bytes.\n", bytes); + printf("CONTROL: Wrote %d bytes.\n", (int)bytes); if (read(infd, command, 1) < 1) { @@ -355,9 +344,9 @@ print_job(int outfd, /* I - Command file descriptor */ while ((bytes = read(fd, buffer, sizeof(buffer))) > 0) { - if (write(outfd, buffer, bytes) < bytes) + if (write(outfd, buffer, (size_t)bytes) < bytes) { - printf("DATA: Unable to write %d bytes!\n", bytes); + printf("DATA: Unable to write %d bytes!\n", (int)bytes); close(fd); return (-1); } @@ -451,21 +440,21 @@ status_long(int outfd, /* I - Command file descriptor */ { char command[1024], /* Command buffer */ buffer[8192]; /* Status buffer */ - int bytes; /* Bytes read/written */ + ssize_t bytes; /* Bytes read/written */ /* * Send the "send short status" command... */ - if (args) + if (args[0]) snprintf(command, sizeof(command), "\004%s %s\n", dest, args[0]); else snprintf(command, sizeof(command), "\004%s\n", dest); - bytes = strlen(command); + bytes = (ssize_t)strlen(command); - if (write(outfd, command, bytes) < bytes) + if (write(outfd, command, (size_t)bytes) < bytes) return (-1); /* @@ -474,7 +463,7 @@ status_long(int outfd, /* I - Command file descriptor */ while ((bytes = read(infd, buffer, sizeof(buffer))) > 0) { - fwrite(buffer, 1, bytes, stdout); + fwrite(buffer, 1, (size_t)bytes, stdout); fflush(stdout); } @@ -494,21 +483,21 @@ status_short(int outfd, /* I - Command file descriptor */ { char command[1024], /* Command buffer */ buffer[8192]; /* Status buffer */ - int bytes; /* Bytes read/written */ + ssize_t bytes; /* Bytes read/written */ /* * Send the "send short status" command... */ - if (args) + if (args[0]) snprintf(command, sizeof(command), "\003%s %s\n", dest, args[0]); else snprintf(command, sizeof(command), "\003%s\n", dest); - bytes = strlen(command); + bytes = (ssize_t)strlen(command); - if (write(outfd, command, bytes) < bytes) + if (write(outfd, command, (size_t)bytes) < bytes) return (-1); /* @@ -517,7 +506,7 @@ status_short(int outfd, /* I - Command file descriptor */ while ((bytes = read(infd, buffer, sizeof(buffer))) > 0) { - fwrite(buffer, 1, bytes, stdout); + fwrite(buffer, 1, (size_t)bytes, stdout); fflush(stdout); } @@ -546,5 +535,5 @@ usage(void) /* - * End of "$Id: testlpd.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: testlpd.c 12644 2015-05-19 21:22:35Z msweet $". */ diff --git a/scheduler/testmime.c b/scheduler/testmime.c index 5a71ea9..0271309 100644 --- a/scheduler/testmime.c +++ b/scheduler/testmime.c @@ -1,24 +1,16 @@ /* - * "$Id: testmime.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: testmime.c 11558 2014-02-06 18:33:34Z msweet $" * - * MIME test program for CUPS. + * MIME test program for CUPS. * - * Copyright 2007-2013 by Apple Inc. - * Copyright 1997-2006 by Easy Software Products, all rights reserved. + * Copyright 2007-2014 by Apple Inc. + * Copyright 1997-2006 by Easy Software Products, all rights reserved. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * main() - Main entry for the test program. - * add_ppd_filter() - Add a printer filter from a PPD. - * add_ppd_filters() - Add all filters from a PPD. - * print_rules() - Print the rules for a file type... - * type_dir() - Show the MIME types for a given directory. + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -135,7 +127,7 @@ main(int argc, /* I - Number of command-line args */ sscanf(argv[i], "%15[^/]/%255s", super, type); dst = mimeType(mime, super, type); - filters = mimeFilter2(mime, src, srcinfo.st_size, dst, &cost); + filters = mimeFilter2(mime, src, (size_t)srcinfo.st_size, dst, &cost); if (!filters) { @@ -264,7 +256,7 @@ add_ppd_filter(mime_t *mime, /* I - MIME database */ { char *ptr; /* Pointer into maxsize(nnnn) program */ - maxsize = strtoll(program + 8, &ptr, 10); + maxsize = (size_t)strtoll(program + 8, &ptr, 10); if (*ptr != ')') { @@ -527,5 +519,5 @@ type_dir(mime_t *mime, /* I - MIME database */ /* - * End of "$Id: testmime.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: testmime.c 11558 2014-02-06 18:33:34Z msweet $". */ diff --git a/scheduler/testspeed.c b/scheduler/testspeed.c index 425f471..9b443cb 100644 --- a/scheduler/testspeed.c +++ b/scheduler/testspeed.c @@ -1,23 +1,16 @@ /* - * "$Id: testspeed.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: testspeed.c 11558 2014-02-06 18:33:34Z msweet $" * - * Scheduler speed test for CUPS. + * Scheduler speed test for CUPS. * - * Copyright 2007-2010 by Apple Inc. - * Copyright 1997-2005 by Easy Software Products. + * Copyright 2007-2014 by Apple Inc. + * Copyright 1997-2005 by Easy Software Products. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * main() - Send multiple IPP requests and report on the average response - * time. - * do_test() - Run a test on a specific host... - * usage() - Show program usage... + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -39,7 +32,7 @@ static int do_test(const char *server, int port, http_encryption_t encryption, int requests, - int verbose); + const char *opstring, int verbose); static void usage(void) __attribute__((noreturn)); @@ -66,6 +59,7 @@ main(int argc, /* I - Number of command-line arguments */ end; /* End time */ double elapsed; /* Elapsed time */ int verbose; /* Verbosity */ + const char *opstring; /* Operation name */ /* @@ -78,6 +72,7 @@ main(int argc, /* I - Number of command-line arguments */ port = ippPort(); encryption = HTTP_ENCRYPT_IF_REQUESTED; verbose = 0; + opstring = NULL; for (i = 1; i < argc; i ++) if (argv[i][0] == '-') @@ -85,6 +80,10 @@ main(int argc, /* I - Number of command-line arguments */ for (ptr = argv[i] + 1; *ptr; ptr ++) switch (*ptr) { + case 'E' : /* Enable encryption */ + encryption = HTTP_ENCRYPT_REQUIRED; + break; + case 'c' : /* Number of children */ i ++; if (i >= argc) @@ -93,16 +92,20 @@ main(int argc, /* I - Number of command-line arguments */ children = atoi(argv[i]); break; - case 'r' : /* Number of requests */ + case 'o' : /* Operation */ i ++; if (i >= argc) usage(); - requests = atoi(argv[i]); + opstring = argv[i]; break; - case 'E' : /* Enable encryption */ - encryption = HTTP_ENCRYPT_REQUIRED; + case 'r' : /* Number of requests */ + i ++; + if (i >= argc) + usage(); + + requests = atoi(argv[i]); break; case 'v' : /* Verbose logging */ @@ -139,9 +142,10 @@ main(int argc, /* I - Number of command-line arguments */ start = time(NULL); if (children < 1) - return (do_test(server, port, encryption, requests, verbose)); + return (do_test(server, port, encryption, requests, opstring, verbose)); else if (children == 1) - good_children = do_test(server, port, encryption, requests, verbose) ? 0 : 1; + good_children = do_test(server, port, encryption, requests, opstring, + verbose) ? 0 : 1; else { char options[255], /* Command-line options for child */ @@ -174,7 +178,12 @@ main(int argc, /* I - Number of command-line arguments */ * Child goes here... */ - execlp(argv[0], argv[0], options, "0", reqstr, serverstr, (char *)NULL); + if (opstring) + execlp(argv[0], argv[0], options, "0", reqstr, "-o", opstring, + serverstr, (char *)NULL); + else + execlp(argv[0], argv[0], options, "0", reqstr, serverstr, (char *)NULL); + exit(errno); } else if (pid < 0) @@ -237,6 +246,7 @@ do_test(const char *server, /* I - Server to use */ int port, /* I - Port number to use */ http_encryption_t encryption, /* I - Encryption to use */ int requests, /* I - Number of requests to send */ + const char *opstring, /* I - Operation string */ int verbose) /* I - Verbose output? */ { int i; /* Looping var */ @@ -247,9 +257,10 @@ do_test(const char *server, /* I - Server to use */ double reqtime, /* Time for this request */ elapsed; /* Elapsed time */ int op; /* Current operation */ - static ipp_op_t ops[4] = /* Operations to test... */ + static ipp_op_t ops[5] = /* Operations to test... */ { IPP_PRINT_JOB, + CUPS_GET_DEFAULT, CUPS_GET_PRINTERS, CUPS_GET_CLASSES, IPP_GET_JOBS @@ -282,7 +293,11 @@ do_test(const char *server, /* I - Server to use */ * In addition, IPP_GET_JOBS needs a printer-uri attribute. */ - op = ops[i & 3]; + if (opstring) + op = ippOpValue(opstring); + else + op = ops[i % (int)(sizeof(ops) / sizeof(ops[0]))]; + request = ippNewRequest(op); gettimeofday(&start, NULL); @@ -353,13 +368,13 @@ do_test(const char *server, /* I - Server to use */ static void usage(void) { - puts("Usage: testspeed [-c children] [-h] [-r requests] [-v] [-E] " - "hostname[:port]"); + puts("Usage: testspeed [-c children] [-h] [-o operation] [-r requests] [-v] " + "[-E] hostname[:port]"); exit(0); } /* - * End of "$Id: testspeed.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: testspeed.c 11558 2014-02-06 18:33:34Z msweet $". */ diff --git a/scheduler/testsub.c b/scheduler/testsub.c index 66801af..97a3a83 100644 --- a/scheduler/testsub.c +++ b/scheduler/testsub.c @@ -1,23 +1,16 @@ /* - * "$Id: testsub.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: testsub.c 11889 2014-05-22 13:54:15Z msweet $" * - * Scheduler notification tester for CUPS. + * Scheduler notification tester for CUPS. * - * Copyright 2007-2012 by Apple Inc. - * Copyright 2006-2007 by Easy Software Products. + * Copyright 2007-2014 by Apple Inc. + * Copyright 2006-2007 by Easy Software Products. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * main() - Subscribe to the . - * print_attributes() - Print the attributes in a request... - * sigterm_handler() - Flag when the user hits CTRL-C... - * usage() - Show program usage... + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -251,7 +244,7 @@ main(int argc, /* I - Number of command-line arguments */ interval = 5; ippDelete(response); - sleep(interval); + sleep((unsigned)interval); } /* @@ -435,17 +428,10 @@ print_attributes(ipp_t *ipp, /* I - IPP request */ case IPP_TAG_DATE : { - time_t vtime; /* Date/Time value */ - struct tm *vdate; /* Date info */ char vstring[256]; /* Formatted time */ for (i = 0, val = attr->values; i < attr->num_values; i ++, val ++) - { - vtime = ippDateToTime(val->date); - vdate = localtime(&vtime); - strftime(vstring, sizeof(vstring), "%c", vdate); - printf(" (%s)", vstring); - } + printf(" (%s)", _cupsStrDate(vstring, sizeof(vstring), ippDateToTime(val->date))); } putchar('\n'); break; @@ -519,5 +505,5 @@ usage(void) /* - * End of "$Id: testsub.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: testsub.c 11889 2014-05-22 13:54:15Z msweet $". */ diff --git a/scheduler/tls-darwin.c b/scheduler/tls-darwin.c deleted file mode 100644 index bb6998b..0000000 --- a/scheduler/tls-darwin.c +++ /dev/null @@ -1,570 +0,0 @@ -/* - * "$Id: tls-darwin.c 11173 2013-07-23 12:31:34Z msweet $" - * - * TLS support code for the CUPS scheduler on OS X. - * - * Copyright 2007-2012 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. - * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * cupsdEndTLS() - Shutdown a secure session with the client. - * cupsdStartTLS() - Start a secure session with the client. - * copy_cdsa_certificate() - Copy a SSL/TLS certificate from the System - * keychain. - * make_certificate() - Make a self-signed SSL/TLS certificate. - */ - - -/* - * Local functions... - */ - -static CFArrayRef copy_cdsa_certificate(cupsd_client_t *con); -static int make_certificate(cupsd_client_t *con); - - -/* - * 'cupsdEndTLS()' - Shutdown a secure session with the client. - */ - -int /* O - 1 on success, 0 on error */ -cupsdEndTLS(cupsd_client_t *con) /* I - Client connection */ -{ - while (SSLClose(con->http.tls) == errSSLWouldBlock) - usleep(1000); - - SSLDisposeContext(con->http.tls); - con->http.tls = NULL; - - if (con->http.tls_credentials) - CFRelease(con->http.tls_credentials); - - return (1); -} - - -/* - * 'cupsdStartTLS()' - Start a secure session with the client. - */ - -int /* O - 1 on success, 0 on error */ -cupsdStartTLS(cupsd_client_t *con) /* I - Client connection */ -{ - OSStatus error = 0; /* Error code */ - CFArrayRef peerCerts; /* Peer certificates */ - - - cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] Encrypting connection.", - con->http.fd); - - con->http.tls_credentials = copy_cdsa_certificate(con); - - if (!con->http.tls_credentials) - { - /* - * No keychain (yet), make a self-signed certificate... - */ - - if (make_certificate(con)) - con->http.tls_credentials = copy_cdsa_certificate(con); - } - - if (!con->http.tls_credentials) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Could not find signing key in keychain \"%s\"", - ServerCertificate); - error = errSSLBadConfiguration; - } - - if (!error) - error = SSLNewContext(true, &con->http.tls); - - if (!error) - error = SSLSetIOFuncs(con->http.tls, _httpReadCDSA, _httpWriteCDSA); - - if (!error) - error = SSLSetConnection(con->http.tls, HTTP(con)); - - if (!error) - error = SSLSetAllowsExpiredCerts(con->http.tls, true); - - if (!error) - error = SSLSetAllowsAnyRoot(con->http.tls, true); - - if (!error) - error = SSLSetCertificate(con->http.tls, con->http.tls_credentials); - - if (!error) - { - /* - * Perform SSL/TLS handshake - */ - - while ((error = SSLHandshake(con->http.tls)) == errSSLWouldBlock) - usleep(1000); - } - - if (error) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to encrypt connection from %s - %s (%d)", - con->http.hostname, cssmErrorString(error), (int)error); - - con->http.error = error; - con->http.status = HTTP_ERROR; - - if (con->http.tls) - { - SSLDisposeContext(con->http.tls); - con->http.tls = NULL; - } - - if (con->http.tls_credentials) - { - CFRelease(con->http.tls_credentials); - con->http.tls_credentials = NULL; - } - - return (0); - } - - cupsdLogMessage(CUPSD_LOG_DEBUG, "Connection from %s now encrypted.", - con->http.hostname); - - if (!SSLCopyPeerCertificates(con->http.tls, &peerCerts) && peerCerts) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, "Received %d peer certificates!", - (int)CFArrayGetCount(peerCerts)); - CFRelease(peerCerts); - } - else - cupsdLogMessage(CUPSD_LOG_DEBUG, "Received NO peer certificates!"); - - return (1); -} - - -/* - * 'copy_cdsa_certificate()' - Copy a SSL/TLS certificate from the System - * keychain. - */ - -static CFArrayRef /* O - Array of certificates */ -copy_cdsa_certificate( - cupsd_client_t *con) /* I - Client connection */ -{ - OSStatus err; /* Error info */ - SecKeychainRef keychain = NULL;/* Keychain reference */ - SecIdentitySearchRef search = NULL; /* Search reference */ - SecIdentityRef identity = NULL;/* Identity */ - CFArrayRef certificates = NULL; - /* Certificate array */ -# if HAVE_SECPOLICYCREATESSL - SecPolicyRef policy = NULL; /* Policy ref */ - CFStringRef servername = NULL; - /* Server name */ - CFMutableDictionaryRef query = NULL; /* Query qualifiers */ - CFArrayRef list = NULL; /* Keychain list */ -# if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) - char localname[1024];/* Local hostname */ -# endif /* HAVE_DNSSD || HAVE_AVAHI */ -# elif defined(HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY) - SecPolicyRef policy = NULL; /* Policy ref */ - SecPolicySearchRef policy_search = NULL; - /* Policy search ref */ - CSSM_DATA options; /* Policy options */ - CSSM_APPLE_TP_SSL_OPTIONS - ssl_options; /* SSL Option for hostname */ - char localname[1024];/* Local hostname */ -# endif /* HAVE_SECPOLICYCREATESSL */ - - - cupsdLogMessage(CUPSD_LOG_DEBUG, - "copy_cdsa_certificate: Looking for certs for \"%s\"...", - con->servername); - - if ((err = SecKeychainOpen(ServerCertificate, &keychain))) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot open keychain \"%s\" - %s (%d)", - ServerCertificate, cssmErrorString(err), (int)err); - goto cleanup; - } - -# if HAVE_SECPOLICYCREATESSL - servername = CFStringCreateWithCString(kCFAllocatorDefault, con->servername, - kCFStringEncodingUTF8); - - policy = SecPolicyCreateSSL(1, servername); - - if (servername) - CFRelease(servername); - - if (!policy) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create ssl policy reference"); - goto cleanup; - } - - if (!(query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks))) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create query dictionary"); - goto cleanup; - } - - list = CFArrayCreate(kCFAllocatorDefault, (const void **)&keychain, 1, - &kCFTypeArrayCallBacks); - - CFDictionaryAddValue(query, kSecClass, kSecClassIdentity); - CFDictionaryAddValue(query, kSecMatchPolicy, policy); - CFDictionaryAddValue(query, kSecReturnRef, kCFBooleanTrue); - CFDictionaryAddValue(query, kSecMatchLimit, kSecMatchLimitOne); - CFDictionaryAddValue(query, kSecMatchSearchList, list); - - CFRelease(list); - - err = SecItemCopyMatching(query, (CFTypeRef *)&identity); - -# if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) - if (err && DNSSDHostName) - { - /* - * Search for the connection server name failed; try the DNS-SD .local - * hostname instead... - */ - - snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName); - - cupsdLogMessage(CUPSD_LOG_DEBUG, - "copy_cdsa_certificate: Looking for certs for \"%s\"...", - localname); - - servername = CFStringCreateWithCString(kCFAllocatorDefault, localname, - kCFStringEncodingUTF8); - - CFRelease(policy); - - policy = SecPolicyCreateSSL(1, servername); - - if (servername) - CFRelease(servername); - - if (!policy) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create ssl policy reference"); - goto cleanup; - } - - CFDictionarySetValue(query, kSecMatchPolicy, policy); - - err = SecItemCopyMatching(query, (CFTypeRef *)&identity); - } -# endif /* HAVE_DNSSD || HAVE_AVAHI */ - - if (err) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Cannot find signing key in keychain \"%s\": %s (%d)", - ServerCertificate, cssmErrorString(err), (int)err); - goto cleanup; - } - -# elif defined(HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY) - /* - * Use a policy to search for valid certificates whose common name matches the - * servername... - */ - - if (SecPolicySearchCreate(CSSM_CERT_X_509v3, &CSSMOID_APPLE_TP_SSL, - NULL, &policy_search)) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create a policy search reference"); - goto cleanup; - } - - if (SecPolicySearchCopyNext(policy_search, &policy)) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Cannot find a policy to use for searching"); - goto cleanup; - } - - memset(&ssl_options, 0, sizeof(ssl_options)); - ssl_options.Version = CSSM_APPLE_TP_SSL_OPTS_VERSION; - ssl_options.ServerName = con->servername; - ssl_options.ServerNameLen = strlen(con->servername); - - options.Data = (uint8 *)&ssl_options; - options.Length = sizeof(ssl_options); - - if (SecPolicySetValue(policy, &options)) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Cannot set policy value to use for searching"); - goto cleanup; - } - - if ((err = SecIdentitySearchCreateWithPolicy(policy, NULL, CSSM_KEYUSE_SIGN, - keychain, FALSE, &search))) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Cannot create identity search reference: %s (%d)", - cssmErrorString(err), (int)err); - goto cleanup; - } - - err = SecIdentitySearchCopyNext(search, &identity); - -# if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) - if (err && DNSSDHostName) - { - /* - * Search for the connection server name failed; try the DNS-SD .local - * hostname instead... - */ - - snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName); - - ssl_options.ServerName = localname; - ssl_options.ServerNameLen = strlen(localname); - - cupsdLogMessage(CUPSD_LOG_DEBUG, - "copy_cdsa_certificate: Looking for certs for \"%s\"...", - localname); - - if (SecPolicySetValue(policy, &options)) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Cannot set policy value to use for searching"); - goto cleanup; - } - - CFRelease(search); - search = NULL; - if ((err = SecIdentitySearchCreateWithPolicy(policy, NULL, CSSM_KEYUSE_SIGN, - keychain, FALSE, &search))) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Cannot create identity search reference: %s (%d)", - cssmErrorString(err), (int)err); - goto cleanup; - } - - err = SecIdentitySearchCopyNext(search, &identity); - - } -# endif /* HAVE_DNSSD || HAVE_AVAHI */ - - if (err) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Cannot find signing key in keychain \"%s\": %s (%d)", - ServerCertificate, cssmErrorString(err), (int)err); - goto cleanup; - } - -# else - /* - * Assume there is exactly one SecIdentity in the keychain... - */ - - if ((err = SecIdentitySearchCreate(keychain, CSSM_KEYUSE_SIGN, &search))) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Cannot create identity search reference (%d)", (int)err); - goto cleanup; - } - - if ((err = SecIdentitySearchCopyNext(search, &identity))) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Cannot find signing key in keychain \"%s\": %s (%d)", - ServerCertificate, cssmErrorString(err), (int)err); - goto cleanup; - } -# endif /* HAVE_SECPOLICYCREATESSL */ - - if (CFGetTypeID(identity) != SecIdentityGetTypeID()) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "SecIdentity CFTypeID failure!"); - goto cleanup; - } - - if ((certificates = CFArrayCreate(NULL, (const void **)&identity, - 1, &kCFTypeArrayCallBacks)) == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create certificate array"); - goto cleanup; - } - - cleanup : - - if (keychain) - CFRelease(keychain); - if (search) - CFRelease(search); - if (identity) - CFRelease(identity); - -# if HAVE_SECPOLICYCREATESSL - if (policy) - CFRelease(policy); - if (query) - CFRelease(query); -# elif defined(HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY) - if (policy) - CFRelease(policy); - if (policy_search) - CFRelease(policy_search); -# endif /* HAVE_SECPOLICYCREATESSL */ - - return (certificates); -} - - -/* - * 'make_certificate()' - Make a self-signed SSL/TLS certificate. - */ - -static int /* O - 1 on success, 0 on failure */ -make_certificate(cupsd_client_t *con) /* I - Client connection */ -{ - int pid, /* Process ID of command */ - status; /* Status of command */ - char command[1024], /* Command */ - *argv[4], /* Command-line arguments */ - *envp[MAX_ENV + 1], /* Environment variables */ - keychain[1024], /* Keychain argument */ - infofile[1024], /* Type-in information for cert */ -# if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) - localname[1024], /* Local hostname */ -# endif /* HAVE_DNSSD || HAVE_AVAHI */ - *servername; /* Name of server in cert */ - cups_file_t *fp; /* Seed/info file */ - int infofd; /* Info file descriptor */ - - -# if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) - if (con->servername && isdigit(con->servername[0] & 255) && DNSSDHostName) - { - snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName); - servername = localname; - } - else -# endif /* HAVE_DNSSD || HAVE_AVAHI */ - servername = con->servername; - - /* - * Run the "certtool" command to generate a self-signed certificate... - */ - - if (!cupsFileFind("certtool", getenv("PATH"), 1, command, sizeof(command))) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "No SSL certificate and certtool command not found!"); - return (0); - } - - /* - * Create a file with the certificate information fields... - * - * Note: This assumes that the default questions are asked by the certtool - * command... - */ - - if ((fp = cupsTempFile2(infofile, sizeof(infofile))) == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to create certificate information file %s - %s", - infofile, strerror(errno)); - return (0); - } - - cupsFilePrintf(fp, - "%s\n" /* Enter key and certificate label */ - "r\n" /* Generate RSA key pair */ - "2048\n" /* Key size in bits */ - "y\n" /* OK (y = yes) */ - "b\n" /* Usage (b=signing/encryption) */ - "s\n" /* Sign with SHA1 */ - "y\n" /* OK (y = yes) */ - "%s\n" /* Common name */ - "\n" /* Country (default) */ - "\n" /* Organization (default) */ - "\n" /* Organizational unit (default) */ - "\n" /* State/Province (default) */ - "%s\n" /* Email address */ - "y\n", /* OK (y = yes) */ - servername, servername, ServerAdmin); - cupsFileClose(fp); - - cupsdLogMessage(CUPSD_LOG_INFO, - "Generating SSL server key and certificate..."); - - snprintf(keychain, sizeof(keychain), "k=%s", ServerCertificate); - - argv[0] = "certtool"; - argv[1] = "c"; - argv[2] = keychain; - argv[3] = NULL; - - cupsdLoadEnv(envp, MAX_ENV); - - infofd = open(infofile, O_RDONLY); - - if (!cupsdStartProcess(command, argv, envp, infofd, -1, -1, -1, -1, 1, NULL, - NULL, &pid)) - { - close(infofd); - unlink(infofile); - return (0); - } - - close(infofd); - unlink(infofile); - - while (waitpid(pid, &status, 0) < 0) - if (errno != EINTR) - { - status = 1; - break; - } - - cupsdFinishProcess(pid, command, sizeof(command), NULL); - - if (status) - { - if (WIFEXITED(status)) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to create SSL server key and certificate - " - "the certtool command stopped with status %d!", - WEXITSTATUS(status)); - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to create SSL server key and certificate - " - "the certtool command crashed on signal %d!", - WTERMSIG(status)); - } - else - { - cupsdLogMessage(CUPSD_LOG_INFO, - "Created SSL server certificate file \"%s\"...", - ServerCertificate); - } - - return (!status); -} - - -/* - * End of "$Id: tls-darwin.c 11173 2013-07-23 12:31:34Z msweet $". - */ diff --git a/scheduler/tls-gnutls.c b/scheduler/tls-gnutls.c deleted file mode 100644 index c2d7032..0000000 --- a/scheduler/tls-gnutls.c +++ /dev/null @@ -1,292 +0,0 @@ -/* - * "$Id: tls-gnutls.c 11173 2013-07-23 12:31:34Z msweet $" - * - * TLS support code for the CUPS scheduler using GNU TLS. - * - * Copyright 2007-2012 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. - * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * cupsdEndTLS() - Shutdown a secure session with the client. - * cupsdStartTLS() - Start a secure session with the client. - * make_certificate() - Make a self-signed SSL/TLS certificate. - */ - - -/* - * Local functions... - */ - -static int make_certificate(cupsd_client_t *con); - - -/* - * 'cupsdEndTLS()' - Shutdown a secure session with the client. - */ - -int /* O - 1 on success, 0 on error */ -cupsdEndTLS(cupsd_client_t *con) /* I - Client connection */ -{ - int error; /* Error code */ - gnutls_certificate_server_credentials *credentials; - /* TLS credentials */ - - - credentials = (gnutls_certificate_server_credentials *) - (con->http.tls_credentials); - - error = gnutls_bye(con->http.tls, GNUTLS_SHUT_WR); - switch (error) - { - case GNUTLS_E_SUCCESS: - cupsdLogMessage(CUPSD_LOG_DEBUG, - "SSL shutdown successful!"); - break; - default: - cupsdLogMessage(CUPSD_LOG_ERROR, - "SSL shutdown failed: %s", gnutls_strerror(error)); - break; - } - - gnutls_deinit(con->http.tls); - con->http.tls = NULL; - - gnutls_certificate_free_credentials(*credentials); - free(credentials); - - return (1); -} - - -/* - * 'cupsdStartTLS()' - Start a secure session with the client. - */ - -int /* O - 1 on success, 0 on error */ -cupsdStartTLS(cupsd_client_t *con) /* I - Client connection */ -{ - int status; /* Error code */ - gnutls_certificate_server_credentials *credentials; - /* TLS credentials */ - - - cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] Encrypting connection.", - con->http.fd); - - /* - * Verify that we have a certificate... - */ - - if (access(ServerKey, 0) || access(ServerCertificate, 0)) - { - /* - * Nope, make a self-signed certificate... - */ - - if (!make_certificate(con)) - return (0); - } - - /* - * Create the SSL object and perform the SSL handshake... - */ - - credentials = (gnutls_certificate_server_credentials *) - malloc(sizeof(gnutls_certificate_server_credentials)); - if (credentials == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to encrypt connection from %s - %s", - con->http.hostname, strerror(errno)); - - return (0); - } - - gnutls_certificate_allocate_credentials(credentials); - gnutls_certificate_set_x509_key_file(*credentials, ServerCertificate, - ServerKey, GNUTLS_X509_FMT_PEM); - - gnutls_init(&con->http.tls, GNUTLS_SERVER); - gnutls_set_default_priority(con->http.tls); - - gnutls_credentials_set(con->http.tls, GNUTLS_CRD_CERTIFICATE, *credentials); - gnutls_transport_set_ptr(con->http.tls, (gnutls_transport_ptr)HTTP(con)); - gnutls_transport_set_pull_function(con->http.tls, _httpReadGNUTLS); - gnutls_transport_set_push_function(con->http.tls, _httpWriteGNUTLS); - - while ((status = gnutls_handshake(con->http.tls)) != GNUTLS_E_SUCCESS) - { - if (gnutls_error_is_fatal(status)) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to encrypt connection from %s - %s", - con->http.hostname, gnutls_strerror(status)); - - gnutls_deinit(con->http.tls); - gnutls_certificate_free_credentials(*credentials); - con->http.tls = NULL; - free(credentials); - return (0); - } - } - - cupsdLogMessage(CUPSD_LOG_DEBUG, "Connection from %s now encrypted.", - con->http.hostname); - - con->http.tls_credentials = credentials; - return (1); -} - - -/* - * 'make_certificate()' - Make a self-signed SSL/TLS certificate. - */ - -static int /* O - 1 on success, 0 on failure */ -make_certificate(cupsd_client_t *con) /* I - Client connection */ -{ - gnutls_x509_crt crt; /* Self-signed certificate */ - gnutls_x509_privkey key; /* Encryption key */ - cups_lang_t *language; /* Default language info */ - cups_file_t *fp; /* Key/cert file */ - unsigned char buffer[8192]; /* Buffer for x509 data */ - size_t bytes; /* Number of bytes of data */ - unsigned char serial[4]; /* Serial number buffer */ - time_t curtime; /* Current time */ - int result; /* Result of GNU TLS calls */ - - - /* - * Create the encryption key... - */ - - cupsdLogMessage(CUPSD_LOG_INFO, "Generating SSL server key..."); - - gnutls_x509_privkey_init(&key); - gnutls_x509_privkey_generate(key, GNUTLS_PK_RSA, 2048, 0); - - /* - * Save it... - */ - - bytes = sizeof(buffer); - - if ((result = gnutls_x509_privkey_export(key, GNUTLS_X509_FMT_PEM, - buffer, &bytes)) < 0) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to export SSL server key - %s", - gnutls_strerror(result)); - gnutls_x509_privkey_deinit(key); - return (0); - } - else if ((fp = cupsFileOpen(ServerKey, "w")) != NULL) - { - cupsFileWrite(fp, (char *)buffer, bytes); - cupsFileClose(fp); - - cupsdLogMessage(CUPSD_LOG_INFO, "Created SSL server key file \"%s\"...", - ServerKey); - } - else - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to create SSL server key file \"%s\" - %s", - ServerKey, strerror(errno)); - gnutls_x509_privkey_deinit(key); - return (0); - } - - /* - * Create the self-signed certificate... - */ - - cupsdLogMessage(CUPSD_LOG_INFO, "Generating self-signed SSL certificate..."); - - language = cupsLangDefault(); - curtime = time(NULL); - serial[0] = curtime >> 24; - serial[1] = curtime >> 16; - serial[2] = curtime >> 8; - serial[3] = curtime; - - gnutls_x509_crt_init(&crt); - if (strlen(language->language) == 5) - gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COUNTRY_NAME, 0, - language->language + 3, 2); - else - gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COUNTRY_NAME, 0, - "US", 2); - gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COMMON_NAME, 0, - ServerName, strlen(ServerName)); - gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_ORGANIZATION_NAME, 0, - ServerName, strlen(ServerName)); - gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME, - 0, "Unknown", 7); - gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0, - "Unknown", 7); - gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_LOCALITY_NAME, 0, - "Unknown", 7); - gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_PKCS9_EMAIL, 0, - ServerAdmin, strlen(ServerAdmin)); - gnutls_x509_crt_set_key(crt, key); - gnutls_x509_crt_set_serial(crt, serial, sizeof(serial)); - gnutls_x509_crt_set_activation_time(crt, curtime); - gnutls_x509_crt_set_expiration_time(crt, curtime + 10 * 365 * 86400); - gnutls_x509_crt_set_ca_status(crt, 0); - gnutls_x509_crt_set_subject_alternative_name(crt, GNUTLS_SAN_DNSNAME, - ServerName); - gnutls_x509_crt_set_key_purpose_oid(crt, GNUTLS_KP_TLS_WWW_SERVER, 0); - gnutls_x509_crt_set_key_usage(crt, GNUTLS_KEY_KEY_ENCIPHERMENT); - gnutls_x509_crt_set_version(crt, 3); - - bytes = sizeof(buffer); - if (gnutls_x509_crt_get_key_id(crt, 0, buffer, &bytes) >= 0) - gnutls_x509_crt_set_subject_key_id(crt, buffer, bytes); - - gnutls_x509_crt_sign(crt, crt, key); - - /* - * Save it... - */ - - bytes = sizeof(buffer); - if ((result = gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_PEM, - buffer, &bytes)) < 0) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to export SSL server certificate - %s", - gnutls_strerror(result)); - else if ((fp = cupsFileOpen(ServerCertificate, "w")) != NULL) - { - cupsFileWrite(fp, (char *)buffer, bytes); - cupsFileClose(fp); - - cupsdLogMessage(CUPSD_LOG_INFO, - "Created SSL server certificate file \"%s\"...", - ServerCertificate); - } - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to create SSL server certificate file \"%s\" - %s", - ServerCertificate, strerror(errno)); - - /* - * Cleanup... - */ - - gnutls_x509_crt_deinit(crt); - gnutls_x509_privkey_deinit(key); - - return (1); -} - - -/* - * End of "$Id: tls-gnutls.c 11173 2013-07-23 12:31:34Z msweet $". - */ diff --git a/scheduler/tls-openssl.c b/scheduler/tls-openssl.c deleted file mode 100644 index f123d28..0000000 --- a/scheduler/tls-openssl.c +++ /dev/null @@ -1,353 +0,0 @@ -/* - * "$Id: tls-openssl.c 11173 2013-07-23 12:31:34Z msweet $" - * - * TLS support code for the CUPS scheduler using OpenSSL. - * - * Copyright 2007-2012 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. - * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * cupsdEndTLS() - Shutdown a secure session with the client. - * cupsdStartTLS() - Start a secure session with the client. - * make_certificate() - Make a self-signed SSL/TLS certificate. - */ - - -/* - * Local functions... - */ - -static int make_certificate(cupsd_client_t *con); - - -/* - * 'cupsdEndTLS()' - Shutdown a secure session with the client. - */ - -int /* O - 1 on success, 0 on error */ -cupsdEndTLS(cupsd_client_t *con) /* I - Client connection */ -{ - SSL_CTX *context; /* Context for encryption */ - unsigned long error; /* Error code */ - int status; /* Return status */ - - - context = SSL_get_SSL_CTX(con->http.tls); - - switch (SSL_shutdown(con->http.tls)) - { - case 1 : - cupsdLogMessage(CUPSD_LOG_DEBUG, - "SSL shutdown successful!"); - status = 1; - break; - - case -1 : - cupsdLogMessage(CUPSD_LOG_ERROR, - "Fatal error during SSL shutdown!"); - - default : - while ((error = ERR_get_error()) != 0) - cupsdLogMessage(CUPSD_LOG_ERROR, "SSL shutdown failed: %s", - ERR_error_string(error, NULL)); - status = 0; - break; - } - - SSL_CTX_free(context); - SSL_free(con->http.tls); - con->http.tls = NULL; - - return (status); -} - - -/* - * 'cupsdStartTLS()' - Start a secure session with the client. - */ - -int /* O - 1 on success, 0 on error */ -cupsdStartTLS(cupsd_client_t *con) /* I - Client connection */ -{ - SSL_CTX *context; /* Context for encryption */ - BIO *bio; /* BIO data */ - unsigned long error; /* Error code */ - - - cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] Encrypting connection.", - con->http.fd); - - /* - * Verify that we have a certificate... - */ - - if (access(ServerKey, 0) || access(ServerCertificate, 0)) - { - /* - * Nope, make a self-signed certificate... - */ - - if (!make_certificate(con)) - return (0); - } - - /* - * Create the SSL context and accept the connection... - */ - - context = SSL_CTX_new(SSLv23_server_method()); - - SSL_CTX_set_options(context, SSL_OP_NO_SSLv2); /* Only use SSLv3 or TLS */ - if (SSLOptions & CUPSD_SSL_NOEMPTY) - SSL_CTX_set_options(context, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); - SSL_CTX_use_PrivateKey_file(context, ServerKey, SSL_FILETYPE_PEM); - SSL_CTX_use_certificate_chain_file(context, ServerCertificate); - - bio = BIO_new(_httpBIOMethods()); - BIO_ctrl(bio, BIO_C_SET_FILE_PTR, 0, (char *)HTTP(con)); - - con->http.tls = SSL_new(context); - SSL_set_bio(con->http.tls, bio, bio); - - if (SSL_accept(con->http.tls) != 1) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to encrypt connection from %s.", - con->http.hostname); - - while ((error = ERR_get_error()) != 0) - cupsdLogMessage(CUPSD_LOG_ERROR, "%s", ERR_error_string(error, NULL)); - - SSL_CTX_free(context); - SSL_free(con->http.tls); - con->http.tls = NULL; - return (0); - } - - cupsdLogMessage(CUPSD_LOG_DEBUG, "Connection from %s now encrypted.", - con->http.hostname); - - return (1); -} - - -/* - * 'make_certificate()' - Make a self-signed SSL/TLS certificate. - */ - -static int /* O - 1 on success, 0 on failure */ -make_certificate(cupsd_client_t *con) /* I - Client connection */ -{ -#ifdef HAVE_WAITPID - int pid, /* Process ID of command */ - status; /* Status of command */ - char command[1024], /* Command */ - *argv[12], /* Command-line arguments */ - *envp[MAX_ENV + 1], /* Environment variables */ - infofile[1024], /* Type-in information for cert */ - seedfile[1024]; /* Random number seed file */ - int envc, /* Number of environment variables */ - bytes; /* Bytes written */ - cups_file_t *fp; /* Seed/info file */ - int infofd; /* Info file descriptor */ - - - /* - * Run the "openssl" command to seed the random number generator and - * generate a self-signed certificate that is good for 10 years: - * - * openssl rand -rand seedfile 1 - * - * openssl req -new -x509 -keyout ServerKey \ - * -out ServerCertificate -days 3650 -nodes - * - * The seeding step is crucial in ensuring that the openssl command - * does not block on systems without sufficient entropy... - */ - - if (!cupsFileFind("openssl", getenv("PATH"), 1, command, sizeof(command))) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "No SSL certificate and openssl command not found!"); - return (0); - } - - if (access("/dev/urandom", 0)) - { - /* - * If the system doesn't provide /dev/urandom, then any random source - * will probably be blocking-style, so generate some random data to - * use as a seed for the certificate. Note that we have already - * seeded the random number generator in cupsdInitCerts()... - */ - - cupsdLogMessage(CUPSD_LOG_INFO, - "Seeding the random number generator..."); - - /* - * Write the seed file... - */ - - if ((fp = cupsTempFile2(seedfile, sizeof(seedfile))) == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create seed file %s - %s", - seedfile, strerror(errno)); - return (0); - } - - for (bytes = 0; bytes < 262144; bytes ++) - cupsFilePutChar(fp, CUPS_RAND()); - - cupsFileClose(fp); - - /* - * Run the openssl command to seed its random number generator... - */ - - argv[0] = "openssl"; - argv[1] = "rand"; - argv[2] = "-rand"; - argv[3] = seedfile; - argv[4] = "1"; - argv[5] = NULL; - - envc = cupsdLoadEnv(envp, MAX_ENV); - envp[envc] = NULL; - - if (!cupsdStartProcess(command, argv, envp, -1, -1, -1, -1, -1, 1, NULL, - NULL, &pid)) - { - unlink(seedfile); - return (0); - } - - while (waitpid(pid, &status, 0) < 0) - if (errno != EINTR) - { - status = 1; - break; - } - - cupsdFinishProcess(pid, command, sizeof(command), NULL); - - /* - * Remove the seed file, as it is no longer needed... - */ - - unlink(seedfile); - - if (status) - { - if (WIFEXITED(status)) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to seed random number generator - " - "the openssl command stopped with status %d!", - WEXITSTATUS(status)); - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to seed random number generator - " - "the openssl command crashed on signal %d!", - WTERMSIG(status)); - - return (0); - } - } - - /* - * Create a file with the certificate information fields... - * - * Note: This assumes that the default questions are asked by the openssl - * command... - */ - - if ((fp = cupsTempFile2(infofile, sizeof(infofile))) == NULL) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to create certificate information file %s - %s", - infofile, strerror(errno)); - return (0); - } - - cupsFilePrintf(fp, ".\n.\n.\n%s\n.\n%s\n%s\n", - ServerName, ServerName, ServerAdmin); - cupsFileClose(fp); - - cupsdLogMessage(CUPSD_LOG_INFO, - "Generating SSL server key and certificate..."); - - argv[0] = "openssl"; - argv[1] = "req"; - argv[2] = "-new"; - argv[3] = "-x509"; - argv[4] = "-keyout"; - argv[5] = ServerKey; - argv[6] = "-out"; - argv[7] = ServerCertificate; - argv[8] = "-days"; - argv[9] = "3650"; - argv[10] = "-nodes"; - argv[11] = NULL; - - cupsdLoadEnv(envp, MAX_ENV); - - infofd = open(infofile, O_RDONLY); - - if (!cupsdStartProcess(command, argv, envp, infofd, -1, -1, -1, -1, 1, NULL, - NULL, &pid)) - { - close(infofd); - unlink(infofile); - return (0); - } - - close(infofd); - unlink(infofile); - - while (waitpid(pid, &status, 0) < 0) - if (errno != EINTR) - { - status = 1; - break; - } - - cupsdFinishProcess(pid, command, sizeof(command), NULL); - - if (status) - { - if (WIFEXITED(status)) - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to create SSL server key and certificate - " - "the openssl command stopped with status %d!", - WEXITSTATUS(status)); - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to create SSL server key and certificate - " - "the openssl command crashed on signal %d!", - WTERMSIG(status)); - } - else - { - cupsdLogMessage(CUPSD_LOG_INFO, "Created SSL server key file \"%s\"...", - ServerKey); - cupsdLogMessage(CUPSD_LOG_INFO, - "Created SSL server certificate file \"%s\"...", - ServerCertificate); - } - - return (!status); - -#else - return (0); -#endif /* HAVE_WAITPID */ -} - - -/* - * End of "$Id: tls-openssl.c 11173 2013-07-23 12:31:34Z msweet $". - */ diff --git a/scheduler/tls.c b/scheduler/tls.c deleted file mode 100644 index bd18263..0000000 --- a/scheduler/tls.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * "$Id: tls.c 11173 2013-07-23 12:31:34Z msweet $" - * - * TLS support code for the CUPS scheduler. - * - * Copyright 2012 by Apple Inc. - * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - */ - -#include "cupsd.h" - -#ifdef HAVE_SSL -# ifdef HAVE_CDSASSL -# include "tls-darwin.c" -# elif defined(HAVE_GNUTLS) -# include "tls-gnutls.c" -# elif defined(HAVE_LIBSSL) -# include "tls-openssl.c" -# endif /* HAVE_CDSASSL */ -#endif /* HAVE_SSL */ - - -/* - * End of "$Id: tls.c 11173 2013-07-23 12:31:34Z msweet $". - */ diff --git a/scheduler/type.c b/scheduler/type.c index bf014be..68ed07e 100644 --- a/scheduler/type.c +++ b/scheduler/type.c @@ -1,26 +1,16 @@ /* - * "$Id: type.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: type.c 12577 2015-03-30 19:07:17Z msweet $" * - * MIME typing routines for CUPS. + * MIME typing routines for CUPS. * - * Copyright 2007-2011 by Apple Inc. - * Copyright 1997-2006 by Easy Software Products, all rights reserved. + * Copyright 2007-2015 by Apple Inc. + * Copyright 1997-2006 by Easy Software Products, all rights reserved. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * mimeAddType() - Add a MIME type to a database. - * mimeAddTypeRule() - Add a detection rule for a file type. - * mimeFileType() - Determine the type of a file. - * mimeType() - Lookup a file type. - * mime_compare_types() - Compare two MIME super/type names. - * mime_check_rules() - Check each rule in a list. - * mime_patmatch() - Pattern matching. + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -319,7 +309,7 @@ mimeAddTypeRule(mime_type_t *mt, /* I - Type to add to */ */ ptr = name; - while (isalnum(*rule & 255) && (ptr - name) < (sizeof(name) - 1)) + while (isalnum(*rule & 255) && (size_t)(ptr - name) < (sizeof(name) - 1)) *ptr++ = *rule++; *ptr = '\0'; @@ -332,12 +322,12 @@ mimeAddTypeRule(mime_type_t *mt, /* I - Type to add to */ rule ++; for (num_values = 0; - num_values < (sizeof(value) / sizeof(value[0])); + num_values < (int)(sizeof(value) / sizeof(value[0])); num_values ++) { ptr = value[num_values]; - while ((ptr - value[num_values]) < (sizeof(value[0]) - 1) && + while ((size_t)(ptr - value[num_values]) < (sizeof(value[0]) - 1) && *rule != '\0' && *rule != ',' && *rule != ')') { if (isspace(*rule & 255)) @@ -358,7 +348,7 @@ mimeAddTypeRule(mime_type_t *mt, /* I - Type to add to */ quote = *rule++; while (*rule != '\0' && *rule != quote && - (ptr - value[num_values]) < (sizeof(value[0]) - 1)) + (size_t)(ptr - value[num_values]) < (sizeof(value[0]) - 1)) *ptr++ = *rule++; if (*rule == quote) @@ -371,14 +361,14 @@ mimeAddTypeRule(mime_type_t *mt, /* I - Type to add to */ rule ++; while (*rule != '>' && *rule != '\0' && - (ptr - value[num_values]) < (sizeof(value[0]) - 1)) + (size_t)(ptr - value[num_values]) < (sizeof(value[0]) - 1)) { if (isxdigit(rule[0] & 255) && isxdigit(rule[1] & 255)) { if (isdigit(*rule)) - *ptr = (*rule++ - '0') << 4; + *ptr = (char)((*rule++ - '0') << 4); else - *ptr = (tolower(*rule++) - 'a' + 10) << 4; + *ptr = (char)((tolower(*rule++) - 'a' + 10) << 4); if (isdigit(*rule)) *ptr++ |= *rule++ - '0'; @@ -425,6 +415,8 @@ mimeAddTypeRule(mime_type_t *mt, /* I - Type to add to */ op = MIME_MAGIC_ASCII; else if (!strcmp(name, "printable")) op = MIME_MAGIC_PRINTABLE; + else if (!strcmp(name, "regex")) + op = MIME_MAGIC_REGEX; else if (!strcmp(name, "string")) op = MIME_MAGIC_STRING; else if (!strcmp(name, "istring")) @@ -454,7 +446,7 @@ mimeAddTypeRule(mime_type_t *mt, /* I - Type to add to */ */ snprintf(value[0], sizeof(value[0]), "*.%s", name); - length[0] = strlen(value[0]); + length[0] = (int)strlen(value[0]); op = MIME_MAGIC_MATCH; } @@ -465,7 +457,7 @@ mimeAddTypeRule(mime_type_t *mt, /* I - Type to add to */ if ((temp = calloc(1, sizeof(mime_magic_t))) == NULL) return (-1); - temp->invert = invert; + temp->invert = (short)invert; if (current != NULL) { temp->parent = current->parent; @@ -507,15 +499,15 @@ mimeAddTypeRule(mime_type_t *mt, /* I - Type to add to */ */ current = temp; - temp->op = op; + temp->op = (short)op; invert = 0; switch (op) { case MIME_MAGIC_MATCH : - if (length[0] > (sizeof(temp->value.matchv) - 1)) + if ((size_t)length[0] > (sizeof(temp->value.matchv) - 1)) return (-1); - strcpy(temp->value.matchv, value[0]); + strlcpy(temp->value.matchv, value[0], sizeof(temp->value.matchv)); break; case MIME_MAGIC_ASCII : case MIME_MAGIC_PRINTABLE : @@ -524,18 +516,24 @@ mimeAddTypeRule(mime_type_t *mt, /* I - Type to add to */ if (temp->length > MIME_MAX_BUFFER) temp->length = MIME_MAX_BUFFER; break; + case MIME_MAGIC_REGEX : + temp->offset = strtol(value[0], NULL, 0); + temp->length = MIME_MAX_BUFFER; + if (regcomp(&(temp->value.rev), value[1], REG_NOSUB | REG_EXTENDED)) + return (-1); + break; case MIME_MAGIC_STRING : case MIME_MAGIC_ISTRING : temp->offset = strtol(value[0], NULL, 0); - if (length[1] > sizeof(temp->value.stringv)) + if ((size_t)length[1] > sizeof(temp->value.stringv)) return (-1); temp->length = length[1]; - memcpy(temp->value.stringv, value[1], length[1]); + memcpy(temp->value.stringv, value[1], (size_t)length[1]); break; case MIME_MAGIC_CHAR : temp->offset = strtol(value[0], NULL, 0); if (length[1] == 1) - temp->value.charv = value[1][0]; + temp->value.charv = (unsigned char)value[1][0]; else temp->value.charv = (unsigned char)strtol(value[1], NULL, 0); @@ -551,18 +549,18 @@ mimeAddTypeRule(mime_type_t *mt, /* I - Type to add to */ temp->value.intv = (unsigned)strtol(value[1], NULL, 0); break; case MIME_MAGIC_LOCALE : - if (length[0] > (sizeof(temp->value.localev) - 1)) + if ((size_t)length[0] > (sizeof(temp->value.localev) - 1)) return (-1); - strcpy(temp->value.localev, value[0]); + strlcpy(temp->value.localev, value[0], sizeof(temp->value.localev)); break; case MIME_MAGIC_CONTAINS : temp->offset = strtol(value[0], NULL, 0); temp->region = strtol(value[1], NULL, 0); - if (length[2] > sizeof(temp->value.stringv)) + if ((size_t)length[2] > sizeof(temp->value.stringv)) return (-1); temp->length = length[2]; - memcpy(temp->value.stringv, value[2], length[2]); + memcpy(temp->value.stringv, value[2], (size_t)length[2]); break; } } @@ -615,8 +613,23 @@ mimeFileType(mime_t *mime, /* I - MIME database */ return (NULL); } - fb.offset = -1; - fb.length = 0; + /* + * Then preload the first MIME_MAX_BUFFER bytes of the file into the file + * buffer, returning an error if we can't read anything... + */ + + fb.offset = 0; + fb.length = (int)cupsFileRead(fb.fp, (char *)fb.buffer, MIME_MAX_BUFFER); + + if (fb.length <= 0) + { + DEBUG_printf(("1mimeFileType: Unable to read from \"%s\": %s", pathname, strerror(errno))); + DEBUG_puts("1mimeFileType: Returning NULL."); + + cupsFileClose(fb.fp); + + return (NULL); + } /* * Figure out the base filename (without directory portion)... @@ -735,8 +748,8 @@ mime_check_rules( int n; /* Looping var */ int region; /* Region to look at */ int logic, /* Logic to apply */ - result, /* Result of test */ - intv; /* Integer value */ + result; /* Result of test */ + unsigned intv; /* Integer value */ short shortv; /* Short value */ unsigned char *bufptr; /* Pointer into buffer */ @@ -782,6 +795,8 @@ mime_check_rules( fb->length = cupsFileRead(fb->fp, (char *)fb->buffer, sizeof(fb->buffer)); fb->offset = rules->offset; + + DEBUG_printf(("4mime_check_rules: MIME_MAGIC_ASCII fb->length=%d", fb->length)); } /* @@ -824,6 +839,8 @@ mime_check_rules( fb->length = cupsFileRead(fb->fp, (char *)fb->buffer, sizeof(fb->buffer)); fb->offset = rules->offset; + + DEBUG_printf(("4mime_check_rules: MIME_MAGIC_PRINTABLE fb->length=%d", fb->length)); } /* @@ -852,6 +869,52 @@ mime_check_rules( result = (n == 0); break; + case MIME_MAGIC_REGEX : + DEBUG_printf(("5mime_check_rules: regex(%d, \"%s\")", rules->offset, + rules->value.stringv)); + + /* + * Load the buffer if necessary... + */ + + if (fb->offset < 0 || rules->offset < fb->offset || + (rules->offset + rules->length) > (fb->offset + fb->length)) + { + /* + * Reload file buffer... + */ + + cupsFileSeek(fb->fp, rules->offset); + fb->length = cupsFileRead(fb->fp, (char *)fb->buffer, + sizeof(fb->buffer)); + fb->offset = rules->offset; + + DEBUG_printf(("4mime_check_rules: MIME_MAGIC_REGEX fb->length=%d", fb->length)); + + DEBUG_printf(("5mime_check_rules: loaded %d byte fb->buffer at %d, starts " + "with \"%c%c%c%c\".", + fb->length, fb->offset, fb->buffer[0], fb->buffer[1], + fb->buffer[2], fb->buffer[3])); + } + + /* + * Compare the buffer against the string. If the file is too + * short then don't compare - it can't match... + */ + + if (fb->length > 0) + { + char temp[MIME_MAX_BUFFER + 1]; + /* Temporary buffer */ + + memcpy(temp, fb->buffer, (size_t)fb->length); + temp[fb->length] = '\0'; + result = !regexec(&(rules->value.rev), temp, 0, NULL, 0); + } + + DEBUG_printf(("5mime_check_rules: result=%d", result)); + break; + case MIME_MAGIC_STRING : DEBUG_printf(("5mime_check_rules: string(%d, \"%s\")", rules->offset, rules->value.stringv)); @@ -872,6 +935,8 @@ mime_check_rules( sizeof(fb->buffer)); fb->offset = rules->offset; + DEBUG_printf(("4mime_check_rules: MIME_MAGIC_STRING fb->length=%d", fb->length)); + DEBUG_printf(("5mime_check_rules: loaded %d byte fb->buffer at %d, starts " "with \"%c%c%c%c\".", fb->length, fb->offset, fb->buffer[0], fb->buffer[1], @@ -886,8 +951,7 @@ mime_check_rules( if ((rules->offset + rules->length) > (fb->offset + fb->length)) result = 0; else - result = (memcmp(fb->buffer + rules->offset - fb->offset, - rules->value.stringv, rules->length) == 0); + result = !memcmp(fb->buffer + rules->offset - fb->offset, rules->value.stringv, (size_t)rules->length); DEBUG_printf(("5mime_check_rules: result=%d", result)); break; @@ -907,6 +971,8 @@ mime_check_rules( fb->length = cupsFileRead(fb->fp, (char *)fb->buffer, sizeof(fb->buffer)); fb->offset = rules->offset; + + DEBUG_printf(("4mime_check_rules: MIME_MAGIC_ISTRING fb->length=%d", fb->length)); } /* @@ -917,9 +983,7 @@ mime_check_rules( if ((rules->offset + rules->length) > (fb->offset + fb->length)) result = 0; else - result = (_cups_strncasecmp((char *)fb->buffer + rules->offset - - fb->offset, - rules->value.stringv, rules->length) == 0); + result = !_cups_strncasecmp((char *)fb->buffer + rules->offset - fb->offset, rules->value.stringv, (size_t)rules->length); break; case MIME_MAGIC_CHAR : @@ -937,6 +1001,8 @@ mime_check_rules( fb->length = cupsFileRead(fb->fp, (char *)fb->buffer, sizeof(fb->buffer)); fb->offset = rules->offset; + + DEBUG_printf(("4mime_check_rules: MIME_MAGIC_CHAR fb->length=%d", fb->length)); } /* @@ -967,6 +1033,8 @@ mime_check_rules( fb->length = cupsFileRead(fb->fp, (char *)fb->buffer, sizeof(fb->buffer)); fb->offset = rules->offset; + + DEBUG_printf(("4mime_check_rules: MIME_MAGIC_SHORT fb->length=%d", fb->length)); } /* @@ -979,7 +1047,7 @@ mime_check_rules( else { bufptr = fb->buffer + rules->offset - fb->offset; - shortv = (bufptr[0] << 8) | bufptr[1]; + shortv = (short)((bufptr[0] << 8) | bufptr[1]); result = (shortv == rules->value.shortv); } break; @@ -1000,6 +1068,8 @@ mime_check_rules( fb->length = cupsFileRead(fb->fp, (char *)fb->buffer, sizeof(fb->buffer)); fb->offset = rules->offset; + + DEBUG_printf(("4mime_check_rules: MIME_MAGIC_INT fb->length=%d", fb->length)); } /* @@ -1012,19 +1082,16 @@ mime_check_rules( else { bufptr = fb->buffer + rules->offset - fb->offset; - intv = (((((bufptr[0] << 8) | bufptr[1]) << 8) | - bufptr[2]) << 8) | bufptr[3]; + intv = (unsigned)((((((bufptr[0] << 8) | bufptr[1]) << 8) | bufptr[2]) << 8) | bufptr[3]); result = (intv == rules->value.intv); } break; case MIME_MAGIC_LOCALE : #if defined(WIN32) || defined(__EMX__) || defined(__APPLE__) - result = (strcmp(rules->value.localev, - setlocale(LC_ALL, "")) == 0); + result = !strcmp(rules->value.localev, setlocale(LC_ALL, "")); #else - result = (strcmp(rules->value.localev, - setlocale(LC_MESSAGES, "")) == 0); + result = !strcmp(rules->value.localev, setlocale(LC_MESSAGES, "")); #endif /* __APPLE__ */ break; @@ -1044,6 +1111,8 @@ mime_check_rules( fb->length = cupsFileRead(fb->fp, (char *)fb->buffer, sizeof(fb->buffer)); fb->offset = rules->offset; + + DEBUG_printf(("4mime_check_rules: MIME_MAGIC_CONTAINS fb->length=%d", fb->length)); } /* @@ -1061,9 +1130,7 @@ mime_check_rules( region = fb->length - rules->length; for (n = 0; n < region; n ++) - if ((result = (memcmp(fb->buffer + rules->offset - fb->offset + n, - rules->value.stringv, - rules->length) == 0)) != 0) + if ((result = (memcmp(fb->buffer + rules->offset - fb->offset + n, rules->value.stringv, (size_t)rules->length) == 0)) != 0) break; } break; @@ -1212,5 +1279,5 @@ mime_patmatch(const char *s, /* I - String to match against */ /* - * End of "$Id: type.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: type.c 12577 2015-03-30 19:07:17Z msweet $". */ diff --git a/scheduler/util.c b/scheduler/util.c index 74dd9ff..a31be2e 100644 --- a/scheduler/util.c +++ b/scheduler/util.c @@ -1,28 +1,16 @@ /* - * "$Id: util.c 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: util.c 11558 2014-02-06 18:33:34Z msweet $" * - * Mini-daemon utility functions for CUPS. + * Mini-daemon utility functions for CUPS. * - * Copyright 2007-2011 by Apple Inc. - * Copyright 1997-2005 by Easy Software Products. + * Copyright 2007-2014 by Apple Inc. + * Copyright 1997-2005 by Easy Software Products. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * Contents: - * - * cupsdCompareNames() - Compare two names. - * cupsdCreateStringsArray() - Create a CUPS array of strings. - * cupsdExec() - Run a program with the correct environment. - * cupsdPipeCommand() - Read output from a command. - * cupsdSendIPPGroup() - Send a group tag. - * cupsdSendIPPHeader() - Send the IPP response header. - * cupsdSendIPPInteger() - Send an integer attribute. - * cupsdSendIPPString() - Send a string attribute. - * cupsdSendIPPTrailer() - Send the end-of-message tag. + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ /* @@ -163,7 +151,7 @@ cupsdCreateStringsArray(const char *s) /* I - Comma-delimited strings */ if (!s || !*s) return (NULL); else - return (_cupsArrayNewStrings(s)); + return (_cupsArrayNewStrings(s, ',')); } @@ -251,7 +239,7 @@ cups_file_t * /* O - CUPS file or NULL on error */ cupsdPipeCommand(int *pid, /* O - Process ID or 0 on error */ const char *command, /* I - Command to run */ char **argv, /* I - Arguments to pass to command */ - int user) /* I - User to run as or 0 for current */ + uid_t user) /* I - User to run as or 0 for current */ { int fd, /* Temporary file descriptor */ fds[2]; /* Pipe file descriptors */ @@ -404,8 +392,8 @@ cupsdSendIPPInteger( putchar(value_tag); len = strlen(name); - putchar(len >> 8); - putchar(len); + putchar((int)(len >> 8)); + putchar((int)len); fputs(name, stdout); @@ -441,14 +429,14 @@ cupsdSendIPPString( putchar(value_tag); len = strlen(name); - putchar(len >> 8); - putchar(len); + putchar((int)(len >> 8)); + putchar((int)len); fputs(name, stdout); len = strlen(value); - putchar(len >> 8); - putchar(len); + putchar((int)(len >> 8)); + putchar((int)len); fputs(value, stdout); } @@ -467,5 +455,5 @@ cupsdSendIPPTrailer(void) /* - * End of "$Id: util.c 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: util.c 11558 2014-02-06 18:33:34Z msweet $". */ diff --git a/scheduler/util.h b/scheduler/util.h index cf5ae0d..08b495c 100644 --- a/scheduler/util.h +++ b/scheduler/util.h @@ -1,16 +1,16 @@ /* - * "$Id: util.h 11173 2013-07-23 12:31:34Z msweet $" + * "$Id: util.h 11558 2014-02-06 18:33:34Z msweet $" * - * Mini-daemon utility definitions for CUPS. + * Mini-daemon utility definitions for CUPS. * - * Copyright 2007-2011 by Apple Inc. - * Copyright 1997-2005 by Easy Software Products. + * Copyright 2007-2014 by Apple Inc. + * Copyright 1997-2005 by Easy Software Products. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". */ #ifndef _CUPSD_UTIL_H_ @@ -49,7 +49,7 @@ extern int cupsdCompareNames(const char *s, const char *t); extern cups_array_t *cupsdCreateStringsArray(const char *s); extern int cupsdExec(const char *command, char **argv); extern cups_file_t *cupsdPipeCommand(int *pid, const char *command, - char **argv, int user); + char **argv, uid_t user); extern void cupsdSendIPPGroup(ipp_tag_t group_tag); extern void cupsdSendIPPHeader(ipp_status_t status_code, int request_id); @@ -67,5 +67,5 @@ extern void cupsdSendIPPTrailer(void); #endif /* !_CUPSD_UTIL_H_ */ /* - * End of "$Id: util.h 11173 2013-07-23 12:31:34Z msweet $". + * End of "$Id: util.h 11558 2014-02-06 18:33:34Z msweet $". */ |