📄 qrun.c
字号:
/* * qrun.c - Fax spool processor for Renaissoft Qfax 1.3 * Copyright 1994-1996 Robert LeBlanc and Renaissoft */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <time.h>#include "qfax.h"/* Non-exported function prototypes */void kill_daemon(void);void start_daemon(void);int send_fax(char *dialstring, char *filelist);char *error_message(int errcode);void notify_sender(int errcode, char *prefix, char *recipient, char *subject);int ok_to_call(char *dialstring);char *make_pagelist(char *prefix);void store_fax(char *prefix);char *make_pagelist(char *prefix){/* Scans the FAXQUEUE directory for all pages with the same prefix, in order to assemble a whitespace-separated list of files to be sent.*/ static char list[COMMENTLEN]; char cmd[LINELEN]; char tmp[LINELEN]; FILE *ls; sprintf(cmd, "%s -1 %s.[0-9][0-9][0-9]", LS, prefix); strcpy(list, ""); ls = popen(cmd, "r"); while (fscanf(ls, "%s", tmp) != EOF) { strcat(list, " "); strcat(list, tmp); } pclose(ls); return(list);}void store_fax(char *prefix){/* Move all files relating to a given fax to STOREDIR, where they can sit indefinitely until the owner decides what to do with them. By moving them out of the spool directory, we prevent Qrun from trying to send them out again the next time it's invoked. Presumably this is done only once the maximum number of attempts has been made without success.*/ char cmd[LINELEN]; sprintf(cmd, "rm -f %s.try", prefix); system(cmd); sprintf(cmd, "mv %s.* %s", prefix, STOREDIR); system(cmd);}int ok_to_call(char *dialstring){/* Returns true if it's ok to place the call at this time. The idea is to make sure that long-distance faxes only get sent out between their designated hours.*/ int result; int hstart, hend, mstart, mend, hnow, mnow; int vstart, vend; char *ptr; char timerange[10]; char tstart[10]; char tstop[10]; struct tm *tp; time_t now; if ((dialstring[0] == '1') || (dialstring[0] == '0')) { strcpy(timerange, LDPERIOD); ptr = strchr(timerange, '-'); *ptr = '\0'; strcpy(tstart, timerange); strcpy(tstop, (++ptr)); if (strcasecmp(tstart, tstop) == 0) { result = 1; } else { now = time(NULL); tp = localtime(&now); hnow = tp->tm_hour; mnow = tp->tm_min; vstart = atoi(tstart); vend = atoi(tstop); hstart = (vstart / 100); if (hstart == 24) hstart = 0; mstart = (vstart % 100); hend = (vend / 100); if (hend == 24) hend = 0; mend = (vend % 100); if (hend < hstart) { if ((hnow > hstart) || (hnow < hend)) { result = 1; } else if ((hnow == hstart) && (mnow >= mstart)) { result = 1; } else { result = 0; } } else if (hend > hstart) { if ((hnow > hstart) && (hnow < hend)) { result = 1; } else if ((hnow == hstart) && (mnow >= mstart)) { result = 1; } else { result = 0; } } else { if ((mnow >= mstart) && (mnow < mend)) result = 1; else result = 0; } } } else { result = 1; } return (result);}void kill_daemon(void){/* Kills the most recent active fax answer process and writes a .stop file to prevent init() from respawning another one until further notice. This is useful to avoid interruptions from incoming calls while we're trying to dial out.*/ char cmd[LINELEN]; sprintf(cmd, "%s stop > /dev/null", FAXSCRIPT); system(cmd); sleep(2);}void start_daemon(void){/* Removes any .stop files that might be preventing init() from spawning a new fax answer process. We use this once we're done sending out faxes, so that we can continue to receive incoming calls. NOTE: You MUST have an entry in your inittab file running "fax answer", since this routine does NOT actually restart Efax.*/ char cmd[LINELEN]; sprintf(cmd, "%s start", FAXSCRIPT); system(cmd);}int send_fax(char *dialstring, char *pagelist){/* Calls "send fax" with the given phone number and page list to send. Since Efax does its own error-trapping, we need to modify the FAX script to write the resulting error code to a file called RESULT just before it terminates, so that we can read and return this value for our purposes.*/ char cmd[LINELEN]; int errcode; FILE *ifp; sprintf(cmd, "%s send %s %s > /dev/null", FAXSCRIPT, dialstring, pagelist); system(cmd); ifp = fopen(RESULT, "r"); fscanf(ifp, "%d", &errcode); fclose(ifp); return (errcode);}char *error_message(int errcode){/* Returns an error message based on an Efax error code. These messages and codes come from the man page for Efax, and are subject to change.*/ static char message[255]; switch(errcode) { case 0: strcpy(message, "Fax was successfully transmitted."); break; case 1: strcpy(message, "Modem was busy (device in use), retrying later."); break; case 2: strcpy(message, "General error occurred (file not found, disk full, etc.)."); break; case 3: strcpy(message, "Modem protocol error occurred."); break; case 4: strcpy(message, "Modem was not responding."); break; case 5: strcpy(message, "Efax was terminated by a signal."); break; default: strcpy(message, "An unknown error has occurred. Please send in a bug report."); } return(message);}void notify_sender(int errcode, char *prefix, char *recipient, char *subject){/* Sends the (local) sender of the fax an e-mail message notifying him that an attempt to send the fax was made, and the results of this attempt. The time in the e-mail header should serve as a timestamp record of when the fax was last attempted, and the recipient's name and the subject of the fax are quoted for reference.*/ char cmd[LINELEN]; char tmp[LINELEN]; char sender[ALIASLEN]; char letter[COMMENTLEN]; char timestr[SHORTLEN]; char *ptr; FILE *ifp; int code; strcpy(tmp, prefix); ptr = strrchr(tmp, '.'); *ptr = '\0'; ptr = strrchr(tmp, '.'); strcpy(sender, (++ptr)); strcpy(letter, "An attempt to send your fax\n\n"); sprintf(tmp, ">>> To: %s\n", recipient); strcat(letter, tmp); sprintf(tmp, ">>> Subject: %s\n\n", subject); strcat(letter, tmp); strcat(letter, "was made, with the following results:\n\n"); sprintf(tmp, "%s.try", prefix); if ((ifp = fopen(tmp, "r")) != NULL) { while (fscanf(ifp, "%d\n", &code) != EOF) { strcpy(timestr, getsline(ifp)); sprintf(tmp, "%s: [%d] %s\n", timestr, code, error_message(code)); strcat(letter, tmp); } fclose(ifp); } strcpy(timestr, timestring()); sprintf(tmp, "%s: [%d] %s\n", timestr, errcode, error_message(errcode)); strcat(letter, tmp); if (errcode > 0) { strcpy(cmd, prefix); ptr = strrchr(cmd, '/'); strcpy(cmd, (++ptr)); sprintf(tmp, "\nYour fax, %s.*,has been moved to %s.\n", cmd, STOREDIR); strcat(letter, tmp); sprintf(tmp, "To send it again, move these files back to %s.\n", FAXQUEUE); strcat(letter, tmp); } sprintf(cmd, "echo \"%s\" | mail -s \"Fax Transmission Notification\" %s", letter, sender); system(cmd);}void main(int argc, char *argv[]){ int i, faxes, errcode, code, tries; char cmdlist[MAXFAXES][LINELEN]; char dialstring[PHONELEN]; char recipient[LONGLEN]; char subject[LINELEN]; char prefix[LINELEN]; char timestr[SHORTLEN]; char tmp[LINELEN]; char username[SHORTLEN]; FILE *ifp, *ofp; /* Assemble a list of the faxes waiting in FAXQUEUE to go out. */ faxes = make_cmdlist(cmdlist); if (!faxes) /* No faxes waiting to be sent, so we have nothing to do. */ exit(EXIT_SUCCESS);#ifdef USE_DAEMON /* Kill any existing fax answer daemon, just to be sure that we aren't interrupted before we seize the line. */ kill_daemon();#endif if (argc > 1) strcpy(username, argv[1]); else username[0] = '\0'; for (i=0; i < faxes; i++) { get_cmdinfo(cmdlist[i], dialstring, recipient, subject); if (ok_to_call(dialstring)) { strcpy(prefix, make_prefix(cmdlist[i])); if ((argc == 1) || (strstr(prefix, username) != NULL)) { errcode = send_fax(dialstring, make_pagelist(prefix)); if (!errcode) { /* No errors, delete the fax and notify the sender */ notify_sender(errcode, prefix, recipient, subject); delete_fax(prefix); } else { /* An error occurred, so let's see whether we should try again or give up. */ sprintf(tmp, "%s.try", prefix); if ((ifp = fopen(tmp, "r")) != NULL) { /* We've tried to send this fax before */ tries = 0; while (!feof(ifp)) { fscanf(ifp, "%d\n", &code); fgets(timestr, SHORTLEN, ifp); tries++; } fclose(ifp); if (tries >= MAXTRIES) { /* We've reached our limit; give up, store the fax and notify the sender. */ notify_sender(errcode, prefix, recipient, subject); store_fax(prefix); } else { /* Try again next time Qrun is invoked, but make a note of the fact that we tried, writing the errorcode and the time/date to the *.try file. */ ofp = fopen(tmp, "a"); strcpy(timestr, timestring()); fprintf(ofp, "%d\n%s\n", errcode, timestr); fclose(ofp); } } else { /* We've never tried to send this fax before, so we make a record of the fact that we've failed once now. */ ofp = fopen(tmp, "a"); strcpy(timestr, timestring()); fprintf(ofp, "%d\n%s\n", errcode, timestr); fclose(ofp); } } sleep(15); } } }#ifdef USE_DAEMON /* Restart the fax answer daemon so we can continue to receive incoming faxes, now that we're done sending. */ start_daemon();#endif exit(EXIT_SUCCESS);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -