?? oldprotocol.c++
字號(hào):
fflush(stdout);}/* * General job manipulation support. */#include <pwd.h>boolOldProtocolServer::_checkUser(const char* requestor, struct passwd* pwd){ char buf[1024]; char* cp; buf[0] = '\0'; if (pwd->pw_gecos) { if (pwd->pw_gecos[0] == '&') { strcpy(buf, pwd->pw_name); strcat(buf, pwd->pw_gecos+1); if (islower(buf[0])) buf[0] = toupper(buf[0]); } else strcpy(buf, pwd->pw_gecos); if ((cp = strchr(buf,',')) != 0) *cp = '\0'; /* see FaxClient::setupUserIdentity; strip SysV junk */ if ((cp = strchr(buf,'(')) != 0) *cp = '\0'; } else strcpy(buf, pwd->pw_name); if (TRACE(PROTOCOL)) { if (*buf) logDebug("%s user: \"%s\"", pwd->pw_name, buf); else logDebug("name of %s user unknown", pwd->pw_name); } return (strcmp(requestor, buf) == 0);}boolOldProtocolServer::isAdmin(const char* requestor){ static bool checked = false; static bool isadmin = false; if (!checked) { struct passwd* pwd = getpwuid(getuid()); if (!pwd) { logError("getpwuid failed for uid %d: %m", getuid()); pwd = getpwuid(geteuid()); } if (!pwd) { logError("getpwuid failed for effective uid %d: %m", geteuid()); isadmin = false; } isadmin = _checkUser(requestor, pwd); if (!isadmin) { /* not fax user */ pwd = getpwnam("root"); if (!pwd) { logError("getpwnam failed for \"root\": %m"); isadmin = false; } else isadmin = _checkUser(requestor, pwd); /* root user */ } checked = true; } return (isadmin);}voidOldProtocolServer::applyToJob(const char* tag, const char* op, void (OldProtocolServer::*f)(Job&, const char*)){ char* requestor = (char *) strchr(tag, ':'); if (!requestor) protocolBotch("no requestor name for \"%s\" command.", op); *requestor++ = '\0'; char* arg = strchr(requestor, ':'); if (arg) *arg++ = '\0'; fxStr emsg; Job* job = findJob(tag, emsg); if (job) { /* * Validate requestor is permitted to do op to the * requested job. We permit the person that submitted * the job, the fax user, and root. Using the GECOS * field in doing the comparison is a crock, but not * something to change now--leave it for a protocol * redesign. */ if (job->sender == requestor || isAdmin(requestor)) { if (TRACE(PROTOCOL)) logDebug("%s request by %s for %s", op, requestor, tag); (this->*f)(*job, arg); } else sendClient("jobOwner", tag); } else sendClient("notQueued", tag);}voidOldProtocolServer::applyToJobGroup(const char* tag, const char* op, void (OldProtocolServer::*f)(Job&, const char*)){ char* requestor = (char *) strchr(tag, ':'); if (!requestor) protocolBotch("no requestor name for \"%s\" command.", op); *requestor++ = '\0'; char* arg = strchr(requestor, ':'); if (arg) *arg++ = '\0'; if (jobs.size() == 0) readJobs(); u_int jobsDone = 0; u_int jobsSkipped = 0; for (JobDictIter iter(jobs); iter.notDone(); iter++) { Job& job = *iter.value(); if (job.groupid != tag) continue; /* * Validate requestor is permitted to do op to the * requested job. We permit the person that submitted * the job, the fax user, and root. Using the GECOS * field in doing the comparison is a crock, but not * something to change now--leave it for a protocol * redesign. */ if (job.sender == requestor || isAdmin(requestor)) { if (TRACE(PROTOCOL)) logDebug("%s request by %s for %s", op, requestor, tag); (this->*f)(job, arg); jobsDone++; } else jobsSkipped++; } if (jobsDone == 0) sendClient(jobsSkipped ? "jobOwner" : "notQueued", tag);}/* * Job parameter alteration support. */#define DEFINE_Alter(param) \void OldProtocolServer::alterJob##param(const char* tag) \ { applyToJob(tag, "alter", &OldProtocolServer::reallyAlterJob##param); }\void OldProtocolServer::alterJobGroup##param(const char* tag) \ { applyToJobGroup(tag, "alter", &OldProtocolServer::reallyAlterJob##param); }boolOldProtocolServer::alterSuspend(Job& job){ if (job.state == FaxRequest::state_active) { sendClient("jobLocked", job.jobid); // NB: maintain old semantics return (false); } fxStr emsg; if (!sendQueuerACK(emsg, "X%s", (const char*) job.jobid)) { sendError("Unable to suspend job: %s", (const char*) emsg); return (false); } return (true);}voidOldProtocolServer::alterResubmit(Job& job){ fxStr emsg; const char* jobid = job.jobid; if (updateJobOnDisk(job, emsg)) { // update q file if (sendQueuerACK(emsg, "S%s", jobid)) // resubmit job sendClient("altered", jobid); else sendError("Could not resubmit job: %s", (const char*) emsg); } else { sendError("Could not update job state: %s", (const char*) emsg); (void) sendQueuer(emsg, "S%s", jobid); }}voidOldProtocolServer::reallyAlterJobTTS(Job& job, const char* spec){ time_t now = Sys::now(); time_t t = cvtTime(spec, localtime(&now), "time-to-send"); if (alterSuspend(job)) { job.tts = t; alterResubmit(job); }}DEFINE_Alter(TTS)voidOldProtocolServer::reallyAlterJobKillTime(Job& job, const char* spec){ time_t now = Sys::now(); time_t t = cvtTime(spec, localtime(&now), "kill-time"); if (alterSuspend(job)) { job.killtime = t; alterResubmit(job); }}DEFINE_Alter(KillTime)voidOldProtocolServer::reallyAlterJobModem(Job& job, const char* device){ if (alterSuspend(job)) { job.modem = device; alterResubmit(job); }}DEFINE_Alter(Modem)voidOldProtocolServer::reallyAlterJobPriority(Job& job, const char* priority){ if (alterSuspend(job)) { job.usrpri = atoi(priority); alterResubmit(job); }}DEFINE_Alter(Priority)voidOldProtocolServer::reallyAlterJobMaxDials(Job& job, const char* max){ if (alterSuspend(job)) { job.maxdials = atoi(max); alterResubmit(job); }}DEFINE_Alter(MaxDials)voidOldProtocolServer::reallyAlterJobNotification(Job& job, const char* note){ if (alterSuspend(job)) { job.checkNotifyValue(note); alterResubmit(job); }}DEFINE_Alter(Notification)/* * Job removal and aborting support. */voidOldProtocolServer::reallyRemoveJob(const char* op, Job& job){ /* * First ask server to do removal. If the job is being * processed, it will first be aborted. Otherwise, do * the cleanup here. */ fxStr emsg; const char* cmd = (strcmp(op, "remove") == 0 ? "R" : "K"); if (sendQueuerACK(emsg, "%s%s", cmd, (const char*) job.jobid)) { sendClient("removed", job.jobid); } else if (lockJob(job, LOCK_EX|LOCK_NB, emsg)) { for (u_int i = 0, n = job.items.length(); i < n; i++) { const FaxItem& fitem = job.items[i]; switch (fitem.op) { case FaxRequest::send_tiff: case FaxRequest::send_tiff_saved: case FaxRequest::send_pdf: case FaxRequest::send_pdf_saved: case FaxRequest::send_postscript: case FaxRequest::send_postscript_saved: case FaxRequest::send_pcl: case FaxRequest::send_pcl_saved: Sys::unlink(fitem.item); break; case FaxRequest::send_fax: if (job.isUnreferenced(i)) Sys::unlink(fitem.item); break; } } if (Sys::unlink(job.qfile) < 0) { logError("%s: unlink %s failed (%m)", op, (const char*) job.qfile); sendClient("unlinkFailed", job.jobid); } else { logInfo("%s %s completed", strcmp(op, "remove") == 0 ? "REMOVE" : "KILL", (const char*) job.jobid); sendClient("removed", job.jobid); } unlockJob(job); }}voidOldProtocolServer::doremove(Job& job, const char*){ reallyRemoveJob("remove", job);}void OldProtocolServer::removeJob(const char* tag) { applyToJob(tag, fxQUOTE(op), &OldProtocolServer::doremove); }void OldProtocolServer::removeJobGroup(const char* tag) { applyToJobGroup(tag, fxQUOTE(op), &OldProtocolServer::doremove); }voidOldProtocolServer::dokill(Job& job, const char*){ reallyRemoveJob("kill", job);}void OldProtocolServer::killJob(const char* tag) { applyToJob(tag, fxQUOTE(op), &OldProtocolServer::dokill); }void OldProtocolServer::killJobGroup(const char* tag) { applyToJobGroup(tag, fxQUOTE(op), &OldProtocolServer::dokill); }/* * Job submission support. */static voidlower(char* cp){ while (*cp) { if (isupper(*cp)) *cp = tolower(*cp); cp++; }}voidOldProtocolServer::submitJob(const char*){ fxStr emsg; curJob = &defJob; // inherit from default if (!newJob(emsg)) { sendError("Can not create new job: %s.", (const char*) emsg); dologout(1); } time_t t = Sys::now(); struct tm now = *localtime(&t); Job& job = *curJob; for (;;) { char line[1024]; char* tag; getCommandLine(line, tag); if (isCmd("end") || isCmd(".")) { setupData(); break; } lower(line); u_int ix; if (FaxRequest::isStrCmd(line, ix)) { if (isCmd("cover")) coverProtocol(0, atoi(tag)); else job.*FaxRequest::strvals[ix].p = tag; } else if (FaxRequest::isShortCmd(line, ix)) { job.*FaxRequest::shortvals[ix].p = atoi(tag); } else if (isCmd("sendAt")) { job.tts = (time_t) cvtTime(tag, &now, "time-to-send"); } else if (isCmd("killtime")) { struct tm* tm; if (job.tts) { // NB: assumes sendAt precedes killtime t = job.tts; tm = localtime(&t); } else tm = &now; job.killtime = cvtTime(tag, tm, "kill-time"); } else if (isCmd("retrytime")) { job.retrytime = (time_t) atoi(tag); } else if (isCmd("notify")) { // email notification job.checkNotifyValue(tag); } else if (isCmd("pagechop")) { job.checkChopValue(tag); } else if (isCmd("chopthreshold")) { job.chopthreshold = atof(tag); } else if (isCmd("zcover")) { coverProtocol(1, atoi(tag)); } else if (isCmd("page")) { job.items.append(FaxItem(FaxRequest::send_page, 0, "", tag)); } else if (isCmd("!page")) { job.items.append(FaxItem(FaxRequest::send_page_saved, 0, "", tag)); } else // XXX discard unknown items logInfo("Unknown job item %s:%s", line, tag); } if (job.external == "") job.external = job.number; job.modem = modem; if (!updateJobOnDisk(job, emsg)) sendError("%s", (const char*) emsg); else { setFileOwner(job.qfile); // force ownership FileCache::chmod(job.qfile, 0660); // sync cache if (sendQueuerACK(emsg, "S%s", (const char*) job.jobid)) sendClient("job", version > 1 ? "%s:%s" : "%s", (const char*) job.jobid, (const char*) job.groupid); else sendError("Warning, no job scheduler appears to be running."); }}voidOldProtocolServer::coverProtocol(int isLZW, int cc){ fxStr templ = fxStr::format(FAX_DOCDIR "/doc%s.cover", (const char*) curJob->jobid); FILE* fd = fopen(templ, "w"); if (fd == NULL) sendAndLogError("Could not create cover sheet file %s.", (const char*) templ); if (isLZW) { /* * Cover sheet comes across as LZW-compressed data; * the version id is the count of the decompressed * data bytes to expect (sigh, what a hack!) */ setupLZW(); long total = decodeLZW(stdin, fd); if (total != cc) protocolBotch("not enough data received: expected %u, got %u.", cc, total); if (TRACE(PROTOCOL)) logDebug(templ | ": %ld-byte compressed %s", cc, "PostScript document"); } else { /* * Old-style, data comes across as * ascii terminated by "..". */ char line[1024]; char* tag; for (;;) { getCommandLine(line, tag); if (isCmd("..")) break; fprintf(fd, "%s\n", tag); } } if (fflush(fd) != 0) sendAndLogError("Error writing cover sheet data: %s.", strerror(errno)); fclose(fd); curJob->items.append( FaxItem(FaxRequest::send_postscript, 0, "", templ));}voidOldProtocolServer::setupData(void){ for (u_int i = 0, n = reqs.length(); i < n; i++) { const FaxItem& fitem = reqs[i]; if (fitem.op != FaxRequest::send_poll) { const char* cp = strrchr(fitem.item, '/'); if (!cp) // relative name, e.g. doc123 cp = fitem.item; fxStr doc = fxStr::format("/" FAX_DOCDIR "%s.", cp) | curJob->jobid; if (Sys::link(fitem.item, doc) < 0) { logError("Can not link document \"%s\": %s", (const char*) doc, strerror(errno)); sendError("Problem setting up document file: %s", strerror(errno));
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -