home *** CD-ROM | disk | FTP | other *** search
- /*
- * lpr.c - Windows NT lpr
- *
- * by Eric W. Brown
- * 28 October '92
- */
-
- #include <windows.h>
- #include <winbase.h>
- #include <winsock.h>
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
- #include <fcntl.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/locking.h>
- #include <io.h>
-
- #include "lp.h"
-
- /*
- * #defines
- */
- #define HOSTNAME_LEN (MAX_COMPUTERNAME_LENGTH + 1)
- #define USERNAME_LEN (32 /* MAX_USERNAME_LENGTH */ + 1)
-
-
- /*
- * Global Variables
- */
- int sockfd = -1;
- char hostname[HOSTNAME_LEN];
- char username[USERNAME_LEN];
- char *printer = NULL;
- char *server = NULL;
- char *temp_dir = NULL;
- char *class = NULL;
- char *job = NULL;
- char *title = NULL;
- char filter = 'f';
- int noburst = 0;
- int debug = 0;
- int dosfilter = 0;
- int width = 0;
- int copies = 1;
- int indent = -1;
- int tcp_initialized = 0;
- int seqno;
- FILE *cf_file = NULL;
- char tmp_cfname[33] = "";
- char tmp_dfname[33] = "";
- char tmp_stdin_fname[33] = "";
-
-
- /*
- * Prototypes
- */
- int usage();
- void lpr_start_protocol();
- void lpr_finish_protocol();
- void lpr_print_file(char *filename, char *name);
- void lpr_send_file(int fd, int length);
- void lpr_send(char *buf, int cnt);
- void lpr_check_ack();
- void lpr_create_control_file(char *tmp_cfname);
- void lpr_capture_stdin(char *fname);
- long lpr_text_filelength(int fd);
- void lpr_filter_dos(char *infname, char *outfname);
- int lpr_get_seqno(char *seq_fname);
- void lpr_crash(int report, char *fmt, ...);
- #define NO_REPORT 0
- #define REPORT_SOCKERR 1
- #define REPORT_FILEERR 2
- #define REPORT_ERR 3
-
- int usage()
- {
- fprintf(stderr, "Usage: lpr [ -Pprinter ] [ -Sserver ] [ -#num ] [ -C class ] [ -J job ]\n");
- fprintf(stderr, " [ -T title ] [ -i [ numcols ]] [ -wnum ] [ -pvcgdntlfhD ]\n");
- fprintf(stderr, " [ -u ] [ -#n ] [ name ... ]\n");
- fprintf(stderr, " -u : filter for unix (remove ^M and ^D characters)\n");
- exit(1);
- return 0;
- } /* usage() */
-
- void main(int argc, char **argv)
- {
- char *ptr;
- long fileHandle;
- struct _finddata_t fileinfo;
- int length;
- char filename[256];
-
- /*
- * Get environment variables:
- * server, printer, hostname, username & temp_dir
- */
- server = getenv("SERVER");
- printer = getenv("PRINTER");
- if (!printer)
- printer = DEFAULT_PRINTER;
-
- length = HOSTNAME_LEN;
- if (!GetComputerName(hostname, &length) || length == 0)
- lpr_crash(REPORT_ERR, "lpr: No hostname, name your computer!!!\n");
-
- length = USERNAME_LEN;
- if (!GetUserName(username, &length))
- strncpy(username, hostname, USERNAME_LEN);
-
- temp_dir = getenv("TEMP");
- if (!temp_dir) {
- fprintf(stderr, "lpr: TEMP environment variable not set.\n");
- exit(1);
- }
- else if (_access(temp_dir, 06) < 0) {
- fprintf(stderr, "lpr: TEMP directory, %s, does not exist or %s\n",
- temp_dir, "invalid permissions");
- exit(1);
- } /* else */
-
-
- /*
- * Parse command line
- */
- #define NEXT_ARG() (argc--, argv++, argc ? *argv : (char *)(usage(), NULL))
- #define ARG_ARG() (strlen(*argv) == 2 ? NEXT_ARG() : (*argv) + 2)
- while (argc > 1 && argv[1][0] == '-') {
- NEXT_ARG();
- switch(argv[0][1]) {
- case 'P': printer = ARG_ARG(); break;
- case 'S': server = ARG_ARG(); break;
- case 'C': class = ARG_ARG(); break;
- case 'J': job = ARG_ARG(); break;
- case 'T': title = ARG_ARG(); break;
- case 'p':
- case 'v':
- case 'c':
- case 'g':
- case 'd':
- case 'n':
- case 't':
- case 'l': filter = argv[0][1]; break;
- case 'f': filter = 'r'; break;
- case 'h': noburst = 1; break;
- case 'D': debug = 1; break;
- case 'u': dosfilter = 1; break;
-
- case 'i':
- indent = (*argv[2] ? atoi(*argv + 2) : 8);
- if (indent < 0 || indent > 255) {
- fprintf(stderr, "lpr: %s: invalid indentation, %s",
- *argv, "please keep it between 0 and 255.\n");
- usage();
- } /* if */
- break;
-
- case 'w':
- if (sscanf(ARG_ARG(), "%d", &width) != 1) {
- fprintf(stderr, "lpr: invalid width\n");
- usage();
- } /* if */
- break;
-
- case '#':
- if (sscanf(ARG_ARG(), "%d", &copies) != 1) {
- fprintf(stderr, "lpr: # of copies must be an integer.\n");
- exit(1);
- } /* if */
- break;
-
- default:
- fprintf(stderr, "lpr: '%s' invalid option\n", *argv);
- usage();
- } /* switch */
- } /* while argc */
-
-
- /*
- * Loop over remaining arguments, (Print these files ...)
- */
- while (argc > 1) {
- NEXT_ARG();
-
- /* For unix compatibility, replace '/'s with '\'s */
- ptr = *argv;
- while(*ptr)
- if (*ptr++ == '/')
- ptr[-1] = '\\';
-
-
- if ((fileHandle = _findfirst(*argv, &fileinfo)) != -1L) {
- do {
- if (!tcp_initialized)
- lpr_start_protocol();
- strcpy(filename, *argv);
- if (ptr = strrchr(filename, '\\'))
- ptr[1] = '\0';
- else if (ptr = strrchr(filename, ':'))
- ptr[1] = '\0';
- else
- filename[0] = '\0';
- strcat(filename, fileinfo.name);
- lpr_print_file(filename, filename);
- } while (_findnext(fileHandle, &fileinfo) == 0);
- _findclose(fileHandle);
- }
- else {
- fprintf(stderr, "lpr: %s: Invalid file spec.\n", *argv);
- if (tcp_initialized)
- break;
- else
- exit(1);
- } /* else */
- } /* while argc */
-
-
- /*
- * See if we should take input from stdin
- */
- if (!tcp_initialized) {
- lpr_start_protocol();
- sprintf(tmp_stdin_fname, "%s\\sin%03d.tmp", temp_dir, seqno);
- lpr_capture_stdin(tmp_stdin_fname);
- lpr_print_file(tmp_stdin_fname, "(standard input)");
- unlink(tmp_stdin_fname);
- } /* if */
-
-
- /*
- * Clean up
- */
- if (tcp_initialized) {
- lpr_finish_protocol();
- closesocket(sockfd);
- lp_tcp_shutdown();
- fclose(cf_file);
- unlink(tmp_cfname);
- } /* if */
-
- exit(0);
- } /* main() */
-
-
- void lpr_start_protocol()
- {
- char seq_fname[33];
- char message[80];
-
- /*
- * Do a lookup in the printcap file if necessary
- */
- if (!server)
- if (!(server = lp_printcap_server_lookup(printer))) {
- fprintf(stderr, "lpr: No server, %s, and no printer, %s, %s",
- server, printer, "in printcap file!\n");
- usage();
- } /* if */
-
-
- /*
- * Initialize tcp
- */
- if (lp_tcp_startup())
- lpr_crash(REPORT_SOCKERR, "lpr: Couldn't initialize tcp/ip\n");
- tcp_initialized = 1;
- if (debug) fprintf(stderr, "lpr: Initialized TCP/IP\n");
-
-
- /*
- * Open a socket
- */
- if ((sockfd = lp_tcp_open(server)) < 0)
- lpr_crash(REPORT_SOCKERR, "lpr: Couldn't open connection to server, %s\n",
- server);
- if (debug) fprintf(stderr, "lpr: Connected to server, %s\n", server);
-
-
- /*
- * Get sequence number and increment it
- */
- sprintf(seq_fname, "%s\\lpr.seq", temp_dir);
- seqno = lpr_get_seqno(seq_fname);
-
-
- /*
- * Create control file
- */
- sprintf(tmp_cfname, "%s\\cfA%03d.tmp", temp_dir, seqno);
- lpr_create_control_file(tmp_cfname);
-
-
- /*
- * Tell LPD to receive a job
- */
- sprintf(message, "%c%s\n", LPD_PRINT_JOB, printer);
- lpr_send(message, strlen(message));
- lpr_check_ack();
- if (debug) fprintf(stderr, "lpr: Server is accepting job.\n");
- } /* lpr_start_protocol() */
-
-
- void lpr_finish_protocol()
- {
- int length;
- char message[80];
-
- /*
- * Send control file receive message
- */
- fflush(cf_file);
- length = _filelength(_fileno(cf_file));
- sprintf(message, "%c%d cfA%03d%s\n", LPD_RECEIVE_CONTROL_FILE,
- length, seqno, hostname);
- lpr_send(message, strlen(message));
- lpr_check_ack();
-
- /*
- * Send control file
- */
- if (debug) fprintf(stderr, "lpr: Sending control file to %s\n", server);
- _lseek(_fileno(cf_file), 0, SEEK_SET);
- lpr_send_file(_fileno(cf_file), length);
- } /* lpr_finish_protocol() */
-
-
- void lpr_print_file(char *filename, char *name)
- {
- static int file_count = 0;
- static char *df_prefix = "df?";
- char dfname[65];
- int fd;
- int length;
- char message[80];
- int i;
- int is_text;
-
- /*
- * Create df filename
- */
- if (file_count++ % 26 == 0)
- df_prefix[2]++;
- else if (file_count == 27)
- df_prefix = "dfA@";
- df_prefix[strlen(df_prefix) - 1]++;
- sprintf(dfname, "%s%03d%s", df_prefix, seqno, hostname);
-
-
- /*
- * See if we need to make a temporary file
- */
- if (dosfilter) {
- sprintf(tmp_dfname, "%s\\%s%03d.tmp", temp_dir, df_prefix, seqno);
- lpr_filter_dos(filename, tmp_dfname);
- } /* if */
-
-
- /*
- * Add to control file
- */
- if (width) fprintf(cf_file, "W%d\n", width);
- if (indent != -1) fprintf(cf_file, "I%d\n", indent);
- if (filter == 'p') fprintf(cf_file, "T%s\n", (title ? title : name));
- for(i = 0; i < copies; i++)
- fprintf(cf_file, "%c%s\n", filter, dfname);
- fprintf(cf_file, "U%s\n", dfname);
- fprintf(cf_file, "N%s\n", name);
-
-
- /*
- * Open the file
- */
- is_text = (filter == 'f' || filter == 'p' || filter == 'r' || dosfilter);
- fd = open(dosfilter ? tmp_dfname : filename,
- O_RDONLY | (is_text ? O_TEXT : O_BINARY));
- if (fd < 0)
- lpr_crash(REPORT_FILEERR, "lpr: Couldn't open file, %s\n", filename);
-
-
- /*
- * Try to send a file
- */
- length = (is_text ? lpr_text_filelength(fd) : filelength(fd));
- sprintf(message, "%c%ld %s\n", LPD_RECEIVE_DATA_FILE, length, dfname);
- lpr_send(message, strlen(message));
- lpr_check_ack();
-
-
- /*
- * Send the actual file
- */
- if (debug) fprintf(stderr, "lpr: Sending %s to %s@%s.\n", name, printer, server);
- lpr_send_file(fd, length);
- close(fd);
- if (*tmp_dfname) {
- unlink(tmp_dfname);
- *tmp_dfname = 0;
- } /* if */
- } /* lpr_print_file() */
-
-
- void lpr_send_file(int fd, int length)
- {
- int cnt;
- char buf[1024];
-
- /*
- * Send the file
- */
- while(length) {
- cnt = min(length, 1024);
- if ((cnt = read(fd, buf, cnt)) <= 0)
- lpr_crash(REPORT_FILEERR, "lpr: Error reading file\n");
-
- lpr_send(buf, cnt);
- length -= cnt;
- } /* while */
-
-
- /*
- * Send end mark & get acknowledgement
- */
- sprintf(buf, "%c", LPD_END_TRANSFER);
- lpr_send(buf, 1);
- lpr_check_ack();
- } /* lpr_send_file() */
-
-
- void lpr_send(char *buf, int cnt)
- {
- if (send(sockfd, buf, cnt, 0) != cnt)
- lpr_crash(REPORT_SOCKERR, "lpr: Error talking to server, %s\n", server);
- } /* lpr_send() */
-
-
- void lpr_check_ack()
- {
- char buf[80];
- int len;
-
- while(1) {
- len = recv(sockfd, buf, 79, 0);
- if (len <= 0)
- lpr_crash(REPORT_SOCKERR, "lpr: Server not responding.\n");
- switch(buf[0]) {
- case LPD_OK:
- return;
- case LPD_ERROR:
- lpr_crash(NO_REPORT, "lpr: Server error\n");
- case LPD_NO_SPOOL_SPACE:
- lpr_crash(NO_REPORT, "lpr: Unable to accept job at this time.\n%s",
- "Not enough spool space on server.\n");
- default:
- /* An error message? */
- buf[len] = 0;
- fprintf(stderr, "%s", buf);
- } /* switch */
- } /* while */
- } /* check_ack() */
-
-
- void lpr_create_control_file(char *tmp_cfname)
- {
- /*
- * Open the control file
- */
- cf_file = fopen(tmp_cfname, "w+b");
- if (!cf_file)
- lpr_crash(REPORT_FILEERR, "lpr: Couldn't open file, %s\n", tmp_cfname);
-
-
- /*
- * Start building the control file
- */
- fprintf(cf_file, "H%s\n", hostname);
- fprintf(cf_file, "P%s\n", username);
- if (!noburst) {
- if (job)
- fprintf(cf_file, "J%s\n", job);
- fprintf(cf_file, "C%s\n", class ? class : hostname);
- fprintf(cf_file, "L%s\n", username);
- } /* if */
- } /* lpr_create_control_file() */
-
-
- void lpr_capture_stdin(char *fname)
- {
- char buf[1024];
- int len;
- int fd;
-
- if (debug) fprintf(stderr, "lpr: Capturing stdin to '%s'\n", fname);
-
- fd = open(fname, _O_CREAT | _O_WRONLY | _O_TRUNC | _O_BINARY, 0666);
- if (fd < 0)
- lpr_crash(NO_REPORT, "lpr: Error creating temporary file, %s\n", fname);
-
- while((len = read(0, buf, 1024)) > 0)
- if (_write(fd, buf, len) != len)
- lpr_crash(NO_REPORT, "lpr: Error writing to tmp file, %s\n", fname);
-
- close(fd);
-
- } /* lpr_capture_stdin() */
-
-
- int lpr_get_seqno(char *seq_fname)
- {
- int seqno;
- int fd;
- int cnt;
- char buf[80];
-
- /*
- * Open the sequence file, if it doesn't exist, create it.
- */
- if ((fd = _open(seq_fname, _O_RDWR | _O_CREAT | _O_TEXT)) < 0)
- lpr_crash(REPORT_FILEERR, "lpr: Couldn't open (or create) sequence file (%s)\n",
- seq_fname);
-
-
- /*
- * Lock the file (the first byte of it anyway)
- */
- if (_locking(fd, _LK_LOCK, 1))
- lpr_crash(REPORT_FILEERR, "lpr: Couldn't lock sequence file, %s\n", seq_fname);
-
-
- /*
- * Get the sequence number
- */
- cnt = read(fd, buf, 79);
- buf[cnt] = 0;
- if (sscanf(buf, "%d", &seqno) != 1)
- seqno = 1;
-
-
- /*
- * Write new sequence number
- */
- _lseek(fd, 0, SEEK_SET);
- sprintf(buf, "%03d\n", (seqno + 1) % 1000);
- write(fd, buf, strlen(buf));
-
-
- /*
- * Unlock & close file
- */
- _lseek(fd, 0, SEEK_SET);
- _locking(fd, _LK_UNLCK, 1);
- _close(fd);
-
- return (seqno);
- } /* lpr_get_seqno() */
-
-
- void lpr_crash(int report, char *fmt, ...)
- {
- va_list marker;
-
- if (fmt) {
- va_start(marker, fmt);
- vfprintf(stderr, fmt, marker);
- va_end(marker);
- } /* if */
-
- if (tcp_initialized) {
- if (sockfd != -1) closesocket(sockfd);
- lp_tcp_shutdown();
- if (cf_file) fclose(cf_file);
- if (*tmp_dfname) unlink(tmp_dfname);
- if (*tmp_stdin_fname) unlink(tmp_stdin_fname);
- } /* if */
-
- exit(1);
- } /* lpr_crash() */
-
-
- long lpr_text_filelength(int fd)
- {
- char buf[1024];
- int length = 0;
- int cnt;
-
- /* Read the whole file */
- while((cnt = read(fd, buf, 1024)) > 0)
- length += cnt;
-
- /* Rewind to the beginning */
- lseek(fd, 0, SEEK_SET);
-
- return length;
- } /* lpr_text_filelength() */
-
-
- void lpr_filter_dos(char *infname, char *outfname)
- {
- FILE *in_file;
- FILE *out_file;
- char buf[1024];
- char *ptr;
-
- if (debug) fprintf(stderr, "lpr: Filtering ^D's from '%s' to '%s'\n",
- infname, outfname);
-
- in_file = fopen(infname, "rt");
- if (!in_file)
- lpr_crash(REPORT_FILEERR, "lpr: Couldn't open file '%s'\n", infname);
-
- out_file = fopen(outfname, "wt");
- if (!out_file)
- lpr_crash(REPORT_FILEERR, "lpr: Couldn't create file '%s'\n", outfname);
-
- while(!feof(in_file)) {
- /* Try to get one line of text */
- fgets(ptr = buf, 1023, in_file);
-
- /* Exclude lines that begin with ^D or ^Z */
- if (buf[0] == 4 || buf[0] == 26)
- if (*++ptr == '\n')
- continue;
-
- while(ptr[0] && !feof(in_file)) {
- if (fputs(ptr, out_file) == EOF)
- lpr_crash(REPORT_FILEERR, "lpr: Couldn't write to file '%s'\n",
- outfname);
-
- if (ptr[strlen(ptr) - 1] == '\n')
- break;
-
- fgets(ptr = buf, 1023, in_file);
- } /* while */
- } /* while */
-
- fclose(in_file);
- fclose(out_file);
- } /* lpr_filter_dos() */
-
-