/* lpdClient.c v. 1.01*/
/* Changes for v. 1.01 */
/* added leading "H" to control file */
/* tidied up messages */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <sys/stat.h> /* filesize */
#include <unistd.h> /* close */
#include <dirent.h>
#include <string.h>
#define LPD_PORT 515
#define LPD_LHOST "psion"
#define LPD_RUSER "psion"
#define LPD_OK 0x00
#define MAX_BUF 1024
int connect_to_lpd(char* host);
int getprintfile(char* fname, char* host, char* queue);
int main (int argc, char *argv[]) {
int sd; //Socket desctiptor for tcp link to lpd on remote host
int rc; //Result code
char resp;//LPD response
char pfname[255]; //Local printfile name
char host[255]; //Remote host name
char queue[255]; //Remote lpd queue name
struct stat file_attrib; //structure to store file attributes
FILE * fd; //file descriptor for local print file
int cnt_file_bytes; //length of control file
char buf[MAX_BUF]; //string buffer
int sz_buf; //occupied size of buffer
int job=0; //lpd print job number
while (1) { //loop for ever
job++;
printf("Waiting for printfile.....\n");
rc=0;
while(rc!=1) { //while a valid file is not found
sleep (2); //dont keep thrashing!
rc=getprintfile(pfname,host,queue);
if (rc==-1) return 1; //directory doesnt exist
}
printf("%s found!\n",pfname);
printf("Waiting for spooling to stop....\n");
fd=0;
while(fd==0) { //while a valid file descriptor is not obtained
rc=stat(pfname,&file_attrib);
if (rc != 0 ) {
printf("file disappeared while spooling!\n");
break;
}
fd=fopen(pfname,"r");
if (fd != 0) break; //file is open - spooling has stopped
sleep(2);
}
printf("Stopped!\n");
//get final size of printfile
rc=stat(pfname,&file_attrib);
if (rc !=0) { sleep(2); continue;}
//connect to lpd daemon on remote host
printf("Connecting to %s ....\n",host);
while (1) {
sd=connect_to_lpd(host);
if (sd >0) break;
sleep (5);
}
printf("Success!\n");
//send print job
//Select queue
printf("Connecting to queue %s ....\n",queue);
sz_buf=sprintf(buf,"\2%s\12",queue);
rc = send(sd,buf,sz_buf, 0);
if (!rc) {printf("Send error %d!\n",rc); fclose(fd); close(sd); continue;}
rc = recv(sd,&resp,1, 0); // waits for char
if (!rc) {printf("Receive error %d!\n",rc); fclose(fd); close(sd); continue;}
if (resp!=LPD_OK) {printf("LPD error %d!\n",resp); fclose(fd); close(sd); continue;}
printf("Success!\n");
//Send datafile header
printf("Sending datafile header....\n");
sz_buf=sprintf(buf,"\3%d dfA%03d%s\12",file_attrib.st_size,job,LPD_LHOST);
rc = send(sd,buf,sz_buf, 0);
if (!rc) {printf("Send error %d!\n",rc); fclose(fd); close(sd); continue;}
rc = recv(sd,&resp,1, 0); // waits for char
if (!rc) {printf("Receive error %d!\n",rc); fclose(fd); close(sd); continue;}
if (resp!=LPD_OK) {printf("LPD error %d!\n",resp); fclose(fd); close(sd); continue;}
printf("Success!\n");
//Send datafile
printf("Sending datafile ....\n");
sz_buf = fread(buf,1,MAX_BUF,fd);
while (sz_buf != 0) {
rc = send(sd,buf,sz_buf, 0);
if (!rc) break;
sz_buf = fread(buf,1,MAX_BUF,fd);
}
fclose (fd);
if (!rc) {printf("Send error %d!\n",rc); close(sd); continue;}
rc = send(sd,"\0",1, 0);
if (!rc) {printf("Send error %d!\n",rc); close(sd); continue;}
rc = recv(sd,&resp,1, 0); // waits for char
if (!rc) {printf("Receive error %d!\n",rc); close(sd); continue;}
if (resp!=LPD_OK) {printf("LPD error %d!\n",resp); close(sd); continue;}
printf("Success!\n");
//Size control file
cnt_file_bytes=sprintf(buf,"H%s\nP%s\nfdfA%03d%s\n",LPD_LHOST,LPD_RUSER,job,LPD_LHOST);
//Send control file header
printf("Sending control file header....\n");
sz_buf=sprintf(buf,"\2%d cfA%03d%s\12",cnt_file_bytes,job,LPD_LHOST);
rc = send(sd,buf,sz_buf, 0);
if (!rc) {printf("Send error %d!\n",rc); close(sd); continue;}
rc = recv(sd,&resp,1, 0); // waits for char
if (!rc) {printf("Receive error %d!\n",rc); close(sd); continue;}
if (resp!=LPD_OK) {printf("LPD error %d!\n",resp); close(sd); continue;}
printf("Success!\n");
//Send control file
printf("Sending control file....\n");
sz_buf=sprintf(buf,"H%s\nP%s\nfdfA%03d%s\n",LPD_LHOST,LPD_RUSER,job,LPD_LHOST);
rc = send(sd,buf,sz_buf, 0);
if (!rc) {printf("Send error %d!\n",rc); close(sd); continue;}
rc = send(sd,"\0",1, 0);
if (!rc) {printf("Send error %d!\n",rc); close(sd); continue;}
rc = recv(sd,&resp,1, 0); // waits for char
if (!rc) {printf("Receive error %d!\n",rc); close(sd); continue;}
if (resp!=LPD_OK) {printf("LPD error %d!\n",resp); close(sd); continue;}
printf("Success!\n");
//disconnect from remote host
printf("Print job successfully submitted!\n");
printf("Disconnecting from %s.\n",host);
close(sd);
sleep(2);
//delete local spool file
while(1) {
rc=stat(pfname,&file_attrib);
if (rc != 0) break; //file doesnt exist
printf("Deleting %s....\n",pfname);
rc= remove(pfname);
if (rc != 0) perror("Error!\n");
sleep(1);
}
printf("Success!\n");
}
return 0;
}
int getprintfile(char* pfname, char* host, char* queue){
/*scans directory once for a valid printfile name,
returns the name of the first print file found
and parses queue and host from the queue@host.lpd format */
char *p, *q;
long len;
struct dirent *de;
DIR *ds;
ds = opendir("c:\\");
if (ds==NULL) return -1;
do{
de=readdir(ds);
if (de==NULL) {closedir(ds);return 0;}
if (strstr(de->d_name,".lpd")!=NULL) {
//valid printfile found
p=strstr(de->d_name,".");
if (p==NULL) continue;
q=strstr(de->d_name,"@");
if (q==NULL) continue;
len=(long)q-(long)de->d_name;
if (len<1) continue;
strcpy(queue,"");
strncat(queue,de->d_name,len);
len=(long)p-(long)q-1;
if (len<1) continue;
strcpy(host,"");
strncat(host,(char *)((long)q+1),len);
break;
}
}
while (1);
strcpy(pfname,"C:\\");
strcat(pfname,de->d_name);
return 1;
}
int connect_to_lpd(char* host) {
int rc, sd;
struct sockaddr_in localAddr, remoteAddr;
struct hostent *h;
/* resolve host ip */
h = gethostbyname(host);
if(h==NULL) {
printf("unknown host '%s'\n",host);
return-1;
}
remoteAddr.sin_family = h->h_addrtype;
memcpy((char *) &remoteAddr.sin_addr.s_addr, h->h_addr_list[0], h->h_length);
remoteAddr.sin_port = htons(LPD_PORT);
/* open socket */
sd = socket(AF_INET, SOCK_STREAM, 0);
if(sd<0) {
perror("cannot open socket ");
return -1;
}
/* bind port 900 - needs to be priveledged for some lpds*/
localAddr.sin_family = AF_INET;
localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
localAddr.sin_port = htons(900);
rc = bind(sd, (struct sockaddr *) &localAddr, sizeof(localAddr));
if(rc<0) {
printf("cannot bind port TCP %u\n",LPD_PORT);
perror("error ");
close (sd);
return -1;
}
/* connect to server */
rc = connect(sd, (struct sockaddr *) &remoteAddr, sizeof(remoteAddr));
if(rc<0) {
perror("cannot connect ");
close (sd);
return -1;
}
/* Success! return socket descriptor */
return sd;
}