00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "includes.h"
00024 #include "printing.h"
00025
00026 extern SIG_ATOMIC_T got_sig_term;
00027 extern SIG_ATOMIC_T reload_after_sighup;
00028 extern struct current_user current_user;
00029 extern userdom_struct current_user_info;
00030
00031
00032 static BOOL remove_from_jobs_changed(const char* sharename, uint32 jobid);
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 static TDB_CONTEXT *rap_tdb;
00049 static uint16 next_rap_jobid;
00050 struct rap_jobid_key {
00051 fstring sharename;
00052 uint32 jobid;
00053 };
00054
00055
00056
00057
00058
00059
00060 uint16 pjobid_to_rap(const char* sharename, uint32 jobid)
00061 {
00062 uint16 rap_jobid;
00063 TDB_DATA data, key;
00064 struct rap_jobid_key jinfo;
00065 uint8 buf[2];
00066
00067 DEBUG(10,("pjobid_to_rap: called.\n"));
00068
00069 if (!rap_tdb) {
00070
00071 rap_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL, (O_RDWR|O_CREAT), 0644);
00072 if (!rap_tdb)
00073 return 0;
00074 }
00075
00076 ZERO_STRUCT( jinfo );
00077 fstrcpy( jinfo.sharename, sharename );
00078 jinfo.jobid = jobid;
00079 key.dptr = (char*)&jinfo;
00080 key.dsize = sizeof(jinfo);
00081
00082 data = tdb_fetch(rap_tdb, key);
00083 if (data.dptr && data.dsize == sizeof(uint16)) {
00084 rap_jobid = SVAL(data.dptr, 0);
00085 SAFE_FREE(data.dptr);
00086 DEBUG(10,("pjobid_to_rap: jobid %u maps to RAP jobid %u\n",
00087 (unsigned int)jobid, (unsigned int)rap_jobid));
00088 return rap_jobid;
00089 }
00090 SAFE_FREE(data.dptr);
00091
00092 rap_jobid = ++next_rap_jobid;
00093 if (rap_jobid == 0)
00094 rap_jobid = ++next_rap_jobid;
00095 SSVAL(buf,0,rap_jobid);
00096 data.dptr = (char*)buf;
00097 data.dsize = sizeof(rap_jobid);
00098 tdb_store(rap_tdb, key, data, TDB_REPLACE);
00099 tdb_store(rap_tdb, data, key, TDB_REPLACE);
00100
00101 DEBUG(10,("pjobid_to_rap: created jobid %u maps to RAP jobid %u\n",
00102 (unsigned int)jobid, (unsigned int)rap_jobid));
00103 return rap_jobid;
00104 }
00105
00106 BOOL rap_to_pjobid(uint16 rap_jobid, fstring sharename, uint32 *pjobid)
00107 {
00108 TDB_DATA data, key;
00109 uint8 buf[2];
00110
00111 DEBUG(10,("rap_to_pjobid called.\n"));
00112
00113 if (!rap_tdb)
00114 return False;
00115
00116 SSVAL(buf,0,rap_jobid);
00117 key.dptr = (char*)buf;
00118 key.dsize = sizeof(rap_jobid);
00119 data = tdb_fetch(rap_tdb, key);
00120 if ( data.dptr && data.dsize == sizeof(struct rap_jobid_key) )
00121 {
00122 struct rap_jobid_key *jinfo = (struct rap_jobid_key*)data.dptr;
00123 fstrcpy( sharename, jinfo->sharename );
00124 *pjobid = jinfo->jobid;
00125 DEBUG(10,("rap_to_pjobid: jobid %u maps to RAP jobid %u\n",
00126 (unsigned int)*pjobid, (unsigned int)rap_jobid));
00127 SAFE_FREE(data.dptr);
00128 return True;
00129 }
00130
00131 DEBUG(10,("rap_to_pjobid: Failed to lookup RAP jobid %u\n",
00132 (unsigned int)rap_jobid));
00133 SAFE_FREE(data.dptr);
00134 return False;
00135 }
00136
00137 static void rap_jobid_delete(const char* sharename, uint32 jobid)
00138 {
00139 TDB_DATA key, data;
00140 uint16 rap_jobid;
00141 struct rap_jobid_key jinfo;
00142 uint8 buf[2];
00143
00144 DEBUG(10,("rap_jobid_delete: called.\n"));
00145
00146 if (!rap_tdb)
00147 return;
00148
00149 ZERO_STRUCT( jinfo );
00150 fstrcpy( jinfo.sharename, sharename );
00151 jinfo.jobid = jobid;
00152 key.dptr = (char*)&jinfo;
00153 key.dsize = sizeof(jinfo);
00154
00155 data = tdb_fetch(rap_tdb, key);
00156 if (!data.dptr || (data.dsize != sizeof(uint16))) {
00157 DEBUG(10,("rap_jobid_delete: cannot find jobid %u\n",
00158 (unsigned int)jobid ));
00159 SAFE_FREE(data.dptr);
00160 return;
00161 }
00162
00163 DEBUG(10,("rap_jobid_delete: deleting jobid %u\n",
00164 (unsigned int)jobid ));
00165
00166 rap_jobid = SVAL(data.dptr, 0);
00167 SAFE_FREE(data.dptr);
00168 SSVAL(buf,0,rap_jobid);
00169 data.dptr = (char*)buf;
00170 data.dsize = sizeof(rap_jobid);
00171 tdb_delete(rap_tdb, key);
00172 tdb_delete(rap_tdb, data);
00173 }
00174
00175 static int get_queue_status(const char* sharename, print_status_struct *);
00176
00177
00178
00179
00180
00181 BOOL print_backend_init(void)
00182 {
00183 const char *sversion = "INFO/version";
00184 pstring printing_path;
00185 int services = lp_numservices();
00186 int snum;
00187
00188 unlink(lock_path("printing.tdb"));
00189 pstrcpy(printing_path,lock_path("printing"));
00190 mkdir(printing_path,0755);
00191
00192
00193
00194 for (snum = 0; snum < services; snum++) {
00195 struct tdb_print_db *pdb;
00196 if (!lp_print_ok(snum))
00197 continue;
00198
00199 pdb = get_print_db_byname(lp_const_servicename(snum));
00200 if (!pdb)
00201 continue;
00202 if (tdb_lock_bystring(pdb->tdb, sversion) == -1) {
00203 DEBUG(0,("print_backend_init: Failed to open printer %s database\n", lp_const_servicename(snum) ));
00204 release_print_db(pdb);
00205 return False;
00206 }
00207 if (tdb_fetch_int32(pdb->tdb, sversion) != PRINT_DATABASE_VERSION) {
00208 tdb_traverse(pdb->tdb, tdb_traverse_delete_fn, NULL);
00209 tdb_store_int32(pdb->tdb, sversion, PRINT_DATABASE_VERSION);
00210 }
00211 tdb_unlock_bystring(pdb->tdb, sversion);
00212 release_print_db(pdb);
00213 }
00214
00215 close_all_print_db();
00216
00217
00218 return nt_printing_init();
00219 }
00220
00221
00222
00223
00224
00225 void printing_end(void)
00226 {
00227 close_all_print_db();
00228 }
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239 static struct printif *get_printer_fns_from_type( enum printing_types type )
00240 {
00241 struct printif *printer_fns = &generic_printif;
00242
00243 #ifdef HAVE_CUPS
00244 if ( type == PRINT_CUPS ) {
00245 printer_fns = &cups_printif;
00246 }
00247 #endif
00248
00249 #ifdef HAVE_IPRINT
00250 if ( type == PRINT_IPRINT ) {
00251 printer_fns = &iprint_printif;
00252 }
00253 #endif
00254
00255 printer_fns->type = type;
00256
00257 return printer_fns;
00258 }
00259
00260 static struct printif *get_printer_fns( int snum )
00261 {
00262 return get_printer_fns_from_type( (enum printing_types)lp_printing(snum) );
00263 }
00264
00265
00266
00267
00268
00269
00270 static TDB_DATA print_key(uint32 jobid)
00271 {
00272 static uint32 j;
00273 TDB_DATA ret;
00274
00275 SIVAL(&j, 0, jobid);
00276 ret.dptr = (char *)&j;
00277 ret.dsize = sizeof(j);
00278 return ret;
00279 }
00280
00281
00282
00283
00284
00285 int unpack_pjob( char* buf, int buflen, struct printjob *pjob )
00286 {
00287 int len = 0;
00288 int used;
00289 uint32 pjpid, pjsysjob, pjfd, pjstarttime, pjstatus;
00290 uint32 pjsize, pjpage_count, pjspooled, pjsmbjob;
00291
00292 if ( !buf || !pjob )
00293 return -1;
00294
00295 len += tdb_unpack(buf+len, buflen-len, "dddddddddffff",
00296 &pjpid,
00297 &pjsysjob,
00298 &pjfd,
00299 &pjstarttime,
00300 &pjstatus,
00301 &pjsize,
00302 &pjpage_count,
00303 &pjspooled,
00304 &pjsmbjob,
00305 pjob->filename,
00306 pjob->jobname,
00307 pjob->user,
00308 pjob->queuename);
00309
00310 if ( len == -1 )
00311 return -1;
00312
00313 if ( (used = unpack_devicemode(&pjob->nt_devmode, buf+len, buflen-len)) == -1 )
00314 return -1;
00315
00316 len += used;
00317
00318 pjob->pid = pjpid;
00319 pjob->sysjob = pjsysjob;
00320 pjob->fd = pjfd;
00321 pjob->starttime = pjstarttime;
00322 pjob->status = pjstatus;
00323 pjob->size = pjsize;
00324 pjob->page_count = pjpage_count;
00325 pjob->spooled = pjspooled;
00326 pjob->smbjob = pjsmbjob;
00327
00328 return len;
00329
00330 }
00331
00332
00333
00334
00335
00336 static struct printjob *print_job_find(const char *sharename, uint32 jobid)
00337 {
00338 static struct printjob pjob;
00339 TDB_DATA ret;
00340 struct tdb_print_db *pdb = get_print_db_byname(sharename);
00341
00342 DEBUG(10,("print_job_find: looking up job %u for share %s\n",
00343 (unsigned int)jobid, sharename ));
00344
00345 if (!pdb) {
00346 return NULL;
00347 }
00348
00349 ret = tdb_fetch(pdb->tdb, print_key(jobid));
00350 release_print_db(pdb);
00351
00352 if (!ret.dptr) {
00353 DEBUG(10,("print_job_find: failed to find jobid %u.\n", (unsigned int)jobid ));
00354 return NULL;
00355 }
00356
00357 if ( pjob.nt_devmode ) {
00358 free_nt_devicemode( &pjob.nt_devmode );
00359 }
00360
00361 ZERO_STRUCT( pjob );
00362
00363 if ( unpack_pjob( ret.dptr, ret.dsize, &pjob ) == -1 ) {
00364 DEBUG(10,("print_job_find: failed to unpack jobid %u.\n", (unsigned int)jobid ));
00365 SAFE_FREE(ret.dptr);
00366 return NULL;
00367 }
00368
00369 SAFE_FREE(ret.dptr);
00370
00371 DEBUG(10,("print_job_find: returning system job %d for jobid %u.\n",
00372 (int)pjob.sysjob, (unsigned int)jobid ));
00373
00374 return &pjob;
00375 }
00376
00377
00378
00379 static uint32 sysjob_to_jobid_value;
00380
00381 static int unixjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
00382 TDB_DATA data, void *state)
00383 {
00384 struct printjob *pjob;
00385 int *sysjob = (int *)state;
00386
00387 if (!data.dptr || data.dsize == 0)
00388 return 0;
00389
00390 pjob = (struct printjob *)data.dptr;
00391 if (key.dsize != sizeof(uint32))
00392 return 0;
00393
00394 if (*sysjob == pjob->sysjob) {
00395 uint32 jobid = IVAL(key.dptr,0);
00396
00397 sysjob_to_jobid_value = jobid;
00398 return 1;
00399 }
00400
00401 return 0;
00402 }
00403
00404
00405
00406
00407
00408
00409 uint32 sysjob_to_jobid(int unix_jobid)
00410 {
00411 int services = lp_numservices();
00412 int snum;
00413
00414 sysjob_to_jobid_value = (uint32)-1;
00415
00416 for (snum = 0; snum < services; snum++) {
00417 struct tdb_print_db *pdb;
00418 if (!lp_print_ok(snum))
00419 continue;
00420 pdb = get_print_db_byname(lp_const_servicename(snum));
00421 if (!pdb) {
00422 continue;
00423 }
00424 tdb_traverse(pdb->tdb, unixjob_traverse_fn, &unix_jobid);
00425 release_print_db(pdb);
00426 if (sysjob_to_jobid_value != (uint32)-1)
00427 return sysjob_to_jobid_value;
00428 }
00429 return (uint32)-1;
00430 }
00431
00432
00433
00434
00435
00436 static struct {
00437 uint32 lpq_status;
00438 uint32 spoolss_status;
00439 } lpq_to_spoolss_status_map[] = {
00440 { LPQ_QUEUED, JOB_STATUS_QUEUED },
00441 { LPQ_PAUSED, JOB_STATUS_PAUSED },
00442 { LPQ_SPOOLING, JOB_STATUS_SPOOLING },
00443 { LPQ_PRINTING, JOB_STATUS_PRINTING },
00444 { LPQ_DELETING, JOB_STATUS_DELETING },
00445 { LPQ_OFFLINE, JOB_STATUS_OFFLINE },
00446 { LPQ_PAPEROUT, JOB_STATUS_PAPEROUT },
00447 { LPQ_PRINTED, JOB_STATUS_PRINTED },
00448 { LPQ_DELETED, JOB_STATUS_DELETED },
00449 { LPQ_BLOCKED, JOB_STATUS_BLOCKED },
00450 { LPQ_USER_INTERVENTION, JOB_STATUS_USER_INTERVENTION },
00451 { -1, 0 }
00452 };
00453
00454
00455
00456
00457 static uint32 map_to_spoolss_status(uint32 lpq_status)
00458 {
00459 int i = 0;
00460
00461 while (lpq_to_spoolss_status_map[i].lpq_status != -1) {
00462 if (lpq_to_spoolss_status_map[i].lpq_status == lpq_status)
00463 return lpq_to_spoolss_status_map[i].spoolss_status;
00464 i++;
00465 }
00466
00467 return 0;
00468 }
00469
00470 static void pjob_store_notify(const char* sharename, uint32 jobid, struct printjob *old_data,
00471 struct printjob *new_data)
00472 {
00473 BOOL new_job = False;
00474
00475 if (!old_data)
00476 new_job = True;
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488 if (new_job) {
00489 notify_job_submitted(sharename, jobid, new_data->starttime);
00490 notify_job_username(sharename, jobid, new_data->user);
00491 }
00492
00493 if (new_job || !strequal(old_data->jobname, new_data->jobname))
00494 notify_job_name(sharename, jobid, new_data->jobname);
00495
00496
00497
00498
00499 if (new_job || !strequal(old_data->jobname, new_data->jobname))
00500 notify_job_name(sharename, jobid, new_data->jobname);
00501
00502 if (new_job || old_data->status != new_data->status)
00503 notify_job_status(sharename, jobid, map_to_spoolss_status(new_data->status));
00504
00505 if (new_job || old_data->size != new_data->size)
00506 notify_job_total_bytes(sharename, jobid, new_data->size);
00507
00508 if (new_job || old_data->page_count != new_data->page_count)
00509 notify_job_total_pages(sharename, jobid, new_data->page_count);
00510 }
00511
00512
00513
00514
00515
00516 static BOOL pjob_store(const char* sharename, uint32 jobid, struct printjob *pjob)
00517 {
00518 TDB_DATA old_data, new_data;
00519 BOOL ret = False;
00520 struct tdb_print_db *pdb = get_print_db_byname(sharename);
00521 char *buf = NULL;
00522 int len, newlen, buflen;
00523
00524
00525 if (!pdb)
00526 return False;
00527
00528
00529
00530 old_data = tdb_fetch(pdb->tdb, print_key(jobid));
00531
00532
00533
00534 newlen = 0;
00535
00536 do {
00537 len = 0;
00538 buflen = newlen;
00539 len += tdb_pack(buf+len, buflen-len, "dddddddddffff",
00540 (uint32)pjob->pid,
00541 (uint32)pjob->sysjob,
00542 (uint32)pjob->fd,
00543 (uint32)pjob->starttime,
00544 (uint32)pjob->status,
00545 (uint32)pjob->size,
00546 (uint32)pjob->page_count,
00547 (uint32)pjob->spooled,
00548 (uint32)pjob->smbjob,
00549 pjob->filename,
00550 pjob->jobname,
00551 pjob->user,
00552 pjob->queuename);
00553
00554 len += pack_devicemode(pjob->nt_devmode, buf+len, buflen-len);
00555
00556 if (buflen != len) {
00557 buf = (char *)SMB_REALLOC(buf, len);
00558 if (!buf) {
00559 DEBUG(0,("pjob_store: failed to enlarge buffer!\n"));
00560 goto done;
00561 }
00562 newlen = len;
00563 }
00564 } while ( buflen != len );
00565
00566
00567
00568
00569 new_data.dptr = buf;
00570 new_data.dsize = len;
00571 ret = (tdb_store(pdb->tdb, print_key(jobid), new_data, TDB_REPLACE) == 0);
00572
00573 release_print_db(pdb);
00574
00575
00576
00577 if ( ret ) {
00578 struct printjob old_pjob;
00579
00580 if ( old_data.dsize )
00581 {
00582 if ( unpack_pjob( old_data.dptr, old_data.dsize, &old_pjob ) != -1 )
00583 {
00584 pjob_store_notify( sharename, jobid, &old_pjob , pjob );
00585 free_nt_devicemode( &old_pjob.nt_devmode );
00586 }
00587 }
00588 else {
00589
00590 pjob_store_notify( sharename, jobid, NULL, pjob );
00591 }
00592 }
00593
00594 done:
00595 SAFE_FREE( old_data.dptr );
00596 SAFE_FREE( buf );
00597
00598 return ret;
00599 }
00600
00601
00602
00603
00604
00605 void pjob_delete(const char* sharename, uint32 jobid)
00606 {
00607 struct printjob *pjob;
00608 uint32 job_status = 0;
00609 struct tdb_print_db *pdb;
00610
00611 pdb = get_print_db_byname( sharename );
00612
00613 if (!pdb)
00614 return;
00615
00616 pjob = print_job_find( sharename, jobid );
00617
00618 if (!pjob) {
00619 DEBUG(5, ("pjob_delete: we were asked to delete nonexistent job %u\n",
00620 (unsigned int)jobid));
00621 release_print_db(pdb);
00622 return;
00623 }
00624
00625
00626
00627
00628
00629 job_status = JOB_STATUS_DELETING|JOB_STATUS_DELETED;
00630 notify_job_status(sharename, jobid, job_status);
00631
00632
00633
00634 tdb_delete(pdb->tdb, print_key(jobid));
00635 remove_from_jobs_changed(sharename, jobid);
00636 release_print_db( pdb );
00637 rap_jobid_delete(sharename, jobid);
00638 }
00639
00640
00641
00642
00643
00644 static uint32 print_parse_jobid(char *fname)
00645 {
00646 int jobid;
00647
00648 if (strncmp(fname,PRINT_SPOOL_PREFIX,strlen(PRINT_SPOOL_PREFIX)) != 0)
00649 return (uint32)-1;
00650 fname += strlen(PRINT_SPOOL_PREFIX);
00651
00652 jobid = atoi(fname);
00653 if (jobid <= 0)
00654 return (uint32)-1;
00655
00656 return (uint32)jobid;
00657 }
00658
00659
00660
00661
00662
00663 static void print_unix_job(const char *sharename, print_queue_struct *q, uint32 jobid)
00664 {
00665 struct printjob pj, *old_pj;
00666
00667 if (jobid == (uint32)-1)
00668 jobid = q->job + UNIX_JOB_START;
00669
00670
00671
00672 old_pj = print_job_find(sharename, jobid);
00673
00674 ZERO_STRUCT(pj);
00675
00676 pj.pid = (pid_t)-1;
00677 pj.sysjob = q->job;
00678 pj.fd = -1;
00679 pj.starttime = old_pj ? old_pj->starttime : q->time;
00680 pj.status = q->status;
00681 pj.size = q->size;
00682 pj.spooled = True;
00683 fstrcpy(pj.filename, old_pj ? old_pj->filename : "");
00684 if (jobid < UNIX_JOB_START) {
00685 pj.smbjob = True;
00686 fstrcpy(pj.jobname, old_pj ? old_pj->jobname : "Remote Downlevel Document");
00687 } else {
00688 pj.smbjob = False;
00689 fstrcpy(pj.jobname, old_pj ? old_pj->jobname : q->fs_file);
00690 }
00691 fstrcpy(pj.user, old_pj ? old_pj->user : q->fs_user);
00692 fstrcpy(pj.queuename, old_pj ? old_pj->queuename : sharename );
00693
00694 pjob_store(sharename, jobid, &pj);
00695 }
00696
00697
00698 struct traverse_struct {
00699 print_queue_struct *queue;
00700 int qcount, snum, maxcount, total_jobs;
00701 const char *sharename;
00702 time_t lpq_time;
00703 const char *lprm_command;
00704 struct printif *print_if;
00705 };
00706
00707
00708
00709
00710
00711 static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *state)
00712 {
00713 struct traverse_struct *ts = (struct traverse_struct *)state;
00714 struct printjob pjob;
00715 uint32 jobid;
00716 int i = 0;
00717
00718 if ( key.dsize != sizeof(jobid) )
00719 return 0;
00720
00721 jobid = IVAL(key.dptr, 0);
00722 if ( unpack_pjob( data.dptr, data.dsize, &pjob ) == -1 )
00723 return 0;
00724 free_nt_devicemode( &pjob.nt_devmode );
00725
00726
00727 if (!pjob.smbjob) {
00728
00729
00730 for (i=0;i<ts->qcount;i++) {
00731 uint32 u_jobid = (ts->queue[i].job + UNIX_JOB_START);
00732 if (jobid == u_jobid)
00733 break;
00734 }
00735 if (i == ts->qcount) {
00736 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !smbjob\n",
00737 (unsigned int)jobid ));
00738 pjob_delete(ts->sharename, jobid);
00739 return 0;
00740 }
00741
00742
00743
00744 }
00745
00746
00747 if (!pjob.spooled) {
00748
00749
00750
00751 if (!process_exists_by_pid(pjob.pid)) {
00752 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !process_exists (%u)\n",
00753 (unsigned int)jobid, (unsigned int)pjob.pid ));
00754 pjob_delete(ts->sharename, jobid);
00755 } else
00756 ts->total_jobs++;
00757 return 0;
00758 }
00759
00760
00761
00762 if ( pjob.smbjob ) {
00763 for (i=0;i<ts->qcount;i++) {
00764 uint32 curr_jobid;
00765
00766 if ( pjob.status == LPQ_DELETED )
00767 continue;
00768
00769 curr_jobid = print_parse_jobid(ts->queue[i].fs_file);
00770
00771 if (jobid == curr_jobid) {
00772
00773
00774
00775 if ( pjob.status == LPQ_DELETING ) {
00776 int result;
00777
00778 result = (*(ts->print_if->job_delete))(
00779 ts->sharename, ts->lprm_command, &pjob );
00780
00781 if ( result != 0 ) {
00782
00783 pjob.status = LPQ_QUEUED;
00784 pjob_store(ts->sharename, jobid, &pjob);
00785 }
00786 else {
00787
00788 pjob_delete(ts->sharename, jobid);
00789 pjob.status = LPQ_DELETED;
00790 }
00791
00792 }
00793
00794 break;
00795 }
00796 }
00797 }
00798
00799
00800
00801
00802 if (i == ts->qcount) {
00803
00804
00805
00806
00807
00808
00809
00810
00811 if (pjob.starttime < ts->lpq_time) {
00812 DEBUG(10,("traverse_fn_delete: pjob %u deleted due to pjob.starttime (%u) < ts->lpq_time (%u)\n",
00813 (unsigned int)jobid,
00814 (unsigned int)pjob.starttime,
00815 (unsigned int)ts->lpq_time ));
00816 pjob_delete(ts->sharename, jobid);
00817 } else
00818 ts->total_jobs++;
00819 return 0;
00820 }
00821
00822
00823
00824
00825
00826 ts->queue[i].job = jobid;
00827 ts->queue[i].size = pjob.size;
00828 ts->queue[i].page_count = pjob.page_count;
00829 ts->queue[i].status = pjob.status;
00830 ts->queue[i].priority = 1;
00831 ts->queue[i].time = pjob.starttime;
00832 fstrcpy(ts->queue[i].fs_user, pjob.user);
00833 fstrcpy(ts->queue[i].fs_file, pjob.jobname);
00834
00835 ts->total_jobs++;
00836
00837 return 0;
00838 }
00839
00840
00841
00842
00843
00844 static void print_cache_flush(const char *sharename)
00845 {
00846 fstring key;
00847 struct tdb_print_db *pdb = get_print_db_byname(sharename);
00848
00849 if (!pdb)
00850 return;
00851 slprintf(key, sizeof(key)-1, "CACHE/%s", sharename);
00852 tdb_store_int32(pdb->tdb, key, -1);
00853 release_print_db(pdb);
00854 }
00855
00856
00857
00858
00859
00860 static pid_t get_updating_pid(const char *sharename)
00861 {
00862 fstring keystr;
00863 TDB_DATA data, key;
00864 pid_t updating_pid;
00865 struct tdb_print_db *pdb = get_print_db_byname(sharename);
00866
00867 if (!pdb)
00868 return (pid_t)-1;
00869 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
00870 key.dptr = keystr;
00871 key.dsize = strlen(keystr);
00872
00873 data = tdb_fetch(pdb->tdb, key);
00874 release_print_db(pdb);
00875 if (!data.dptr || data.dsize != sizeof(pid_t)) {
00876 SAFE_FREE(data.dptr);
00877 return (pid_t)-1;
00878 }
00879
00880 updating_pid = IVAL(data.dptr, 0);
00881 SAFE_FREE(data.dptr);
00882
00883 if (process_exists_by_pid(updating_pid))
00884 return updating_pid;
00885
00886 return (pid_t)-1;
00887 }
00888
00889
00890
00891
00892
00893
00894 static void set_updating_pid(const fstring sharename, BOOL updating)
00895 {
00896 fstring keystr;
00897 TDB_DATA key;
00898 TDB_DATA data;
00899 pid_t updating_pid = sys_getpid();
00900 uint8 buffer[4];
00901
00902 struct tdb_print_db *pdb = get_print_db_byname(sharename);
00903
00904 if (!pdb)
00905 return;
00906
00907 slprintf(keystr, sizeof(keystr)-1, "UPDATING/%s", sharename);
00908 key.dptr = keystr;
00909 key.dsize = strlen(keystr);
00910
00911 DEBUG(5, ("set_updating_pid: %s updating lpq cache for print share %s\n",
00912 updating ? "" : "not ",
00913 sharename ));
00914
00915 if ( !updating ) {
00916 tdb_delete(pdb->tdb, key);
00917 release_print_db(pdb);
00918 return;
00919 }
00920
00921 SIVAL( buffer, 0, updating_pid);
00922 data.dptr = (char *)buffer;
00923 data.dsize = 4;
00924
00925 tdb_store(pdb->tdb, key, data, TDB_REPLACE);
00926 release_print_db(pdb);
00927 }
00928
00929
00930
00931
00932
00933 static int printjob_comp(print_queue_struct *j1, print_queue_struct *j2)
00934 {
00935
00936
00937 if (!j1 && !j2)
00938 return 0;
00939 if (!j1)
00940 return -1;
00941 if (!j2)
00942 return 1;
00943
00944
00945
00946 if (j1->time == j2->time)
00947 return 0;
00948 return (j1->time > j2->time) ? 1 : -1;
00949 }
00950
00951
00952
00953
00954
00955
00956 static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct *pts)
00957 {
00958 TDB_DATA data;
00959 int max_reported_jobs = lp_max_reported_jobs(pts->snum);
00960 print_queue_struct *queue = pts->queue;
00961 size_t len;
00962 size_t i;
00963 uint qcount;
00964
00965 if (max_reported_jobs && (max_reported_jobs < pts->qcount))
00966 pts->qcount = max_reported_jobs;
00967 qcount = 0;
00968
00969
00970 data.dsize = 0;
00971 data.dsize += tdb_pack(NULL, 0, "d", qcount);
00972
00973 for (i = 0; i < pts->qcount; i++) {
00974 if ( queue[i].status == LPQ_DELETED )
00975 continue;
00976
00977 qcount++;
00978 data.dsize += tdb_pack(NULL, 0, "ddddddff",
00979 (uint32)queue[i].job,
00980 (uint32)queue[i].size,
00981 (uint32)queue[i].page_count,
00982 (uint32)queue[i].status,
00983 (uint32)queue[i].priority,
00984 (uint32)queue[i].time,
00985 queue[i].fs_user,
00986 queue[i].fs_file);
00987 }
00988
00989 if ((data.dptr = (char *)SMB_MALLOC(data.dsize)) == NULL)
00990 return;
00991
00992 len = 0;
00993 len += tdb_pack(data.dptr + len, data.dsize - len, "d", qcount);
00994 for (i = 0; i < pts->qcount; i++) {
00995 if ( queue[i].status == LPQ_DELETED )
00996 continue;
00997
00998 len += tdb_pack(data.dptr + len, data.dsize - len, "ddddddff",
00999 (uint32)queue[i].job,
01000 (uint32)queue[i].size,
01001 (uint32)queue[i].page_count,
01002 (uint32)queue[i].status,
01003 (uint32)queue[i].priority,
01004 (uint32)queue[i].time,
01005 queue[i].fs_user,
01006 queue[i].fs_file);
01007 }
01008
01009 tdb_store(pdb->tdb, string_tdb_data("INFO/linear_queue_array"), data,
01010 TDB_REPLACE);
01011 SAFE_FREE(data.dptr);
01012 return;
01013 }
01014
01015 static TDB_DATA get_jobs_changed_data(struct tdb_print_db *pdb)
01016 {
01017 TDB_DATA data;
01018
01019 ZERO_STRUCT(data);
01020
01021 data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_changed"));
01022 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0)) {
01023 SAFE_FREE(data.dptr);
01024 ZERO_STRUCT(data);
01025 }
01026
01027 return data;
01028 }
01029
01030 static void check_job_changed(const char *sharename, TDB_DATA data, uint32 jobid)
01031 {
01032 unsigned int i;
01033 unsigned int job_count = data.dsize / 4;
01034
01035 for (i = 0; i < job_count; i++) {
01036 uint32 ch_jobid;
01037
01038 ch_jobid = IVAL(data.dptr, i*4);
01039 if (ch_jobid == jobid)
01040 remove_from_jobs_changed(sharename, jobid);
01041 }
01042 }
01043
01044
01045
01046
01047
01048 static BOOL print_cache_expired(const char *sharename, BOOL check_pending)
01049 {
01050 fstring key;
01051 time_t last_qscan_time, time_now = time(NULL);
01052 struct tdb_print_db *pdb = get_print_db_byname(sharename);
01053 BOOL result = False;
01054
01055 if (!pdb)
01056 return False;
01057
01058 snprintf(key, sizeof(key), "CACHE/%s", sharename);
01059 last_qscan_time = (time_t)tdb_fetch_int32(pdb->tdb, key);
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071 if (last_qscan_time == ((time_t)-1)
01072 || (time_now - last_qscan_time) >= lp_lpqcachetime()
01073 || last_qscan_time > (time_now + MAX_CACHE_VALID_TIME))
01074 {
01075 uint32 u;
01076 time_t msg_pending_time;
01077
01078 DEBUG(4, ("print_cache_expired: cache expired for queue %s "
01079 "(last_qscan_time = %d, time now = %d, qcachetime = %d)\n",
01080 sharename, (int)last_qscan_time, (int)time_now,
01081 (int)lp_lpqcachetime() ));
01082
01083
01084
01085
01086
01087
01088 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
01089
01090 if ( check_pending
01091 && tdb_fetch_uint32( pdb->tdb, key, &u )
01092 && (msg_pending_time=u) > 0
01093 && msg_pending_time <= time_now
01094 && (time_now - msg_pending_time) < 60 )
01095 {
01096 DEBUG(4,("print_cache_expired: message already pending for %s. Accepting cache\n",
01097 sharename));
01098 goto done;
01099 }
01100
01101 result = True;
01102 }
01103
01104 done:
01105 release_print_db(pdb);
01106 return result;
01107 }
01108
01109
01110
01111
01112
01113 static void print_queue_update_internal( const char *sharename,
01114 struct printif *current_printif,
01115 char *lpq_command, char *lprm_command )
01116 {
01117 int i, qcount;
01118 print_queue_struct *queue = NULL;
01119 print_status_struct status;
01120 print_status_struct old_status;
01121 struct printjob *pjob;
01122 struct traverse_struct tstruct;
01123 TDB_DATA data, key;
01124 TDB_DATA jcdata;
01125 fstring keystr, cachestr;
01126 struct tdb_print_db *pdb = get_print_db_byname(sharename);
01127
01128 if (!pdb) {
01129 return;
01130 }
01131
01132 DEBUG(5,("print_queue_update_internal: printer = %s, type = %d, lpq command = [%s]\n",
01133 sharename, current_printif->type, lpq_command));
01134
01135
01136
01137
01138
01139
01140
01141 slprintf(cachestr, sizeof(cachestr)-1, "CACHE/%s", sharename);
01142 tdb_store_int32(pdb->tdb, cachestr, (int)time(NULL));
01143
01144
01145 ZERO_STRUCT(status);
01146
01147 qcount = (*(current_printif->queue_get))(sharename,
01148 current_printif->type,
01149 lpq_command, &queue, &status);
01150
01151 DEBUG(3, ("print_queue_update_internal: %d job%s in queue for %s\n",
01152 qcount, (qcount != 1) ? "s" : "", sharename));
01153
01154
01155
01156
01157 qsort(queue, qcount, sizeof(print_queue_struct),
01158 QSORT_CAST(printjob_comp));
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171 jcdata = get_jobs_changed_data(pdb);
01172
01173 for (i=0; i<qcount; i++) {
01174 uint32 jobid = print_parse_jobid(queue[i].fs_file);
01175
01176 if (jobid == (uint32)-1) {
01177
01178 print_unix_job(sharename, &queue[i], jobid);
01179 continue;
01180 }
01181
01182
01183 pjob = print_job_find(sharename, jobid);
01184 if (!pjob) {
01185
01186
01187
01188 print_unix_job(sharename, &queue[i], jobid);
01189 continue;
01190 }
01191
01192 pjob->sysjob = queue[i].job;
01193
01194
01195
01196 if ( pjob->status != LPQ_DELETING )
01197 pjob->status = queue[i].status;
01198
01199 pjob_store(sharename, jobid, pjob);
01200
01201 check_job_changed(sharename, jcdata, jobid);
01202 }
01203
01204 SAFE_FREE(jcdata.dptr);
01205
01206
01207
01208 tstruct.queue = queue;
01209 tstruct.qcount = qcount;
01210 tstruct.snum = -1;
01211 tstruct.total_jobs = 0;
01212 tstruct.lpq_time = time(NULL);
01213 tstruct.sharename = sharename;
01214 tstruct.lprm_command = lprm_command;
01215 tstruct.print_if = current_printif;
01216
01217 tdb_traverse(pdb->tdb, traverse_fn_delete, (void *)&tstruct);
01218
01219
01220 store_queue_struct(pdb, &tstruct);
01221
01222 SAFE_FREE(tstruct.queue);
01223
01224 DEBUG(10,("print_queue_update_internal: printer %s INFO/total_jobs = %d\n",
01225 sharename, tstruct.total_jobs ));
01226
01227 tdb_store_int32(pdb->tdb, "INFO/total_jobs", tstruct.total_jobs);
01228
01229 get_queue_status(sharename, &old_status);
01230 if (old_status.qcount != qcount)
01231 DEBUG(10,("print_queue_update_internal: queue status change %d jobs -> %d jobs for printer %s\n",
01232 old_status.qcount, qcount, sharename));
01233
01234
01235 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
01236 key.dptr = keystr;
01237 key.dsize = strlen(keystr);
01238
01239 status.qcount = qcount;
01240 data.dptr = (char *)&status;
01241 data.dsize = sizeof(status);
01242 tdb_store(pdb->tdb, key, data, TDB_REPLACE);
01243
01244
01245
01246
01247
01248
01249 slprintf(keystr, sizeof(keystr)-1, "CACHE/%s", sharename);
01250 tdb_store_int32(pdb->tdb, keystr, (int32)time(NULL));
01251
01252
01253
01254 snprintf(keystr, sizeof(keystr), "MSG_PENDING/%s", sharename);
01255
01256 if ( !tdb_store_uint32( pdb->tdb, keystr, 0 ) ) {
01257
01258
01259 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
01260 sharename));
01261 }
01262
01263 release_print_db( pdb );
01264
01265 return;
01266 }
01267
01268
01269
01270
01271
01272
01273
01274 static void print_queue_update_with_lock( const char *sharename,
01275 struct printif *current_printif,
01276 char *lpq_command, char *lprm_command )
01277 {
01278 fstring keystr;
01279 struct tdb_print_db *pdb;
01280
01281 DEBUG(5,("print_queue_update_with_lock: printer share = %s\n", sharename));
01282 pdb = get_print_db_byname(sharename);
01283 if (!pdb)
01284 return;
01285
01286 if ( !print_cache_expired(sharename, False) ) {
01287 DEBUG(5,("print_queue_update_with_lock: print cache for %s is still ok\n", sharename));
01288 release_print_db(pdb);
01289 return;
01290 }
01291
01292
01293
01294
01295
01296
01297 if (get_updating_pid(sharename) != -1) {
01298 release_print_db(pdb);
01299 return;
01300 }
01301
01302
01303
01304 slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", sharename);
01305
01306 if (tdb_lock_bystring_with_timeout(pdb->tdb, keystr, 10) == -1) {
01307 DEBUG(0,("print_queue_update_with_lock: Failed to lock printer %s database\n", sharename));
01308 release_print_db(pdb);
01309 return;
01310 }
01311
01312
01313
01314
01315
01316
01317
01318 if (get_updating_pid(sharename) != -1) {
01319
01320
01321
01322 tdb_unlock_bystring(pdb->tdb, keystr);
01323 release_print_db(pdb);
01324 return;
01325 }
01326
01327
01328
01329
01330
01331
01332 set_updating_pid(sharename, True);
01333
01334
01335
01336
01337
01338
01339 tdb_unlock_bystring(pdb->tdb, keystr);
01340
01341
01342
01343 print_queue_update_internal( sharename, current_printif,
01344 lpq_command, lprm_command );
01345
01346
01347 set_updating_pid(sharename, False);
01348 release_print_db(pdb);
01349 }
01350
01351
01352
01353
01354 static void print_queue_receive(int msg_type, struct process_id src,
01355 void *buf, size_t msglen,
01356 void *private_data)
01357 {
01358 fstring sharename;
01359 pstring lpqcommand, lprmcommand;
01360 int printing_type;
01361 size_t len;
01362
01363 len = tdb_unpack( (char *)buf, msglen, "fdPP",
01364 sharename,
01365 &printing_type,
01366 lpqcommand,
01367 lprmcommand );
01368
01369 if ( len == -1 ) {
01370 DEBUG(0,("print_queue_receive: Got invalid print queue update message\n"));
01371 return;
01372 }
01373
01374 print_queue_update_with_lock(sharename,
01375 get_printer_fns_from_type((enum printing_types)printing_type),
01376 lpqcommand, lprmcommand );
01377
01378 return;
01379 }
01380
01381 static pid_t background_lpq_updater_pid = -1;
01382
01383
01384
01385
01386 void start_background_queue(void)
01387 {
01388 DEBUG(3,("start_background_queue: Starting background LPQ thread\n"));
01389 background_lpq_updater_pid = sys_fork();
01390
01391 if (background_lpq_updater_pid == -1) {
01392 DEBUG(5,("start_background_queue: background LPQ thread failed to start. %s\n", strerror(errno) ));
01393 exit(1);
01394 }
01395
01396 if(background_lpq_updater_pid == 0) {
01397
01398 DEBUG(5,("start_background_queue: background LPQ thread started\n"));
01399
01400 claim_connection( NULL, "smbd lpq backend", 0, False,
01401 FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL);
01402
01403 if (!locking_init(0)) {
01404 exit(1);
01405 }
01406
01407 message_register(MSG_PRINTER_UPDATE, print_queue_receive,
01408 NULL);
01409
01410 DEBUG(5,("start_background_queue: background LPQ thread waiting for messages\n"));
01411 while (1) {
01412 pause();
01413
01414
01415
01416 if (got_sig_term) {
01417 exit_server_cleanly(NULL);
01418 }
01419
01420 if (reload_after_sighup) {
01421 change_to_root_user();
01422 DEBUG(1,("Reloading services after SIGHUP\n"));
01423 reload_services(False);
01424 reload_after_sighup = 0;
01425 }
01426
01427
01428
01429 DEBUG(10,("start_background_queue: background LPQ thread got a message\n"));
01430 message_dispatch();
01431
01432
01433
01434 print_notify_send_messages(0);
01435 }
01436 }
01437 }
01438
01439
01440
01441
01442
01443 static void print_queue_update(int snum, BOOL force)
01444 {
01445 fstring key;
01446 fstring sharename;
01447 pstring lpqcommand, lprmcommand;
01448 char *buffer = NULL;
01449 size_t len = 0;
01450 size_t newlen;
01451 struct tdb_print_db *pdb;
01452 int type;
01453 struct printif *current_printif;
01454
01455 fstrcpy( sharename, lp_const_servicename(snum));
01456
01457
01458
01459 pstrcpy( lpqcommand, lp_lpqcommand(snum));
01460 string_sub2( lpqcommand, "%p", PRINTERNAME(snum), sizeof(lpqcommand),
01461 False, False, False );
01462 standard_sub_advanced(lp_servicename(snum),
01463 current_user_info.unix_name, "",
01464 current_user.ut.gid,
01465 get_current_username(),
01466 current_user_info.domain,
01467 lpqcommand, sizeof(lpqcommand) );
01468
01469 pstrcpy( lprmcommand, lp_lprmcommand(snum));
01470 string_sub2( lprmcommand, "%p", PRINTERNAME(snum), sizeof(lprmcommand),
01471 False, False, False );
01472 standard_sub_advanced(lp_servicename(snum),
01473 current_user_info.unix_name, "",
01474 current_user.ut.gid,
01475 get_current_username(),
01476 current_user_info.domain,
01477 lprmcommand, sizeof(lprmcommand) );
01478
01479
01480
01481
01482
01483
01484 if ( force || background_lpq_updater_pid == -1 ) {
01485 DEBUG(4,("print_queue_update: updating queue [%s] myself\n", sharename));
01486 current_printif = get_printer_fns( snum );
01487 print_queue_update_with_lock( sharename, current_printif, lpqcommand, lprmcommand );
01488
01489 return;
01490 }
01491
01492 type = lp_printing(snum);
01493
01494
01495
01496 len = tdb_pack( NULL, 0, "fdPP",
01497 sharename,
01498 type,
01499 lpqcommand,
01500 lprmcommand );
01501
01502 buffer = SMB_XMALLOC_ARRAY( char, len );
01503
01504
01505 newlen = tdb_pack( buffer, len, "fdPP",
01506 sharename,
01507 type,
01508 lpqcommand,
01509 lprmcommand );
01510
01511 SMB_ASSERT( newlen == len );
01512
01513 DEBUG(10,("print_queue_update: Sending message -> printer = %s, "
01514 "type = %d, lpq command = [%s] lprm command = [%s]\n",
01515 sharename, type, lpqcommand, lprmcommand ));
01516
01517
01518
01519
01520
01521 pdb = get_print_db_byname(sharename);
01522 if (!pdb) {
01523 SAFE_FREE(buffer);
01524 return;
01525 }
01526
01527 snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
01528
01529 if ( !tdb_store_uint32( pdb->tdb, key, time(NULL) ) ) {
01530
01531
01532 DEBUG(0,("print_queue_update: failed to store MSG_PENDING flag for [%s]!\n",
01533 sharename));
01534 }
01535
01536 release_print_db( pdb );
01537
01538
01539
01540 message_send_pid(pid_to_procid(background_lpq_updater_pid),
01541 MSG_PRINTER_UPDATE, buffer, len, False);
01542
01543 SAFE_FREE( buffer );
01544
01545 return;
01546 }
01547
01548
01549
01550
01551
01552
01553 BOOL print_notify_register_pid(int snum)
01554 {
01555 TDB_DATA data;
01556 struct tdb_print_db *pdb = NULL;
01557 TDB_CONTEXT *tdb = NULL;
01558 const char *printername;
01559 uint32 mypid = (uint32)sys_getpid();
01560 BOOL ret = False;
01561 size_t i;
01562
01563
01564
01565
01566
01567 if (snum == -1)
01568 {
01569 int num_services = lp_numservices();
01570 int idx;
01571
01572 for ( idx=0; idx<num_services; idx++ ) {
01573 if (lp_snum_ok(idx) && lp_print_ok(idx) )
01574 print_notify_register_pid(idx);
01575 }
01576
01577 return True;
01578 }
01579 else
01580 {
01581 printername = lp_const_servicename(snum);
01582 pdb = get_print_db_byname(printername);
01583 if (!pdb)
01584 return False;
01585 tdb = pdb->tdb;
01586 }
01587
01588 if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) {
01589 DEBUG(0,("print_notify_register_pid: Failed to lock printer %s\n",
01590 printername));
01591 if (pdb)
01592 release_print_db(pdb);
01593 return False;
01594 }
01595
01596 data = get_printer_notify_pid_list( tdb, printername, True );
01597
01598
01599
01600 for (i = 0; i < data.dsize; i += 8) {
01601 if (IVAL(data.dptr,i) == mypid) {
01602 uint32 new_refcount = IVAL(data.dptr, i+4) + 1;
01603 SIVAL(data.dptr, i+4, new_refcount);
01604 break;
01605 }
01606 }
01607
01608 if (i == data.dsize) {
01609
01610 data.dptr = (char *)SMB_REALLOC(data.dptr, data.dsize + 8);
01611 if (!data.dptr) {
01612 DEBUG(0,("print_notify_register_pid: Relloc fail for printer %s\n",
01613 printername));
01614 goto done;
01615 }
01616 data.dsize += 8;
01617 SIVAL(data.dptr,data.dsize - 8,mypid);
01618 SIVAL(data.dptr,data.dsize - 4,1);
01619 }
01620
01621
01622 if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) == -1) {
01623 DEBUG(0,("print_notify_register_pid: Failed to update pid \
01624 list for printer %s\n", printername));
01625 goto done;
01626 }
01627
01628 ret = True;
01629
01630 done:
01631
01632 tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
01633 if (pdb)
01634 release_print_db(pdb);
01635 SAFE_FREE(data.dptr);
01636 return ret;
01637 }
01638
01639
01640
01641
01642
01643
01644 BOOL print_notify_deregister_pid(int snum)
01645 {
01646 TDB_DATA data;
01647 struct tdb_print_db *pdb = NULL;
01648 TDB_CONTEXT *tdb = NULL;
01649 const char *printername;
01650 uint32 mypid = (uint32)sys_getpid();
01651 size_t i;
01652 BOOL ret = False;
01653
01654
01655
01656
01657 if (snum == -1)
01658 {
01659 int num_services = lp_numservices();
01660 int idx;
01661
01662 for ( idx=0; idx<num_services; idx++ ) {
01663 if ( lp_snum_ok(idx) && lp_print_ok(idx) )
01664 print_notify_deregister_pid(idx);
01665 }
01666
01667 return True;
01668 }
01669 else
01670 {
01671 printername = lp_const_servicename(snum);
01672 pdb = get_print_db_byname(printername);
01673 if (!pdb)
01674 return False;
01675 tdb = pdb->tdb;
01676 }
01677
01678 if (tdb_lock_bystring_with_timeout(tdb, NOTIFY_PID_LIST_KEY, 10) == -1) {
01679 DEBUG(0,("print_notify_register_pid: Failed to lock \
01680 printer %s database\n", printername));
01681 if (pdb)
01682 release_print_db(pdb);
01683 return False;
01684 }
01685
01686 data = get_printer_notify_pid_list( tdb, printername, True );
01687
01688
01689
01690 for (i = 0; i < data.dsize; ) {
01691 if (IVAL(data.dptr,i) == mypid) {
01692 uint32 refcount = IVAL(data.dptr, i+4);
01693
01694 refcount--;
01695
01696 if (refcount == 0) {
01697 if (data.dsize - i > 8)
01698 memmove( &data.dptr[i], &data.dptr[i+8], data.dsize - i - 8);
01699 data.dsize -= 8;
01700 continue;
01701 }
01702 SIVAL(data.dptr, i+4, refcount);
01703 }
01704
01705 i += 8;
01706 }
01707
01708 if (data.dsize == 0)
01709 SAFE_FREE(data.dptr);
01710
01711
01712 if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) == -1) {
01713 DEBUG(0,("print_notify_register_pid: Failed to update pid \
01714 list for printer %s\n", printername));
01715 goto done;
01716 }
01717
01718 ret = True;
01719
01720 done:
01721
01722 tdb_unlock_bystring(tdb, NOTIFY_PID_LIST_KEY);
01723 if (pdb)
01724 release_print_db(pdb);
01725 SAFE_FREE(data.dptr);
01726 return ret;
01727 }
01728
01729
01730
01731
01732
01733 BOOL print_job_exists(const char* sharename, uint32 jobid)
01734 {
01735 struct tdb_print_db *pdb = get_print_db_byname(sharename);
01736 BOOL ret;
01737
01738 if (!pdb)
01739 return False;
01740 ret = tdb_exists(pdb->tdb, print_key(jobid));
01741 release_print_db(pdb);
01742 return ret;
01743 }
01744
01745
01746
01747
01748
01749 int print_job_fd(const char* sharename, uint32 jobid)
01750 {
01751 struct printjob *pjob = print_job_find(sharename, jobid);
01752 if (!pjob)
01753 return -1;
01754
01755 if (pjob->pid != sys_getpid())
01756 return -1;
01757 return pjob->fd;
01758 }
01759
01760
01761
01762
01763
01764
01765
01766 char *print_job_fname(const char* sharename, uint32 jobid)
01767 {
01768 struct printjob *pjob = print_job_find(sharename, jobid);
01769 if (!pjob || pjob->spooled || pjob->pid != sys_getpid())
01770 return NULL;
01771 return pjob->filename;
01772 }
01773
01774
01775
01776
01777
01778
01779
01780
01781 NT_DEVICEMODE *print_job_devmode(const char* sharename, uint32 jobid)
01782 {
01783 struct printjob *pjob = print_job_find(sharename, jobid);
01784
01785 if ( !pjob )
01786 return NULL;
01787
01788 return pjob->nt_devmode;
01789 }
01790
01791
01792
01793
01794
01795 BOOL print_job_set_place(const char *sharename, uint32 jobid, int place)
01796 {
01797 DEBUG(2,("print_job_set_place not implemented yet\n"));
01798 return False;
01799 }
01800
01801
01802
01803
01804
01805 BOOL print_job_set_name(const char *sharename, uint32 jobid, char *name)
01806 {
01807 struct printjob *pjob;
01808
01809 pjob = print_job_find(sharename, jobid);
01810 if (!pjob || pjob->pid != sys_getpid())
01811 return False;
01812
01813 fstrcpy(pjob->jobname, name);
01814 return pjob_store(sharename, jobid, pjob);
01815 }
01816
01817
01818
01819
01820
01821 static BOOL remove_from_jobs_changed(const char* sharename, uint32 jobid)
01822 {
01823 struct tdb_print_db *pdb = get_print_db_byname(sharename);
01824 TDB_DATA data, key;
01825 size_t job_count, i;
01826 BOOL ret = False;
01827 BOOL gotlock = False;
01828
01829 if (!pdb) {
01830 return False;
01831 }
01832
01833 ZERO_STRUCT(data);
01834
01835 key = string_tdb_data("INFO/jobs_changed");
01836
01837 if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) == -1)
01838 goto out;
01839
01840 gotlock = True;
01841
01842 data = tdb_fetch(pdb->tdb, key);
01843
01844 if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0))
01845 goto out;
01846
01847 job_count = data.dsize / 4;
01848 for (i = 0; i < job_count; i++) {
01849 uint32 ch_jobid;
01850
01851 ch_jobid = IVAL(data.dptr, i*4);
01852 if (ch_jobid == jobid) {
01853 if (i < job_count -1 )
01854 memmove(data.dptr + (i*4), data.dptr + (i*4) + 4, (job_count - i - 1)*4 );
01855 data.dsize -= 4;
01856 if (tdb_store(pdb->tdb, key, data, TDB_REPLACE) == -1)
01857 goto out;
01858 break;
01859 }
01860 }
01861
01862 ret = True;
01863 out:
01864
01865 if (gotlock)
01866 tdb_chainunlock(pdb->tdb, key);
01867 SAFE_FREE(data.dptr);
01868 release_print_db(pdb);
01869 if (ret)
01870 DEBUG(10,("remove_from_jobs_changed: removed jobid %u\n", (unsigned int)jobid ));
01871 else
01872 DEBUG(10,("remove_from_jobs_changed: Failed to remove jobid %u\n", (unsigned int)jobid ));
01873 return ret;
01874 }
01875
01876
01877
01878
01879
01880 static BOOL print_job_delete1(int snum, uint32 jobid)
01881 {
01882 const char* sharename = lp_const_servicename(snum);
01883 struct printjob *pjob = print_job_find(sharename, jobid);
01884 int result = 0;
01885 struct printif *current_printif = get_printer_fns( snum );
01886
01887 if (!pjob)
01888 return False;
01889
01890
01891
01892
01893
01894 if (pjob->status == LPQ_DELETING)
01895 return True;
01896
01897
01898
01899
01900
01901
01902 if (pjob->sysjob == -1) {
01903 DEBUG(5, ("attempt to delete job %u not seen by lpr\n", (unsigned int)jobid));
01904 }
01905
01906
01907
01908 pjob->status = LPQ_DELETING;
01909 pjob_store(sharename, jobid, pjob);
01910
01911 if (pjob->spooled && pjob->sysjob != -1)
01912 {
01913 result = (*(current_printif->job_delete))(
01914 PRINTERNAME(snum),
01915 lp_lprmcommand(snum),
01916 pjob);
01917
01918
01919
01920
01921 if (result == 0) {
01922 struct tdb_print_db *pdb = get_print_db_byname(sharename);
01923 int njobs = 1;
01924
01925 if (!pdb)
01926 return False;
01927 pjob_delete(sharename, jobid);
01928
01929 tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, -1);
01930 release_print_db(pdb);
01931 }
01932 }
01933
01934 remove_from_jobs_changed( sharename, jobid );
01935
01936 return (result == 0);
01937 }
01938
01939
01940
01941
01942
01943 static BOOL is_owner(struct current_user *user, const char *servicename,
01944 uint32 jobid)
01945 {
01946 struct printjob *pjob = print_job_find(servicename, jobid);
01947 user_struct *vuser;
01948
01949 if (!pjob || !user)
01950 return False;
01951
01952 if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
01953 return strequal(pjob->user, vuser->user.smb_name);
01954 } else {
01955 return strequal(pjob->user, uidtoname(user->ut.uid));
01956 }
01957 }
01958
01959
01960
01961
01962
01963 BOOL print_job_delete(struct current_user *user, int snum, uint32 jobid, WERROR *errcode)
01964 {
01965 const char* sharename = lp_const_servicename( snum );
01966 struct printjob *pjob;
01967 BOOL owner;
01968 char *fname;
01969
01970 *errcode = WERR_OK;
01971
01972 owner = is_owner(user, lp_const_servicename(snum), jobid);
01973
01974
01975
01976
01977 if (!owner &&
01978 !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
01979 DEBUG(3, ("delete denied by security descriptor\n"));
01980 *errcode = WERR_ACCESS_DENIED;
01981
01982
01983 sys_adminlog( LOG_ERR,
01984 "Permission denied-- user not allowed to delete, \
01985 pause, or resume print job. User name: %s. Printer name: %s.",
01986 uidtoname(user->ut.uid), PRINTERNAME(snum) );
01987
01988
01989 return False;
01990 }
01991
01992
01993
01994
01995
01996
01997
01998
01999 if ( (fname = print_job_fname( sharename, jobid )) != NULL )
02000 {
02001
02002 DEBUG(10,("print_job_delete: Removing spool file [%s]\n", fname ));
02003 if ( unlink( fname ) == -1 ) {
02004 *errcode = map_werror_from_unix(errno);
02005 return False;
02006 }
02007 }
02008
02009 if (!print_job_delete1(snum, jobid)) {
02010 *errcode = WERR_ACCESS_DENIED;
02011 return False;
02012 }
02013
02014
02015
02016
02017 print_queue_update(snum, True);
02018
02019 pjob = print_job_find(sharename, jobid);
02020 if ( pjob && (pjob->status != LPQ_DELETING) )
02021 *errcode = WERR_ACCESS_DENIED;
02022
02023 return (pjob == NULL );
02024 }
02025
02026
02027
02028
02029
02030 BOOL print_job_pause(struct current_user *user, int snum, uint32 jobid, WERROR *errcode)
02031 {
02032 const char* sharename = lp_const_servicename(snum);
02033 struct printjob *pjob;
02034 int ret = -1;
02035 struct printif *current_printif = get_printer_fns( snum );
02036
02037 pjob = print_job_find(sharename, jobid);
02038
02039 if (!pjob || !user) {
02040 DEBUG(10, ("print_job_pause: no pjob or user for jobid %u\n",
02041 (unsigned int)jobid ));
02042 return False;
02043 }
02044
02045 if (!pjob->spooled || pjob->sysjob == -1) {
02046 DEBUG(10, ("print_job_pause: not spooled or bad sysjob = %d for jobid %u\n",
02047 (int)pjob->sysjob, (unsigned int)jobid ));
02048 return False;
02049 }
02050
02051 if (!is_owner(user, lp_const_servicename(snum), jobid) &&
02052 !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
02053 DEBUG(3, ("pause denied by security descriptor\n"));
02054
02055
02056 sys_adminlog( LOG_ERR,
02057 "Permission denied-- user not allowed to delete, \
02058 pause, or resume print job. User name: %s. Printer name: %s.",
02059 uidtoname(user->ut.uid), PRINTERNAME(snum) );
02060
02061
02062 *errcode = WERR_ACCESS_DENIED;
02063 return False;
02064 }
02065
02066
02067 ret = (*(current_printif->job_pause))(snum, pjob);
02068
02069 if (ret != 0) {
02070 *errcode = WERR_INVALID_PARAM;
02071 return False;
02072 }
02073
02074
02075 print_cache_flush(lp_const_servicename(snum));
02076
02077
02078
02079 notify_job_status(sharename, jobid, JOB_STATUS_PAUSED);
02080
02081
02082
02083 return True;
02084 }
02085
02086
02087
02088
02089
02090 BOOL print_job_resume(struct current_user *user, int snum, uint32 jobid, WERROR *errcode)
02091 {
02092 const char *sharename = lp_const_servicename(snum);
02093 struct printjob *pjob;
02094 int ret;
02095 struct printif *current_printif = get_printer_fns( snum );
02096
02097 pjob = print_job_find(sharename, jobid);
02098
02099 if (!pjob || !user) {
02100 DEBUG(10, ("print_job_resume: no pjob or user for jobid %u\n",
02101 (unsigned int)jobid ));
02102 return False;
02103 }
02104
02105 if (!pjob->spooled || pjob->sysjob == -1) {
02106 DEBUG(10, ("print_job_resume: not spooled or bad sysjob = %d for jobid %u\n",
02107 (int)pjob->sysjob, (unsigned int)jobid ));
02108 return False;
02109 }
02110
02111 if (!is_owner(user, lp_const_servicename(snum), jobid) &&
02112 !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
02113 DEBUG(3, ("resume denied by security descriptor\n"));
02114 *errcode = WERR_ACCESS_DENIED;
02115
02116
02117 sys_adminlog( LOG_ERR,
02118 "Permission denied-- user not allowed to delete, \
02119 pause, or resume print job. User name: %s. Printer name: %s.",
02120 uidtoname(user->ut.uid), PRINTERNAME(snum) );
02121
02122 return False;
02123 }
02124
02125 ret = (*(current_printif->job_resume))(snum, pjob);
02126
02127 if (ret != 0) {
02128 *errcode = WERR_INVALID_PARAM;
02129 return False;
02130 }
02131
02132
02133 print_cache_flush(lp_const_servicename(snum));
02134
02135
02136
02137 notify_job_status(sharename, jobid, JOB_STATUS_QUEUED);
02138
02139 return True;
02140 }
02141
02142
02143
02144
02145
02146 ssize_t print_job_write(int snum, uint32 jobid, const char *buf, SMB_OFF_T pos, size_t size)
02147 {
02148 const char* sharename = lp_const_servicename(snum);
02149 int return_code;
02150 struct printjob *pjob;
02151
02152 pjob = print_job_find(sharename, jobid);
02153
02154 if (!pjob)
02155 return -1;
02156
02157 if (pjob->pid != sys_getpid())
02158 return -1;
02159
02160 return_code = write_data_at_offset(pjob->fd, buf, size, pos);
02161
02162 if (return_code>0) {
02163 pjob->size += size;
02164 pjob_store(sharename, jobid, pjob);
02165 }
02166 return return_code;
02167 }
02168
02169
02170
02171
02172
02173 static int get_queue_status(const char* sharename, print_status_struct *status)
02174 {
02175 fstring keystr;
02176 TDB_DATA data;
02177 struct tdb_print_db *pdb = get_print_db_byname(sharename);
02178 int len;
02179
02180 if (status) {
02181 ZERO_STRUCTP(status);
02182 }
02183
02184 if (!pdb)
02185 return 0;
02186
02187 if (status) {
02188 fstr_sprintf(keystr, "STATUS/%s", sharename);
02189 data = tdb_fetch(pdb->tdb, string_tdb_data(keystr));
02190 if (data.dptr) {
02191 if (data.dsize == sizeof(print_status_struct))
02192
02193
02194 memcpy(status, data.dptr, sizeof(print_status_struct));
02195 SAFE_FREE(data.dptr);
02196 }
02197 }
02198 len = tdb_fetch_int32(pdb->tdb, "INFO/total_jobs");
02199 release_print_db(pdb);
02200 return (len == -1 ? 0 : len);
02201 }
02202
02203
02204
02205
02206
02207 int print_queue_length(int snum, print_status_struct *pstatus)
02208 {
02209 const char* sharename = lp_const_servicename( snum );
02210 print_status_struct status;
02211 int len;
02212
02213 ZERO_STRUCT( status );
02214
02215
02216 if (print_cache_expired(lp_const_servicename(snum), True))
02217 print_queue_update(snum, False);
02218
02219
02220 memset(&status, 0, sizeof(status));
02221 len = get_queue_status(sharename, &status);
02222
02223 if (pstatus)
02224 *pstatus = status;
02225
02226 return len;
02227 }
02228
02229
02230
02231
02232
02233 static BOOL allocate_print_jobid(struct tdb_print_db *pdb, int snum, const char *sharename, uint32 *pjobid)
02234 {
02235 int i;
02236 uint32 jobid;
02237
02238 *pjobid = (uint32)-1;
02239
02240 for (i = 0; i < 3; i++) {
02241
02242 if (tdb_lock_bystring_with_timeout(pdb->tdb, "INFO/nextjob", 20) == -1) {
02243 DEBUG(0,("allocate_print_jobid: failed to lock printing database %s\n", sharename));
02244 return False;
02245 }
02246
02247 if (!tdb_fetch_uint32(pdb->tdb, "INFO/nextjob", &jobid)) {
02248 if (tdb_error(pdb->tdb) != TDB_ERR_NOEXIST) {
02249 DEBUG(0, ("allocate_print_jobid: failed to fetch INFO/nextjob for print queue %s\n",
02250 sharename));
02251 return False;
02252 }
02253 jobid = 0;
02254 }
02255
02256 jobid = NEXT_JOBID(jobid);
02257
02258 if (tdb_store_int32(pdb->tdb, "INFO/nextjob", jobid)==-1) {
02259 DEBUG(3, ("allocate_print_jobid: failed to store INFO/nextjob.\n"));
02260 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
02261 return False;
02262 }
02263
02264
02265 tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
02266
02267 if (!print_job_exists(sharename, jobid))
02268 break;
02269 }
02270
02271 if (i > 2) {
02272 DEBUG(0, ("allocate_print_jobid: failed to allocate a print job for queue %s\n",
02273 sharename));
02274
02275 errno = ENOSPC;
02276 return False;
02277 }
02278
02279
02280 {
02281 TDB_DATA dum;
02282 dum.dptr = NULL;
02283 dum.dsize = 0;
02284 if (tdb_store(pdb->tdb, print_key(jobid), dum, TDB_INSERT) == -1) {
02285 DEBUG(3, ("allocate_print_jobid: jobid (%d) failed to store placeholder.\n",
02286 jobid ));
02287 return False;
02288 }
02289 }
02290
02291 *pjobid = jobid;
02292 return True;
02293 }
02294
02295
02296
02297
02298
02299 static BOOL add_to_jobs_changed(struct tdb_print_db *pdb, uint32 jobid)
02300 {
02301 TDB_DATA data;
02302 uint32 store_jobid;
02303
02304 SIVAL(&store_jobid, 0, jobid);
02305 data.dptr = (char *)&store_jobid;
02306 data.dsize = 4;
02307
02308 DEBUG(10,("add_to_jobs_changed: Added jobid %u\n", (unsigned int)jobid ));
02309
02310 return (tdb_append(pdb->tdb, string_tdb_data("INFO/jobs_changed"),
02311 data) == 0);
02312 }
02313
02314
02315
02316
02317
02318 uint32 print_job_start(struct current_user *user, int snum, char *jobname, NT_DEVICEMODE *nt_devmode )
02319 {
02320 uint32 jobid;
02321 char *path;
02322 struct printjob pjob;
02323 user_struct *vuser;
02324 const char *sharename = lp_const_servicename(snum);
02325 struct tdb_print_db *pdb = get_print_db_byname(sharename);
02326 int njobs;
02327
02328 errno = 0;
02329
02330 if (!pdb)
02331 return (uint32)-1;
02332
02333 if (!print_access_check(user, snum, PRINTER_ACCESS_USE)) {
02334 DEBUG(3, ("print_job_start: job start denied by security descriptor\n"));
02335 release_print_db(pdb);
02336 return (uint32)-1;
02337 }
02338
02339 if (!print_time_access_check(lp_servicename(snum))) {
02340 DEBUG(3, ("print_job_start: job start denied by time check\n"));
02341 release_print_db(pdb);
02342 return (uint32)-1;
02343 }
02344
02345 path = lp_pathname(snum);
02346
02347
02348 if (lp_minprintspace(snum)) {
02349 SMB_BIG_UINT dspace, dsize;
02350 if (sys_fsusage(path, &dspace, &dsize) == 0 &&
02351 dspace < 2*(SMB_BIG_UINT)lp_minprintspace(snum)) {
02352 DEBUG(3, ("print_job_start: disk space check failed.\n"));
02353 release_print_db(pdb);
02354 errno = ENOSPC;
02355 return (uint32)-1;
02356 }
02357 }
02358
02359
02360 if (lp_autoloaded(snum) && !pcap_printername_ok(lp_const_servicename(snum))) {
02361 DEBUG(3, ("print_job_start: printer name %s check failed.\n", lp_const_servicename(snum) ));
02362 release_print_db(pdb);
02363 errno = ENOENT;
02364 return (uint32)-1;
02365 }
02366
02367
02368 if ((njobs = print_queue_length(snum,NULL)) > lp_maxprintjobs(snum)) {
02369 DEBUG(3, ("print_job_start: Queue %s number of jobs (%d) larger than max printjobs per queue (%d).\n",
02370 sharename, njobs, lp_maxprintjobs(snum) ));
02371 release_print_db(pdb);
02372 errno = ENOSPC;
02373 return (uint32)-1;
02374 }
02375
02376 DEBUG(10,("print_job_start: Queue %s number of jobs (%d), max printjobs = %d\n",
02377 sharename, njobs, lp_maxprintjobs(snum) ));
02378
02379 if (!allocate_print_jobid(pdb, snum, sharename, &jobid))
02380 goto fail;
02381
02382
02383
02384 ZERO_STRUCT(pjob);
02385
02386 pjob.pid = sys_getpid();
02387 pjob.sysjob = -1;
02388 pjob.fd = -1;
02389 pjob.starttime = time(NULL);
02390 pjob.status = LPQ_SPOOLING;
02391 pjob.size = 0;
02392 pjob.spooled = False;
02393 pjob.smbjob = True;
02394 pjob.nt_devmode = nt_devmode;
02395
02396 fstrcpy(pjob.jobname, jobname);
02397
02398 if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
02399 fstrcpy(pjob.user, lp_printjob_username(snum));
02400 standard_sub_advanced(sharename, vuser->user.smb_name, path,
02401 vuser->gid, vuser->user.smb_name,
02402 vuser->user.domain, pjob.user,
02403 sizeof(pjob.user) - 1);
02404
02405 pjob.user[sizeof(pjob.user)-1] = '\0';
02406 } else {
02407 fstrcpy(pjob.user, uidtoname(user->ut.uid));
02408 }
02409
02410 fstrcpy(pjob.queuename, lp_const_servicename(snum));
02411
02412
02413 slprintf(pjob.filename, sizeof(pjob.filename)-1, "%s/%s%.8u.XXXXXX",
02414 path, PRINT_SPOOL_PREFIX, (unsigned int)jobid);
02415 pjob.fd = smb_mkstemp(pjob.filename);
02416
02417 if (pjob.fd == -1) {
02418 if (errno == EACCES) {
02419
02420 DEBUG(0, ("print_job_start: insufficient permissions \
02421 to open spool file %s.\n", pjob.filename));
02422 } else {
02423
02424 DEBUG(3, ("print_job_start: can't open spool file %s,\n", pjob.filename));
02425 DEBUGADD(3, ("errno = %d (%s).\n", errno, strerror(errno)));
02426 }
02427 goto fail;
02428 }
02429
02430 pjob_store(sharename, jobid, &pjob);
02431
02432
02433 add_to_jobs_changed(pdb, jobid);
02434
02435
02436 tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, 1);
02437
02438 release_print_db(pdb);
02439
02440 return jobid;
02441
02442 fail:
02443 if (jobid != -1)
02444 pjob_delete(sharename, jobid);
02445
02446 release_print_db(pdb);
02447
02448 DEBUG(3, ("print_job_start: returning fail. Error = %s\n", strerror(errno) ));
02449 return (uint32)-1;
02450 }
02451
02452
02453
02454
02455
02456 void print_job_endpage(int snum, uint32 jobid)
02457 {
02458 const char* sharename = lp_const_servicename(snum);
02459 struct printjob *pjob;
02460
02461 pjob = print_job_find(sharename, jobid);
02462 if (!pjob)
02463 return;
02464
02465 if (pjob->pid != sys_getpid())
02466 return;
02467
02468 pjob->page_count++;
02469 pjob_store(sharename, jobid, pjob);
02470 }
02471
02472
02473
02474
02475
02476
02477
02478 BOOL print_job_end(int snum, uint32 jobid, enum file_close_type close_type)
02479 {
02480 const char* sharename = lp_const_servicename(snum);
02481 struct printjob *pjob;
02482 int ret;
02483 SMB_STRUCT_STAT sbuf;
02484 struct printif *current_printif = get_printer_fns( snum );
02485
02486 pjob = print_job_find(sharename, jobid);
02487
02488 if (!pjob)
02489 return False;
02490
02491 if (pjob->spooled || pjob->pid != sys_getpid())
02492 return False;
02493
02494 if ((close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE) &&
02495 (sys_fstat(pjob->fd, &sbuf) == 0)) {
02496 pjob->size = sbuf.st_size;
02497 close(pjob->fd);
02498 pjob->fd = -1;
02499 } else {
02500
02501
02502
02503
02504
02505 close(pjob->fd);
02506 pjob->fd = -1;
02507 DEBUG(3,("print_job_end: failed to stat file for jobid %d\n", jobid ));
02508 goto fail;
02509 }
02510
02511
02512
02513
02514 if (pjob->size == 0 || pjob->status == LPQ_DELETING) {
02515
02516 DEBUG(5,("print_job_end: canceling spool of %s (%s)\n",
02517 pjob->filename, pjob->size ? "deleted" : "zero length" ));
02518 unlink(pjob->filename);
02519 pjob_delete(sharename, jobid);
02520 return True;
02521 }
02522
02523 pjob->smbjob = jobid;
02524
02525 ret = (*(current_printif->job_submit))(snum, pjob);
02526
02527 if (ret)
02528 goto fail;
02529
02530
02531
02532 pjob->spooled = True;
02533 pjob->status = LPQ_QUEUED;
02534 pjob_store(sharename, jobid, pjob);
02535
02536
02537 if (print_cache_expired(lp_const_servicename(snum), True))
02538 print_queue_update(snum, False);
02539
02540 return True;
02541
02542 fail:
02543
02544
02545
02546 unlink(pjob->filename);
02547 pjob_delete(sharename, jobid);
02548 return False;
02549 }
02550
02551
02552
02553
02554
02555 static BOOL get_stored_queue_info(struct tdb_print_db *pdb, int snum, int *pcount, print_queue_struct **ppqueue)
02556 {
02557 TDB_DATA data, cgdata;
02558 print_queue_struct *queue = NULL;
02559 uint32 qcount = 0;
02560 uint32 extra_count = 0;
02561 int total_count = 0;
02562 size_t len = 0;
02563 uint32 i;
02564 int max_reported_jobs = lp_max_reported_jobs(snum);
02565 BOOL ret = False;
02566 const char* sharename = lp_servicename(snum);
02567
02568
02569 if (print_cache_expired(lp_const_servicename(snum), True))
02570 print_queue_update(snum, False);
02571
02572 *pcount = 0;
02573 *ppqueue = NULL;
02574
02575 ZERO_STRUCT(data);
02576 ZERO_STRUCT(cgdata);
02577
02578
02579 data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/linear_queue_array"));
02580
02581 if (data.dptr && data.dsize >= sizeof(qcount))
02582 len += tdb_unpack(data.dptr + len, data.dsize - len, "d", &qcount);
02583
02584
02585 cgdata = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_changed"));
02586 if (cgdata.dptr != NULL && (cgdata.dsize % 4 == 0))
02587 extra_count = cgdata.dsize/4;
02588
02589 DEBUG(5,("get_stored_queue_info: qcount = %u, extra_count = %u\n", (unsigned int)qcount, (unsigned int)extra_count));
02590
02591
02592 if (qcount == 0 && extra_count == 0)
02593 goto out;
02594
02595 if ((queue = SMB_MALLOC_ARRAY(print_queue_struct, qcount + extra_count)) == NULL)
02596 goto out;
02597
02598
02599
02600 for( i = 0; i < qcount; i++) {
02601 uint32 qjob, qsize, qpage_count, qstatus, qpriority, qtime;
02602 len += tdb_unpack(data.dptr + len, data.dsize - len, "ddddddff",
02603 &qjob,
02604 &qsize,
02605 &qpage_count,
02606 &qstatus,
02607 &qpriority,
02608 &qtime,
02609 queue[i].fs_user,
02610 queue[i].fs_file);
02611 queue[i].job = qjob;
02612 queue[i].size = qsize;
02613 queue[i].page_count = qpage_count;
02614 queue[i].status = qstatus;
02615 queue[i].priority = qpriority;
02616 queue[i].time = qtime;
02617 }
02618
02619 total_count = qcount;
02620
02621
02622 for( i = 0; i < extra_count; i++) {
02623 uint32 jobid;
02624 struct printjob *pjob;
02625
02626 jobid = IVAL(cgdata.dptr, i*4);
02627 DEBUG(5,("get_stored_queue_info: changed job = %u\n", (unsigned int)jobid));
02628 pjob = print_job_find(lp_const_servicename(snum), jobid);
02629 if (!pjob) {
02630 DEBUG(5,("get_stored_queue_info: failed to find changed job = %u\n", (unsigned int)jobid));
02631 remove_from_jobs_changed(sharename, jobid);
02632 continue;
02633 }
02634
02635 queue[total_count].job = jobid;
02636 queue[total_count].size = pjob->size;
02637 queue[total_count].page_count = pjob->page_count;
02638 queue[total_count].status = pjob->status;
02639 queue[total_count].priority = 1;
02640 queue[total_count].time = pjob->starttime;
02641 fstrcpy(queue[total_count].fs_user, pjob->user);
02642 fstrcpy(queue[total_count].fs_file, pjob->jobname);
02643 total_count++;
02644 }
02645
02646
02647
02648
02649 qsort(queue, total_count, sizeof(print_queue_struct), QSORT_CAST(printjob_comp));
02650
02651 DEBUG(5,("get_stored_queue_info: total_count = %u\n", (unsigned int)total_count));
02652
02653 if (max_reported_jobs && total_count > max_reported_jobs)
02654 total_count = max_reported_jobs;
02655
02656 *ppqueue = queue;
02657 *pcount = total_count;
02658
02659 ret = True;
02660
02661 out:
02662
02663 SAFE_FREE(data.dptr);
02664 SAFE_FREE(cgdata.dptr);
02665 return ret;
02666 }
02667
02668
02669
02670
02671
02672
02673 int print_queue_status(int snum,
02674 print_queue_struct **ppqueue,
02675 print_status_struct *status)
02676 {
02677 fstring keystr;
02678 TDB_DATA data, key;
02679 const char *sharename;
02680 struct tdb_print_db *pdb;
02681 int count = 0;
02682
02683
02684
02685 if (print_cache_expired(lp_const_servicename(snum), True))
02686 print_queue_update(snum, False);
02687
02688
02689 if ( !ppqueue || !status )
02690 return 0;
02691
02692 *ppqueue = NULL;
02693 sharename = lp_const_servicename(snum);
02694 pdb = get_print_db_byname(sharename);
02695
02696 if (!pdb)
02697 return 0;
02698
02699
02700
02701
02702
02703
02704 ZERO_STRUCTP(status);
02705 slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename);
02706 key.dptr = keystr;
02707 key.dsize = strlen(keystr);
02708 data = tdb_fetch(pdb->tdb, key);
02709 if (data.dptr) {
02710 if (data.dsize == sizeof(*status)) {
02711
02712
02713 memcpy(status, data.dptr, sizeof(*status));
02714 }
02715 SAFE_FREE(data.dptr);
02716 }
02717
02718
02719
02720
02721
02722
02723 if (!get_stored_queue_info(pdb, snum, &count, ppqueue)) {
02724 release_print_db(pdb);
02725 return 0;
02726 }
02727
02728 release_print_db(pdb);
02729 return count;
02730 }
02731
02732
02733
02734
02735
02736 BOOL print_queue_pause(struct current_user *user, int snum, WERROR *errcode)
02737 {
02738 int ret;
02739 struct printif *current_printif = get_printer_fns( snum );
02740
02741 if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
02742 *errcode = WERR_ACCESS_DENIED;
02743 return False;
02744 }
02745
02746
02747 become_root();
02748
02749 ret = (*(current_printif->queue_pause))(snum);
02750
02751 unbecome_root();
02752
02753 if (ret != 0) {
02754 *errcode = WERR_INVALID_PARAM;
02755 return False;
02756 }
02757
02758
02759 print_cache_flush(lp_const_servicename(snum));
02760
02761
02762
02763 notify_printer_status(snum, PRINTER_STATUS_PAUSED);
02764
02765 return True;
02766 }
02767
02768
02769
02770
02771
02772 BOOL print_queue_resume(struct current_user *user, int snum, WERROR *errcode)
02773 {
02774 int ret;
02775 struct printif *current_printif = get_printer_fns( snum );
02776
02777 if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
02778 *errcode = WERR_ACCESS_DENIED;
02779 return False;
02780 }
02781
02782 become_root();
02783
02784 ret = (*(current_printif->queue_resume))(snum);
02785
02786 unbecome_root();
02787
02788 if (ret != 0) {
02789 *errcode = WERR_INVALID_PARAM;
02790 return False;
02791 }
02792
02793
02794 if (print_cache_expired(lp_const_servicename(snum), True))
02795 print_queue_update(snum, True);
02796
02797
02798
02799 notify_printer_status(snum, PRINTER_STATUS_OK);
02800
02801 return True;
02802 }
02803
02804
02805
02806
02807
02808 BOOL print_queue_purge(struct current_user *user, int snum, WERROR *errcode)
02809 {
02810 print_queue_struct *queue;
02811 print_status_struct status;
02812 int njobs, i;
02813 BOOL can_job_admin;
02814
02815
02816 print_queue_update(snum, True);
02817
02818 can_job_admin = print_access_check(user, snum, JOB_ACCESS_ADMINISTER);
02819 njobs = print_queue_status(snum, &queue, &status);
02820
02821 if ( can_job_admin )
02822 become_root();
02823
02824 for (i=0;i<njobs;i++) {
02825 BOOL owner = is_owner(user, lp_const_servicename(snum), queue[i].job);
02826
02827 if (owner || can_job_admin) {
02828 print_job_delete1(snum, queue[i].job);
02829 }
02830 }
02831
02832 if ( can_job_admin )
02833 unbecome_root();
02834
02835
02836 print_queue_update( snum, True );
02837
02838 SAFE_FREE(queue);
02839
02840 return True;
02841 }