diff options
Diffstat (limited to 'src/cmd/lp/lpdsend.c')
-rw-r--r-- | src/cmd/lp/lpdsend.c | 428 |
1 files changed, 428 insertions, 0 deletions
diff --git a/src/cmd/lp/lpdsend.c b/src/cmd/lp/lpdsend.c new file mode 100644 index 00000000..0dc70259 --- /dev/null +++ b/src/cmd/lp/lpdsend.c @@ -0,0 +1,428 @@ +#include <u.h> +#include <sys/types.h> +#include <unistd.h> +#include <sys/stat.h> +#include <sys/param.h> +#include <stdlib.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <signal.h> +#include <libc.h> + +#define REDIALTIMEOUT 15 +#define TIMEOUT 600 + +char tmpfilename[L_tmpnam+1]; +int alarmstate = 0; +int debugflag = 0; +int killflag = 0; +int statflag = 0; + +void +cleanup(void) { + unlink(tmpfilename); +} + +#define SBSIZE 8192 +unsigned char sendbuf[SBSIZE]; + +void +debug(char *str) { + if (debugflag) + fprintf(stderr, "%s", str); +} + +void +alarmhandler(int sig) { + fprintf(stderr, "timeout occurred, check printer.\n"); + exit(2); +} + +/* send a message after each WARNPC percent of data sent */ +#define WARNPC 5 + +int +copyfile(int in, int out, long tosend) { + int n; + int sent = 0; + int percent = 0; + + if (debugflag) + fprintf(stderr, "lpdsend: copyfile(%d,%d,%ld)\n", + in, out, tosend); + while ((n=read(in, sendbuf, SBSIZE)) > 0) { + if (debugflag) + fprintf(stderr, "lpdsend: copyfile read %d bytes from %d\n", + n, in); + alarm(TIMEOUT); alarmstate = 1; + if (write(out, sendbuf, n) != n) { + alarm(0); + fprintf(stderr, "write to fd %d failed\n", out); + return(0); + } + alarm(0); + if (debugflag) + fprintf(stderr, "lpdsend: copyfile wrote %d bytes to %d\n", + n, out); + sent += n; + if (tosend && ((sent*100/tosend)>=(percent+WARNPC))) { + percent += WARNPC; + fprintf(stderr, ": %5.2f%% sent\n", sent*100.0/tosend); + } + } + if (debugflag) + fprintf(stderr, "lpdsend: copyfile read %d bytes from %d\n", + n, in); + return(!n); +} + +char strbuf[120]; +char hostname[MAXHOSTNAMELEN], *username, *printername, *killarg; +char *inputname; +char filetype = 'o'; /* 'o' is for PostScript */ +int seqno = 0; +char *seqfilename; + +void +killjob(int printerfd) { + int strlength; + if (printername==0) { + fprintf(stderr, "no printer name\n"); + exit(1); + } + if (username==0) { + fprintf(stderr, "no user name given\n"); + exit(1); + } + if (killarg==0) { + fprintf(stderr, "no job to kill\n"); + exit(1); + } + sprintf(strbuf, "%c%s %s %s\n", '\5', printername, username, killarg); + strlength = strlen(strbuf); + if (write(printerfd, strbuf, strlength) != strlength) { + fprintf(stderr, "write(printer) error\n"); + exit(1); + } + copyfile(printerfd, 2, 0L); +} + +void +checkqueue(int printerfd) { + int strlength; + + sprintf(strbuf, "%c%s\n", '\4', printername); + strlength = strlen(strbuf); + if (write(printerfd, strbuf, strlength) != strlength) { + fprintf(stderr, "write(printer) error\n"); + exit(1); + } + copyfile(printerfd, 2, 0L); +/* +{ int n; + unsigned char sendbuf[1]; + while ((n=read(printerfd, sendbuf, 1)) > 0) { + write(2, sendbuf, n); + } +} +*/ +} + +void +getack(int printerfd, int as) { + char resp; + int rv; + + alarm(TIMEOUT); alarmstate = as; + if ((rv=read(printerfd, &resp, 1)) != 1 || resp != '\0') { + fprintf(stderr, "getack failed: read returned %d, read value (if any) %d, alarmstate=%d\n", + rv, resp, alarmstate); + exit(1); + } + alarm(0); +} + +/* send control file */ +void +sendctrl(int printerfd) { + char cntrlstrbuf[256]; + int strlength, cntrlen; + + sprintf(cntrlstrbuf, "H%s\nP%s\n%cdfA%3.3d%s\n", hostname, username, filetype, seqno, hostname); + cntrlen = strlen(cntrlstrbuf); + sprintf(strbuf, "%c%d cfA%3.3d%s\n", '\2', cntrlen, seqno, hostname); + strlength = strlen(strbuf); + if (write(printerfd, strbuf, strlength) != strlength) { + fprintf(stderr, "write(printer) error\n"); + exit(1); + } + getack(printerfd, 3); + if (write(printerfd, cntrlstrbuf, cntrlen) != cntrlen) { + fprintf(stderr, "write(printer) error\n"); + exit(1); + } + if (write(printerfd, "\0", 1) != 1) { + fprintf(stderr, "write(printer) error\n"); + exit(1); + } + getack(printerfd, 4); +} + +/* send data file */ +void +senddata(int inputfd, int printerfd, long size) { + int strlength; + + sprintf(strbuf, "%c%ld dfA%3.3d%s\n", '\3', size, seqno, hostname); + strlength = strlen(strbuf); + if (write(printerfd, strbuf, strlength) != strlength) { + fprintf(stderr, "write(printer) error\n"); + exit(1); + } + getack(printerfd, 5); + if (!copyfile(inputfd, printerfd, size)) { + fprintf(stderr, "failed to send file to printer\n"); + exit(1); + } + if (write(printerfd, "\0", 1) != 1) { + fprintf(stderr, "write(printer) error\n"); + exit(1); + } + fprintf(stderr, "%ld bytes sent, status: waiting for end of job\n", size); + getack(printerfd, 6); +} + +void +sendjob(int inputfd, int printerfd) { + struct stat statbuf; + int strlength; + + if (fstat(inputfd, &statbuf) < 0) { + fprintf(stderr, "fstat(%s) failed\n", inputname); + exit(1); + } + sprintf(strbuf, "%c%s\n", '\2', printername); + strlength = strlen(strbuf); + if (write(printerfd, strbuf, strlength) != strlength) { + fprintf(stderr, "write(printer) error\n"); + exit(1); + } + getack(printerfd, 2); + debug("send data\n"); + senddata(inputfd, printerfd, statbuf.st_size); + debug("send control info\n"); + sendctrl(printerfd); + fprintf(stderr, "%ld bytes sent, status: end of job\n", (long)statbuf.st_size); +} + +/* + * make an address, add the defaults + */ +char * +netmkaddr(char *linear, char *defnet, char *defsrv) +{ + static char addr[512]; + char *cp; + + /* + * dump network name + */ + cp = strchr(linear, '!'); + if(cp == 0){ + if(defnet==0){ + if(defsrv) + sprintf(addr, "net!%s!%s", linear, defsrv); + else + sprintf(addr, "net!%s", linear); + } + else { + if(defsrv) + sprintf(addr, "%s!%s!%s", defnet, linear, defsrv); + else + sprintf(addr, "%s!%s", defnet, linear); + } + return addr; + } + + /* + * if there is already a service, use it + */ + cp = strchr(cp+1, '!'); + if(cp) + return linear; + + /* + * add default service + */ + if(defsrv == 0) + return linear; + sprintf(addr, "%s!%s", linear, defsrv); + + return addr; +} + +void +main(int argc, char *argv[]) { + int c, usgflg = 0; + char *desthostname; + int printerfd; + int inputfd; + int sendport; + char portstr[4]; + + desthostname = nil; + if (signal(SIGALRM, alarmhandler) == SIG_ERR) { + fprintf(stderr, "failed to set alarm handler\n"); + exit(1); + } + while ((c = getopt(argc, argv, "Dd:k:qs:t:H:P:")) != -1) + switch (c) { + case 'D': + debugflag = 1; + debug("debugging on\n"); + break; + case 'd': + printername = optarg; + break; + case 'k': + if (statflag) { + fprintf(stderr, "cannot have both -k and -q flags\n"); + exit(1); + } + killflag = 1; + killarg = optarg; + break; + case 'q': + if (killflag) { + fprintf(stderr, "cannot have both -q and -k flags\n"); + exit(1); + } + statflag = 1; + break; + case 's': + seqno = strtol(optarg, NULL, 10); + if (seqno < 0 || seqno > 999) + seqno = 0; + break; + case 't': + switch (filetype) { + case 'c': + case 'd': + case 'f': + case 'g': + case 'l': + case 'n': + case 'o': + case 'p': + case 'r': + case 't': + case 'v': + case 'z': + filetype = optarg[0]; + break; + default: + usgflg++; + break; + } + break; + case 'H': + strncpy(hostname, optarg, MAXHOSTNAMELEN); + break; + case 'P': + username = optarg; + break; + default: + case '?': + fprintf(stderr, "unknown option %c\n", c); + usgflg++; + } + if (argc < 2) usgflg++; + if (optind < argc) { + desthostname = argv[optind++]; + } else + usgflg++; + if (usgflg) { + fprintf(stderr, "usage: to send a job - %s -d printer -H hostname -P username [-s seqno] [-t[cdfgklnoprtvz]] desthost [filename]\n", argv[0]); + fprintf(stderr, " to check status - %s -d printer -q desthost\n", argv[0]); + fprintf(stderr, " to kill a job - %s -d printer -P username -k jobname desthost\n", argv[0]); + exit(1); + } + +/* make sure the file to send is here and ready + * otherwise the TCP connection times out. + */ + inputfd = -1; + if (!statflag && !killflag) { + if (optind < argc) { + inputname = argv[optind++]; + debug("open("); debug(inputname); debug(")\n"); + inputfd = open(inputname, O_RDONLY); + if (inputfd < 0) { + fprintf(stderr, "open(%s) failed\n", inputname); + exit(1); + } + } else { + inputname = "stdin"; + tmpnam(tmpfilename); + debug("using stdin\n"); + if ((inputfd = create(tmpfilename, ORDWR, 0600)) < 0) { + fprintf(stderr, "open(%s) failed\n", tmpfilename); + exit(1); + } + atexit(cleanup); + debug("copy input to temp file "); + debug(tmpfilename); + debug("\n"); + if (!copyfile(0, inputfd, 0L)) { + fprintf(stderr, "failed to copy file to temporary file\n"); + exit(1); + } + if (lseek(inputfd, 0L, 0) < 0) { + fprintf(stderr, "failed to seek back to the beginning of the temporary file\n"); + exit(1); + } + } + } + + sprintf(strbuf, "%s", netmkaddr(desthostname, "tcp", "printer")); + fprintf(stderr, "connecting to %s\n", strbuf); + for (sendport=721; sendport<=731; sendport++) { + sprintf(portstr, "%3.3d", sendport); + fprintf(stderr, " trying from port %s...", portstr); + debug(" dial("); debug(strbuf); debug(", "); debug(portstr); debug(", 0, 0) ..."); + printerfd = dial(strbuf, portstr, 0, 0); + if (printerfd >= 0) { + fprintf(stderr, "connected\n"); + break; + } + fprintf(stderr, "failed\n"); + sleep(REDIALTIMEOUT); + } + if (printerfd < 0) { + fprintf(stderr, "Cannot open a valid port!\n"); + fprintf(stderr, "- All source ports [721-731] may be busy.\n"); + fprintf(stderr, "- Is recipient ready and online?\n"); + fprintf(stderr, "- If all else fails, cycle the power!\n"); + exit(1); + } +/* hostname[8] = '\0'; */ +#ifndef PLAN9 + if (gethostname(hostname, sizeof(hostname)) < 0) { + perror("gethostname"); + exit(1); + } +#endif +/* char *hnend; + if ((hnend = strchr(hostname, '.')) != NULL) + *hnend = '\0'; + */ + if (statflag) { + checkqueue(printerfd); + } else if (killflag) { + killjob(printerfd); + } else { + sendjob(inputfd, printerfd); + } + exit(0); +} |